Add sizeof expression parser, fix nkNone issue, reduce size of typeof expressions
Cleanup, fix bugs
This commit is contained in:
parent
055d6bee73
commit
62c68d69ee
3 changed files with 97 additions and 58 deletions
|
|
@ -963,7 +963,7 @@ proc getTypeArray(gState: State, node: TSNode, tident: PNode, name: string): PNo
|
||||||
let
|
let
|
||||||
# Size of array could be a Nim expression
|
# Size of array could be a Nim expression
|
||||||
size = gState.getLit(gState.getNodeVal(cnode[1]), expression = true)
|
size = gState.getLit(gState.getNodeVal(cnode[1]), expression = true)
|
||||||
if size.kind != nkNilLit:
|
if size.kind != nkNone:
|
||||||
result = gState.newArrayTree(cnode, result, size)
|
result = gState.newArrayTree(cnode, result, size)
|
||||||
cnode = cnode[0]
|
cnode = cnode[0]
|
||||||
elif cnode.len == 1:
|
elif cnode.len == 1:
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,24 @@ template val(node: TSNode): string =
|
||||||
proc mode(exprParser: ExprParser): string =
|
proc mode(exprParser: ExprParser): string =
|
||||||
exprParser.state.gState.mode
|
exprParser.state.gState.mode
|
||||||
|
|
||||||
|
proc getIdent(exprParser: ExprParser, identName: string, kind = nskConst, parent = ""): PNode =
|
||||||
|
## Gets a cPlugin transformed identifier from `identName`
|
||||||
|
##
|
||||||
|
## Returns PNode(nkNone) if the identifier is blank
|
||||||
|
result = newNode(nkNone)
|
||||||
|
var ident = identName
|
||||||
|
if ident != "_":
|
||||||
|
# Process the identifier through cPlugin
|
||||||
|
ident = exprParser.state.getIdentifier(ident, kind, parent)
|
||||||
|
if ident != "":
|
||||||
|
result = exprParser.state.getIdent(ident)
|
||||||
|
|
||||||
|
proc getIdent(exprParser: ExprParser, node: TSNode, kind = nskConst, parent = ""): PNode =
|
||||||
|
## Gets a cPlugin transformed identifier from `identName`
|
||||||
|
##
|
||||||
|
## Returns PNode(nkNone) if the identifier is blank
|
||||||
|
exprParser.getIdent(node.val, kind, parent)
|
||||||
|
|
||||||
template withCodeAst(exprParser: ExprParser, body: untyped): untyped =
|
template withCodeAst(exprParser: ExprParser, body: untyped): untyped =
|
||||||
## A simple template to inject the TSNode into a body of code
|
## A simple template to inject the TSNode into a body of code
|
||||||
var parser = tsParserNew()
|
var parser = tsParserNew()
|
||||||
|
|
@ -56,7 +74,7 @@ proc getNumNode(number, suffix: string): PNode {.inline.} =
|
||||||
## Convert a C number to a Nim number PNode
|
## Convert a C number to a Nim number PNode
|
||||||
result = newNode(nkNone)
|
result = newNode(nkNone)
|
||||||
if number.contains("."):
|
if number.contains("."):
|
||||||
let floatSuffix = number[result.len-1]
|
let floatSuffix = number[number.len-1]
|
||||||
try:
|
try:
|
||||||
case floatSuffix
|
case floatSuffix
|
||||||
of 'l', 'L':
|
of 'l', 'L':
|
||||||
|
|
@ -66,7 +84,7 @@ proc getNumNode(number, suffix: string): PNode {.inline.} =
|
||||||
of 'f', 'F':
|
of 'f', 'F':
|
||||||
result = newFloatNode(nkFloat64Lit, parseFloat(number[0 ..< number.len - 1]))
|
result = newFloatNode(nkFloat64Lit, parseFloat(number[0 ..< number.len - 1]))
|
||||||
else:
|
else:
|
||||||
result = newFloatNode(nkFloatLit, parseFloat(number[0 ..< number.len - 1]))
|
result = newFloatNode(nkFloatLit, parseFloat(number))
|
||||||
return
|
return
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise newException(ExprParseError, &"Could not parse float value \"{number}\".")
|
raise newException(ExprParseError, &"Could not parse float value \"{number}\".")
|
||||||
|
|
@ -100,11 +118,12 @@ proc getNumNode(number, suffix: string): PNode {.inline.} =
|
||||||
result.intVal = parseInt(number)
|
result.intVal = parseInt(number)
|
||||||
|
|
||||||
proc processNumberLiteral*(exprParser: ExprParser, node: TSNode): PNode =
|
proc processNumberLiteral*(exprParser: ExprParser, node: TSNode): PNode =
|
||||||
|
## Parse a number literal from a TSNode. Can be a float, hex, long, etc
|
||||||
result = newNode(nkNone)
|
result = newNode(nkNone)
|
||||||
let nodeVal = node.val
|
let nodeVal = node.val
|
||||||
|
|
||||||
var match: RegexMatch
|
var match: RegexMatch
|
||||||
const reg = re"(\-)?(0\d+|0[xX][0-9a-fA-F]+|0[bB][01]+|\d+|\d+\.?\d*[fFlL]?|\d*\.?\d+[fFlL]?)([ulUL]*)"
|
const reg = re"(\-)?(0\d+|0[xX][0-9a-fA-F]+|0[bB][01]+|\d+\.\d*[fFlL]?|\d*\.\d+[fFlL]?|\d+)([ulUL]*)"
|
||||||
let found = nodeVal.find(reg, match)
|
let found = nodeVal.find(reg, match)
|
||||||
if found:
|
if found:
|
||||||
let
|
let
|
||||||
|
|
@ -130,9 +149,9 @@ proc processStringLiteral*(exprParser: ExprParser, node: TSNode): PNode =
|
||||||
let nodeVal = node.val
|
let nodeVal = node.val
|
||||||
result = newStrNode(nkStrLit, nodeVal[1 ..< nodeVal.len - 1])
|
result = newStrNode(nkStrLit, nodeVal[1 ..< nodeVal.len - 1])
|
||||||
|
|
||||||
proc processTSNode*(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil): PNode
|
proc processTSNode*(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode
|
||||||
|
|
||||||
proc processShiftExpression*(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil): PNode =
|
proc processShiftExpression*(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode =
|
||||||
result = newNode(nkInfix)
|
result = newNode(nkInfix)
|
||||||
let
|
let
|
||||||
left = node[0]
|
left = node[0]
|
||||||
|
|
@ -149,27 +168,35 @@ proc processShiftExpression*(exprParser: ExprParser, node: TSNode, typeofNode: P
|
||||||
|
|
||||||
let leftNode = exprParser.processTSNode(left, typeofNode)
|
let leftNode = exprParser.processTSNode(left, typeofNode)
|
||||||
|
|
||||||
var tnode = typeofNode
|
# If the typeofNode is nil, set it
|
||||||
if tnode.isNil:
|
# to be the leftNode because C's type coercion
|
||||||
tnode = leftNode
|
# happens left to right, and we want to emulate it
|
||||||
|
if typeofNode.isNil:
|
||||||
|
typeofNode = nkCall.newTree(
|
||||||
|
exprParser.state.getIdent("typeof"),
|
||||||
|
leftNode
|
||||||
|
)
|
||||||
|
|
||||||
let rightNode = exprParser.processTSNode(right, tnode)
|
let rightNode = exprParser.processTSNode(right, typeofNode)
|
||||||
|
|
||||||
result.add leftNode
|
result.add leftNode
|
||||||
result.add nkCast.newTree(
|
result.add nkCast.newTree(
|
||||||
nkCall.newTree(
|
typeofNode,
|
||||||
exprParser.state.getIdent("typeof"),
|
|
||||||
tnode
|
|
||||||
),
|
|
||||||
rightNode
|
rightNode
|
||||||
)
|
)
|
||||||
|
|
||||||
proc processParenthesizedExpr*(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil): PNode =
|
proc processParenthesizedExpr*(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode =
|
||||||
result = newNode(nkPar)
|
result = newNode(nkPar)
|
||||||
for i in 0 ..< node.len():
|
for i in 0 ..< node.len():
|
||||||
result.add(exprParser.processTSNode(node[i], typeofNode))
|
result.add(exprParser.processTSNode(node[i], typeofNode))
|
||||||
|
|
||||||
proc processLogicalExpression*(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil): PNode =
|
proc processCastExpression*(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode =
|
||||||
|
result = nkCast.newTree(
|
||||||
|
exprParser.processTSNode(node[0], typeofNode),
|
||||||
|
exprParser.processTSNode(node[1], typeofNode)
|
||||||
|
)
|
||||||
|
|
||||||
|
proc processLogicalExpression*(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode =
|
||||||
result = newNode(nkPar)
|
result = newNode(nkPar)
|
||||||
let child = node[0]
|
let child = node[0]
|
||||||
var nimSym = ""
|
var nimSym = ""
|
||||||
|
|
@ -189,7 +216,7 @@ proc processLogicalExpression*(exprParser: ExprParser, node: TSNode, typeofNode:
|
||||||
exprParser.processTSNode(child, typeofNode)
|
exprParser.processTSNode(child, typeofNode)
|
||||||
)
|
)
|
||||||
|
|
||||||
proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil): PNode =
|
proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode =
|
||||||
if node.len > 1:
|
if node.len > 1:
|
||||||
# Node has left and right children ie: (2 + 7)
|
# Node has left and right children ie: (2 + 7)
|
||||||
var
|
var
|
||||||
|
|
@ -204,19 +231,20 @@ proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNo
|
||||||
res.add exprParser.state.getIdent(mathSym)
|
res.add exprParser.state.getIdent(mathSym)
|
||||||
let leftNode = exprParser.processTSNode(left, typeofNode)
|
let leftNode = exprParser.processTSNode(left, typeofNode)
|
||||||
|
|
||||||
var tnode = typeofNode
|
# If the typeofNode is nil, set it
|
||||||
if tnode.isNil:
|
# to be the leftNode because C's type coercion
|
||||||
tnode = leftNode
|
# happens left to right, and we want to emulate it
|
||||||
|
if typeofNode.isNil:
|
||||||
|
typeofNode = nkCall.newTree(
|
||||||
|
exprParser.state.getIdent("typeof"),
|
||||||
|
leftNode
|
||||||
|
)
|
||||||
|
|
||||||
let rightNode = exprParser.processTSNode(right, tnode)
|
let rightNode = exprParser.processTSNode(right, typeofNode)
|
||||||
|
|
||||||
res.add leftNode
|
res.add leftNode
|
||||||
# res.add rightNode
|
|
||||||
res.add nkCast.newTree(
|
res.add nkCast.newTree(
|
||||||
nkCall.newTree(
|
typeofNode,
|
||||||
exprParser.state.getIdent("typeof"),
|
|
||||||
tnode
|
|
||||||
),
|
|
||||||
rightNode
|
rightNode
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -224,10 +252,7 @@ proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNo
|
||||||
# hand argument, since some expressions return a differing
|
# hand argument, since some expressions return a differing
|
||||||
# type than the input types (2/3 == float)
|
# type than the input types (2/3 == float)
|
||||||
result = nkCall.newTree(
|
result = nkCall.newTree(
|
||||||
nkCall.newTree(
|
typeofNode,
|
||||||
exprParser.state.getIdent("typeof"),
|
|
||||||
tnode
|
|
||||||
),
|
|
||||||
res
|
res
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -248,6 +273,8 @@ proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNo
|
||||||
# so we have to make a gental cast here to coerce it to one.
|
# so we have to make a gental cast here to coerce it to one.
|
||||||
# Might be bad because we are overwriting the type
|
# Might be bad because we are overwriting the type
|
||||||
# There's probably a better way of doing this
|
# There's probably a better way of doing this
|
||||||
|
if typeofNode.isNil:
|
||||||
|
typeofNode = exprParser.state.getIdent("int64")
|
||||||
result.add nkPrefix.newTree(
|
result.add nkPrefix.newTree(
|
||||||
exprParser.state.getIdent(unarySym),
|
exprParser.state.getIdent(unarySym),
|
||||||
nkPar.newTree(
|
nkPar.newTree(
|
||||||
|
|
@ -268,7 +295,7 @@ proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNo
|
||||||
else:
|
else:
|
||||||
raise newException(ExprParseError, &"Invalid bitwise_expression \"{node.val}\"")
|
raise newException(ExprParseError, &"Invalid bitwise_expression \"{node.val}\"")
|
||||||
|
|
||||||
proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil): PNode =
|
proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode =
|
||||||
if node.len() > 1:
|
if node.len() > 1:
|
||||||
result = newNode(nkInfix)
|
result = newNode(nkInfix)
|
||||||
|
|
||||||
|
|
@ -288,24 +315,25 @@ proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode:
|
||||||
nimSym = "and"
|
nimSym = "and"
|
||||||
of "^":
|
of "^":
|
||||||
nimSym = "xor"
|
nimSym = "xor"
|
||||||
|
of "==", "!=":
|
||||||
|
nimSym = binarySym
|
||||||
else:
|
else:
|
||||||
raise newException(ExprParseError, &"Unsupported binary symbol \"{binarySym}\"")
|
raise newException(ExprParseError, &"Unsupported binary symbol \"{binarySym}\"")
|
||||||
|
|
||||||
result.add exprParser.state.getIdent(nimSym)
|
result.add exprParser.state.getIdent(nimSym)
|
||||||
let leftNode = exprParser.processTSNode(left, typeofNode)
|
let leftNode = exprParser.processTSNode(left, typeofNode)
|
||||||
|
|
||||||
var tnode = typeofNode
|
if typeofNode.isNil:
|
||||||
if tnode.isNil:
|
typeofNode = nkCall.newTree(
|
||||||
tnode = leftNode
|
exprParser.state.getIdent("typeof"),
|
||||||
|
leftNode
|
||||||
|
)
|
||||||
|
|
||||||
let rightNode = exprParser.processTSNode(right, tnode)
|
let rightNode = exprParser.processTSNode(right, typeofNode)
|
||||||
|
|
||||||
result.add leftNode
|
result.add leftNode
|
||||||
result.add nkCall.newTree(
|
result.add nkCall.newTree(
|
||||||
nkCall.newTree(
|
typeofNode,
|
||||||
exprParser.state.getIdent("typeof"),
|
|
||||||
tnode
|
|
||||||
),
|
|
||||||
rightNode
|
rightNode
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -317,6 +345,7 @@ proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode:
|
||||||
var unarySym = exprParser.code[node.tsNodeStartByte() ..< child.tsNodeStartByte()].strip()
|
var unarySym = exprParser.code[node.tsNodeStartByte() ..< child.tsNodeStartByte()].strip()
|
||||||
techo "BIN SYM: ", unarySym
|
techo "BIN SYM: ", unarySym
|
||||||
|
|
||||||
|
# TODO: Support more symbols here
|
||||||
case unarySym
|
case unarySym
|
||||||
of "~":
|
of "~":
|
||||||
nimSym = "not"
|
nimSym = "not"
|
||||||
|
|
@ -330,7 +359,13 @@ proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode:
|
||||||
else:
|
else:
|
||||||
raise newException(ExprParseError, &"Invalid bitwise_expression \"{node.val}\"")
|
raise newException(ExprParseError, &"Invalid bitwise_expression \"{node.val}\"")
|
||||||
|
|
||||||
proc processTSNode(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil): PNode =
|
proc processSizeofExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode =
|
||||||
|
result = nkCall.newTree(
|
||||||
|
exprParser.state.getIdent("sizeof"),
|
||||||
|
exprParser.processTSNode(node[0], typeofNode)
|
||||||
|
)
|
||||||
|
|
||||||
|
proc processTSNode(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode =
|
||||||
## Handle all of the types of expressions here. This proc gets called recursively
|
## Handle all of the types of expressions here. This proc gets called recursively
|
||||||
## in the processX procs and will drill down to sub nodes.
|
## in the processX procs and will drill down to sub nodes.
|
||||||
result = newNode(nkNone)
|
result = newNode(nkNone)
|
||||||
|
|
@ -351,42 +386,48 @@ proc processTSNode(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil
|
||||||
raise newException(ExprParseError, &"Node type \"{nodeName}\" has no children")
|
raise newException(ExprParseError, &"Node type \"{nodeName}\" has no children")
|
||||||
of "parenthesized_expression":
|
of "parenthesized_expression":
|
||||||
result = exprParser.processParenthesizedExpr(node, typeofNode)
|
result = exprParser.processParenthesizedExpr(node, typeofNode)
|
||||||
of "bitwise_expression":
|
of "sizeof_expression":
|
||||||
|
result = exprParser.processSizeofExpression(node, typeofNode)
|
||||||
|
of "bitwise_expression", "equality_expression":
|
||||||
result = exprParser.processBitwiseExpression(node, typeofNode)
|
result = exprParser.processBitwiseExpression(node, typeofNode)
|
||||||
of "math_expression":
|
of "math_expression":
|
||||||
result = exprParser.processMathExpression(node, typeofNode)
|
result = exprParser.processMathExpression(node, typeofNode)
|
||||||
of "shift_expression":
|
of "shift_expression":
|
||||||
result = exprParser.processShiftExpression(node, typeofNode)
|
result = exprParser.processShiftExpression(node, typeofNode)
|
||||||
|
of "cast_expression":
|
||||||
|
result = exprParser.processCastExpression(node, typeofNode)
|
||||||
of "logical_expression":
|
of "logical_expression":
|
||||||
result = exprParser.processLogicalExpression(node, typeofNode)
|
result = exprParser.processLogicalExpression(node, typeofNode)
|
||||||
# Why are these node types named true/false?
|
# Why are these node types named true/false?
|
||||||
of "true", "false":
|
of "true", "false":
|
||||||
result = exprParser.state.parseString(node.val)
|
result = exprParser.state.parseString(node.val)
|
||||||
of "identifier":
|
of "type_descriptor":
|
||||||
var ident = node.val
|
let ty = getType(node.val)
|
||||||
if ident != "_":
|
result = exprParser.getIdent(ty, nskType, parent=node.getName())
|
||||||
# Process the identifier through cPlugin
|
|
||||||
ident = exprParser.state.getIdentifier(ident, nskConst)
|
|
||||||
techo ident
|
|
||||||
if ident != "":
|
|
||||||
result = exprParser.state.getIdent(ident)
|
|
||||||
if result.kind == nkNone:
|
if result.kind == nkNone:
|
||||||
raise newException(ExprParseError, &"Could not get identifier \"{ident}\"")
|
result = exprParser.state.getIdent(ty)
|
||||||
|
of "identifier":
|
||||||
|
result = exprParser.getIdent(node, parent=node.getName())
|
||||||
|
if result.kind == nkNone:
|
||||||
|
raise newException(ExprParseError, &"Could not get identifier \"{node.val}\"")
|
||||||
else:
|
else:
|
||||||
raise newException(ExprParseError, &"Unsupported node type \"{nodeName}\" for node \"{node.val}\"")
|
raise newException(ExprParseError, &"Unsupported node type \"{nodeName}\" for node \"{node.val}\"")
|
||||||
|
|
||||||
techo "NODE RES: ", result
|
techo "NODE RESULT: ", result
|
||||||
|
|
||||||
proc codeToNode*(state: NimState, code: string): PNode =
|
proc codeToNode*(state: NimState, code: string): PNode =
|
||||||
## Convert the C string to a nim PNode tree
|
## Convert the C string to a nim PNode tree
|
||||||
result = newNode(nkNone)
|
result = newNode(nkNone)
|
||||||
|
# This is used for keeping track of the type of the first
|
||||||
|
# symbol
|
||||||
|
var tnode: PNode = nil
|
||||||
|
let exprParser = newExprParser(state, code)
|
||||||
try:
|
try:
|
||||||
let exprParser = newExprParser(state, code)
|
|
||||||
withCodeAst(exprParser):
|
withCodeAst(exprParser):
|
||||||
result = exprParser.processTSNode(root)
|
result = exprParser.processTSNode(root, tnode)
|
||||||
except ExprParseError as e:
|
except ExprParseError as e:
|
||||||
echo e.msg.getCommented
|
techo e.msg
|
||||||
result = newNode(nkNone)
|
result = newNode(nkNone)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
echo e.msg.getCommented
|
techo "UNEXPECTED EXCEPTION: ", e.msg
|
||||||
result = newNode(nkNone)
|
result = newNode(nkNone)
|
||||||
|
|
@ -460,18 +460,16 @@ proc printTree*(gState: State, pnode: PNode, offset = ""): string =
|
||||||
result &= "\n"
|
result &= "\n"
|
||||||
|
|
||||||
proc printDebug*(nimState: NimState, node: TSNode) =
|
proc printDebug*(nimState: NimState, node: TSNode) =
|
||||||
discard
|
|
||||||
# This causes random segfaults for some reason on macOS Catalina
|
# This causes random segfaults for some reason on macOS Catalina
|
||||||
if nimState.gState.debug:
|
if nimState.gState.debug:
|
||||||
necho ("Input => " & nimState.getNodeVal(node)).getCommented()
|
necho ("Input => " & nimState.getNodeVal(node)).getCommented()
|
||||||
necho nimState.gState.printLisp(node).getCommented()
|
necho nimState.gState.printLisp(node).getCommented()
|
||||||
|
|
||||||
proc printDebug*(nimState: NimState, pnode: PNode) =
|
proc printDebug*(nimState: NimState, pnode: PNode) =
|
||||||
discard
|
|
||||||
# This causes random segfaults for some reason on macOS Catalina
|
# This causes random segfaults for some reason on macOS Catalina
|
||||||
if nimState.gState.debug and pnode.kind != nkNone:
|
if nimState.gState.debug and pnode.kind != nkNone:
|
||||||
necho ("Output => " & $pnode).getCommented()
|
necho ("Output => " & $pnode).getCommented()
|
||||||
necho nimState.printTree(pnode)
|
necho nimState.printTree(pnode).getCommented()
|
||||||
|
|
||||||
# Compiler shortcuts
|
# Compiler shortcuts
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue