diff options
| author | Ganesh Viswanathan <dev@genotrance.com> | 2018-11-28 11:08:45 -0600 |
|---|---|---|
| committer | Ganesh Viswanathan <dev@genotrance.com> | 2018-11-28 11:08:45 -0600 |
| commit | 7344042029bf6319219c11b318372f55904c6491 (patch) | |
| tree | ca559801ed238a6b88981a1108e0892d0f856868 | |
| parent | d7ca43f49fb544d1d1299a445ad519874ec63f3a (diff) | |
| download | nimterop-7344042029bf6319219c11b318372f55904c6491.tar.gz nimterop-7344042029bf6319219c11b318372f55904c6491.zip | |
Move AST to Nim processing into toast
| -rw-r--r-- | nimterop/ast.nim | 312 | ||||
| -rw-r--r-- | nimterop/cimport.nim | 72 | ||||
| -rw-r--r-- | nimterop/getters.nim | 29 | ||||
| -rw-r--r-- | nimterop/globals.nim | 44 | ||||
| -rw-r--r-- | toast.nim | 78 |
5 files changed, 264 insertions, 271 deletions
diff --git a/nimterop/ast.nim b/nimterop/ast.nim index cc1cd61..4cee1db 100644 --- a/nimterop/ast.nim +++ b/nimterop/ast.nim @@ -1,53 +1,41 @@ -import macros, os, strformat +import macros, os, strformat, strutils -import regex +import treesitter/runtime import getters, globals -proc addReorder*(): NimNode = - result = newNimNode(nnkStmtList) - if not gReorder: - gReorder = true - result.add parseStmt( - "{.experimental: \"codeReordering\".}" - ) - -proc addHeader*(fullpath: string) = - gCurrentHeader = ("header" & fullpath.splitFile().name.replace(re"[-.]+", "")) - gConstStr &= &" {gCurrentHeader} = \"{fullpath}\" # addHeader()\n" - # # Preprocessor # -proc pPreprocDef(node: ref Ast) = - if node.children.len == 2: +proc pPreprocDef(node: TSNode) = + if node.tsNodeNamedChildCount() == 2: let - name = getNodeValIf(node.children[0], identifier) - val = getNodeValIf(node.children[1], preproc_arg) + name = getNodeValIf(node.tsNodeNamedChild(0), "identifier") + val = getNodeValIf(node.tsNodeNamedChild(1), "preproc_arg") - if name.nBl and val.nBl and name notin gConsts: - gConsts.add(name) + if name.nBl and val.nBl and name notin gStateRT.consts: + gStateRT.consts.add(name) if val.getLit().nBl: # #define NAME VALUE - gConstStr &= &" {name.getIdentifier()}* = {val} # pPreprocDef()\n" + gStateRT.constStr &= &" {name.getIdentifier()}* = {val} # pPreprocDef()\n" # # Types # -proc typeScan(node: ref Ast, sym, id: Sym, offset: string): string = - if node.sym != sym or node.children.len != 2: +proc typeScan(node: TSNode, sym, id: string, offset: string): string = + if node.tsNodeIsNull() or $node.tsNodeType() != sym or node.tsNodeNamedChildCount() != 2: return var - name = getNodeValIf(node.children[1], id) - ptyp = getNodeValIf(node.children[0], primitive_type) - ttyp = getNodeValIf(node.children[0], type_identifier) + name = getNodeValIf(node.tsNodeNamedChild(1), id) + ptyp = getNodeValIf(node.tsNodeNamedChild(0), "primitive_type") + ttyp = getNodeValIf(node.tsNodeNamedChild(0), "type_identifier") ptrname = false - if name.len == 0 and node.children[1].sym == pointer_declarator and node.children[1].children.len == 1: - name = getNodeValIf(node.children[1].children[0], id) + if name.len == 0 and $node.tsNodeNamedChild(1).tsNodeType() == "pointer_declarator" and node.tsNodeNamedChild(1).tsNodeNamedChildCount() == 1: + name = getNodeValIf(node.tsNodeNamedChild(1).tsNodeNamedChild(0), id) ptrname = true if name.len == 0: @@ -61,194 +49,238 @@ proc typeScan(node: ref Ast, sym, id: Sym, offset: string): string = if ptrname: ttyp = &"ptr {ttyp}" result = &"{offset}{name.getIdentifier()}: {ttyp}" - elif node.children[0].sym in [struct_specifier, enum_specifier] and node.children[0].children.len == 1: - var styp = getNodeValIf(node.children[0].children[0], type_identifier) + elif $node.tsNodeNamedChild(0).tsNodeType() in ["struct_specifier", "enum_specifier"] and node.tsNodeNamedChild(0).tsNodeNamedChildCount() == 1: + var styp = getNodeValIf(node.tsNodeNamedChild(0).tsNodeNamedChild(0), "type_identifier") if styp.nBl: if ptrname: styp = &"ptr {styp}" result = &"{offset}{name.getIdentifier()}: {styp}" - else: - return -proc pStructSpecifier(node: ref Ast, name = "") = +proc pStructSpecifier(node: TSNode, name = "") = var stmt: string - if node.children.len == 1 and name notin gTypes: - case node.children[0].sym: - of type_identifier: - let typ = getNodeValIf(node.children[0], type_identifier) + if node.tsNodeNamedChildCount() == 1 and name notin gStateRT.types: + case $node.tsNodeNamedChild(0).tsNodeType(): + of "type_identifier": + let typ = getNodeValIf(node.tsNodeNamedChild(0), "type_identifier") if typ.nBl: - gTypes.add(name) + gStateRT.types.add(name) if name != typ: # typedef struct X Y - gTypeStr &= &" {name.getIdentifier()}* = {typ} #1 pStructSpecifier()\n" + gStateRT.typeStr &= &" {name.getIdentifier()}* = {typ} #1 pStructSpecifier()\n" else: # typedef struct X X - gTypeStr &= &" {name.getIdentifier()}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #2 pStructSpecifier()\n" + gStateRT.typeStr &= &" {name.getIdentifier()}* {{.importc: \"{name}\", header: {gStateRT.currentHeader}, bycopy.}} = object #2 pStructSpecifier()\n" - of field_declaration_list: + of "field_declaration_list": # typedef struct { fields } X - stmt = &" {name.getIdentifier()}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #3 pStructSpecifier()\n" + stmt = &" {name.getIdentifier()}* {{.importc: \"{name}\", header: {gStateRT.currentHeader}, bycopy.}} = object #3 pStructSpecifier()\n" - for field in node.children[0].children: - let ts = typeScan(field, field_declaration, field_identifier, " ") - if ts.len == 0: - return - stmt &= ts & "\n" + if node.tsNodeNamedChild(0).tsNodeNamedChildCount() != 0: + for i in 0 .. node.tsNodeNamedChild(0).tsNodeNamedChildCount()-1: + let ts = typeScan(node.tsNodeNamedChild(0).tsNodeNamedChild(i), "field_declaration", "field_identifier", " ") + if ts.len == 0: + return + stmt &= ts & "\n" - gTypes.add(name) - gTypeStr &= stmt + gStateRT.types.add(name) + gStateRT.typeStr &= stmt else: discard - elif name.len == 0 and node.children.len == 2 and node.children[1].sym == field_declaration_list: - let ename = getNodeValIf(node.children[0], type_identifier) - if ename.nBl and ename notin gTypes: + elif name.len == 0 and node.tsNodeNamedChildCount() == 2 and $node.tsNodeNamedChild(1).tsNodeType() == "field_declaration_list": + let ename = getNodeValIf(node.tsNodeNamedChild(0), "type_identifier") + if ename.nBl and ename notin gStateRT.types: # struct X { fields } - stmt &= &" {ename}* {{.importc: \"struct {ename}\", header: {gCurrentHeader}, bycopy.}} = object #4 pStructSpecifier()\n" + stmt &= &" {ename}* {{.importc: \"struct {ename}\", header: {gStateRT.currentHeader}, bycopy.}} = object #4 pStructSpecifier()\n" - for field in node.children[1].children: - let ts = typeScan(field, field_declaration, field_identifier, " ") - if ts.len == 0: - return - stmt &= ts & "\n" + if node.tsNodeNamedChild(1).tsNodeNamedChildCount() != 0: + for i in 0 .. node.tsNodeNamedChild(1).tsNodeNamedChildCount()-1: + let ts = typeScan(node.tsNodeNamedChild(1).tsNodeNamedChild(i), "field_declaration", "field_identifier", " ") + if ts.len == 0: + return + stmt &= ts & "\n" - gTypes.add(name) - gTypeStr &= stmt + gStateRT.types.add(name) + gStateRT.typeStr &= stmt -proc pEnumSpecifier(node: ref Ast, name = "") = +proc pEnumSpecifier(node: TSNode, name = "") = var ename: string - elid: int + elid: uint32 stmt: string - if node.children.len == 1 and node.children[0].sym == enumerator_list: + if node.tsNodeNamedChildCount() == 1 and $node.tsNodeNamedChild(0).tsNodeType() == "enumerator_list": # typedef enum { fields } X ename = name elid = 0 stmt = &" {name.getIdentifier()}* = enum #1 pEnumSpecifier()\n" - elif name.len == 0 and node.children.len == 2 and node.children[1].sym == enumerator_list: - ename = getNodeValIf(node.children[0], type_identifier) + elif name.len == 0 and node.tsNodeNamedChildCount() == 2 and $node.tsNodeNamedChild(1).tsNodeType() == "enumerator_list": + ename = getNodeValIf(node.tsNodeNamedChild(0), "type_identifier") elid = 1 if ename.nBl: # enum X { fields } stmt = &" {ename}* = enum #2 pEnumSpecifier()\n" else: return + else: + return - for field in node.children[elid].children: - if field.sym == enumerator: - let fname = getNodeValIf(field.children[0], identifier) - if field.children.len == 1: - stmt &= &" {fname}\n" - elif field.children.len == 2 and field.children[1].sym == number_literal: - let num = getNodeValIf(field.children[1], number_literal) - stmt &= &" {fname} = {num}\n" - else: - return + if node.tsNodeNamedChild(elid).tsNodeNamedChildCount() != 0: + for i in 0 .. node.tsNodeNamedChild(elid).tsNodeNamedChildCount()-1: + let field = node.tsNodeNamedChild(elid).tsNodeNamedChild(i) + if not field.tsNodeIsNull() and $field.tsNodeType() == "enumerator": + let fname = getNodeValIf(field.tsNodeNamedChild(0), "identifier") + if field.tsNodeNamedChildCount() == 1: + stmt &= &" {fname}\n" + elif field.tsNodeNamedChildCount() == 2 and $field.tsNodeNamedChild(1).tsNodeType() == "number_literal": + let num = getNodeValIf(field.tsNodeNamedChild(1), "number_literal") + stmt &= &" {fname} = {num}\n" + else: + return - if ename notin gTypes: - gTypes.add(name) - gTypeStr &= stmt + if ename notin gStateRT.types: + gStateRT.types.add(name) + gStateRT.typeStr &= stmt -proc pTypeDefinition(node: ref Ast) = - if node.children.len == 2: +proc pTypeDefinition(node: TSNode) = + if node.tsNodeNamedChildCount() == 2: var - name = getNodeValIf(node.children[1], type_identifier) - ptyp = getNodeValIf(node.children[0], primitive_type) - ttyp = getNodeValIf(node.children[0], type_identifier) + name = getNodeValIf(node.tsNodeNamedChild(1), "type_identifier") + ptyp = getNodeValIf(node.tsNodeNamedChild(0), "primitive_type") + ttyp = getNodeValIf(node.tsNodeNamedChild(0), "type_identifier") ptrname = false - if name.len == 0 and node.children[1].sym == pointer_declarator and node.children[1].children.len == 1: - name = getNodeValIf(node.children[1].children[0], type_identifier) + if name.len == 0 and $node.tsNodeNamedChild(1).tsNodeType() == "pointer_declarator" and node.tsNodeNamedChild(1).tsNodeNamedChildCount() == 1: + name = getNodeValIf(node.tsNodeNamedChild(1).tsNodeNamedChild(0), "type_identifier") ptrname = true - if name.nBl and name notin gTypes: + if name.nBl and name notin gStateRT.types: if ptyp.nBl: # typedef int X - gTypes.add(name) + gStateRT.types.add(name) ptyp = ptyp.getType() if ptyp != "object" and ptrname: ptyp = &"ptr {ptyp}" - gTypeStr &= &" {name.getIdentifier()}* = {ptyp} #1 pTypeDefinition()\n" + gStateRT.typeStr &= &" {name.getIdentifier()}* = {ptyp} #1 pTypeDefinition()\n" elif ttyp.nBl: # typedef X Y - gTypes.add(name) + gStateRT.types.add(name) if ptrname: ttyp = &"ptr {ttyp}" - gTypeStr &= &" {name.getIdentifier()}* = {ttyp} #2 pTypeDefinition()\n" + gStateRT.typeStr &= &" {name.getIdentifier()}* = {ttyp} #2 pTypeDefinition()\n" else: - case node.children[0].sym: - of struct_specifier: - pStructSpecifier(node.children[0], name) - of enum_specifier: - pEnumSpecifier(node.children[0], name) + case $node.tsNodeNamedChild(0).tsNodeType(): + of "struct_specifier": + pStructSpecifier(node.tsNodeNamedChild(0), name) + of "enum_specifier": + pEnumSpecifier(node.tsNodeNamedChild(0), name) else: discard -proc pFunctionDeclarator(node: ref Ast, typ: string) = - if node.children.len == 2: +proc pFunctionDeclarator(node: TSNode, typ: string) = + if node.tsNodeNamedChildCount() == 2: let - name = getNodeValIf(node.children[0], identifier) + name = getNodeValIf(node.tsNodeNamedChild(0), "identifier") - if name.nBl and name notin gProcs and node.children[1].sym == parameter_list: + if name.nBl and name notin gStateRT.procs and $node.tsNodeNamedChild(1).tsNodeType() == "parameter_list": # typ function(typ param1, ...) var stmt = &"# pFunctionDeclarator()\nproc {name.getIdentifier()}*(" - for i in 0 .. node.children[1].children.len-1: - let ts = typeScan(node.children[1].children[i], parameter_declaration, identifier, "") - if ts.len == 0: - return - stmt &= ts - if i != node.children[1].children.len-1: - stmt &= ", " + if node.tsNodeNamedChild(1).tsNodeNamedChildCount() != 0: + for i in 0 .. node.tsNodeNamedChild(1).tsNodeNamedChildCount()-1: + let ts = typeScan(node.tsNodeNamedChild(1).tsNodeNamedChild(i), "parameter_declaration", "identifier", "") + if ts.len == 0: + return + stmt &= ts + if i != node.tsNodeNamedChild(1).tsNodeNamedChildCount()-1: + stmt &= ", " if typ != "void": stmt &= &"): {typ.getType()} " else: stmt &= ") " - stmt &= &"{{.importc: \"{name}\", header: {gCurrentHeader}.}}\n" + stmt &= &"{{.importc: \"{name}\", header: {gStateRT.currentHeader}.}}\n" - gProcs.add(name) - gProcStr &= stmt + gStateRT.procs.add(name) + gStateRT.procStr &= stmt -proc pDeclaration*(node: ref Ast) = - if node.children.len == 2 and node.children[1].sym == function_declarator: +proc pDeclaration*(node: TSNode) = + if node.tsNodeNamedChildCount() == 2 and $node.tsNodeNamedChild(1).tsNodeType() == "function_declarator": let - ptyp = getNodeValIf(node.children[0], primitive_type) - ttyp = getNodeValIf(node.children[0], type_identifier) + ptyp = getNodeValIf(node.tsNodeNamedChild(0), "primitive_type") + ttyp = getNodeValIf(node.tsNodeNamedChild(0), "type_identifier") if ptyp.nBl: - pFunctionDeclarator(node.children[1], ptyp.getType()) + pFunctionDeclarator(node.tsNodeNamedChild(1), ptyp.getType()) elif ttyp.nBl: - pFunctionDeclarator(node.children[1], ttyp) - elif node.children[0].sym == struct_specifier and node.children[0].children.len == 1: - let styp = getNodeValIf(node.children[0].children[0], type_identifier) + pFunctionDeclarator(node.tsNodeNamedChild(1), ttyp) + elif $node.tsNodeNamedChild(0).tsNodeType() == "struct_specifier" and node.tsNodeNamedChild(0).tsNodeNamedChildCount() == 1: + let styp = getNodeValIf(node.tsNodeNamedChild(0).tsNodeNamedChild(0), "type_identifier") if styp.nBl: - pFunctionDeclarator(node.children[1], styp) + pFunctionDeclarator(node.tsNodeNamedChild(1), styp) -proc genNimAst*(node: ref Ast) = - if node.isNil: - return +proc genNimAst(root: TSNode) = + var + node = root + nextnode: TSNode + + while true: + if not node.tsNodeIsNull(): + case $node.tsNodeType(): + of "ERROR": + let (line, col) = getLineCol(node) + echo &"Potentially invalid syntax at line {line} column {col}" + of "preproc_def": + pPreprocDef(node) + of "type_definition": + pTypeDefinition(node) + of "declaration": + pDeclaration(node) + of "struct_specifier": + if $node.tsNodeParent().tsNodeType() notin ["type_definition", "declaration"]: + pStructSpecifier(node) + of "enum_specifier": + if $node.tsNodeParent.tsNodeType() notin ["type_definition", "declaration"]: + pEnumSpecifier(node) + else: + discard + else: + return - case node.sym: - of ERROR: - let (line, col) = getLineCol(node) - echo &"Potentially invalid syntax at line {line} column {col}" - of preproc_def: - pPreprocDef(node) - of type_definition: - pTypeDefinition(node) - of declaration: - pDeclaration(node) - of struct_specifier: - if node.parent.sym notin [type_definition, declaration]: - pStructSpecifier(node) - of enum_specifier: - if node.parent.sym notin [type_definition, declaration]: - pEnumSpecifier(node) + if node.tsNodeNamedChildCount() != 0: + nextnode = node.tsNodeNamedChild(0) else: - discard + nextnode = node.tsNodeNextNamedSibling() + + if nextnode.tsNodeIsNull(): + while true: + node = node.tsNodeParent() + if node == root: + break + if not node.tsNodeNextNamedSibling().tsNodeIsNull(): + node = node.tsNodeNextNamedSibling() + break + else: + node = nextnode + + if node == root: + break + +proc printNim*(fullpath: string, root: TSNode) = + echo "{.experimental: \"codeReordering\".}" + + var fp = fullpath.replace("\\", "/") + gStateRT.currentHeader = getCurrentHeader(fullpath) + gStateRT.constStr &= &" {gStateRT.currentHeader} = \"{fp}\"\n" + + genNimAst(root) + + if gStateRT.constStr.nBl: + echo "const\n" & gStateRT.constStr + + if gStateRT.typeStr.nBl: + echo "type\n" & gStateRT.typeStr - for child in node.children: - genNimAst(child) + if gStateRT.procStr.nBl: + echo gStateRT.procStr diff --git a/nimterop/cimport.nim b/nimterop/cimport.nim index 0317787..fc0d057 100644 --- a/nimterop/cimport.nim +++ b/nimterop/cimport.nim @@ -1,6 +1,6 @@ import macros, os, strformat, strutils -import ast, getters, globals, lisp +import getters, globals proc interpPath(dir: string): string= # TODO: more robust: needs a DirSep after "$projpath" @@ -24,19 +24,31 @@ proc findPath(path: string, fail = true): string = else: return "" +proc getToast(fullpath: string): string = + var + cmd = "toast -n -p " + + for i in gStateCT.defines: + cmd &= &"-D\"{i}\" " + + for i in gStateCT.includeDirs: + cmd &= &"-I\"{i}\" " + + result = staticExec(cmd & fullpath) + proc cSearchPath*(path: string): string {.compileTime.}= result = findPath(path, fail = false) if result.len == 0: var found = false - for inc in gSearchDirs: + for inc in gStateCT.searchDirs: result = (inc & "/" & path).replace("\\", "/") if fileExists(result) or dirExists(result): found = true break - doAssert found, "File or directory not found: " & path & " gSearchDirs: " & $gSearchDirs + doAssert found, "File or directory not found: " & path & " gStateCT.searchDirs: " & $gStateCT.searchDirs macro cDebug*(): untyped = - gDebug = true + gStateCT.debug = true macro cDefine*(name: static string, val: static string = ""): untyped = result = newNimNode(nnkStmtList) @@ -45,21 +57,21 @@ macro cDefine*(name: static string, val: static string = ""): untyped = if val.nBl: str &= &"=\"{val}\"" - if str notin gDefines: - gDefines.add(str) + if str notin gStateCT.defines: + gStateCT.defines.add(str) str = "-D" & str result.add(quote do: {.passC: `str`.} ) - if gDebug: + if gStateCT.debug: echo result.repr macro cAddSearchDir*(dir: static string): untyped = var dir = interpPath(dir) - if dir notin gSearchDirs: - gSearchDirs.add(dir) + if dir notin gStateCT.searchDirs: + gStateCT.searchDirs.add(dir) macro cIncludeDir*(dir: static string): untyped = var dir = interpPath(dir) @@ -69,14 +81,14 @@ macro cIncludeDir*(dir: static string): untyped = fullpath = findPath(dir) str = &"-I\"{fullpath}\"" - if fullpath notin gIncludeDirs: - gIncludeDirs.add(fullpath) + if fullpath notin gStateCT.includeDirs: + gStateCT.includeDirs.add(fullpath) result.add(quote do: {.passC: `str`.} ) - if gDebug: + if gStateCT.debug: echo result.repr macro cAddStdDir*(mode = "c"): untyped = @@ -109,11 +121,11 @@ macro cCompile*(path: static string): untyped = var ufn = fn uniq = 1 - while ufn in gCompile: + while ufn in gStateCT.compile: ufn = fn & $uniq uniq += 1 - gCompile.add(ufn) + gStateCT.compile.add(ufn) if fn == ufn: return "{.compile: \"$#\".}" % file.replace("\\", "/") else: @@ -138,44 +150,18 @@ macro cCompile*(path: static string): untyped = result.add stmt.parseStmt() - if gDebug: + if gStateCT.debug: echo result.repr macro cImport*(filename: static string): untyped = result = newNimNode(nnkStmtList) - result.add addReorder() let fullpath = findPath(filename) - root = parseLisp(fullpath) echo "Importing " & fullpath - gCode = staticRead(fullpath) - gConstStr = "" - gTypeStr = "" - - addHeader(fullpath) - genNimAst(root) - - if gConstStr.nBl: - if gDebug: - echo "const\n" & gConstStr - result.add parseStmt( - "const\n" & gConstStr - ) - - if gTypeStr.nBl: - if gDebug: - echo "type\n" & gTypeStr - result.add parseStmt( - "type\n" & gTypeStr - ) - - if gProcStr.nBl: - if gDebug: - echo gProcStr - result.add gProcStr.parseStmt() + result.add parseStmt(getToast(fullpath)) - if gDebug: + if gStateCT.debug: echo result.repr diff --git a/nimterop/getters.nim b/nimterop/getters.nim index c9ac3b9..a402610 100644 --- a/nimterop/getters.nim +++ b/nimterop/getters.nim @@ -2,6 +2,8 @@ import macros, ospaths, strformat, strutils import regex +import treesitter/runtime + import git, globals proc sanitizePath*(path: string): string = @@ -19,21 +21,24 @@ proc getLit*(str: string): string = str.contains(re"^0x[\d]+$"): return str -proc getNodeValIf*(node: ref Ast, esym: Sym): string = - if esym != node.sym: +proc getNodeValIf*(node: TSNode, esym: string): string = + if esym != $node.tsNodeType(): return - return gCode[node.start .. node.stop-1].strip() + return gStateRT.code[node.tsNodeStartByte() .. node.tsNodeEndByte()-1].strip() -proc getLineCol*(node: ref Ast): tuple[line, col: int] = +proc getLineCol*(node: TSNode): tuple[line, col: int] = result.line = 1 result.col = 1 - for i in 0 .. node.start-1: - if gCode[i] == '\n': + for i in 0 .. node.tsNodeStartByte()-1: + if gStateRT.code[i] == '\n': result.col = 0 result.line += 1 result.col += 1 +proc getCurrentHeader*(fullpath: string): string = + ("header" & fullpath.splitFile().name.replace(re"[-.]+", "")) + proc getGccPaths*(mode = "c"): string = var nul = when defined(Windows): "nul" else: "/dev/null" @@ -45,23 +50,15 @@ proc getPreprocessor*(fullpath: string, mode = "cpp"): string = var mmode = if mode == "cpp": "c++" else: mode cmd = &"gcc -E -dD -x{mmode} " - gdef, gdir: seq[string] rdata: seq[string] = @[] start = false sfile = fullpath.sanitizePath - when nimvm: - gdef = gDefines - gdir = gIncludeDirs - else: - gdef = gDefinesRT - gdir = gIncludeDirsRT - - for inc in gdir: + for inc in gStateRT.includeDirs: cmd &= &"-I\"{inc}\" " - for def in gdef: + for def in gStateRT.defines: cmd &= &"-D{def} " cmd &= &"\"{fullpath}\"" diff --git a/nimterop/globals.nim b/nimterop/globals.nim index 8797af8..98e4249 100644 --- a/nimterop/globals.nim +++ b/nimterop/globals.nim @@ -1,42 +1,16 @@ -import macros - type - Sym* = enum - ERROR, IGNORED, - enumerator, enumerator_list, enum_specifier, - declaration, - field_declaration, field_declaration_list, field_identifier, function_declarator, - identifier, - number_literal, - parameter_declaration, parameter_list, pointer_declarator, preproc_arg, preproc_def, primitive_type, - struct_specifier, - type_definition, type_identifier + State* = object + compile*, defines*, headers*, includeDirs*, searchDirs*: seq[string] - Ast* = object - sym*: Sym - start*, stop*: int - parent*: ref Ast - children*: seq[ref Ast] + debug*, past*, preprocess*, pnim*, pretty*: bool -var - gDefines* {.compiletime.}: seq[string] - gDefinesRT*: seq[string] - gCompile* {.compiletime.}: seq[string] - gConsts* {.compiletime.}: seq[string] - gHeaders* {.compiletime.}: seq[string] - gIncludeDirs* {.compiletime.}: seq[string] - gIncludeDirsRT*: seq[string] - gProcs* {.compiletime.}: seq[string] - gSearchDirs* {.compiletime.}: seq[string] - gTypes* {.compiletime.}: seq[string] + consts*, procs*, types*: seq[string] - gCode* {.compiletime.}: string - gConstStr* {.compiletime.}: string - gCurrentHeader* {.compiletime.}: string - gDebug* {.compiletime.}: bool - gReorder* {.compiletime.}: bool - gProcStr* {.compiletime.}: string - gTypeStr* {.compiletime.}: string + code*, constStr*, currentHeader*, mode*, procStr*, typeStr*: string + +var + gStateCT* {.compiletime.}: State + gStateRT*: State template nBl*(s: untyped): untyped = (s.len != 0)
\ No newline at end of file @@ -2,18 +2,20 @@ import os, strutils import treesitter/[runtime, c, cpp] -import nimterop/[globals, getters] +import nimterop/[ast, globals, getters] const HELP = """ > toast header.h -a print AST output --c C mode - CPP is default -m print minimized AST output - non-pretty (implies -a) +-n print Nim output + +-c C mode - CPP is default -p run preprocessor on header -D definitions to pass to preprocessor -I include directory to pass to preprocessor""" -proc printLisp(root: TSNode, data: var string, pretty = true) = +proc printLisp(root: TSNode) = var node = root nextnode: TSNode @@ -21,19 +23,19 @@ proc printLisp(root: TSNode, data: var string, pretty = true) = while true: if not node.tsNodeIsNull(): - if pretty: + if gStateRT.pretty: stdout.write spaces(depth) stdout.write "(" & $node.tsNodeType() & " " & $node.tsNodeStartByte() & " " & $node.tsNodeEndByte() else: return if node.tsNodeNamedChildCount() != 0: - if pretty: + if gStateRT.pretty: echo "" nextnode = node.tsNodeNamedChild(0) depth += 1 else: - if pretty: + if gStateRT.pretty: echo ")" else: stdout.write ")" @@ -45,7 +47,7 @@ proc printLisp(root: TSNode, data: var string, pretty = true) = depth -= 1 if depth == -1: break - if pretty: + if gStateRT.pretty: echo spaces(depth) & ")" else: stdout.write ")" @@ -60,7 +62,7 @@ proc printLisp(root: TSNode, data: var string, pretty = true) = if node == root: break -proc process(path: string, mode="cpp", past, pretty, preprocess: bool) = +proc process(path: string) = if not existsFile(path): echo "Invalid path " & path return @@ -68,54 +70,54 @@ proc process(path: string, mode="cpp", past, pretty, preprocess: bool) = var parser = tsParserNew() ext = path.splitFile().ext - pmode = "" - data = "" defer: parser.tsParserDelete() - if mode.len != 0: - pmode = mode + if gStateRT.mode.len != 0: + gStateRT.mode = "cpp" elif ext in [".h", ".c"]: - pmode = "c" + gStateRT.mode = "c" elif ext in [".hxx", ".hpp", ".hh", ".H", ".h++", ".cpp", ".cxx", ".cc", ".C", ".c++"]: - pmode = "cpp" + gStateRT.mode = "cpp" - if preprocess: - data = getPreprocessor(path) + if gStateRT.preprocess: + gStateRT.code = getPreprocessor(path) else: - data = readFile(path) + gStateRT.code = readFile(path) - if pmode == "c": + if gStateRT.mode == "c": if not parser.tsParserSetLanguage(treeSitterC()): echo "Failed to load C parser" quit() - elif pmode == "cpp": + elif gStateRT.mode == "cpp": if not parser.tsParserSetLanguage(treeSitterCpp()): echo "Failed to load C++ parser" quit() else: - echo "Invalid parser " & mode + echo "Invalid parser " & gStateRT.mode quit() var - tree = parser.tsParserParseString(nil, data.cstring, data.len.uint32) + tree = parser.tsParserParseString(nil, gStateRT.code.cstring, gStateRT.code.len.uint32) root = tree.tsTreeRootNode() defer: tree.tsTreeDelete() - if past: - printLisp(root, data, pretty) + if gStateRT.past: + printLisp(root) + elif gStateRT.pnim: + printNim(path, root) proc parseCli() = - var - mode = "cpp" - params = commandLineParams() + var params = commandLineParams() - past = false - pretty = true - preprocess = false + gStateRT.mode = "cpp" + gStateRT.past = false + gStateRT.pnim = false + gStateRT.pretty = true + gStateRT.preprocess = false for param in params: let flag = if param.len() <= 2: param else: param[0..<2] @@ -124,19 +126,21 @@ proc parseCli() = echo HELP quit() elif flag == "-a": - past = true + gStateRT.past = true elif flag == "-c": - mode = "c" + gStateRT.mode = "c" elif flag == "-m": - past = true - pretty = false + gStateRT.past = true + gStateRT.pretty = false + elif flag == "-n": + gStateRT.pnim = true elif flag == "-p": - preprocess = true + gStateRT.preprocess = true elif flag == "-D": - gDefinesRT.add(param[2..^1]) + gStateRT.defines.add(param[2..^1].strip(chars={'"'})) elif flag == "-I": - gIncludeDirsRT.add(param[2..^1]) + gStateRT.includeDirs.add(param[2..^1].strip(chars={'"'})) else: - process(param, mode, past, pretty, preprocess) + process(param) parseCli() |
