diff options
| author | Joey Yakimowich-Payne <jyapayne@gmail.com> | 2020-04-18 13:13:33 -0600 |
|---|---|---|
| committer | Joey Yakimowich-Payne <jyapayne@gmail.com> | 2020-04-26 09:11:22 -0600 |
| commit | 62c68d69ee0409558a846aae3a85cf1a29f9442b (patch) | |
| tree | 12d02048a1e2c7e4ebd6902e4a2ec8edfa4aab52 | |
| parent | 055d6bee73eb988ae498a57d29dd3d80a8928721 (diff) | |
| download | nimterop-62c68d69ee0409558a846aae3a85cf1a29f9442b.tar.gz nimterop-62c68d69ee0409558a846aae3a85cf1a29f9442b.zip | |
Add sizeof expression parser, fix nkNone issue, reduce size of typeof expressions
Cleanup, fix bugs
| -rw-r--r-- | nimterop/ast2.nim | 2 | ||||
| -rw-r--r-- | nimterop/exprparser.nim | 147 | ||||
| -rw-r--r-- | nimterop/getters.nim | 4 |
3 files changed, 96 insertions, 57 deletions
diff --git a/nimterop/ast2.nim b/nimterop/ast2.nim index 85b555f..8c5da8c 100644 --- a/nimterop/ast2.nim +++ b/nimterop/ast2.nim @@ -963,7 +963,7 @@ proc getTypeArray(gState: State, node: TSNode, tident: PNode, name: string): PNo let # Size of array could be a Nim expression size = gState.getLit(gState.getNodeVal(cnode[1]), expression = true) - if size.kind != nkNilLit: + if size.kind != nkNone: result = gState.newArrayTree(cnode, result, size) cnode = cnode[0] elif cnode.len == 1: diff --git a/nimterop/exprparser.nim b/nimterop/exprparser.nim index 505453c..d27f23b 100644 --- a/nimterop/exprparser.nim +++ b/nimterop/exprparser.nim @@ -29,6 +29,24 @@ template val(node: TSNode): string = proc mode(exprParser: ExprParser): string = 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 = ## A simple template to inject the TSNode into a body of code var parser = tsParserNew() @@ -56,7 +74,7 @@ proc getNumNode(number, suffix: string): PNode {.inline.} = ## Convert a C number to a Nim number PNode result = newNode(nkNone) if number.contains("."): - let floatSuffix = number[result.len-1] + let floatSuffix = number[number.len-1] try: case floatSuffix of 'l', 'L': @@ -66,7 +84,7 @@ proc getNumNode(number, suffix: string): PNode {.inline.} = of 'f', 'F': result = newFloatNode(nkFloat64Lit, parseFloat(number[0 ..< number.len - 1])) else: - result = newFloatNode(nkFloatLit, parseFloat(number[0 ..< number.len - 1])) + result = newFloatNode(nkFloatLit, parseFloat(number)) return except ValueError: raise newException(ExprParseError, &"Could not parse float value \"{number}\".") @@ -100,11 +118,12 @@ proc getNumNode(number, suffix: string): PNode {.inline.} = result.intVal = parseInt(number) proc processNumberLiteral*(exprParser: ExprParser, node: TSNode): PNode = + ## Parse a number literal from a TSNode. Can be a float, hex, long, etc result = newNode(nkNone) let nodeVal = node.val 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) if found: let @@ -130,9 +149,9 @@ proc processStringLiteral*(exprParser: ExprParser, node: TSNode): PNode = let nodeVal = node.val 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) let left = node[0] @@ -149,27 +168,35 @@ proc processShiftExpression*(exprParser: ExprParser, node: TSNode, typeofNode: P let leftNode = exprParser.processTSNode(left, typeofNode) - var tnode = typeofNode - if tnode.isNil: - tnode = leftNode + # If the typeofNode is nil, set it + # to be the leftNode because C's type coercion + # 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 nkCast.newTree( - nkCall.newTree( - exprParser.state.getIdent("typeof"), - tnode - ), + typeofNode, rightNode ) -proc processParenthesizedExpr*(exprParser: ExprParser, node: TSNode, typeofNode: PNode = nil): PNode = +proc processParenthesizedExpr*(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode = result = newNode(nkPar) for i in 0 ..< node.len(): 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) let child = node[0] var nimSym = "" @@ -189,7 +216,7 @@ proc processLogicalExpression*(exprParser: ExprParser, node: TSNode, 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: # Node has left and right children ie: (2 + 7) var @@ -204,19 +231,20 @@ proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNo res.add exprParser.state.getIdent(mathSym) let leftNode = exprParser.processTSNode(left, typeofNode) - var tnode = typeofNode - if tnode.isNil: - tnode = leftNode + # If the typeofNode is nil, set it + # to be the leftNode because C's type coercion + # 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 rightNode res.add nkCast.newTree( - nkCall.newTree( - exprParser.state.getIdent("typeof"), - tnode - ), + typeofNode, rightNode ) @@ -224,10 +252,7 @@ proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNo # hand argument, since some expressions return a differing # type than the input types (2/3 == float) result = nkCall.newTree( - nkCall.newTree( - exprParser.state.getIdent("typeof"), - tnode - ), + typeofNode, 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. # Might be bad because we are overwriting the type # There's probably a better way of doing this + if typeofNode.isNil: + typeofNode = exprParser.state.getIdent("int64") result.add nkPrefix.newTree( exprParser.state.getIdent(unarySym), nkPar.newTree( @@ -268,7 +295,7 @@ proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: PNo else: 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: result = newNode(nkInfix) @@ -288,24 +315,25 @@ proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode: nimSym = "and" of "^": nimSym = "xor" + of "==", "!=": + nimSym = binarySym else: raise newException(ExprParseError, &"Unsupported binary symbol \"{binarySym}\"") result.add exprParser.state.getIdent(nimSym) let leftNode = exprParser.processTSNode(left, typeofNode) - var tnode = typeofNode - if tnode.isNil: - tnode = leftNode + 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 nkCall.newTree( - nkCall.newTree( - exprParser.state.getIdent("typeof"), - tnode - ), + typeofNode, rightNode ) @@ -317,6 +345,7 @@ proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode: var unarySym = exprParser.code[node.tsNodeStartByte() ..< child.tsNodeStartByte()].strip() techo "BIN SYM: ", unarySym + # TODO: Support more symbols here case unarySym of "~": nimSym = "not" @@ -330,7 +359,13 @@ proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode: else: 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 ## in the processX procs and will drill down to sub nodes. 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") of "parenthesized_expression": 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) of "math_expression": result = exprParser.processMathExpression(node, typeofNode) of "shift_expression": result = exprParser.processShiftExpression(node, typeofNode) + of "cast_expression": + result = exprParser.processCastExpression(node, typeofNode) of "logical_expression": result = exprParser.processLogicalExpression(node, typeofNode) # Why are these node types named true/false? of "true", "false": result = exprParser.state.parseString(node.val) + of "type_descriptor": + let ty = getType(node.val) + result = exprParser.getIdent(ty, nskType, parent=node.getName()) + if result.kind == nkNone: + result = exprParser.state.getIdent(ty) of "identifier": - var ident = node.val - if ident != "_": - # Process the identifier through cPlugin - ident = exprParser.state.getIdentifier(ident, nskConst) - techo ident - if ident != "": - result = exprParser.state.getIdent(ident) + result = exprParser.getIdent(node, parent=node.getName()) if result.kind == nkNone: - raise newException(ExprParseError, &"Could not get identifier \"{ident}\"") + raise newException(ExprParseError, &"Could not get identifier \"{node.val}\"") else: 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 = ## Convert the C string to a nim PNode tree 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: - let exprParser = newExprParser(state, code) withCodeAst(exprParser): - result = exprParser.processTSNode(root) + result = exprParser.processTSNode(root, tnode) except ExprParseError as e: - echo e.msg.getCommented + techo e.msg result = newNode(nkNone) except Exception as e: - echo e.msg.getCommented + techo "UNEXPECTED EXCEPTION: ", e.msg result = newNode(nkNone)
\ No newline at end of file diff --git a/nimterop/getters.nim b/nimterop/getters.nim index f43f199..216d2e6 100644 --- a/nimterop/getters.nim +++ b/nimterop/getters.nim @@ -460,18 +460,16 @@ proc printTree*(gState: State, pnode: PNode, offset = ""): string = result &= "\n" proc printDebug*(nimState: NimState, node: TSNode) = - discard # This causes random segfaults for some reason on macOS Catalina if nimState.gState.debug: necho ("Input => " & nimState.getNodeVal(node)).getCommented() necho nimState.gState.printLisp(node).getCommented() proc printDebug*(nimState: NimState, pnode: PNode) = - discard # This causes random segfaults for some reason on macOS Catalina if nimState.gState.debug and pnode.kind != nkNone: necho ("Output => " & $pnode).getCommented() - necho nimState.printTree(pnode) + necho nimState.printTree(pnode).getCommented() # Compiler shortcuts |
