More pointer support, cpp mode default in toast, cleanup
This commit is contained in:
parent
a8bb2dc01f
commit
b9b5174759
11 changed files with 132 additions and 89 deletions
|
|
@ -65,6 +65,8 @@ Detailed documentation is still forthcoming.
|
|||
|
||||
`cAddSearchDir("XXX")` - add directory XXX to search path in calls to `cSearchPath()`
|
||||
|
||||
`cAddStdDir("XXX")` - add standard "c" [default] or "cpp" include paths to search path
|
||||
|
||||
`cSearchPath("header.h")` - return a file or directory found in search path configured using `cSearchPath()` - can be used in `cCompile()`, `cIncludeDir()` and `cImport()` calls
|
||||
|
||||
`gitPull()` - pull a git repository prior to C/C++ interop
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ proc addHeader*(fullpath: string) =
|
|||
#
|
||||
|
||||
proc pPreprocDef(node: ref Ast) =
|
||||
if node.children.len() == 2:
|
||||
if node.children.len == 2:
|
||||
let
|
||||
name = getNodeValIf(node.children[0], identifier)
|
||||
val = getNodeValIf(node.children[1], preproc_arg)
|
||||
|
|
@ -37,30 +37,42 @@ proc pPreprocDef(node: ref Ast) =
|
|||
#
|
||||
|
||||
proc typeScan(node: ref Ast, sym, id: Sym, offset: string): string =
|
||||
if node.sym != sym or node.children.len() != 2:
|
||||
if node.sym != sym or node.children.len != 2:
|
||||
return
|
||||
|
||||
let
|
||||
pname = getNodeValIf(node.children[1], id)
|
||||
var
|
||||
name = getNodeValIf(node.children[1], id)
|
||||
ptyp = getNodeValIf(node.children[0], primitive_type)
|
||||
ttyp = getNodeValIf(node.children[0], type_identifier)
|
||||
ptrname = false
|
||||
|
||||
if pname.len() == 0:
|
||||
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)
|
||||
ptrname = true
|
||||
|
||||
if name.len == 0:
|
||||
return
|
||||
elif ptyp.nBl:
|
||||
result = &"{offset}{pname.getIdentifier()}: {ptyp.getType()}"
|
||||
ptyp = ptyp.getType()
|
||||
if ptyp != "object" and ptrname:
|
||||
ptyp = &"ptr {ptyp}"
|
||||
result = &"{offset}{name.getIdentifier()}: {ptyp}"
|
||||
elif ttyp.nBl:
|
||||
result = &"{offset}{pname.getIdentifier()}: {ttyp}"
|
||||
elif node.children[0].sym in [struct_specifier, enum_specifier] and node.children[0].children.len() == 1:
|
||||
let styp = getNodeValIf(node.children[0].children[0], type_identifier)
|
||||
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)
|
||||
if styp.nBl:
|
||||
result = &"{offset}{pname.getIdentifier()}: {styp}"
|
||||
if ptrname:
|
||||
styp = &"ptr {styp}"
|
||||
result = &"{offset}{name.getIdentifier()}: {styp}"
|
||||
else:
|
||||
return
|
||||
|
||||
proc pStructSpecifier(node: ref Ast, name = "") =
|
||||
var stmt: string
|
||||
if node.children.len() == 1 and name notin gTypes:
|
||||
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)
|
||||
|
|
@ -68,18 +80,18 @@ proc pStructSpecifier(node: ref Ast, name = "") =
|
|||
gTypes.add(name)
|
||||
if name != typ:
|
||||
# typedef struct X Y
|
||||
gTypeStr &= &" {name}* = {typ} #1 pStructSpecifier()\n"
|
||||
gTypeStr &= &" {name.getIdentifier()}* = {typ} #1 pStructSpecifier()\n"
|
||||
else:
|
||||
# typedef struct X X
|
||||
gTypeStr &= &" {name}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #2 pStructSpecifier()\n"
|
||||
gTypeStr &= &" {name.getIdentifier()}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #2 pStructSpecifier()\n"
|
||||
|
||||
of field_declaration_list:
|
||||
# typedef struct { fields } X
|
||||
stmt = &" {name}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #3 pStructSpecifier()\n"
|
||||
stmt = &" {name.getIdentifier()}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #3 pStructSpecifier()\n"
|
||||
|
||||
for field in node.children[0].children:
|
||||
let ts = typeScan(field, field_declaration, field_identifier, " ")
|
||||
if ts.len() == 0:
|
||||
if ts.len == 0:
|
||||
return
|
||||
stmt &= ts & "\n"
|
||||
|
||||
|
|
@ -88,7 +100,7 @@ proc pStructSpecifier(node: ref Ast, name = "") =
|
|||
else:
|
||||
discard
|
||||
|
||||
elif name.len() == 0 and node.children.len() == 2 and node.children[1].sym == field_declaration_list:
|
||||
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:
|
||||
# struct X { fields }
|
||||
|
|
@ -96,7 +108,7 @@ proc pStructSpecifier(node: ref Ast, name = "") =
|
|||
|
||||
for field in node.children[1].children:
|
||||
let ts = typeScan(field, field_declaration, field_identifier, " ")
|
||||
if ts.len() == 0:
|
||||
if ts.len == 0:
|
||||
return
|
||||
stmt &= ts & "\n"
|
||||
|
||||
|
|
@ -109,12 +121,12 @@ proc pEnumSpecifier(node: ref Ast, name = "") =
|
|||
elid: int
|
||||
stmt: string
|
||||
|
||||
if node.children.len() == 1 and node.children[0].sym == enumerator_list:
|
||||
if node.children.len == 1 and node.children[0].sym == enumerator_list:
|
||||
# typedef enum { fields } X
|
||||
ename = name
|
||||
elid = 0
|
||||
stmt = &" {name}* = enum #1 pEnumSpecifier()\n"
|
||||
elif name.len() == 0 and node.children.len() == 2 and node.children[1].sym == enumerator_list:
|
||||
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)
|
||||
elid = 1
|
||||
if ename.nBl:
|
||||
|
|
@ -126,9 +138,9 @@ proc pEnumSpecifier(node: ref Ast, name = "") =
|
|||
for field in node.children[elid].children:
|
||||
if field.sym == enumerator:
|
||||
let fname = getNodeValIf(field.children[0], identifier)
|
||||
if field.children.len() == 1:
|
||||
if field.children.len == 1:
|
||||
stmt &= &" {fname}\n"
|
||||
elif field.children.len() == 2 and field.children[1].sym == number_literal:
|
||||
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:
|
||||
|
|
@ -139,25 +151,31 @@ proc pEnumSpecifier(node: ref Ast, name = "") =
|
|||
gTypeStr &= stmt
|
||||
|
||||
proc pTypeDefinition(node: ref Ast) =
|
||||
if node.children.len() == 2:
|
||||
if node.children.len == 2:
|
||||
var
|
||||
name = getNodeValIf(node.children[1], type_identifier)
|
||||
pname = getNodeValIf(node.children[1], pointer_declarator)
|
||||
ptyp = getNodeValIf(node.children[0], primitive_type)
|
||||
ttyp = getNodeValIf(node.children[0], type_identifier)
|
||||
ptrname = false
|
||||
|
||||
if name.len() == 0 and node.children[1].sym == pointer_declarator and node.children[1].children.len() == 1:
|
||||
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)
|
||||
ptrname = true
|
||||
|
||||
if name.nBl and name notin gTypes:
|
||||
if ptyp.nBl:
|
||||
# typedef int X
|
||||
gTypes.add(name)
|
||||
gTypeStr &= &" {name}* = {ptyp.getType()} #1 pTypeDefinition()\n"
|
||||
ptyp = ptyp.getType()
|
||||
if ptyp != "object" and ptrname:
|
||||
ptyp = &"ptr {ptyp}"
|
||||
gTypeStr &= &" {name.getIdentifier()}* = {ptyp} #1 pTypeDefinition()\n"
|
||||
elif ttyp.nBl:
|
||||
# typedef X Y
|
||||
gTypes.add(name)
|
||||
gTypeStr &= &" {name}* = {ttyp} #2 pTypeDefinition()\n"
|
||||
if ptrname:
|
||||
ttyp = &"ptr {ttyp}"
|
||||
gTypeStr &= &" {name.getIdentifier()}* = {ttyp} #2 pTypeDefinition()\n"
|
||||
else:
|
||||
case node.children[0].sym:
|
||||
of struct_specifier:
|
||||
|
|
@ -168,20 +186,20 @@ proc pTypeDefinition(node: ref Ast) =
|
|||
discard
|
||||
|
||||
proc pFunctionDeclarator(node: ref Ast, typ: string) =
|
||||
if node.children.len() == 2:
|
||||
if node.children.len == 2:
|
||||
let
|
||||
name = getNodeValIf(node.children[0], identifier)
|
||||
|
||||
if name.nBl and name notin gProcs and node.children[1].sym == parameter_list:
|
||||
# typ function(typ param1, ...)
|
||||
var stmt = &"# pFunctionDeclarator()\nproc {name}*("
|
||||
var stmt = &"# pFunctionDeclarator()\nproc {name.getIdentifier()}*("
|
||||
|
||||
for i in 0 .. node.children[1].children.len()-1:
|
||||
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:
|
||||
if ts.len == 0:
|
||||
return
|
||||
stmt &= ts
|
||||
if i != node.children[1].children.len()-1:
|
||||
if i != node.children[1].children.len-1:
|
||||
stmt &= ", "
|
||||
|
||||
if typ != "void":
|
||||
|
|
@ -195,7 +213,7 @@ proc pFunctionDeclarator(node: ref Ast, typ: string) =
|
|||
gProcStr &= stmt
|
||||
|
||||
proc pDeclaration*(node: ref Ast) =
|
||||
if node.children.len() == 2 and node.children[1].sym == function_declarator:
|
||||
if node.children.len == 2 and node.children[1].sym == function_declarator:
|
||||
let
|
||||
ptyp = getNodeValIf(node.children[0], primitive_type)
|
||||
ttyp = getNodeValIf(node.children[0], type_identifier)
|
||||
|
|
@ -204,7 +222,7 @@ proc pDeclaration*(node: ref Ast) =
|
|||
pFunctionDeclarator(node.children[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:
|
||||
elif node.children[0].sym == struct_specifier and node.children[0].children.len == 1:
|
||||
let styp = getNodeValIf(node.children[0].children[0], type_identifier)
|
||||
if styp.nBl:
|
||||
pFunctionDeclarator(node.children[1], styp)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ proc findPath(path: string, fail = true): string =
|
|||
|
||||
proc cSearchPath*(path: string): string =
|
||||
result = findPath(path, fail = false)
|
||||
if result.len() == 0:
|
||||
if result.len == 0:
|
||||
var found = false
|
||||
for inc in gSearchDirs:
|
||||
result = (inc & "/" & path).replace("\\", "/")
|
||||
|
|
@ -31,12 +31,12 @@ proc cSearchPath*(path: string): string =
|
|||
macro cDebug*(): untyped =
|
||||
gDebug = true
|
||||
|
||||
macro cDefine*(name: static[string], val: static[string] = ""): untyped =
|
||||
macro cDefine*(name: static string, val: static string = ""): untyped =
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
var str = "-D" & name
|
||||
if val.nBl:
|
||||
str &= "=\"" & val & "\""
|
||||
str &= &"=\"{val}\""
|
||||
|
||||
result.add(quote do:
|
||||
{.passC: `str`.}
|
||||
|
|
@ -45,36 +45,37 @@ macro cDefine*(name: static[string], val: static[string] = ""): untyped =
|
|||
if gDebug:
|
||||
echo result.repr
|
||||
|
||||
macro cAddSearchDir*(dir: static[string]): untyped =
|
||||
macro cAddSearchDir*(dir: static string): untyped =
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
let fullpath = cSearchPath(dir)
|
||||
if fullpath notin gSearchDirs:
|
||||
gSearchDirs.add(fullpath)
|
||||
|
||||
macro cIncludeDir*(dir: static[string]): untyped =
|
||||
macro cIncludeDir*(dir: static string): untyped =
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
let
|
||||
fullpath = findPath(dir)
|
||||
str = "-I\"" & fullpath & "\""
|
||||
str = &"-I\"{fullpath}\""
|
||||
|
||||
if fullpath notin gIncludeDirs:
|
||||
gIncludeDirs.add(fullpath)
|
||||
|
||||
result.add(quote do:
|
||||
{.passC: `str`.}
|
||||
)
|
||||
result.add(quote do:
|
||||
{.passC: `str`.}
|
||||
)
|
||||
|
||||
if gDebug:
|
||||
echo result.repr
|
||||
|
||||
macro cIncludeC*(): untyped =
|
||||
macro cAddStdDir*(mode = "c"): untyped =
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
var
|
||||
inc = false
|
||||
for line in getGccPaths().splitLines():
|
||||
|
||||
for line in getGccPaths(mode.strVal()).splitLines():
|
||||
if "#include <...> search starts here" in line:
|
||||
inc = true
|
||||
continue
|
||||
|
|
@ -82,10 +83,11 @@ macro cIncludeC*(): untyped =
|
|||
break
|
||||
|
||||
if inc:
|
||||
result = quote do:
|
||||
cIncludeDir(line)
|
||||
let sline = line.strip()
|
||||
result.add quote do:
|
||||
cAddSearchDir(`sline`)
|
||||
|
||||
macro cCompile*(path: static[string]): untyped =
|
||||
macro cCompile*(path: static string): untyped =
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
var
|
||||
|
|
@ -129,7 +131,7 @@ macro cCompile*(path: static[string]): untyped =
|
|||
if gDebug:
|
||||
echo result.repr
|
||||
|
||||
macro cImport*(filename: static[string]): untyped =
|
||||
macro cImport*(filename: static string): untyped =
|
||||
result = newNimNode(nnkStmtList)
|
||||
result.add addReorder()
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,11 @@ proc getNodeValIf*(node: ref Ast, esym: Sym): string =
|
|||
return gCode[node.start .. node.stop-1].strip()
|
||||
|
||||
proc getGccPaths*(mode = "c"): string =
|
||||
let
|
||||
var
|
||||
nul = when defined(Windows): "nul" else: "/dev/null"
|
||||
mmode = if mode == "cpp": "c++" else: mode
|
||||
|
||||
return staticExec("gcc -Wp,-v -x" & mode & " " & nul)
|
||||
return staticExec("gcc -Wp,-v -x" & mmode & " " & nul)
|
||||
|
||||
proc getLineCol*(node: ref Ast): tuple[line, col: int] =
|
||||
result.line = 1
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ proc execAction*(cmd: string): string =
|
|||
echo result
|
||||
quit(1)
|
||||
|
||||
macro extractZip*(zipfile, outdir: static[string]): untyped =
|
||||
macro extractZip*(zipfile, outdir: static string): untyped =
|
||||
var cmd = "unzip -o $#"
|
||||
if defined(Windows):
|
||||
cmd = "powershell -nologo -noprofile -command \"& { Add-Type -A " &
|
||||
|
|
@ -28,7 +28,7 @@ macro extractZip*(zipfile, outdir: static[string]): untyped =
|
|||
echo "Extracting " & zipfile
|
||||
discard execAction(&"cd \"{getProjectPath()/outdir}\" && " & cmd % zipfile)
|
||||
|
||||
macro downloadUrl*(url, outdir: static[string]): untyped =
|
||||
macro downloadUrl*(url, outdir: static string): untyped =
|
||||
let
|
||||
file = url.extractFilename()
|
||||
ext = file.splitFile().ext.toLowerAscii()
|
||||
|
|
@ -45,7 +45,7 @@ macro downloadUrl*(url, outdir: static[string]): untyped =
|
|||
discard quote do:
|
||||
extractZip(`file`, `outdir`)
|
||||
|
||||
macro gitReset*(outdir: static[string]): untyped =
|
||||
macro gitReset*(outdir: static string): untyped =
|
||||
echo "Resetting " & outdir
|
||||
|
||||
let cmd = &"cd \"{getProjectPath()/outdir}\" && git reset --hard"
|
||||
|
|
@ -53,7 +53,7 @@ macro gitReset*(outdir: static[string]): untyped =
|
|||
sleep(1000)
|
||||
echo " Retrying ..."
|
||||
|
||||
macro gitCheckout*(file, outdir: static[string]): untyped =
|
||||
macro gitCheckout*(file, outdir: static string): untyped =
|
||||
echo "Resetting " & file
|
||||
|
||||
let cmd = &"cd \"{getProjectPath()/outdir}\" && git checkout $#" % file.replace(outdir & "/", "")
|
||||
|
|
@ -61,7 +61,7 @@ macro gitCheckout*(file, outdir: static[string]): untyped =
|
|||
sleep(500)
|
||||
echo " Retrying ..."
|
||||
|
||||
macro gitPull*(url: static[string], outdirN = "", plistN = "", checkoutN = ""): untyped =
|
||||
macro gitPull*(url: static string, outdirN = "", plistN = "", checkoutN = ""): untyped =
|
||||
let
|
||||
outdir = getProjectPath()/outdirN.strVal()
|
||||
plist = plistN.strVal()
|
||||
|
|
@ -78,14 +78,14 @@ macro gitPull*(url: static[string], outdirN = "", plistN = "", checkoutN = ""):
|
|||
discard execAction(&"cd \"{outdir}\" && git init .")
|
||||
discard execAction(&"cd \"{outdir}\" && git remote add origin " & url)
|
||||
|
||||
if plist.len() != 0:
|
||||
if plist.len != 0:
|
||||
let sparsefile = &"{outdir}/.git/info/sparse-checkout"
|
||||
|
||||
discard execAction(&"cd \"{outdir}\" && git config core.sparsecheckout true")
|
||||
writeFile(sparsefile, plist)
|
||||
echo "Wrote"
|
||||
|
||||
if checkout.len() != 0:
|
||||
if checkout.len != 0:
|
||||
echo "Checking out " & checkout
|
||||
discard execAction(&"cd \"{outdir}\" && git pull --tags origin master")
|
||||
discard execAction(&"cd \"{outdir}\" && git checkout {checkout}")
|
||||
|
|
|
|||
|
|
@ -37,4 +37,4 @@ var
|
|||
gTypeStr* {.compiletime.}: string
|
||||
|
||||
template nBl*(s: untyped): untyped =
|
||||
(s.len() != 0)
|
||||
(s.len != 0)
|
||||
|
|
@ -13,7 +13,7 @@ proc tokenize(fullpath: string) =
|
|||
|
||||
gTokens = @[]
|
||||
idx = 0
|
||||
for i in staticExec("toast -u " & fullpath):
|
||||
for i in staticExec("toast -m " & fullpath):
|
||||
case i:
|
||||
of ' ', '\n', '\r', '(', ')':
|
||||
if collect.nBl:
|
||||
|
|
@ -24,17 +24,17 @@ proc tokenize(fullpath: string) =
|
|||
else:
|
||||
collect &= $i
|
||||
|
||||
if gTokens.len() == 0:
|
||||
if gTokens.len == 0:
|
||||
echo "toast binary not installed - nimble install nimterop to force build"
|
||||
quit(1)
|
||||
|
||||
proc readFromTokens(): ref Ast =
|
||||
if idx == gTokens.len():
|
||||
if idx == gTokens.len:
|
||||
echo "Bad AST"
|
||||
quit(1)
|
||||
|
||||
if gTokens[idx] == "(":
|
||||
if gTokens.len() - idx < 2:
|
||||
if gTokens.len - idx < 2:
|
||||
echo "Corrupt AST"
|
||||
quit(1)
|
||||
if gTokens[idx+1] != "comment":
|
||||
|
|
@ -60,7 +60,7 @@ proc readFromTokens(): ref Ast =
|
|||
|
||||
proc printAst*(node: ref Ast, offset=""): string =
|
||||
result = offset & "(" & $node.sym & " " & $node.start & " " & $node.stop
|
||||
if node.children.len() != 0:
|
||||
if node.children.len != 0:
|
||||
result &= "\n"
|
||||
for child in node.children:
|
||||
result &= printAst(child, offset & " ")
|
||||
|
|
|
|||
|
|
@ -4,13 +4,15 @@ int test_call_int() {
|
|||
return 5;
|
||||
}
|
||||
|
||||
struct STRUCT1 test_call_int_param(int param1) {
|
||||
#ifdef FORCE
|
||||
struct STRUCT1 _test_call_int_param_(int param1) {
|
||||
struct STRUCT1 s;
|
||||
|
||||
s.field1 = param1;
|
||||
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
STRUCT2 test_call_int_param2(int param1, STRUCT2 param2) {
|
||||
STRUCT2 s;
|
||||
|
|
|
|||
|
|
@ -29,8 +29,15 @@ typedef enum {
|
|||
enum6
|
||||
} ENUM2;
|
||||
|
||||
typedef void * VOIDPTR;
|
||||
typedef int * INTPTR;
|
||||
|
||||
typedef struct {
|
||||
int *field;
|
||||
} STRUCT4;
|
||||
|
||||
int test_call_int();
|
||||
struct STRUCT1 test_call_int_param(int param1);
|
||||
struct STRUCT1 _test_call_int_param_(int param1);
|
||||
STRUCT2 test_call_int_param2(int param1, STRUCT2 param2);
|
||||
STRUCT2 test_call_int_param3(int param1, struct STRUCT1 param2);
|
||||
ENUM2 test_call_int_param4(enum ENUM param1);
|
||||
|
|
@ -2,6 +2,7 @@ import nimterop/cimport
|
|||
|
||||
cDebug()
|
||||
|
||||
cDefine("FORCE")
|
||||
cIncludeDir "include"
|
||||
cAddSearchDir "include"
|
||||
cCompile cSearchPath("test.c")
|
||||
|
|
@ -18,10 +19,14 @@ var
|
|||
s: STRUCT1
|
||||
s2: STRUCT2
|
||||
s3: STRUCT3
|
||||
s4: STRUCT4
|
||||
|
||||
e: ENUM
|
||||
e2: ENUM2 = enum5
|
||||
|
||||
vptr: VOIDPTR
|
||||
iptr: INTPTR
|
||||
|
||||
pt = 3
|
||||
ct = 4
|
||||
|
||||
|
|
@ -31,9 +36,11 @@ s3.field1 = 7
|
|||
|
||||
e = enum1
|
||||
e2 = enum4
|
||||
|
||||
|
||||
doAssert test_call_int() == 5
|
||||
doAssert test_call_int_param(5).field1 == 5
|
||||
doAssert test_call_int_param2(5, s2).field1 == 11
|
||||
doAssert test_call_int_param3(5, s).field1 == 10
|
||||
doAssert test_call_int_param4(e) == e2
|
||||
|
||||
cAddStdDir()
|
||||
|
|
|
|||
48
toast.nim
48
toast.nim
|
|
@ -6,30 +6,28 @@ import treesitter/[runtime, c, cpp]
|
|||
|
||||
const HELP = """
|
||||
> toast header.h
|
||||
"""
|
||||
-m minimized output - non-pretty
|
||||
-c C mode - CPP is default"""
|
||||
|
||||
var
|
||||
gPretty = true
|
||||
|
||||
proc printLisp(root: TSNode, data: var string) =
|
||||
proc printLisp(root: TSNode, data: var string, pretty = true) =
|
||||
var
|
||||
node = root
|
||||
nextnode: TSNode
|
||||
depth = 0
|
||||
|
||||
|
||||
while true:
|
||||
if not node.tsNodeIsNull():
|
||||
if gPretty:
|
||||
if pretty:
|
||||
stdout.write spaces(depth)
|
||||
stdout.write "(" & $node.tsNodeType() & " " & $node.tsNodeStartByte() & " " & $node.tsNodeEndByte()
|
||||
|
||||
if node.tsNodeNamedChildCount() != 0:
|
||||
if gPretty:
|
||||
if pretty:
|
||||
echo ""
|
||||
nextnode = node.tsNodeNamedChild(0)
|
||||
depth += 1
|
||||
else:
|
||||
if gPretty:
|
||||
if pretty:
|
||||
echo ")"
|
||||
else:
|
||||
stdout.write ")"
|
||||
|
|
@ -39,7 +37,7 @@ proc printLisp(root: TSNode, data: var string) =
|
|||
while true:
|
||||
node = node.tsNodeParent()
|
||||
depth -= 1
|
||||
if gPretty:
|
||||
if pretty:
|
||||
echo spaces(depth) & ")"
|
||||
else:
|
||||
stdout.write ")"
|
||||
|
|
@ -54,11 +52,11 @@ proc printLisp(root: TSNode, data: var string) =
|
|||
if node == root:
|
||||
break
|
||||
|
||||
proc process(path: string, mode="") =
|
||||
proc process(path: string, mode="cpp", pretty = true) =
|
||||
if not existsFile(path):
|
||||
echo "Invalid path " & path
|
||||
return
|
||||
|
||||
|
||||
var
|
||||
parser = tsParserNew()
|
||||
ext = path.splitFile().ext
|
||||
|
|
@ -67,14 +65,14 @@ proc process(path: string, mode="") =
|
|||
|
||||
defer:
|
||||
parser.tsParserDelete()
|
||||
|
||||
if mode.len() != 0:
|
||||
|
||||
if mode.len != 0:
|
||||
pmode = mode
|
||||
elif ext in [".h", ".c"]:
|
||||
pmode = "c"
|
||||
elif ext in [".hxx", ".hpp", ".hh", ".H", ".h++", ".cpp", ".cxx", ".cc", ".C", ".c++"]:
|
||||
pmode = "cpp"
|
||||
|
||||
|
||||
if "cplusplus" in data or "extern \"C\"" in data:
|
||||
pmode = "cpp"
|
||||
|
||||
|
|
@ -91,23 +89,29 @@ proc process(path: string, mode="") =
|
|||
quit()
|
||||
|
||||
var
|
||||
tree = parser.tsParserParseString(nil, data.cstring, data.len().uint32)
|
||||
tree = parser.tsParserParseString(nil, data.cstring, data.len.uint32)
|
||||
root = tree.tsTreeRootNode()
|
||||
|
||||
defer:
|
||||
tree.tsTreeDelete()
|
||||
|
||||
printLisp(root, data)
|
||||
|
||||
printLisp(root, data, pretty)
|
||||
|
||||
proc parseCli() =
|
||||
let params = commandLineParams()
|
||||
var
|
||||
mode = "cpp"
|
||||
params = commandLineParams()
|
||||
pretty = true
|
||||
|
||||
for param in params:
|
||||
if param in ["-h", "--help", "-?", "/?", "/h"]:
|
||||
echo HELP
|
||||
quit()
|
||||
elif param == "-u":
|
||||
gPretty = false
|
||||
elif param == "-c":
|
||||
mode = "c"
|
||||
elif param == "-m":
|
||||
pretty = false
|
||||
else:
|
||||
process(param)
|
||||
process(param, mode, pretty)
|
||||
|
||||
parseCli()
|
||||
Loading…
Add table
Add a link
Reference in a new issue