Skip to content

Commit

Permalink
[CHECKPOINT] Infer list of superclasses
Browse files Browse the repository at this point in the history
  • Loading branch information
haxscramper committed Nov 3, 2021
1 parent a5d4d7a commit dad2233
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 47 deletions.
45 changes: 40 additions & 5 deletions src/hcparse/hc_codegen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,27 @@ proc toNNode*[N](
isDistinct = false
))

func getCbindAs*(pr: CxxProc): CxxBind =
result = pr.cbind
if result.icpp.len == 0:
if pr.isConstructor:
raise newArgumentError(
"Cannot get cbind for constructor proc")

else:
if pr.isMethod():
if pr.isStatic():
result.icpp = staticMethod(
pr.getMethodOf().cxxStr(), pr.getIcppName())

else:
result.icpp.dotMethod(pr.getIcppName())

else:
result.icpp.standaloneProc(pr.getIcppName())



proc toNNode*[N](
def: CxxProc,
conf: CodegenConf,
Expand Down Expand Up @@ -302,11 +323,19 @@ proc toNNode*[N](
result.name = "new" & name

elif def.isMethod():
var ret = toNNode[N](def.methodOf.get(), conf, anon)
if not def.isConst():
ret = newNType[N]("var", @[ret])
if cpfStatic notin def.flags:
var ret = toNNode[N](
#[ V FIXME - does not account for template type parameters in parent
classes ]#
def.methodOf.get().cxxTypeUse(),
conf,
anon)

if not def.isConst():
ret = newNType[N]("var", @[ret])

result.addArgument("this", ret)

result.addArgument("this", ret)
result.addPragma toNNode[N](def.getCbindAs(), conf, def.nimName)

else:
Expand All @@ -316,7 +345,8 @@ proc toNNode*[N](

let ret: NType[N] =
if def.isConstructor:
let base: NType[N] = toNNode[N](def.getConstructed(), conf, anon)
let base: NType[N] = toNNode[N](
def.getConstructed().cxxTypeUse(), conf, anon)
case onConstructor:
of nctRegular: base
of nctPtr: newNType[N]("ptr", @[base])
Expand Down Expand Up @@ -360,6 +390,11 @@ proc toNNode*[N](
for n in obj.nested:
result.add toNNode[N](n, conf, anon)

echov "super of", obj
for super in obj.decl.store.getSuperTypes(obj.decl):
echov ">>", super


proc toNNode*[N](obj: CxxForward, conf: CodegenConf): ObjectDecl[N] =
result = newObjectDecl[N](obj.nimName)
result.addPragma("bycopy")
Expand Down
4 changes: 2 additions & 2 deletions src/hcparse/hc_irgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,10 @@ proc toCxxProc*(
# result.header = conf.makeHeader(pr.cursor, conf)

if pr.cursor.kind in {ckConstructor}:
result.constructorOf = some parent.get().cxxTypeUse()
result.constructorOf = some parent.get().name

elif parent.isSome():
result.methodOf = some parent.get().cxxTypeUse()
result.methodOf = some parent.get().name

for argIdx, arg in pr.arguments:
result.add toCxxArg(arg, conf, cache)
Expand Down
3 changes: 3 additions & 0 deletions src/hcparse/hc_parsefront.nim
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ proc postFixEntries*(
for item in mitems(entries):
setFileRec(item, file.get())

for item in mitems(entries):
registerDeclarations(item, store, lib)

# Register type declarations in the store, add missing flags to type uses
for item in mitems(entries):
postprocessTypeUses(item, store, lib)
Expand Down
39 changes: 30 additions & 9 deletions src/hcparse/hc_tsreader.nim
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,16 @@ proc mapOpName*(node: CppNode): string =
else: node.strVal()

proc mapTypeName*(node: CppNode): string =
if node.kind == cppTypeIdentifier:
node.strVal()
case node.kind:
of cppTypeIdentifier:
result = node.strVal()

else:
mapPrimitiveName(node.primitiveName())
of cppQualifiedIdentifier:
for item in items(node):
result.add item.strVal()

else:
result = mapPrimitiveName(node.primitiveName())


proc toCxxComment*(comm: CppNode): CxxComment =
Expand All @@ -77,6 +82,13 @@ proc toCxxType*(node: CppNode, parent, user: Option[CxxNamePair]): CxxTypeUse =
result.podKind = node.primitiveName().mapPrimitivePod()
result.flags.incl ctfIsPodType

of cppQualifiedIdentifier:
var names: seq[string]
for name in items(node):
names.add name.strVal()

result = cxxPair(mapTypeName(node), cxxName(names)).cxxTypeUse()

of cppStructSpecifier, cppEnumSpecifier, cppUnionSpecifier:
if node[0] of cppFieldDeclarationList:
var coms: seq[CxxComment]
Expand Down Expand Up @@ -302,11 +314,14 @@ proc toCxxProc*(
)

if parent.isSome():
result.methodOf = some parent.get().decl.cxxTypeUse()
result.methodOf = some parent.get().name()

if node[0].kind == cppTypeQualifier:
if node[0] of cppTypeQualifier:
result.returnType.flags.incl ctfConst

if node[0] of cppStorageClassSpecifier:
result.flags.incl cpfStatic

pointerWraps(node["declarator"], result.returnType)

let decl =
Expand Down Expand Up @@ -380,6 +395,12 @@ proc toCxxObject*(node: CppNode, coms): CxxObject =

var signal = cqsNone

for part in node:
if part of cppBaseClassClause:
for class in part:
result.super.add toCxxType(
class, none CxxNamePair, none CxxNamePair)

for field in node["body"]:
if field of cppAccessSpecifier:
let ts = field.getTs()
Expand Down Expand Up @@ -423,14 +444,14 @@ proc toCxxObject*(node: CppNode, coms): CxxObject =
coms.clear()

if meth.cxxName().scopes.last() == result.cxxName().scopes.last():
meth.constructorOf = some result.decl.cxxTypeUse()
meth.constructorOf = some result.name()

elif node["declarator"]["declarator"] of cppDestructorName:
meth.destructorOf = some result.decl.cxxTypeUse()
meth.destructorOf = some result.name()

result.methods.add meth

of cppFieldDeclaration:
of cppFieldDeclaration, cppFunctionDefinition:
if field["declarator"] of cppFunctionDeclarator:
let name = field["declarator"]["declarator"]
if name of cppParenthesizedDeclarator:
Expand Down
12 changes: 11 additions & 1 deletion src/hcparse/interop_ir/wrap_icpp.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import std/[parseutils, strutils]
import std/[parseutils, strutils, with]
import hmisc/core/all

type
Expand Down Expand Up @@ -40,6 +40,16 @@ func initIcpp*(parts: varargs[IcppPart, icpp]): IcppPattern =
result.add part


func staticMethod*(className, methodName: string): IcppPattern =
with result:
add icpp(className)
add icpp("::")
add icpp(methodName)
add icpp("(")
add icpp(ipkArgSplice)
add icpp(")")


func dotMethod*(icpp: var IcppPattern, methodName: string) =
icpp.add icpp(ipkNextDotArg)
icpp.add icpp(methodName)
Expand Down
79 changes: 58 additions & 21 deletions src/hcparse/interop_ir/wrap_store.nim
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ type

CxxProcFlag* = enum
cpfConst
cpfStatic
cpfOperator
cpfOverride
cpfExportc
Expand All @@ -300,9 +301,9 @@ type

flags*: set[CxxProcFlag]

constructorOf*: Option[CxxTypeUse]
destructorOf*: Option[CxxTypeUse]
methodOf*: Option[CxxTypeUse]
constructorOf*: Option[CxxNamePair]
destructorOf*: Option[CxxNamePair]
methodOf*: Option[CxxNamePair]

CxxExprKind = enum
cekIntLit
Expand Down Expand Up @@ -524,6 +525,7 @@ func `$`*(cxx: CxxLibImport): string =
func `$`*(file: CxxFile): string = $file.savePath

func cxxStr*(name: CxxName): string = name.scopes.join("::")
func cxxStr*(name: CxxNamePair): string = name.cxx.scopes.join("::")
func `$`*(name: CxxName): string = name.cxxStr()
func `$`*(name: CxxNamePair): string =
let nim = $name.nim
Expand Down Expand Up @@ -643,6 +645,8 @@ func `$`*(p: CxxProc): string =
func `$`*(alias: CxxAlias): string =
$alias.decl & " = " & $alias.baseType

func `$`*(obj: CxxObject): string = "object!" & $obj.decl

func `$`*(e: CxxEntry): string =
case e.kind:
of cekEnum: result = "enum!" & $e.cxxEnum.decl
Expand Down Expand Up @@ -813,10 +817,13 @@ func `nimName=`*(pr: var CxxProc, name: string) =
func `name=`*(en: var CxxEnum, name: CxxNamePair) = en.decl.name = name
func `name=`*(obj: var CxxObject, name: CxxNamePair) = obj.decl.name = name

func `name`*(use: CxxTypeUse): CxxNamePair =
func name*(use: CxxTypeUse): CxxNamePair =
assertKind(use, {ctkIdent})
result = use.cxxType.name

func name*(pr: CxxProc): CxxNamePair = pr.head.name
func name*(pr: CxxObject): CxxNamePair = pr.decl.name

func `nimName=`*(obj: var CxxAlias, name: string) = obj.decl.name.nim = name

func nimName*(pr: CxxProc): string = pr.head.name.nim
Expand Down Expand Up @@ -895,9 +902,12 @@ func `&`*(p1, p2: CxxNamePair): CxxNamePair =
cxx: CxxName(scopes: p1.cxx.scopes & p2.cxx.scopes))

func isConst*(pr: CxxProc): bool = cpfConst in pr.flags
func isStatic*(pr: CxxProc): bool = cpfStatic in pr.flags
func isConstructor*(pr: CxxProc): bool = pr.constructorOf.isSome()
func isDestructor*(pr: CxxProc): bool = pr.destructorOf.isSome()
func isMethod*(pr: CxxProc): bool = pr.methodOf.isSome()
func getMethodOf*(pr: CxxProc): CxxNamePair =
pr.methodOf.get()

func isEmpty*(name: CxxName): bool =
name.scopes.len == 0 or
Expand All @@ -909,7 +919,7 @@ func add*(t: var CxxTypeUse, other: CxxTypeUse) =
t.genParams.add other
t.genParams.last().flags.incl ctfParam

func getConstructed*(pr: CxxProc): CxxTypeUse =
func getConstructed*(pr: CxxProc): CxxNamePair =
assertOption(pr.constructorOf)
pr.constructorOf.get()

Expand Down Expand Up @@ -1008,6 +1018,10 @@ func addDecl*(store: var CxxTypeStore, decl: CxxTypeDecl) =
store.forwardDecls.del(decl.name.cxx)
store.typeDecls.mgetOrPut(decl.name.cxx, @[]).add decl

func addDecl*(store: var CxxTypeStore, decl: CxxObject) =
store.addDecl(decl.decl)
store.classDecls.mgetOrPut(decl.decl.name.cxx, @[]).add decl

func addForwardDecl*(store: var CxxTypeStore, decl: CxxTypeDecl) =
store.forwardDecls.mgetOrPut(decl.name.cxx, @[]).add decl

Expand Down Expand Up @@ -1037,6 +1051,23 @@ func getDecl*(
result = some store.forwardDecls[name][0]


func getObject*(
store: CxxTypeStore,
name: CxxName,
lib: Option[string]
): Option[CxxObject] =

assertRef store
if name in store.classDecls:
for class in store.classDecls[name]:
# No library for import, or no library for the type declaration
if lib.isNone() or class.decl.typeImport.isNone():
return some class

else:
# Has library name for both type declaration and use
if class.decl.typeImport.get().library == lib.get():
return some class

func getDecl*(use: CxxTypeUse): Option[CxxTypeDecl] =
## Get first type declaration with matching cxx name. In case of multiple
Expand Down Expand Up @@ -1374,23 +1405,29 @@ func getBindImports*(file: CxxFile): HashSet[CxxLibImport] =
aux(entry, result)


func getCbindAs*(pr: CxxProc): CxxBind =
result = pr.cbind
if result.icpp.len == 0:
if pr.isConstructor:
raise newArgumentError(
"Cannot get cbind for constructor proc")
func newTypeStore*(): CxxTypeStore = CxxTypeStore()

else:
if pr.isMethod:
result.icpp.dotMethod(pr.getIcppName())
# func registerTypeDeclarations*()

else:
result.icpp.standaloneProc(pr.getIcppName())
func getSuperTypes*(store: CxxTypeStore, decl: CxxTypeDecl): seq[CxxObject] =
var outset: OrderedTable[CxxName, CxxObject]
var stack: seq[CxxName] = @[decl.cxxName()]

while len(stack) > 0:
let top = stack.pop()

let decl = store.getObject(top, none string)
if ?decl:
outset[top] = decl.get()
for super in decl.get().super:
stack.add super.cxxName()

outset.del decl.cxxName()

for key, val in outset:
result.add val

func newTypeStore*(): CxxTypeStore = CxxTypeStore()

# func registerTypeDeclarations*()

func registerDeclarations*(
entry: var CxxEntry,
Expand Down Expand Up @@ -1425,7 +1462,7 @@ func registerDeclarations*(
of cekObject:
entry.cxxObject.decl.typeImport = some lib
entry.cxxObject.decl.store = store
store.addDecl(entry.cxxObject.decl)
store.addDecl(entry.cxxObject)

for nest in mitems(entry.cxxObject.nested):
registerDeclarations(entry, store, lib)
Expand Down Expand Up @@ -1550,10 +1587,10 @@ proc fixIdentsRec*(

proc aux(decl: var CxxProc, cache: var StringNameCache) =
if decl.isMethod():
aux(decl.methodOf.get(), cache)
aux(decl.methodOf.get())

if decl.isConstructor():
aux(decl.constructorOf.get(), cache)
aux(decl.constructorOf.get())

for idx, arg in mpairs(decl.arguments):
if isEmpty(arg.cxxName()):
Expand Down
Loading

0 comments on commit dad2233

Please sign in to comment.