Working towards arc codegen (#13153)

fixes #13029
This commit is contained in:
cooldome 2020-01-16 13:16:17 +00:00 • committed by Andreas Rumpf
commit 5ef0494677
2 changed files with 96 additions and 31 deletions

View file

@ -9,6 +9,10 @@
# included from cgen.nim # included from cgen.nim
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode,
result: var Rope; count: var int;
isConst: bool, info: TLineInfo)
# -------------------------- constant expressions ------------------------ # -------------------------- constant expressions ------------------------
proc int64Literal(i: BiggestInt): Rope = proc int64Literal(i: BiggestInt): Rope =
@ -2742,11 +2746,10 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
else: else:
result = rope"{NIM_NIL, NIM_NIL}" result = rope"{NIM_NIL, NIM_NIL}"
of tyObject: of tyObject:
# XXX Needs to be recursive! var count = 0
if not isObjLackingTypeField(t): result.add "{"
result = "{{$1}}" % [genTypeInfo(p.module, t, info)] getNullValueAuxT(p, t, t, t.n, nil, result, count, true, info)
else: result.add "}"
result = rope"{}"
of tyTuple: of tyTuple:
result = rope"{" result = rope"{"
for i in 0..<t.len: for i in 0..<t.len:
@ -2766,56 +2769,62 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
else: else:
globalError(p.config, info, "cannot create null element for: " & $t.kind) globalError(p.config, info, "cannot create null element for: " & $t.kind)
proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode, proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
result: var Rope; count: var int; result: var Rope; count: var int;
isConst: bool) = isConst: bool, info: TLineInfo) =
case obj.kind case obj.kind
of nkRecList: of nkRecList:
for it in obj.sons: for it in obj.sons:
getNullValueAux(p, t, it, cons, result, count, isConst) getNullValueAux(p, t, it, constOrNil, result, count, isConst, info)
of nkRecCase: of nkRecCase:
getNullValueAux(p, t, obj[0], cons, result, count, isConst) getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info)
if count > 0: result.add ", " if count > 0: result.add ", "
result.add "{{" # struct inside union
# XXX select default case branch here! # XXX select default case branch here!
#for i in 1..<obj.len: #for i in 1..<obj.len:
let selectedBranch = 1
result.add "{" # struct inside union
if lastSon(obj[selectedBranch]).kind != nkSym:
result.add "{"
var countB = 0 var countB = 0
getNullValueAux(p, t, lastSon(obj[1]), cons, result, countB, isConst) getNullValueAux(p, t, lastSon(obj[selectedBranch]), constOrNil, result, countB, isConst, info)
result.add "}}" if lastSon(obj[selectedBranch]).kind != nkSym:
result.add "}"
result.add "}"
of nkSym: of nkSym:
if count > 0: result.add ", " if count > 0: result.add ", "
inc count inc count
let field = obj.sym let field = obj.sym
for i in 1..<cons.len: if constOrNil != nil:
if cons[i].kind == nkExprColonExpr: for i in 1..<constOrNil.len:
if cons[i][0].sym.name.id == field.name.id: if constOrNil[i].kind == nkExprColonExpr:
result.add genBracedInit(p, cons[i][1], isConst) if constOrNil[i][0].sym.name.id == field.name.id:
result.add genBracedInit(p, constOrNil[i][1], isConst)
return return
elif i == field.position: elif i == field.position:
result.add genBracedInit(p, cons[i], isConst) result.add genBracedInit(p, constOrNil[i], isConst)
return return
# not found, produce default value: # not found, produce default value:
result.add getDefaultValue(p, field.typ, cons.info) result.add getDefaultValue(p, field.typ, info)
else: else:
localError(p.config, cons.info, "cannot create null element for: " & $obj) localError(p.config, info, "cannot create null element for: " & $obj)
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode, proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode,
result: var Rope; count: var int; result: var Rope; count: var int;
isConst: bool) = isConst: bool, info: TLineInfo) =
var base = t[0] var base = t[0]
let oldRes = result let oldRes = result
if not p.module.compileToCpp: result.add "{"
let oldcount = count let oldcount = count
if base != nil: if base != nil:
result.add "{"
base = skipTypes(base, skipPtrs) base = skipTypes(base, skipPtrs)
getNullValueAuxT(p, orig, base, base.n, cons, result, count, isConst) getNullValueAuxT(p, orig, base, base.n, constOrNil, result, count, isConst, info)
result.add "}"
elif not isObjLackingTypeField(t): elif not isObjLackingTypeField(t):
result.addf("{$1}", [genTypeInfo(p.module, orig, obj.info)]) result.add genTypeInfo(p.module, orig, obj.info)
inc count inc count
getNullValueAux(p, t, obj, cons, result, count, isConst) getNullValueAux(p, t, obj, constOrNil, result, count, isConst, info)
# do not emit '{}' as that is not valid C: # do not emit '{}' as that is not valid C:
if oldcount == count: result = oldRes if oldcount == count: result = oldRes
elif not p.module.compileToCpp: result.add "}"
proc genConstObjConstr(p: BProc; n: PNode; isConst: bool): Rope = proc genConstObjConstr(p: BProc; n: PNode; isConst: bool): Rope =
result = nil result = nil
@ -2825,8 +2834,7 @@ proc genConstObjConstr(p: BProc; n: PNode; isConst: bool): Rope =
# result.addf("{$1}", [genTypeInfo(p.module, t)]) # result.addf("{$1}", [genTypeInfo(p.module, t)])
# inc count # inc count
if t.kind == tyObject: if t.kind == tyObject:
getNullValueAuxT(p, t, t, t.n, n, result, count, isConst) getNullValueAuxT(p, t, t, t.n, n, result, count, isConst, n.info)
if p.module.compileToCpp:
result = "{$1}$n" % [result] result = "{$1}$n" % [result]
proc genConstSimpleList(p: BProc, n: PNode; isConst: bool): Rope = proc genConstSimpleList(p: BProc, n: PNode; isConst: bool): Rope =

View file

@ -0,0 +1,57 @@
discard """
cmd: '''nim c --gc:arc $file'''
"""
when defined(cpp):
{.passC: "-std=gnu++17".}
type
TokenKind* = enum
tkColon
tkComma
tkString
tkNumber
tkInt64
tkIdent
Token* = object
case kind*: TokenKind
of tkString: strVal*: string
of tkNumber: numVal*: float
of tkInt64: int64Val*: int64
of tkIdent: ident*: string
else: discard
pos*: Natural
BaseLexer* = object of RootObj
input*: string
pos*: Natural
Json5Lexer* = object of BaseLexer
JsonLexer* = object of BaseLexer
allowComments*: bool
allowSpecialFloats*: bool
Lexer* = Json5Lexer | JsonLexer
Parser[T: Lexer] = object
l: T
tok: Token
allowTrailingComma: bool
allowIdentifierObjectKey: bool
proc initJson5Lexer*(input: string): Json5Lexer =
result.input = input
proc parseJson5*(input: string) =
var p = Parser[Json5Lexer](
l: initJson5Lexer(input),
allowTrailingComma: true,
allowIdentifierObjectKey: true
)
let x = "string"
parseJson5(x)