Skip to content

Commit

Permalink
[FEATURE] Generate helper enum code
Browse files Browse the repository at this point in the history
  • Loading branch information
haxscramper committed Oct 18, 2021
1 parent da4d279 commit 5b44614
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 38 deletions.
97 changes: 83 additions & 14 deletions src/hcparse/hc_codegen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import
hmisc/core/all,
hmisc/macros/argpass,
hmisc/other/oswrap,
std/[macros, sequtils, sets, strformat, algorithm]
std/[macros, sequtils, sets, strformat, algorithm, strutils]

type
CodegenConf* = object
Expand All @@ -18,6 +18,8 @@ type
perOs: seq[(string, CxxBind)]
]]

nameStyle*: IdentStyle

const
cxxCodegenConf* = CodegenConf(
isIcpp: true
Expand All @@ -27,6 +29,17 @@ const
it.isIcpp = false


func getPrefix*(conf: CodegenConf, name: string): string =
case conf.nameStyle:
of idsSnake: name & "_"
of idsCamel: capitalizeAscii(name)

func getSuffix*(conf: CodegenConf, name: string): string =
case conf.nameStyle:
of idsSnake: "_" & name
of idsCamel: capitalizeAscii(name)


func getImport*(conf: CodegenConf): string =
if conf.isIcpp: "importcpp" else: "importc"

Expand Down Expand Up @@ -72,7 +85,13 @@ proc toNNode*[N](

case t.kind:
of ctkIdent:
result = newNNType[N](t.nimName, @[])
if ctfIsEnumType in t.flags:
result = newNNType[N](
conf.getPrefix("c") & t.nimName,
@[])

else:
result = newNNType[N](t.nimName, @[])

of ctkPtr:
if t.wrapped of ctkIdent:
Expand Down Expand Up @@ -308,25 +327,75 @@ proc toNNode*[N](obj: CxxForward, conf: CodegenConf): ObjectDecl[N] =
result.addPragma toNNode[N](obj.cbind, conf, obj.nimName)
result.docComment.add toNimComment(obj.docComment)

proc toNNode*[N](field: CxxEnumValue, conf: CodegenConf): EnumField[N] =
result = makeEnumField(
field.nimName, some newNLit[N, BiggestInt](field.value))
proc toNNode*[N](field: CxxEnumValue, conf: CodegenConf): tuple[c, n: EnumField[N]] =
result.c = makeEnumField(
conf.getPrefix("c") & field.nimName,
some newNLit[N, BiggestInt](field.value))

result.c.docComment = toNimComment(field.docComment)

result.n = makeEnumField[N](field.nimName)
result.n.docComment = toNimComment(field.docComment)

proc toNNode*[N](en: CxxEnum, conf: CodegenConf): seq[NimDecl[N]] =
var
cenum = newEnumDecl[N](conf.getPrefix("c") & en.nimName)
nenum = newEnumDecl[N](en.nimName)
values = en.values.sortedByIt(it.value)
visited: HashSet[BiggestInt]
generated: seq[tuple[c, n: EnumField[N]]]

result.docComment = toNimComment(field.docComment)

proc toNNode*[N](en: CxxEnum, conf: CodegenConf): EnumDecl[N] =
result = newEnumDecl[N](en.nimName)
let arg = newNIdent[N]("arg")

var fieldList: seq[EnumField[N]]
var values = en.values.sortedByIt(it.value)
var
forwardConv = newCase(arg)
backwardConv = newCase(arg)

var visited: HashSet[BiggestInt]
for value in values:
if value.value notin visited:
visited.incl value.value
result.add toNNode[N](value, conf)
let (c, n) = toNNode[N](value, conf)
cenum.add c
nenum.add n

forwardConv.add newOf(
newNIdent[N](c.name), wrapStmtList(newNIdent[N](n.name)))

backwardConv.add newOf(
newNIdent[N](n.name), wrapStmtList(newNIdent[N](c.name)))

cenum.docComment.add toNimComment(en.docComment)
nenum.docComment.add toNimComment(en.docComment)

result.add cenum
result.add nenum

result.add newPProcDecl(
name = conf.getPrefix("to") & cenum.name,
args = @{"arg": newNNtype[N](nenum.name)},
returnType = some newNNtype[N](cenum.name),
impl = backwardConv
)

result.add newPProcDecl(
name = conf.getPrefix("to") & nenum.name,
args = @{"arg": newNNtype[N](cenum.name)},
returnType = some newNNtype[N](nenum.name),
declType = ptkConverter,
impl = forwardConv
)

block:
let arg = newPident(cenum.name)
result.add pquote do:
converter toCint*(arg: `arg`): cint =
cint(ord(arg))

result.docComment.add toNimComment(en.docComment)
func `+`*(arg: `arg`, offset: int): `arg` = `arg`(ord(arg) + offset)
func `+`*(offset: int, arg: `arg`): `arg` = `arg`(ord(arg) + offset)
func `-`*(arg: `arg`, offset: int): `arg` = `arg`(ord(arg) - offset)
func `-`*(offset: int, arg: `arg`): `arg` = `arg`(ord(arg) - offset)


proc toNNode*[N](
Expand All @@ -339,7 +408,7 @@ proc toNNode*[N](
result.add toNNode[N](entry.cxxObject, conf, anon)

of cekEnum:
result.add toNNode[N](entry.cxxEnum, conf).toNimDecl()
result.add toNNode[N](entry.cxxEnum, conf)

of cekProc:
result.add toNNode[N](
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 @@ -505,7 +505,7 @@ proc toCxxAlias*(
baseType = wrapBase.decl.cxxTypeUse()

for newName in al.newTypes:
var newType = cxxPair(conf, newName).cxxTypeDecl()
var newType = cxxPair(conf, newName).cxxTypeDecl(ctdkTypedef)
# newType.genParams = baseType.genParams # FIXME port generic parameters from
if newType.cxxName() != baseType.cxxName():
# Alias names might be the same for `typedef struct St {} St;`
Expand All @@ -516,7 +516,7 @@ proc toCxxAlias*(
let aliasof = al.cursor.cxType().getCanonicalType()

# Create new identifier for aliased type
var newAlias = conf.cxxPair(al.ident, cache).cxxTypeDecl()
var newAlias = conf.cxxPair(al.ident, cache).cxxTypeDecl(ctdkTypedef)

# Identifier for old aliased type
var baseType: CxxTypeUse
Expand Down
16 changes: 11 additions & 5 deletions src/hcparse/hc_parsefront.nim
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,12 @@ proc writeFiles*(
proc wrapCSharedLibViaTsWave*(
inDir, tmpDir, outDir: AbsDir,
libName, packageName: string,
ignoreIn: seq[string] = @[],
persistentOut: seq[string] = @[
ignoreIn: seq[string] = @[],
persistentOut: seq[string] = @[
"hcparse_generate", "lib" & libName & "_config"],
depDirs: seq[AbsDir] = @[],
extraTypes: seq[(CxxName, CxxLibImport)] = @[]
depDirs: seq[AbsDir] = @[],
extraTypes: seq[(CxxName, CxxLibImport)] = @[],
codegen: CodegenConf = cCodegenConf
): GenFiles =
var expandMap = expandViaWave(
listFiles(inDir, ignoreNames = ignoreIn),
Expand All @@ -411,12 +412,17 @@ proc wrapCSharedLibViaTsWave*(

rmFiles(outDir, @["nim"], persistentOut)

var codegen = codegen

let
fixConf = initCSharedLibFixConf(
libName, packageName, false, inDir, expandMap, depDirs = depDirs)

codegen.nameStyle = fixConf.libNameStyle

let
resultWrapped = tmpDir.wrapViaTs(fixConf)
resultGrouped = writeFiles(outDir, resultWrapped, cCodegenConf, extraTypes = extraTypes)
resultGrouped = writeFiles(outDir, resultWrapped, codegen, extraTypes = extraTypes)

return resultGrouped

Expand Down
13 changes: 9 additions & 4 deletions src/hcparse/hc_tsreader.nim
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,10 @@ proc toCxxField*(node: CppNode, coms; parent: CxxNamePair): CxxField =
pointerWraps(decl, result.nimType)

proc toCxxForwardType*(node: CppNode, coms): CxxForward =
result = cxxForward(cxxPair(node["name"].strVal()))
result = cxxForward(
cxxPair(node["name"].strVal()),
ctdkStruct #[ TEMP implement better detection ]#)

result.add coms
coms.clear()

Expand Down Expand Up @@ -406,7 +409,7 @@ proc toCxxTypeDefinition*(node: CppNode, coms): seq[CxxEntry] =
let newType = toCxxType(
node["declarator"],
parent = none CxxNamePair,
user = none CxxNamePair).toDecl()
user = none CxxNamePair).toDecl(ctdkTypedef #[ XXXX ]#)

let baseBody = node[0]
if baseBody of {
Expand All @@ -427,7 +430,9 @@ proc toCxxTypeDefinition*(node: CppNode, coms): seq[CxxEntry] =
if alias.baseType of ctkIdent and
alias.decl.cxxName() == alias.baseType.cxxName():
# `typedef struct T T;`
result.add cxxForward(alias.decl.name).withIt do:
result.add cxxForward(
alias.decl.name, ctdkStruct #[ TEMP ]#).withIt do:

it.add coms
coms.clear()

Expand Down Expand Up @@ -493,7 +498,7 @@ proc toCxxTypeDefinition*(node: CppNode, coms): seq[CxxEntry] =
coms.clear()

result.add cxxAlias(
body[d].getName().cxxPair().cxxTypeDecl(),
body[d].getName().cxxPair().cxxTypeDecl(ctdkTypedef),
cxxTypeUse(
args, toCxxType(node["type"], none CxxNamePair, none CxxNamePair)))

Expand Down
65 changes: 56 additions & 9 deletions src/hcparse/interop_ir/wrap_store.nim
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,19 @@ type

CxxGenParams* = seq[tuple[name: CxxNamePair, default: Option[CxxTypeUse]]]

CxxTypeDeclKind* = enum
ctdkNone

ctdkEnum
ctdkStruct
ctdkClass
ctdkUnion
ctdkTypedef

ctdkProc # HACK because proc also uses type declaration for it's head

CxxTypeDecl* = object
kind*: CxxTypeDeclKind
isForward*: bool
name*: CxxNamePair
typeImport*: Option[CxxLibImport]
Expand Down Expand Up @@ -150,12 +162,21 @@ type
typeStore*: CxxTypeStore

CxxTypeFlag* = enum
ctfNone

ctfConst
ctfMutable
ctfComplex
ctfParam
ctfDefaultedParam

ctfIsPodType
ctfIsEnumType
ctfIsStructType
ctfIsUnionType
ctfIsClassType
ctfIsTypedefType


ctfPtrToArray
ctfNoCdeclProc
Expand Down Expand Up @@ -443,6 +464,9 @@ type
libName*: string
isIcpp*: bool

export IdentStyle


proc getBind*(conf: CxxFixConf, entry: CxxEntry): CxxBind =
assertRef conf.getBindImpl
return conf.getBindImpl(entry, conf)
Expand Down Expand Up @@ -569,6 +593,8 @@ func `$`*(decl: CxxTypeDecl): string =
result.add "?"


result.add $decl.kind
result.add "."
result.add $decl.name
if ?decl.genParams:
result.add "["
Expand Down Expand Up @@ -924,8 +950,10 @@ func cxxTypeRef*(
result.name.context = cncType

func cxxTypeDecl*(
head: CxxNamePair, genParams: CxxGenParams = @[]): CxxTypeDecl =
result = CxxTypeDecl(name: head, genParams: genParams)
head: CxxNamePair,
kind: CxxTypeDeclKind,
genParams: CxxGenParams = @[]): CxxTypeDecl =
result = CxxTypeDecl(name: head, genParams: genParams, kind: kind)
result.name.context = cncType

func cxxTypeUse*(
Expand Down Expand Up @@ -953,9 +981,9 @@ func cxxTypeUse*(
kind: ctkAnonEnum, enumDef: enumDef,
enumParent: parent, enumUser: user)

func toDecl*(use: CxxTypeUse): CxxTypeDecl =
func toDecl*(use: CxxTypeUse, kind: CxxTypeDeclKind): CxxTypeDecl =
assertKind(use, {ctkIdent})
return cxxTypeDecl(use.cxxType.name)
return cxxTypeDecl(use.cxxType.name, kind)

func addDecl*(store: var CxxTypeStore, decl: CxxTypeDecl) =
store.forwardDecls.del(decl.name.cxx)
Expand Down Expand Up @@ -1185,14 +1213,18 @@ func cxxTypeUse*(name: string, args: seq[CxxTypeUse]): CxxTypeUse =
cxxTypeUse(cxxPair(name), args)

func cxxObject*(name: CxxNamePair, genParams: CxxGenParams = @[]): CxxObject =
CxxObject(decl: cxxTypeDecl(name, genParams), haxdocIdent: newJNull())
CxxObject(
decl: cxxTypeDecl(name, ctdkStruct, genParams),
haxdocIdent: newJNull())

func cxxForward*(name: CxxNamePair, kind: CxxTypeDeclKind): CxxForward =
result = CxxForward(
decl: cxxTypeDecl(name, kind, @[]), haxdocIdent: newJNull())

func cxxForward*(name: CxxNamePair): CxxForward =
result = CxxForward(decl: cxxTypeDecl(name, @[]), haxdocIdent: newJNull())
result.decl.isForward = true

func cxxEnum*(name: CxxNamePair): CxxEnum =
CxxEnum(decl: cxxTypeDecl(name), haxdocIdent: newJNull())
CxxEnum(decl: cxxTypeDecl(name, ctdkEnum), haxdocIdent: newJNull())


func cxxContext*(name: sink CxxNamePair, ctx: CxxNameContext): CxxNamePair =
Expand Down Expand Up @@ -1230,7 +1262,7 @@ func cxxProc*(
): CxxProc =

CxxProc(
head: cxxTypeDecl(name, genParams).cxxContext(cncProc),
head: cxxTypeDecl(name, ctdkProc, genParams).cxxContext(cncProc),
haxdocIdent: newJNull(),
returnType: returnType,
arguments: arguments
Expand Down Expand Up @@ -1365,6 +1397,21 @@ func setTypeStoreRec*(
use.cxxType.typeStore = store
use.cxxType.typeLib = some lib.library

let decl = use.getDecl()
if decl.isSome():
use.flags.incl():
case decl.get().kind:
of ctdkEnum: ctfIsEnumType
of ctdkStruct: ctfIsStructType
of ctdkClass: ctfIsClassType
of ctdkUnion: ctfIsUnionType
of ctdkTypedef: ctfIsTypedefType
of ctdkProc, ctdkNone: ctfNone


else:
use.flags.incl(ctfIsPodType)

func aux(decl: var CxxProc, store: var CxxTypeStore) =
for arg in mitems(decl.arguments):
aux(arg, store)
Expand Down
Loading

0 comments on commit 5b44614

Please sign in to comment.