From f08e90f0d651861e5caa77bfccaa57b1e63d346e Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 7 Apr 2019 21:14:54 +0200 Subject: [PATCH] more efficient enumToStr implementation that works without the old typeinfo structures --- compiler/ast.nim | 14 ++++++++++++ compiler/ccgexprs.nim | 23 +++++++++++++++++++- compiler/cgen.nim | 5 ++++- compiler/cgendata.nim | 2 +- compiler/enumtostr.nim | 42 ++++++++++++++++++++++++++++++++++++ compiler/liftdestructors.nim | 14 ------------ compiler/sempass2.nim | 6 +++--- 7 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 compiler/enumtostr.nim diff --git a/compiler/ast.nim b/compiler/ast.nim index 0aeb94bb5a..1f10328d5a 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1811,3 +1811,17 @@ template detailedInfo*(sym: PSym): string = proc isInlineIterator*(s: PSym): bool {.inline.} = s.kind == skIterator and s.typ.callConv != ccClosure + +proc newProcType*(info: TLineInfo; owner: PSym): PType = + result = newType(tyProc, owner) + result.n = newNodeI(nkFormalParams, info) + rawAddSon(result, nil) # return type + # result.n[0] used to be `nkType`, but now it's `nkEffectList` because + # the effects are now stored in there too ... this is a bit hacky, but as + # usual we desperately try to save memory: + addSon(result.n, newNodeI(nkEffectList, info)) + +proc addParam*(procType: PType; param: PSym) = + param.position = procType.len-1 + addSon(procType.n, newSymNode(param)) + rawAddSon(procType, param.typ) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 9d1731708e..420dc9c542 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1481,6 +1481,8 @@ proc genOf(p: BProc, n: PNode, d: var TLoc) = genOf(p, n.sons[1], n.sons[2].typ, d) proc genRepr(p: BProc, e: PNode, d: var TLoc) = + if optNimV2 in p.config.globalOptions: + localError(p.config, e.info, "'repr' is not available for --newruntime") var a: TLoc initLocExpr(p, e.sons[1], a) var t = skipTypes(e.sons[1].typ, abstractVarRange) @@ -1980,6 +1982,21 @@ proc genDispose(p: BProc; n: PNode) = # destructor, but it uses the runtime type. Afterwards the memory is freed: lineCg(p, cpsStmts, "#nimDestroyAndDispose($#)", rdLoc(a)) +proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) = + const ToStringProcSlot = -4 + let t = e[1].typ.skipTypes(abstractInst) + var toStrProc: PSym = nil + for (idx, p) in t.methods: + if idx == ToStringProcSlot: + toStrProc = p + break + if toStrProc == nil: + toStrProc = genEnumToStrProc(t, e.info, p.module.g.graph) + t.methods.add((ToStringProcSlot, toStrProc)) + var n = copyTree(e) + n[0] = newSymNode(toStrProc) + expr(p, n, d) + proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = case op of mOr, mAnd: genAndOr(p, e, d, op) @@ -2046,7 +2063,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)") of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)") of mStrToStr: expr(p, e.sons[1], d) - of mEnumToStr: genRepr(p, e, d) + of mEnumToStr: + if optNimV2 in p.config.globalOptions: + genEnumToStr(p, e, d) + else: + genRepr(p, e, d) of mOf: genOf(p, e, d) of mNew: genNew(p, e) of mNewFinalize: genNewFinalize(p, e) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 223ed4dbcc..f3a6e5a26c 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -14,7 +14,7 @@ import nversion, nimsets, msgs, std / sha1, bitsets, idents, types, ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth, condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, - lowerings, tables, sets, ndi, lineinfos, pathutils, transf + lowerings, tables, sets, ndi, lineinfos, pathutils, transf, enumtostr when not defined(leanCompiler): import semparallel @@ -307,6 +307,9 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc, s = skipTypes(s.sons[0], skipPtrs) linefmt(p, section, "$1.m_type = $2;$n", r, genTypeInfo(p.module, t, a.lode.info)) of frEmbedded: + if optNimV2 in p.config.globalOptions: + localError(p.config, p.prc.info, + "complex object initialization is not supported with --newruntime") # worst case for performance: var r = if takeAddr: addrLoc(p.config, a) else: rdLoc(a) linefmt(p, section, "#objectInit($1, $2);$n", r, genTypeInfo(p.module, t, a.lode.info)) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index 6c38ae1c49..9d12a5740f 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -160,7 +160,7 @@ type typeNodesName*, nimTypesName*: Rope # used for type info generation labels*: Natural # for generating unique module-scope names extensionLoaders*: array['0'..'9', Rope] # special procs for the - # OpenGL wrapper + # OpenGL wrapper injectStmt*: Rope sigConflicts*: CountTable[SigHash] g*: BModuleList diff --git a/compiler/enumtostr.nim b/compiler/enumtostr.nim new file mode 100644 index 0000000000..34d5f2d669 --- /dev/null +++ b/compiler/enumtostr.nim @@ -0,0 +1,42 @@ + +import ast, idents, lineinfos, modulegraphs, magicsys + +proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym = + result = newSym(skProc, getIdent(g.cache, "$"), t.owner, info) + + let dest = newSym(skParam, getIdent(g.cache, "e"), result, info) + dest.typ = t + + let res = newSym(skResult, getIdent(g.cache, "result"), result, info) + res.typ = getSysType(g, info, tyString) + + result.typ = newType(tyProc, t.owner) + result.typ.n = newNodeI(nkFormalParams, info) + rawAddSon(result.typ, res.typ) + addSon(result.typ.n, newNodeI(nkEffectList, info)) + + result.typ.addParam dest + + var body = newNodeI(nkStmtList, info) + var caseStmt = newNodeI(nkCaseStmt, info) + caseStmt.add(newSymNode dest) + + # copy the branches over, but replace the fields with the for loop body: + for i in 0 ..< t.n.len: + assert(t.n[i].kind == nkSym) + var field = t.n[i].sym + let val = if field.ast == nil: field.name.s else: field.ast.strVal + caseStmt.add newTree(nkOfBranch, newSymNode(field), + newTree(nkStmtList, newTree(nkFastAsgn, newSymNode(res), newStrNode(val, info)))) + #newIntTypeNode(nkIntLit, field.position, t) + + body.add(caseStmt) + + var n = newNodeI(nkProcDef, info, bodyPos+2) + for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info) + n.sons[namePos] = newSymNode(result) + n.sons[paramsPos] = result.typ.n + n.sons[bodyPos] = body + n.sons[resultPos] = newSymNode(res) + result.ast = n + incl result.flags, sfFromGeneric diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 6abaf0bfdb..5aed8bb8d3 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -484,20 +484,6 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) = tyGenericInst, tyStatic, tyAlias, tySink: liftBodyAux(c, lastSon(t), body, x, y) -proc newProcType(info: TLineInfo; owner: PSym): PType = - result = newType(tyProc, owner) - result.n = newNodeI(nkFormalParams, info) - rawAddSon(result, nil) # return type - # result.n[0] used to be `nkType`, but now it's `nkEffectList` because - # the effects are now stored in there too ... this is a bit hacky, but as - # usual we desperately try to save memory: - addSon(result.n, newNodeI(nkEffectList, info)) - -proc addParam(procType: PType; param: PSym) = - param.position = procType.len-1 - addSon(procType.n, newSymNode(param)) - rawAddSon(procType, param.typ) - proc liftBodyDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym = assert typ.kind == tyDistinct let baseType = typ[0] diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index f09a45ce8d..03fd34c860 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -70,7 +70,7 @@ type tags: PNode # list of tags bottom, inTryStmt: int owner: PSym - owner_module: PSym + ownerModule: PSym init: seq[int] # list of initialized variables guards: TModel # nested guards locked: seq[PNode] # locked locations @@ -705,7 +705,7 @@ proc track(tracked: PEffects, n: PNode) = # p's effects are ours too: var a = n.sons[0] let op = a.typ - if getConstExpr(tracked.owner_module, n, tracked.graph) != nil: + if getConstExpr(tracked.ownerModule, n, tracked.graph) != nil: return if op != nil: if tracked.owner.kind != skMacro: @@ -950,7 +950,7 @@ proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects; c: PC t.exc = effects.sons[exceptionEffects] t.tags = effects.sons[tagEffects] t.owner = s - t.owner_module = s.getModule + t.ownerModule = s.getModule t.init = @[] t.guards.s = @[] t.guards.o = initOperators(g)