diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2022-09-27 10:57:47 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-27 10:57:47 +0200 |
commit | ca1f3f36b9aff3b8284b2f529fd6fedb72a396c5 (patch) | |
tree | 48f077966234410b5de7b64dffe74e300ad6c1f6 /compiler/jsgen.nim | |
parent | 805186809c0591bb24ff30b6ce48b60527a7a9e8 (diff) | |
download | Nim-ca1f3f36b9aff3b8284b2f529fd6fedb72a396c5.tar.gz |
no ropes WIP (#20433)
* refactorings in preparation for ropes elimination of the C code generator; mostly the usual ': Rope' -> 'result: var Rope' rewrite * rewrote ccgcalls.nim * refactored ccgexprs.nim * ccgliterals: refactoring * refactoring: code dealing with name mangling * refactoring: getRecordFieldsAux * ropes are strings (insert obscene joke here) * optimize JS code gen * optimizations and code improvements * more optimizations * final cleanups
Diffstat (limited to 'compiler/jsgen.nim')
-rw-r--r-- | compiler/jsgen.nim | 139 |
1 files changed, 68 insertions, 71 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index f3477cd48..1a37ab7cf 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -35,7 +35,8 @@ import cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils, transf, injectdestructors, sourcemap, astmsgs -import json, sets, math, tables, intsets, strutils +import json, sets, math, tables, intsets +import strutils except addf when defined(nimPreviewSlimSystem): import std/[assertions, syncio] @@ -110,21 +111,18 @@ type template config*(p: PProc): ConfigRef = p.module.config proc indentLine(p: PProc, r: Rope): Rope = - result = r var p = p + var ind = 0 while true: - for i in 0..<p.blocks.len + p.extraIndent: - prepend(result, rope" ") + inc ind, p.blocks.len + p.extraIndent if p.up == nil or p.up.prc != p.prc.owner: break p = p.up + result = repeat(' ', ind*2) & r template line(p: PProc, added: string) = p.body.add(indentLine(p, rope(added))) -template line(p: PProc, added: Rope) = - p.body.add(indentLine(p, added)) - template lineF(p: PProc, frmt: FormatStr, args: varargs[Rope]) = p.body.add(indentLine(p, ropes.`%`(frmt, args))) @@ -140,9 +138,9 @@ proc newGlobals(): PGlobals = result.typeInfoGenerated = initIntSet() proc initCompRes(r: var TCompRes) = - r.address = nil - r.res = nil - r.tmpLoc = nil + r.address = "" + r.res = "" + r.tmpLoc = "" r.typ = etyNone r.kind = resNone @@ -241,7 +239,7 @@ proc mangleName(m: BModule, s: PSym): Rope = if chr notin {'A'..'Z','a'..'z','_','$','0'..'9'}: return false result = s.loc.r - if result == nil: + if result == "": if s.kind == skField and s.name.s.validJsName: result = rope(s.name.s) elif s.kind == skTemp: @@ -464,7 +462,7 @@ proc maybeMakeTemp(p: PProc, n: PNode; x: TCompRes): tuple[a, tmp: Rope] = b = a if needsTemp(p, n): # if we have tmp just use it - if x.tmpLoc != nil and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}): + if x.tmpLoc != "" and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}): b = "$1[0][$1[1]]" % [x.tmpLoc] (a: a, tmp: b) else: @@ -481,10 +479,10 @@ proc maybeMakeTempAssignable(p: PProc, n: PNode; x: TCompRes): tuple[a, tmp: Rop b = a if needsTemp(p, n): # if we have tmp just use it - if x.tmpLoc != nil and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}): + if x.tmpLoc != "" and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}): b = "$1[0][$1[1]]" % [x.tmpLoc] result = (a: a, tmp: b) - elif x.tmpLoc != nil and n.kind == nkBracketExpr: + elif x.tmpLoc != "" and n.kind == nkBracketExpr: # genArrayAddr var address, index: TCompRes @@ -745,7 +743,7 @@ proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) = else: lineF(p, "$1;$n", [src.rdLoc]) src.kind = resNone - src.res = nil + src.res = "" proc genTry(p: PProc, n: PNode, r: var TCompRes) = # code to generate: @@ -800,7 +798,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = moveInto(p, a, r) if i > 1: lineF(p, "}$n", []) else: - var orExpr: Rope = nil + var orExpr: Rope = "" var excAlias: PNode = nil useMagic(p, "isObj") @@ -813,13 +811,13 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = excAlias = it[2] # If this is a ``except exc as sym`` branch there must be no following # nodes - doAssert orExpr == nil + doAssert orExpr == "" elif it.kind == nkType: throwObj = it else: internalError(p.config, n.info, "genTryStmt") - if orExpr != nil: orExpr.add("||") + if orExpr != "": orExpr.add("||") # Generate the correct type checking code depending on whether this is a # NIM-native or a JS-native exception # if isJsObject(throwObj.typ): @@ -907,7 +905,7 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = gen(p, e[1], b) if j != itLen - 2: lineF(p, "$1 >= $2 && $1 <= $3 || $n", [cond.rdLoc, a.rdLoc, b.rdLoc]) - else: + else: lineF(p, "$1 >= $2 && $1 <= $3", [cond.rdLoc, a.rdLoc, b.rdLoc]) else: var v = copyNode(e[0]) @@ -998,7 +996,7 @@ proc genBreakStmt(p: PProc, n: PNode) = proc genAsmOrEmitStmt(p: PProc, n: PNode) = genLineDir(p, n) - p.body.add p.indentLine(nil) + p.body.add p.indentLine("") for i in 0..<n.len: let it = n[i] case it.kind @@ -1016,12 +1014,12 @@ proc genAsmOrEmitStmt(p: PProc, n: PNode) = if it.typ.kind == tyPointer: # A fat pointer is disguised as an array r.res = r.address - r.address = nil + r.address = "" r.typ = etyNone elif r.typ == etyBaseIndex: # Deference first r.res = "$1[$2]" % [r.address, r.res] - r.address = nil + r.address = "" r.typ = etyNone p.body.add(r.rdLoc) @@ -1055,12 +1053,12 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) = line(p, repeat('}', toClose) & "\L") proc generateHeader(p: PProc, typ: PType): Rope = - result = nil + result = "" for i in 1..<typ.n.len: assert(typ.n[i].kind == nkSym) var param = typ.n[i].sym if isCompileTimeOnly(param.typ): continue - if result != nil: result.add(", ") + if result != "": result.add(", ") var name = mangleName(p.module, param) result.add(name) if mapType(param.typ) == etyBaseIndex: @@ -1135,7 +1133,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = elif b.typ == etyBaseIndex: lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res]) elif b.typ == etyNone: - internalAssert p.config, b.address == nil + internalAssert p.config, b.address == "" lineF(p, "$# = [$#, 0];$n", [a.address, b.res]) elif x.typ.kind == tyVar and y.typ.kind == tyPtr: lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res]) @@ -1143,13 +1141,13 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc]) elif a.typ == etyBaseIndex: # array indexing may not map to var type - if b.address != nil: + if b.address != "": lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res]) else: lineF(p, "$1 = $2;$n", [a.address, b.res]) else: internalError(p.config, x.info, $("genAsgn", b.typ, a.typ)) - elif b.address != nil: + elif b.address != "": lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res]) else: lineF(p, "$1 = $2;$n", [a.address, b.res]) @@ -1201,7 +1199,7 @@ proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) = else: if b[1].kind != nkSym: internalError(p.config, b[1].info, "genFieldAddr") var f = b[1].sym - if f.loc.r == nil: f.loc.r = mangleName(p.module, f) + if f.loc.r == "": f.loc.r = mangleName(p.module, f) r.res = makeJSString($f.loc.r) internalAssert p.config, a.typ != etyBaseIndex r.address = a.res @@ -1229,7 +1227,7 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) = else: if n[1].kind != nkSym: internalError(p.config, n[1].info, "genFieldAccess") var f = n[1].sym - if f.loc.r == nil: f.loc.r = mangleName(p.module, f) + if f.loc.r == "": f.loc.r = mangleName(p.module, f) r.res = "$1.$2" % [r.res, f.loc.r] mkTemp(1) r.kind = resExpr @@ -1250,11 +1248,11 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) = # Field symbol var field = accessExpr[1].sym internalAssert p.config, field.kind == skField - if field.loc.r == nil: field.loc.r = mangleName(p.module, field) + if field.loc.r == "": field.loc.r = mangleName(p.module, field) # Discriminant symbol let disc = checkExpr[2].sym internalAssert p.config, disc.kind == skField - if disc.loc.r == nil: disc.loc.r = mangleName(p.module, disc) + if disc.loc.r == "": disc.loc.r = mangleName(p.module, disc) var setx: TCompRes gen(p, checkExpr[1], setx) @@ -1271,7 +1269,7 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) = useMagic(p, "reprDiscriminant") # no need to offset by firstOrd unlike for cgen let msg = genFieldDefect(p.config, field.name.s, disc) lineF(p, "if ($1[$2.$3]$4undefined) { raiseFieldError2(makeNimstrLit($5), reprDiscriminant($2.$3, $6)); }$n", - setx.res, tmp, disc.loc.r, if negCheck: ~"!==" else: ~"===", + setx.res, tmp, disc.loc.r, if negCheck: "!==" else: "===", makeJSString(msg), genTypeInfo(p, disc.typ)) if addrTyp != nil and mapType(p, addrTyp) == etyBaseIndex: @@ -1320,7 +1318,7 @@ proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) = genFieldAddr(p, n, r) else: internalError(p.config, n.info, "expr(nkBracketExpr, " & $ty.kind & ')') r.typ = mapType(n.typ) - if r.res == nil: internalError(p.config, n.info, "genArrayAccess") + if r.res == "": internalError(p.config, n.info, "genArrayAccess") if ty.kind == tyCstring: r.res = "$1.charCodeAt($2)" % [r.address, r.res] elif r.typ == etyBaseIndex: @@ -1347,11 +1345,11 @@ template isIndirect(x: PSym): bool = proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) = let s = n.sym - if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3") + if s.loc.r == "": internalError(p.config, n.info, "genAddr: 3") case s.kind of skParam: r.res = s.loc.r - r.address = nil + r.address = "" r.typ = etyNone of skVar, skLet, skResult: r.kind = resExpr @@ -1367,7 +1365,7 @@ proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) = r.res = s.loc.r & "[0]" else: r.res = s.loc.r - r.address = nil + r.address = "" elif {sfGlobal, sfAddrTaken} * s.flags != {} or jsType == etyBaseIndex: # for ease of code generation, we do not distinguish between # sfAddrTaken and sfGlobal. @@ -1466,7 +1464,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) = var s = n.sym case s.kind of skVar, skLet, skParam, skTemp, skResult, skForVar: - if s.loc.r == nil: + if s.loc.r == "": internalError(p.config, n.info, "symbol has no generated name: " & s.name.s) if sfCompileTime in s.flags: genVarInit(p, s, if s.ast != nil: s.ast else: newNodeI(nkEmpty, s.info)) @@ -1491,7 +1489,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) = r.res = s.loc.r of skConst: genConstant(p, s) - if s.loc.r == nil: + if s.loc.r == "": internalError(p.config, n.info, "symbol has no generated name: " & s.name.s) r.res = s.loc.r of skProc, skFunc, skConverter, skMethod: @@ -1511,7 +1509,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) = else: genProcForSymIfNeeded(p, s) else: - if s.loc.r == nil: + if s.loc.r == "": internalError(p.config, n.info, "symbol has no generated name: " & s.name.s) if mapType(p, s.typ) == etyBaseIndex: r.address = s.loc.r @@ -1536,7 +1534,7 @@ proc genDeref(p: PProc, n: PNode, r: var TCompRes) = r.res = "$1[1]" % [tmp] r.tmpLoc = tmp elif a.typ == etyBaseIndex: - if a.tmpLoc != nil: + if a.tmpLoc != "": r.tmpLoc = a.tmpLoc r.res = a.rdLoc else: @@ -1659,9 +1657,9 @@ proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType; proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) = # don't call '$' here for efficiency: let f = n[0].sym - if f.loc.r == nil: f.loc.r = mangleName(p.module, f) + if f.loc.r == "": f.loc.r = mangleName(p.module, f) if sfInfixCall in f.flags: - let pat = n[0].sym.loc.r.data + let pat = $n[0].sym.loc.r internalAssert p.config, pat.len > 0 if pat.contains({'#', '(', '@'}): var typ = skipTypes(n[0].typ, abstractInst) @@ -1671,10 +1669,10 @@ proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) = if n.len != 1: gen(p, n[1], r) if r.typ == etyBaseIndex: - if r.address == nil: + if r.address == "": globalError(p.config, n.info, "cannot invoke with infix syntax") r.res = "$1[$2]" % [r.address, r.res] - r.address = nil + r.address = "" r.typ = etyNone r.res.add(".") var op: TCompRes @@ -1826,12 +1824,12 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = result = createVar(p, lastSon t, indirect) else: internalError(p.config, "createVar: " & $t.kind) - result = nil + result = "" else: internalError(p.config, "createVar: " & $t.kind) - result = nil + result = "" -template returnType: untyped = ~"" +template returnType: untyped = "" proc genVarInit(p: PProc, v: PSym, n: PNode) = var @@ -1929,8 +1927,7 @@ proc genVarStmt(p: PProc, n: PNode) = proc genConstant(p: PProc, c: PSym) = if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id): - let oldBody = p.body - p.body = nil + let oldBody = move p.body #genLineDir(p, c.ast) genVarInit(p, c, c.ast) p.g.constants.add(p.body) @@ -1984,7 +1981,7 @@ proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) = else: r.res.add("$1 || [])" % [a.res]) -proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope = nil) = +proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope = "") = useMagic(p, magic) r.res.add(magic & "(") var a: TCompRes @@ -1993,7 +1990,7 @@ proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope = if magic == "reprAny": # the pointer argument in reprAny is expandend to # (pointedto, pointer), so we need to fill it - if a.address.isNil: + if a.address.len == 0: r.res.add(a.res) r.res.add(", null") else: @@ -2001,14 +1998,14 @@ proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope = else: r.res.add(a.res) - if not typ.isNil: + if typ != "": r.res.add(", ") r.res.add(typ) r.res.add(")") proc genRepr(p: PProc, n: PNode, r: var TCompRes) = let t = skipTypes(n[1].typ, abstractVarRange) - case t.kind: + case t.kind of tyInt..tyInt64, tyUInt..tyUInt64: genReprAux(p, n, r, "reprInt") of tyChar: @@ -2327,7 +2324,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = let val = it[1] gen(p, val, a) var f = it[0].sym - if f.loc.r == nil: f.loc.r = mangleName(p.module, f) + if f.loc.r == "": f.loc.r = mangleName(p.module, f) fieldIDs.incl(lookupFieldAgain(nTyp, f).id) let typ = val.typ.skipTypes(abstractInst) @@ -2388,7 +2385,7 @@ proc convStrToCStr(p: PProc, n: PNode, r: var TCompRes) = gen(p, n[0][0], r) else: gen(p, n[0], r) - if r.res == nil: internalError(p.config, n.info, "convStrToCStr") + if r.res == "": internalError(p.config, n.info, "convStrToCStr") useMagic(p, "toJSStr") r.res = "toJSStr($1)" % [r.res] r.kind = resExpr @@ -2400,7 +2397,7 @@ proc convCStrToStr(p: PProc, n: PNode, r: var TCompRes) = gen(p, n[0][0], r) else: gen(p, n[0], r) - if r.res == nil: internalError(p.config, n.info, "convCStrToStr") + if r.res == "": internalError(p.config, n.info, "convCStrToStr") useMagic(p, "cstrToNimstr") r.res = "cstrToNimstr($1)" % [r.res] r.kind = resExpr @@ -2430,11 +2427,11 @@ proc genProcBody(p: PProc, prc: PSym): Rope = makeJSString(prc.owner.name.s & '.' & prc.name.s), makeJSString(toFilenameOption(p.config, prc.info.fileIndex, foStacktrace))) else: - result = nil + result = "" if p.beforeRetNeeded: - result.add p.indentLine(~"BeforeRet: {$n") + result.add p.indentLine("BeforeRet: {\n") result.add p.body - result.add p.indentLine(~"};$n") + result.add p.indentLine("};\n") else: result.add(p.body) if prc.typ.callConv == ccSysCall: @@ -2444,8 +2441,8 @@ proc genProcBody(p: PProc, prc: PSym): Rope = result.add(frameDestroy(p)) proc optionalLine(p: Rope): Rope = - if p == nil: - return nil + if p == "": + return "" else: return p & "\L" @@ -2458,8 +2455,8 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = # echo "BEGIN generating code for: " & prc.name.s var p = newProc(oldProc.g, oldProc.module, prc.ast, prc.options) p.up = oldProc - var returnStmt: Rope = nil - var resultAsgn: Rope = nil + var returnStmt: Rope = "" + var resultAsgn: Rope = "" var name = mangleName(p.module, prc) let header = generateHeader(p, prc.typ) if prc.typ[0] != nil and sfPure notin prc.flags: @@ -2503,7 +2500,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = optionalLine(p.indentLine(returnStmt))]) else: # if optLineDir in p.config.options: - # result.add(~"\L") + # result.add("\L") if p.config.hcrOn: # Here, we introduce thunks that create the equivalent of a jump table @@ -2526,7 +2523,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = dec p.extraIndent result.add p.indentLine(def) - result.add p.indentLine(~"}$n") + result.add p.indentLine("}\n") #if gVerbosity >= 3: # echo "END generated code for: " & prc.name.s @@ -2534,7 +2531,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = proc genStmt(p: PProc, n: PNode) = var r: TCompRes gen(p, n, r) - if r.res != nil: lineF(p, "$#;$n", [r.res]) + if r.res != "": lineF(p, "$#;$n", [r.res]) proc genPragma(p: PProc, n: PNode) = for it in n.sons: @@ -2574,7 +2571,7 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) = r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer] elif (src.kind == tyPtr and mapType(p, src) == etyObject) and dest.kind == tyPointer: r.address = r.res - r.res = ~"null" + r.res = "null" r.typ = etyBaseIndex elif (dest.kind == tyPtr and mapType(p, dest) == etyObject) and src.kind == tyPointer: r.res = r.address @@ -2583,8 +2580,8 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) = proc gen(p: PProc, n: PNode, r: var TCompRes) = r.typ = etyNone if r.kind != resCallee: r.kind = resNone - #r.address = nil - r.res = nil + #r.address = "" + r.res = "" case n.kind of nkSym: @@ -2723,7 +2720,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = var s = n[namePos].sym if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}: genSym(p, n[namePos], r) - r.res = nil + r.res = "" of nkGotoState, nkState: globalError(p.config, n.info, "First class iterators not implemented") of nkPragmaBlock: gen(p, n.lastSon, r) @@ -2840,7 +2837,7 @@ proc getClassName(t: PType): Rope = s = skipTypes(t, abstractPtrs).sym if s.isNil or sfAnon in s.flags: doAssert(false, "cannot retrieve class name") - if s.loc.r != nil: result = s.loc.r + if s.loc.r != "": result = s.loc.r else: result = rope(s.name.s) proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode = |