Struct fields support, multiple bugs

This commit is contained in:
Ganesh Viswanathan 2020-01-07 01:12:42 -06:00
commit 166eae7a5a
2 changed files with 264 additions and 107 deletions

View file

@ -13,3 +13,8 @@ switch("stackTrace", "on")
# Path to compiler # Path to compiler
switch("path", "$nim") switch("path", "$nim")
# Case objects
when not defined(danger):
switch("define", "nimOldCaseObjects")

View file

@ -49,12 +49,16 @@ proc addConst(nimState: NimState, node: TSNode) =
nimState.printDebug(constDef) nimState.printDebug(constDef)
proc newTypeIdent(nimState: NimState, node: TSNode): PNode = proc newTypeIdent(nimState: NimState, node: TSNode, override = ""): PNode =
# Create nkTypeDef PNode with first ident # Create nkTypeDef PNode with first ident
let let
(name, info) = nimState.getNameInfo(node.getAtom(), nskType) (name, info) = nimState.getNameInfo(node.getAtom(), nskType)
# TODO - check blank and override # TODO - check blank and override
ident = nimState.getIdent(name, info) ident =
if override.len != 0:
nimState.getIdent(override, info)
else:
nimState.getIdent(name, info)
result = newNode(nkTypeDef) result = newNode(nkTypeDef)
result.add ident result.add ident
@ -111,10 +115,29 @@ proc newArrayTree(nimState: NimState, node: TSNode, typ, size: PNode): PNode =
result.add typ result.add typ
proc getTypeArray(nimState: NimState, node: TSNode): PNode proc getTypeArray(nimState: NimState, node: TSNode): PNode
proc getTypeProc(nimState: NimState, node: TSNode, name: string): PNode proc getTypeProc(nimState: NimState, name: string, node: TSNode): PNode
proc newProcParam(nimState: NimState, name: string, node: TSNode, offset: uint64): PNode = proc newIdentDefs(nimState: NimState, name: string, node: TSNode, offset: uint64, exported = false): PNode =
# Create nkIdentDefs tree for specified parameter # Create nkIdentDefs tree for specified proc parameter or object field
#
# For proc, param should not be exported
#
# nkIdentDefs(
# nkIdent(pname),
# typ,
# nkEmpty()
# )
#
# For object, field should be exported
#
# nkIdentDefs(
# nkPostfix(
# nkIdent("*"),
# nkIdent(pname)
# ),
# typ,
# nkEmpty()
# )
result = newNode(nkIdentDefs) result = newNode(nkIdentDefs)
let let
@ -123,9 +146,12 @@ proc newProcParam(nimState: NimState, name: string, node: TSNode, offset: uint64
tident = nimState.getIdent(tname, tinfo, exported = false) tident = nimState.getIdent(tname, tinfo, exported = false)
if node.len == 1: if node.len == 1:
# Only for proc with no named param - create a param name based on offset
#
# int func(char, int);
let let
pname = "a" & $(offset+1) pname = "a" & $(offset+1)
pident = nimState.getIdent(pname, tinfo, exported = false) pident = nimState.getIdent(pname, tinfo, exported)
result.add pident result.add pident
result.add tident result.add tident
result.add newNode(nkEmpty) result.add newNode(nkEmpty)
@ -136,17 +162,22 @@ proc newProcParam(nimState: NimState, name: string, node: TSNode, offset: uint64
abst = node[1].getName() == "abstract_pointer_declarator" abst = node[1].getName() == "abstract_pointer_declarator"
if fdecl.isNil and adecl.isNil: if fdecl.isNil and adecl.isNil:
if abst: if abst:
# Only for proc with no named param with pointer type
# Create a param name based on offset
#
# int func(char *, int **);
let let
pname = "a" & $(offset+1) pname = "a" & $(offset+1)
pident = nimState.getIdent(pname, tinfo, exported = false) pident = nimState.getIdent(pname, tinfo, exported)
acount = node[1].getXCount("abstract_pointer_declarator") acount = node[1].getXCount("abstract_pointer_declarator")
result.add pident result.add pident
result.add newPtrTree(acount, tident) result.add newPtrTree(acount, tident)
result.add newNode(nkEmpty) result.add newNode(nkEmpty)
else: else:
# Named param, simple type
let let
(pname, pinfo) = nimState.getNameInfo(node[1].getAtom(), nskField, parent = name) (pname, pinfo) = nimState.getNameInfo(node[1].getAtom(), nskField, parent = name)
pident = nimState.getIdent(pname, pinfo, exported = false) pident = nimState.getIdent(pname, pinfo, exported)
count = node[1].getPtrCount() count = node[1].getPtrCount()
result.add pident result.add pident
@ -156,16 +187,18 @@ proc newProcParam(nimState: NimState, name: string, node: TSNode, offset: uint64
result.add tident result.add tident
result.add newNode(nkEmpty) result.add newNode(nkEmpty)
elif not fdecl.isNil: elif not fdecl.isNil:
# Named param, function pointer
let let
(pname, pinfo) = nimState.getNameInfo(node[1].getAtom(), nskField, parent = name) (pname, pinfo) = nimState.getNameInfo(node[1].getAtom(), nskField, parent = name)
pident = nimState.getIdent(pname, pinfo, exported = false) pident = nimState.getIdent(pname, pinfo, exported)
result.add pident result.add pident
result.add nimState.getTypeProc(node, name) result.add nimState.getTypeProc(name, node)
result.add newNode(nkEmpty) result.add newNode(nkEmpty)
elif not adecl.isNil: elif not adecl.isNil:
# Named param, array type
let let
(pname, pinfo) = nimState.getNameInfo(node[1].getAtom(), nskField, parent = name) (pname, pinfo) = nimState.getNameInfo(node[1].getAtom(), nskField, parent = name)
pident = nimState.getIdent(pname, pinfo, exported = false) pident = nimState.getIdent(pname, pinfo, exported)
result.add pident result.add pident
result.add nimState.getTypeArray(node) result.add nimState.getTypeArray(node)
result.add newNode(nkEmpty) result.add newNode(nkEmpty)
@ -173,81 +206,66 @@ proc newProcParam(nimState: NimState, name: string, node: TSNode, offset: uint64
result = nil result = nil
proc newProcTree(nimState: NimState, name: string, node: TSNode, rtyp: PNode): PNode = proc newProcTree(nimState: NimState, name: string, node: TSNode, rtyp: PNode): PNode =
# Create nkProcTy tree for specified proc type
#
# nkProcTy(
# nkFormalParams(
# rtyp,
# nkIdentDefs( # multiple depending on params
# ..
# )
# ),
# nkEmpty()
# )
result = newNode(nkProcTy) result = newNode(nkProcTy)
let let
fparam = newNode(nkFormalParams) fparam = newNode(nkFormalParams)
result.add fparam
result.add newNode(nkEmpty)
# Add return type # Add return type
fparam.add rtyp fparam.add rtyp
if not node.isNil: if not node.isNil:
for i in 0 ..< node.len: for i in 0 ..< node.len:
# Add nkIdentDefs for each param
let let
a = nimState.newProcParam(name, node[i], i) param = nimState.newIdentDefs(name, node[i], i, exported = false)
if not a.isNil: if not param.isNil:
fparam.add a fparam.add param
proc addTypeObject(nimState: NimState, node: TSNode) = result.add fparam
# Add a type of object result.add newNode(nkEmpty)
let
# TODO - check blank and override
typeDef = nimState.newTypeIdent(node)
# type X* = object proc newRecListTree(nimState: NimState, name: string, node: TSNode): PNode =
# Create nkRecList tree for specified object
# #
# nkTypeDef( # nkRecList(
# nkPostfix( # nkIdentDefs( # multiple depending on fields
# nkIdent("*"), # ..
# nkIdent("X")
# ),
# nkEmpty(),
# nkObjectTy(
# nkEmpty(),
# nkEmpty(),
# nkEmpty()
# ) # )
# ) # )
typeDef.add(block: if not node.isNil:
let result = newNode(nkRecList)
obj = newNode(nkObjectTy)
obj.add newNode(nkEmpty)
obj.add newNode(nkEmpty)
obj.add newNode(nkEmpty)
obj for i in 0 ..< node.len:
) # Add nkIdentDefs for each field
let
field = nimState.newIdentDefs(name, node[i], i, exported = true)
if not field.isNil:
result.add field
# nkTypeSection.add proc addTypeObject(nimState: NimState, node: TSNode, override = "", duplicate = "") =
nimState.typeSection.add typeDef # Add a type of object
#
nimState.printDebug(typeDef) # If `override` is set, use it as the name
# If `duplicate` is set, don't add the same name
proc addTypeTyped(nimState: NimState, node: TSNode) =
# Add a type of a specific type
let let
# node[1] = identifer = name
# TODO - check blank and override # TODO - check blank and override
typeDef = nimState.newTypeIdent(node[1]) typeDef = nimState.newTypeIdent(node, override)
name = $typeDef[0][1]
# node[0] = identifier = type name if name != duplicate:
(name, info) = nimState.getNameInfo(node[0].getAtom(), nskType) # type X* = object
ident = nimState.getIdent(name, info, exported = false)
# node[1] could have nested pointers
count = node[1].getPtrCount()
# Skip typedef X X;
if $typeDef[0][1] != name:
if count > 0:
# If pointers
typeDef.add newPtrTree(count, ident)
else:
typeDef.add ident
# type X* = [ptr ..] Y
# #
# nkTypeDef( # nkTypeDef(
# nkPostfix( # nkPostfix(
@ -255,16 +273,83 @@ proc addTypeTyped(nimState: NimState, node: TSNode) =
# nkIdent("X") # nkIdent("X")
# ), # ),
# nkEmpty(), # nkEmpty(),
# nkPtrTy( # optional, nested # nkObjectTy(
# nkIdent("Y") # nkEmpty(),
# nkEmpty(),
# nkEmpty()
# ) # )
# ) # )
let
obj = newNode(nkObjectTy)
obj.add newNode(nkEmpty)
obj.add newNode(nkEmpty)
let
fdlist = node.anyChildInTree("field_declaration_list")
if not fdlist.isNil and fdlist.len > 0:
# Add fields to object if present
obj.add nimState.newRecListTree(name, fdlist)
else:
obj.add newNode(nkEmpty)
typeDef.add obj
# nkTypeSection.add # nkTypeSection.add
nimState.typeSection.add typeDef nimState.typeSection.add typeDef
nimState.printDebug(typeDef) nimState.printDebug(typeDef)
proc addTypeTyped(nimState: NimState, node: TSNode, toverride = "", duplicate = "") =
# Add a type of a specified type
#
# If `toverride` is set, use it as the type name
# If `duplicate` is set, don't add the same name
for i in 1 ..< node.len:
# Add a type of a specific type
let
# node[i] = identifer = name
# TODO - check blank and override
typeDef = nimState.newTypeIdent(node[i])
# node[0] = identifier = type name
(tname0, tinfo) = nimState.getNameInfo(node[0].getAtom(), nskType)
# Override type name
tname = if toverride.len != 0: toverride else: tname0
ident = nimState.getIdent(tname, tinfo, exported = false)
# node[i] could have nested pointers
count = node[i].getPtrCount()
# Skip typedef X X;
if $typeDef[0][1] != tname:
if count > 0:
# If pointers
typeDef.add newPtrTree(count, ident)
else:
typeDef.add ident
# type X* = [ptr ..] Y
#
# nkTypeDef(
# nkPostfix(
# nkIdent("*"),
# nkIdent("X")
# ),
# nkEmpty(),
# nkPtrTy( # optional, nested
# nkIdent("Y")
# )
# )
# nkTypeSection.add
nimState.typeSection.add typeDef
nimState.printDebug(typeDef)
else:
nimState.addTypeObject(node, duplicate)
proc getTypeArray(nimState: NimState, node: TSNode): PNode = proc getTypeArray(nimState: NimState, node: TSNode): PNode =
# Create array type tree # Create array type tree
let let
@ -350,7 +435,7 @@ proc addTypeArray(nimState: NimState, node: TSNode) =
nimState.printDebug(typeDef) nimState.printDebug(typeDef)
proc getTypeProc(nimState: NimState, node: TSNode, name: string): PNode = proc getTypeProc(nimState: NimState, name: string, node: TSNode): PNode =
# Create proc type tree # Create proc type tree
let let
# node[0] = identifier = return type name # node[0] = identifier = return type name
@ -396,7 +481,7 @@ proc addTypeProc(nimState: NimState, node: TSNode) =
typeDef = nimState.newTypeIdent(node[1]) typeDef = nimState.newTypeIdent(node[1])
name = $typeDef[0][1] name = $typeDef[0][1]
procTy = nimState.getTypeProc(node, name) procTy = nimState.getTypeProc(name, node)
typeDef.add procTy typeDef.add procTy
@ -437,48 +522,59 @@ proc addType(nimState: NimState, node: TSNode) =
nimState.printDebug(node) nimState.printDebug(node)
if node.getName() == "struct_specifier": if node.getName() == "struct_specifier":
if node.len == 1: # struct X;
# struct X; #
# # (struct_specifier
# (struct_specifier # (type_identifier)
# (type_identifier) # )
# ) #
nimState.addTypeObject(node) # struct X {};
elif node.len == 2: #
if node[1].getName() == "field_declaration_list" and node[1].len == 0: # (struct_specifier
# struct X {}; # (type_identifier)
# # (field_declaration_list = "{}")
# (struct_specifier # )
# (type_identifier) #
# (field_declaration_list = "{}") # struct X { char *a1; };
# ) #
nimState.addTypeObject(node) # (struct_specifier
# (type_identifier)
# (field_declaration_list
# (field_declaration
# (type_identifier|primitive_type|)
# (struct_specifier
# (type_identifier)
# )
#
# (field_identifier)
# )
# (field_declaration ...)
# )
nimState.addTypeObject(node)
elif node.getName() == "type_definition": elif node.getName() == "type_definition":
if node.len == 2: if node.len >= 2:
let let
fdlist = node[0].anyChildInTree("field_declaration_list") fdlist = node[0].anyChildInTree("field_declaration_list")
if nimState.getNodeVal(node[1]) == "": if nimState.getNodeVal(node[1]) == "":
if fdlist.isNil(): # typedef struct X;
# typedef struct X; #
# # (type_definition
# (type_definition # (struct_specifier
# (struct_specifier # (type_identifier)
# (type_identifier) # )
# ) # (type_definition = "")
# (type_definition = "") # )
# ) #
nimState.addTypeObject(node) # typedef struct X {};
elif fdlist.len == 0: #
# typedef struct X {}; # (type_definition
# # (struct_specifier
# (type_definition # (type_identifier)
# (struct_specifier # (field_declaration_list = "{}")
# (type_identifier) # )
# (field_declaration_list = "{}") # (type_definition = "")
# ) # )
# (type_definition = "") nimState.addTypeObject(node[0])
# )
nimState.addTypeObject(node)
else: else:
let let
fdecl = node[1].anyChildInTree("function_declarator") fdecl = node[1].anyChildInTree("function_declarator")
@ -551,6 +647,62 @@ proc addType(nimState: NimState, node: TSNode) =
# ) # )
# ) # )
nimState.addTypeArray(node) nimState.addTypeArray(node)
else:
if node.firstChildInTree("field_declaration_list").isNil:
# typedef struct X { .. } Y, *Z;
#
# (type_definition
# (struct_specifier
# (type_identifier) - named struct <====
# (field_declaration_list
# (field_declaration - optional, multiple
# (type_identifier|primitive_type|)
# (function_declarator|array_declarator
# ..
# )
#
# (field_identifier)
# )
# )
# )
#
# (type_identifier)
# (pointer_declarator - optional, nested
# (type_identifier)
# )
# )
# First add struct as object
nimState.addTypeObject(node[0])
if node.len > 1 and nimState.getNodeVal(node[1]) != "":
# Add any additional names
nimState.addTypeTyped(node, duplicate = nimState.getNodeVal(node[0].getAtom()))
else:
# Same as above except unnamed struct
#
# typedef struct { .. } Y, *Z;
# Get any name that isn't a pointer
let
name = block:
var
name = ""
for i in 1 ..< node.len:
if node[i].getName() == "type_identifier":
name = nimState.getNodeVal(node[i].getAtom())
if name.len == 0:
name = nimState.getUniqueIdentifier("STRUCT")
name
# Now add struct as object with specified name
nimState.addTypeObject(node[0], override = name)
if node.len > 1 and nimState.getNodeVal(node[1]) != "":
# Add any additional names except duplicate
nimState.addTypeTyped(node, toverride = name, duplicate = name)
proc addEnum(nimState: NimState, node: TSNode) = proc addEnum(nimState: NimState, node: TSNode) =
nimState.printDebug(node) nimState.printDebug(node)