diff options
| author | Joey Yakimowich-Payne <jyapayne@gmail.com> | 2020-04-22 01:16:19 -0600 |
|---|---|---|
| committer | Joey Yakimowich-Payne <jyapayne@gmail.com> | 2020-04-26 09:11:56 -0600 |
| commit | b1a445c34dfff04d5c799b7c4ee0f7e806900e91 (patch) | |
| tree | 6ad5f4baf995e74b6e80f3f0a747ac8194cd076b | |
| parent | 4794c076ffc7f46858dfebfdae47d8e3c47d1cf7 (diff) | |
| download | nimterop-b1a445c34dfff04d5c799b7c4ee0f7e806900e91.tar.gz nimterop-b1a445c34dfff04d5c799b7c4ee0f7e806900e91.zip | |
Update based on comments from review. Need to add more docs and reorg to use gstate
| -rw-r--r-- | nimterop/ast2.nim | 30 | ||||
| -rw-r--r-- | nimterop/comphelp.nim (renamed from nimterop/utils.nim) | 0 | ||||
| -rw-r--r-- | nimterop/exprparser.nim | 384 | ||||
| -rw-r--r-- | nimterop/getters.nim | 20 | ||||
| -rw-r--r-- | nimterop/toast.nim | 20 | ||||
| -rw-r--r-- | nimterop/tshelp.nim | 30 | ||||
| -rw-r--r-- | tests/tast2.nim | 1 |
7 files changed, 244 insertions, 241 deletions
diff --git a/nimterop/ast2.nim b/nimterop/ast2.nim index 08ea2d6..1b7fb3d 100644 --- a/nimterop/ast2.nim +++ b/nimterop/ast2.nim @@ -1,10 +1,12 @@ import macros, os, sequtils, sets, strformat, strutils, tables, times +import options as opts + import compiler/[ast, idents, lineinfos, modulegraphs, msgs, options, renderer] import "."/treesitter/api -import "."/[globals, getters, exprparser, utils] +import "."/[globals, getters, exprparser, comphelp] proc getPtrType*(str: string): string = result = case str: @@ -17,9 +19,6 @@ proc getPtrType*(str: string): string = else: str -proc getLit*(nimState: NimState, str: string, expression = false): PNode = - result = nimState.parseCExpression(str) - proc getOverrideOrSkip(gState: State, node: TSNode, origname: string, kind: NimSymKind): PNode = # Check if symbol `origname` of `kind` and `origname` has any cOverride defined # and use that if present @@ -101,7 +100,7 @@ proc newConstDef(gState: State, node: TSNode, fname = "", fval = ""): PNode = else: gState.getNodeVal(node[1]) valident = - gState.getLit(val) + gState.parseCExpression(val) if name.Bl: # Name skipped or overridden since blank @@ -962,7 +961,7 @@ proc getTypeArray(gState: State, node: TSNode, tident: PNode, name: string): PNo # type name[X] => array[X, type] let # Size of array could be a Nim expression - size = gState.getLit(gState.getNodeVal(cnode[1]), expression = true) + size = gState.parseCExpression(gState.getNodeVal(cnode[1])) if size.kind != nkNone: result = gState.newArrayTree(cnode, result, size) cnode = cnode[0] @@ -1367,6 +1366,7 @@ proc addEnum(gState: State, node: TSNode) = # Create const for fields var fnames: HashSet[string] + fvalSections: seq[tuple[fname: string, fval: string, cexpr: Option[TSNode]]] for i in 0 .. enumlist.len - 1: let en = enumlist[i] @@ -1385,20 +1385,25 @@ proc addEnum(gState: State, node: TSNode) = fval = &"({prev} + 1).{name}" if en.len > 1 and en[1].getName() in gEnumVals: - # Explicit value - fval = "(" & $gState.parseCExpression(gState.getNodeVal(en[1]), name) & ")." & name - - # Cannot use newConstDef() since parseString(fval) adds backticks to and/or - gState.constSection.add gState.parseString(&"const {fname}* = {fval}")[0][0] + fvalSections.add((fname, "", some(en[1]))) + else: + fvalSections.add((fname, fval, none(TSNode))) fnames.incl fname - prev = fname # Add fields to list of consts after processing enum so that we don't cast # enum field to itself gState.constIdentifiers.incl fnames + # parseCExpression requires all const identifiers to be present for the enum + for (fname, fval, cexprNode) in fvalSections: + var fval = fval + if cexprNode.isSome: + fval = "(" & $nimState.parseCExpression(nimState.getNodeVal(cexprNode.get()), name) & ")." & name + # Cannot use newConstDef() since parseString(fval) adds backticks to and/or + nimState.constSection.add nimState.parseString(&"const {fname}* = {fval}")[0][0] + # Add other names if node.getName() == "type_definition" and node.len > 1: gState.addTypeTyped(node, ftname = name, offset = offset) @@ -1486,7 +1491,6 @@ proc addProc(gState: State, node, rnode: TSNode) = # Parameter list plist = node.anyChildInTree("parameter_list") - var procDef = newNode(nkProcDef) # proc X(a1: Y, a2: Z): P {.pragma.} diff --git a/nimterop/utils.nim b/nimterop/comphelp.nim index 025256a..025256a 100644 --- a/nimterop/utils.nim +++ b/nimterop/comphelp.nim diff --git a/nimterop/exprparser.nim b/nimterop/exprparser.nim index 44e59d6..2ce4989 100644 --- a/nimterop/exprparser.nim +++ b/nimterop/exprparser.nim @@ -6,7 +6,7 @@ import compiler/[ast, renderer] import "."/treesitter/[api, c, cpp] -import "."/[globals, getters, utils] +import "."/[globals, getters, comphelp, tshelp] # This version of exprparser should be able to handle: # @@ -41,9 +41,9 @@ proc newExprParser*(state: NimState, code: string, name = ""): ExprParser = ExprParser(state: state, code: code, name: name) template techo(msg: varargs[string, `$`]) = - if exprParser.state.gState.debug: + block: let nimState {.inject.} = exprParser.state - necho join(msg, "").getCommented + decho join(msg, "") template val(node: TSNode): string = exprParser.code.getNodeVal(node) @@ -60,9 +60,11 @@ proc getIdent(exprParser: ExprParser, identName: string, kind = nskConst, parent if ident != "_": # Process the identifier through cPlugin ident = exprParser.state.getIdentifier(ident, kind, parent) - if exprParser.name.nBl and ident in exprParser.state.constIdentifiers: - ident = ident & "." & exprParser.name - if ident != "": + if kind == nskType: + result = exprParser.state.getIdent(ident) + elif ident.nBl and ident in exprParser.state.constIdentifiers: + if exprParser.name.nBl: + ident = ident & "." & exprParser.name result = exprParser.state.getIdent(ident) proc getIdent(exprParser: ExprParser, node: TSNode, kind = nskConst, parent = ""): PNode = @@ -71,29 +73,6 @@ proc getIdent(exprParser: ExprParser, node: TSNode, kind = nskConst, parent = "" ## 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() - defer: - parser.tsParserDelete() - - doAssert exprParser.code.nBl, "Empty code" - if exprParser.mode == "c": - doAssert parser.tsParserSetLanguage(treeSitterC()), "Failed to load C parser" - elif exprParser.mode == "cpp": - doAssert parser.tsParserSetLanguage(treeSitterCpp()), "Failed to load C++ parser" - else: - doAssert false, &"Invalid parser {exprParser.mode}" - - var - tree = parser.tsParserParseString(nil, exprParser.code.cstring, exprParser.code.len.uint32) - root {.inject.} = tree.tsTreeRootNode() - - body - - defer: - tree.tsTreeDelete() - proc parseChar(charStr: string): uint8 {.inline.} = ## Parses a character literal out of a string. This is needed ## because treesitter gives unescaped characters when parsing @@ -161,37 +140,36 @@ proc getNumNode(number, suffix: string): PNode {.inline.} = result = newFloatNode(nkFloat64Lit, parseFloat(number[0 ..< number.len - 1])) else: result = newFloatNode(nkFloatLit, parseFloat(number)) - return except ValueError: raise newException(ExprParseError, &"Could not parse float value \"{number}\".") - - case suffix - of "u", "U": - result = newNode(nkUintLit) - of "l", "L": - result = newNode(nkInt32Lit) - of "ul", "UL": - result = newNode(nkUint32Lit) - of "ll", "LL": - result = newNode(nkInt64Lit) - of "ull", "ULL": - result = newNode(nkUint64Lit) - else: - result = newNode(nkIntLit) - - # I realize these regex are wasteful on performance, but - # couldn't come up with a better idea. - if number.contains(re"0[xX]"): - result.intVal = parseHexInt(number) - result.flags = {nfBase16} - elif number.contains(re"0[bB]"): - result.intVal = parseBinInt(number) - result.flags = {nfBase2} - elif number.contains(re"0[oO]"): - result.intVal = parseOctInt(number) - result.flags = {nfBase8} else: - result.intVal = parseInt(number) + case suffix + of "u", "U": + result = newNode(nkUintLit) + of "l", "L": + result = newNode(nkInt32Lit) + of "ul", "UL": + result = newNode(nkUint32Lit) + of "ll", "LL": + result = newNode(nkInt64Lit) + of "ull", "ULL": + result = newNode(nkUint64Lit) + else: + result = newNode(nkIntLit) + + # I realize these regex are wasteful on performance, but + # couldn't come up with a better idea. + if number.contains(re"0[xX]"): + result.intVal = parseHexInt(number) + result.flags = {nfBase16} + elif number.contains(re"0[bB]"): + result.intVal = parseBinInt(number) + result.flags = {nfBase2} + elif number.contains(re"0[oO]"): + result.intVal = parseOctInt(number) + result.flags = {nfBase8} + else: + 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 @@ -285,168 +263,112 @@ proc processCastExpression(exprParser: ExprParser, node: TSNode, typeofNode: var exprParser.processTSNode(node[1], typeofNode) ) -proc processLogicalExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode = - result = newNode(nkPar) - let child = node[0] - var nimSym = "" - - let binarySym = node.tsNodeChild(0).val.strip() - techo "LOG SYM: ", binarySym - - case binarySym - of "!": - nimSym = "not" +proc getNimUnarySym(csymbol: string): string = + ## Get the Nim equivalent of a unary C symbol + ## + ## TODO: Add ++, --, + case csymbol + of "+", "-": + result = csymbol + of "~", "!": + result = "not" else: - raise newException(ExprParseError, &"Unsupported logical symbol \"{binarySym}\"") + raise newException(ExprParseError, &"Unsupported unary symbol \"{csymbol}\"") + +proc getNimBinarySym(csymbol: string): string = + case csymbol + of "|", "||": + result = "or" + of "&", "&&": + result = "and" + of "^": + result = "xor" + of "==", "!=", + "+", "-", "/", "*", + ">", "<", ">=", "<=": + result = csymbol + of "%": + result = "mod" + else: + raise newException(ExprParseError, &"Unsupported binary symbol \"{csymbol}\"") - techo "LOG CHILD: ", child.val, ", nim: ", nimSym - result.add nkPrefix.newTree( - exprParser.state.getIdent(nimSym), - exprParser.processTSNode(child, typeofNode) - ) +proc processBinaryExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode = + # Node has left and right children ie: (2 + 7) + result = newNode(nkInfix) -proc processMathExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode = - if node.len > 1: - # Node has left and right children ie: (2 + 7) - var - res = newNode(nkInfix) - let - left = node[0] - right = node[1] + let + left = node[0] + right = node[1] + binarySym = node.tsNodeChild(1).val.strip() + nimSym = getNimBinarySym(binarySym) - let mathSym = node.tsNodeChild(1).val.strip() - techo "MATH SYM: ", mathSym + result.add exprParser.state.getIdent(nimSym) + let leftNode = exprParser.processTSNode(left, typeofNode) - res.add exprParser.state.getIdent(mathSym) - let leftNode = exprParser.processTSNode(left, typeofNode) + if typeofNode.isNil: + typeofNode = nkCall.newTree( + exprParser.state.getIdent("typeof"), + 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, typeofNode) - let rightNode = exprParser.processTSNode(right, typeofNode) + result.add leftNode + result.add nkCall.newTree( + typeofNode, + rightNode + ) - res.add leftNode - res.add nkCall.newTree( - typeofNode, - rightNode - ) +proc processUnaryExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode = + result = newNode(nkPar) - # Make sure the statement is of the same type as the left - # hand argument, since some expressions return a differing - # type than the input types (2/3 == float) - result = nkCall.newTree( - typeofNode, - res - ) + let + child = node[0] + unarySym = node.tsNodeChild(0).val.strip() + nimSym = getNimUnarySym(unarySym) + + if nimSym == "-": + # Special case. The minus symbol must be in front of an integer, + # so we have to make a gentle 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") - elif node.len() == 1: - # Node has only one child, ie -(20 + 7) - result = newNode(nkPar) - let child = node[0] - var nimSym = "" - - let unarySym = node.tsNodeChild(0).val.strip() - techo "MATH SYM: ", unarySym - - case unarySym - of "+": - nimSym = "+" - of "-": - # Special case. The minus symbol must be in front of an integer, - # 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( - nkCall.newTree( - exprParser.state.getIdent("int64"), - exprParser.processTSNode(child, typeofNode) - ) + result.add nkPrefix.newTree( + exprParser.state.getIdent(unarySym), + nkPar.newTree( + nkCall.newTree( + exprParser.state.getIdent("int64"), + exprParser.processTSNode(child, typeofNode) ) ) - return - else: - raise newException(ExprParseError, &"Unsupported unary symbol \"{unarySym}\"") - + ) + else: result.add nkPrefix.newTree( exprParser.state.getIdent(nimSym), exprParser.processTSNode(child, typeofNode) ) - else: - raise newException(ExprParseError, &"Invalid bitwise_expression \"{node.val}\"") - -proc processBitwiseExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode = - if node.len() > 1: - result = newNode(nkInfix) - let - left = node[0] - right = node[1] - - var nimSym = "" - - let binarySym = node.tsNodeChild(1).val.strip() - techo "BIN SYM: ", binarySym - - case binarySym - of "|", "||": - nimSym = "or" - of "&", "&&": - 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) - - if typeofNode.isNil: - typeofNode = nkCall.newTree( - exprParser.state.getIdent("typeof"), - leftNode - ) - - let rightNode = exprParser.processTSNode(right, typeofNode) +proc processUnaryOrBinaryExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode = + if node.len > 1: + # Node has left and right children ie: (2 + 7) - result.add leftNode - result.add nkCall.newTree( + # Make sure the statement is of the same type as the left + # hand argument, since some expressions return a differing + # type than the input types (2/3 == float) + let binExpr = processBinaryExpression(exprParser, node, typeofNode) + # Note that this temp var binExpr is needed for some reason, or else we get a segfault + result = nkCall.newTree( typeofNode, - rightNode + binexpr ) elif node.len() == 1: - result = newNode(nkPar) - let child = node[0] - var nimSym = "" - - let unarySym = node.tsNodeChild(0).val.strip() - techo "BIN SYM: ", unarySym - - # TODO: Support more symbols here. ++, --, & - case unarySym - of "~": - nimSym = "not" - else: - raise newException(ExprParseError, &"Unsupported unary symbol \"{unarySym}\"") - - result.add nkPrefix.newTree( - exprParser.state.getIdent(nimSym), - exprParser.processTSNode(child, typeofNode) - ) + # Node has only one child, ie -(20 + 7) + result = processUnaryExpression(exprParser, node, typeofNode) else: - raise newException(ExprParseError, &"Invalid bitwise_expression \"{node.val}\"") + raise newException(ExprParseError, &"Invalid {node.getName()} \"{node.val}\"") proc processSizeofExpression(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): PNode = result = nkCall.newTree( @@ -464,45 +386,85 @@ proc processTSNode(exprParser: ExprParser, node: TSNode, typeofNode: var PNode): case nodeName of "number_literal": + # Input -> 0x1234FE, 1231, 123u, 123ul, 123ull, 1.334f + # Output -> 0x1234FE, 1231, 123'u, 123'u32, 123'u64, 1.334 result = exprParser.processNumberLiteral(node) of "string_literal": + # Input -> "foo\0\x42" + # Output -> "foo\0" result = exprParser.processStringLiteral(node) of "char_literal": + # Input -> 'F', '\034' // Octal, '\x5A' // Hex, '\r' // escape sequences + # Output -> result = exprParser.processCharacterLiteral(node) of "expression_statement", "ERROR", "translation_unit": - # This may be wrong. What can be in an expression? - if node.len > 0: + # Note that we're parsing partial expressions, so the TSNode might contain + # an ERROR node. If that's the case, they usually contain children with + # partial results, which will contain parsed expressions + # + # Input (top level statement) -> ((1 + 3 - IDENT) - (int)400.0) + # Output -> (1 + typeof(1)(3) - typeof(1)(IDENT) - typeof(1)(cast[int](400.0))) # Type casting in case some args differ + if node.len == 1: result = exprParser.processTSNode(node[0], typeofNode) + elif node.len > 1: + result = newNode(nkStmtListExpr) + for i in 0 ..< node.len: + result.add exprParser.processTSNode(node[i], typeofNode) else: raise newException(ExprParseError, &"Node type \"{nodeName}\" has no children") of "parenthesized_expression": + # Input -> (IDENT - OTHERIDENT) + # Output -> (IDENT - typeof(IDENT)(OTHERIDENT)) # Type casting in case OTHERIDENT is a slightly different type (uint vs int) result = exprParser.processParenthesizedExpr(node, typeofNode) of "sizeof_expression": + # Input -> sizeof(char) + # Output -> sizeof(cchar) result = exprParser.processSizeofExpression(node, typeofNode) # binary_expression from the new treesitter upgrade should work here # once we upgrade - of "bitwise_expression", "equality_expression", "binary_expression": - result = exprParser.processBitwiseExpression(node, typeofNode) - of "math_expression": - result = exprParser.processMathExpression(node, typeofNode) + of "math_expression", "logical_expression", "relational_expression", + "bitwise_expression", "equality_expression", "binary_expression": + # Input -> a == b, a != b, !a, ~a, a < b, a > b, a <= b, a >= b + # Output -> + # typeof(a)(a == typeof(a)(b)) + # typeof(a)(a != typeof(a)(b)) + # (not a) + # (not a) + # typeof(a)(a < typeof(a)(b)) + # typeof(a)(a > typeof(a)(b)) + # typeof(a)(a <= typeof(a)(b)) + # typeof(a)(a >= typeof(a)(b)) + result = exprParser.processUnaryOrBinaryExpression(node, typeofNode) of "shift_expression": + # Input -> a >> b, a << b + # Output -> a shr typeof(a)(b), a shl typeof(a)(b) result = exprParser.processShiftExpression(node, typeofNode) of "cast_expression": + # Input -> (int) a + # Output -> cast[cint](a) result = exprParser.processCastExpression(node, typeofNode) - of "logical_expression": - result = exprParser.processLogicalExpression(node, typeofNode) # Why are these node types named true/false? of "true", "false": + # Input -> true, false + # Output -> true, false result = exprParser.state.parseString(node.val) of "type_descriptor", "sized_type_specifier": + # Input -> int, unsigned int, long int, etc + # Output -> cint, cuint, clong, etc let ty = getType(node.val) - result = exprParser.getIdent(ty, nskType, parent=node.getName()) - if result.kind == nkNone: - result = exprParser.state.getIdent(ty) + if ty.len > 0: + # If ty is not empty, one of C's builtin types has been found + result = exprParser.getIdent(ty, nskType, parent=node.getName()) + else: + result = exprParser.getIdent(node.val, nskType, parent=node.getName()) + if result.kind == nkNone: + raise newException(ExprParseError, &"Missing type specifier \"{node.val}\"") of "identifier": + # Input -> IDENT + # Output -> IDENT (if found in sym table, else error) result = exprParser.getIdent(node, parent=node.getName()) if result.kind == nkNone: - raise newException(ExprParseError, &"Could not get identifier \"{node.val}\"") + raise newException(ExprParseError, &"Missing identifier \"{node.val}\"") else: raise newException(ExprParseError, &"Unsupported node type \"{nodeName}\" for node \"{node.val}\"") @@ -512,15 +474,15 @@ proc parseCExpression*(state: NimState, code: string, name = ""): 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 + # symbol used for type casting var tnode: PNode = nil let exprParser = newExprParser(state, code, name) try: - withCodeAst(exprParser): + withCodeAst(exprParser.code, exprParser.mode): result = exprParser.processTSNode(root, tnode) except ExprParseError as e: techo e.msg result = newNode(nkNone) except Exception as e: techo "UNEXPECTED EXCEPTION: ", e.msg - result = newNode(nkNone) + result = newNode(nkNone)
\ No newline at end of file diff --git a/nimterop/getters.nim b/nimterop/getters.nim index 216d2e6..b7744ce 100644 --- a/nimterop/getters.nim +++ b/nimterop/getters.nim @@ -401,7 +401,7 @@ proc printLisp*(code: var string, root: TSNode): string = if node.len() != 0: result &= "\n" - nextnode = node.tsNodeNamedChild(0) + nextnode = node[0] depth += 1 else: result &= ")\n" @@ -432,7 +432,7 @@ proc getCommented*(str: string): string = "\n# " & str.strip().replace("\n", "\n# ") proc printTree*(gState: State, pnode: PNode, offset = ""): string = - if gState.debug and pnode.kind != nkNone: + if not pnode.isNil and gState.debug and pnode.kind != nkNone: result &= "\n# " & offset & $pnode.kind & "(" case pnode.kind of nkCharLit: @@ -459,17 +459,17 @@ proc printTree*(gState: State, pnode: PNode, offset = ""): string = if offset.len == 0: result &= "\n" -proc printDebug*(nimState: NimState, node: TSNode) = +proc printDebug*(gState: State, node: TSNode) = # 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() + if gState.debug: + gecho ("Input => " & gState.getNodeVal(node)).getCommented() + gecho gState.printLisp(node).getCommented() -proc printDebug*(nimState: NimState, pnode: PNode) = +proc printDebug*(gState: State, pnode: PNode) = # 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).getCommented() + if gState.debug and pnode.kind != nkNone: + gecho ("Output => " & $pnode).getCommented() + gecho gState.printTree(pnode).getCommented() # Compiler shortcuts diff --git a/nimterop/toast.nim b/nimterop/toast.nim index ab44970..afb511d 100644 --- a/nimterop/toast.nim +++ b/nimterop/toast.nim @@ -2,16 +2,11 @@ import os, osproc, strformat, strutils, tables, times import "."/treesitter/[api, c, cpp] -import "."/[ast, ast2, globals, getters, grammar, build] +import "."/[ast, ast2, globals, getters, grammar, build, tshelp] proc process(gState: State, path: string, astTable: AstTable) = doAssert existsFile(path), &"Invalid path {path}" - var parser = tsParserNew() - - defer: - parser.tsParserDelete() - if gState.mode.Bl: gState.mode = getCompilerMode(path) @@ -20,6 +15,7 @@ proc process(gState: State, path: string, astTable: AstTable) = else: gState.code = readFile(path) +<<<<<<< HEAD doAssert gState.code.nBl, "Empty file or preprocessor error" if gState.mode == "c": @@ -45,6 +41,18 @@ proc process(gState: State, path: string, astTable: AstTable) = ast.parseNim(gState, path, root, astTable) elif gState.preprocess: gecho gState.code +======= + withCodeAst(gState.code, gState.mode): + if gState.past: + gecho gState.printLisp(root) + elif gState.pnim: + if Feature.ast2 in gState.feature: + ast2.printNim(gState, path, root) + else: + ast.printNim(gState, path, root, astTable) + elif gState.preprocess: + gecho gState.code +>>>>>>> Update based on comments from review. Need to add more docs and reorg to use gstate # CLI processing with default values proc main( diff --git a/nimterop/tshelp.nim b/nimterop/tshelp.nim new file mode 100644 index 0000000..f234bc0 --- /dev/null +++ b/nimterop/tshelp.nim @@ -0,0 +1,30 @@ +template withCodeAst*(inputCode: string, inputMode: string, body: untyped): untyped = + ## A simple template to inject the TSNode into a body of code + + # This section is needed to be able to reference + # mode in strformat calls + let + code = inputCode + mode {.inject.} = inputMode + + var parser = tsParserNew() + defer: + parser.tsParserDelete() + + doAssert code.nBl, "Empty code or preprocessor error" + + if mode == "c": + doAssert parser.tsParserSetLanguage(treeSitterC()), "Failed to load C parser" + elif mode == "cpp": + doAssert parser.tsParserSetLanguage(treeSitterCpp()), "Failed to load C++ parser" + else: + doAssert false, &"Invalid parser {mode}" + + var + tree = parser.tsParserParseString(nil, code.cstring, code.len.uint32) + root {.inject.} = tree.tsTreeRootNode() + + body + + defer: + tree.tsTreeDelete()
\ No newline at end of file diff --git a/tests/tast2.nim b/tests/tast2.nim index 0b3762a..e82430b 100644 --- a/tests/tast2.nim +++ b/tests/tast2.nim @@ -12,7 +12,6 @@ static: const path = currentSourcePath.parentDir() / "include" / "tast2.h" - when defined(HEADER): cDefine("HEADER") const |
