aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoey Yakimowich-Payne <jyapayne@gmail.com>2020-04-18 13:13:33 -0600
committerJoey Yakimowich-Payne <jyapayne@gmail.com>2020-04-26 09:11:22 -0600
commit62c68d69ee0409558a846aae3a85cf1a29f9442b (patch)
tree12d02048a1e2c7e4ebd6902e4a2ec8edfa4aab52
parent055d6bee73eb988ae498a57d29dd3d80a8928721 (diff)
downloadnimterop-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.nim2
-rw-r--r--nimterop/exprparser.nim147
-rw-r--r--nimterop/getters.nim4
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