aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoey Yakimowich-Payne <jyapayne@gmail.com>2020-04-22 01:16:19 -0600
committerJoey Yakimowich-Payne <jyapayne@gmail.com>2020-04-26 09:11:56 -0600
commitb1a445c34dfff04d5c799b7c4ee0f7e806900e91 (patch)
tree6ad5f4baf995e74b6e80f3f0a747ac8194cd076b
parent4794c076ffc7f46858dfebfdae47d8e3c47d1cf7 (diff)
downloadnimterop-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.nim30
-rw-r--r--nimterop/comphelp.nim (renamed from nimterop/utils.nim)0
-rw-r--r--nimterop/exprparser.nim384
-rw-r--r--nimterop/getters.nim20
-rw-r--r--nimterop/toast.nim20
-rw-r--r--nimterop/tshelp.nim30
-rw-r--r--tests/tast2.nim1
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