diff options
Diffstat (limited to 'compiler/jsgen.nim')
-rw-r--r-- | compiler/jsgen.nim | 263 |
1 files changed, 143 insertions, 120 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 6c667a3a7..6e317fb7e 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -30,8 +30,8 @@ implements the required case distinction. import - ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, - options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os, + ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, + nversion, nimsets, msgs, securehash, bitsets, idents, lists, types, os, times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils, intsets, cgmeth, lowerings @@ -124,7 +124,7 @@ proc newProc(globals: PGlobals, module: BModule, procDef: PNode, const MappedToObject = {tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, - tySet, tyVar, tyRef, tyPtr, tyBigNum, tyVarargs} + tySet, tyBigNum, tyVarargs} proc mapType(typ: PType): TJSTypeKind = let t = skipTypes(typ, abstractInst) @@ -163,7 +163,8 @@ proc mangleName(s: PSym): Rope = add(result, rope(s.id)) s.loc.r = result -proc makeJSString(s: string): Rope = strutils.escape(s).rope +proc makeJSString(s: string): Rope = + (if s.isNil: "null".rope else: strutils.escape(s).rope) include jstypes @@ -257,11 +258,6 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI ["divInt", "", "divInt($1, $2)", "Math.floor($1 / $2)"], # DivI ["modInt", "", "modInt($1, $2)", "Math.floor($1 % $2)"], # ModI - ["addInt64", "", "addInt64($1, $2)", "($1 + $2)"], # AddI64 - ["subInt64", "", "subInt64($1, $2)", "($1 - $2)"], # SubI64 - ["mulInt64", "", "mulInt64($1, $2)", "($1 * $2)"], # MulI64 - ["divInt64", "", "divInt64($1, $2)", "Math.floor($1 / $2)"], # DivI64 - ["modInt64", "", "modInt64($1, $2)", "Math.floor($1 % $2)"], # ModI64 ["addInt", "", "addInt($1, $2)", "($1 + $2)"], # Succ ["subInt", "", "subInt($1, $2)", "($1 - $2)"], # Pred ["", "", "($1 + $2)", "($1 + $2)"], # AddF64 @@ -275,13 +271,6 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI - ["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI64 - ["", "", "($1 << $2)", "($1 << $2)"], # ShlI64 - ["", "", "($1 & $2)", "($1 & $2)"], # BitandI64 - ["", "", "($1 | $2)", "($1 | $2)"], # BitorI64 - ["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI64 - ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI64 - ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI64 ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64 ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64 ["addU", "addU", "addU($1, $2)", "addU($1, $2)"], # addU @@ -292,9 +281,6 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["", "", "($1 == $2)", "($1 == $2)"], # EqI ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI ["", "", "($1 < $2)", "($1 < $2)"], # LtI - ["", "", "($1 == $2)", "($1 == $2)"], # EqI64 - ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI64 - ["", "", "($1 < $2)", "($1 < $2)"], # LtI64 ["", "", "($1 == $2)", "($1 == $2)"], # EqF64 ["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64 ["", "", "($1 < $2)", "($1 < $2)"], # LtF64 @@ -321,12 +307,9 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["negInt", "", "negInt($1)", "-($1)"], # UnaryMinusI ["negInt64", "", "negInt64($1)", "-($1)"], # UnaryMinusI64 ["absInt", "", "absInt($1)", "Math.abs($1)"], # AbsI - ["absInt64", "", "absInt64($1)", "Math.abs($1)"], # AbsI64 ["", "", "!($1)", "!($1)"], # Not ["", "", "+($1)", "+($1)"], # UnaryPlusI ["", "", "~($1)", "~($1)"], # BitnotI - ["", "", "+($1)", "+($1)"], # UnaryPlusI64 - ["", "", "~($1)", "~($1)"], # BitnotI64 ["", "", "+($1)", "+($1)"], # UnaryPlusF64 ["", "", "-($1)", "-($1)"], # UnaryMinusF64 ["", "", "Math.abs($1)", "Math.abs($1)"], # AbsF64 @@ -359,11 +342,6 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI ["divInt", "", "divInt($1, $2)", "Math.floor($1 / $2)"], # DivI ["modInt", "", "modInt($1, $2)", "Math.floor($1 % $2)"], # ModI - ["addInt64", "", "addInt64($1, $2)", "($1 + $2)"], # AddI64 - ["subInt64", "", "subInt64($1, $2)", "($1 - $2)"], # SubI64 - ["mulInt64", "", "mulInt64($1, $2)", "($1 * $2)"], # MulI64 - ["divInt64", "", "divInt64($1, $2)", "Math.floor($1 / $2)"], # DivI64 - ["modInt64", "", "modInt64($1, $2)", "Math.floor($1 % $2)"], # ModI64 ["addInt", "", "addInt($1, $2)", "($1 + $2)"], # Succ ["subInt", "", "subInt($1, $2)", "($1 - $2)"], # Pred ["", "", "($1 + $2)", "($1 + $2)"], # AddF64 @@ -377,13 +355,6 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI - ["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI64 - ["", "", "($1 << $2)", "($1 << $2)"], # ShlI64 - ["", "", "($1 & $2)", "($1 & $2)"], # BitandI64 - ["", "", "($1 | $2)", "($1 | $2)"], # BitorI64 - ["", "", "($1 ^ $2)", "($1 ^ $2)"], # BitxorI64 - ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinI64 - ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxI64 ["nimMin", "nimMin", "nimMin($1, $2)", "nimMin($1, $2)"], # MinF64 ["nimMax", "nimMax", "nimMax($1, $2)", "nimMax($1, $2)"], # MaxF64 ["addU", "addU", "addU($1, $2)", "addU($1, $2)"], # addU @@ -394,9 +365,6 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["", "", "($1 == $2)", "($1 == $2)"], # EqI ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI ["", "", "($1 < $2)", "($1 < $2)"], # LtI - ["", "", "($1 == $2)", "($1 == $2)"], # EqI64 - ["", "", "($1 <= $2)", "($1 <= $2)"], # LeI64 - ["", "", "($1 < $2)", "($1 < $2)"], # LtI64 ["", "", "($1 == $2)", "($1 == $2)"], # EqF64 ["", "", "($1 <= $2)", "($1 <= $2)"], # LeF64 ["", "", "($1 < $2)", "($1 < $2)"], # LtF64 @@ -423,12 +391,9 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["negInt", "", "negInt($1)", "-($1)"], # UnaryMinusI ["negInt64", "", "negInt64($1)", "-($1)"], # UnaryMinusI64 ["absInt", "", "absInt($1)", "Math.abs($1)"], # AbsI - ["absInt64", "", "absInt64($1)", "Math.abs($1)"], # AbsI64 ["", "", "not ($1)", "not ($1)"], # Not ["", "", "+($1)", "+($1)"], # UnaryPlusI ["", "", "~($1)", "~($1)"], # BitnotI - ["", "", "+($1)", "+($1)"], # UnaryPlusI64 - ["", "", "~($1)", "~($1)"], # BitnotI64 ["", "", "+($1)", "+($1)"], # UnaryPlusF64 ["", "", "-($1)", "-($1)"], # UnaryMinusF64 ["", "", "Math.abs($1)", "Math.abs($1)"], # AbsF64 @@ -540,12 +505,12 @@ proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) = proc genTry(p: PProc, n: PNode, r: var TCompRes) = # code to generate: # - # var sp = {prev: excHandler, exc: null}; - # excHandler = sp; + # ++excHandler; # try { # stmts; - # TMP = e - # } catch (e) { + # } catch (EXC) { + # var prevJSError = lastJSError; lastJSError = EXC; + # --excHandler; # if (e.typ && e.typ == NTI433 || e.typ == NTI2321) { # stmts; # } else if (e.typ && e.typ == NTI32342) { @@ -553,35 +518,41 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = # } else { # stmts; # } + # lastJSError = prevJSError; # } finally { # stmts; - # excHandler = excHandler.prev; # } genLineDir(p, n) if not isEmptyType(n.typ): r.kind = resVal r.res = getTemp(p) inc(p.unique) + var i = 1 + var length = sonsLen(n) + var catchBranchesExist = length > 1 and n.sons[i].kind == nkExceptBranch + if catchBranchesExist: + add(p.body, "++excHandler;" & tnl) var safePoint = "Tmp$1" % [rope(p.unique)] addf(p.body, - "var $1 = {prev: excHandler, exc: null};$nexcHandler = $1;$n" | + "" | "local $1 = pcall(", [safePoint]) if optStackTrace in p.options: add(p.body, "framePtr = F;" & tnl) addf(p.body, "try {$n" | "function()$n", []) - var length = sonsLen(n) var a: TCompRes gen(p, n.sons[0], a) moveInto(p, a, r) - var i = 1 - if p.target == targetJS and length > 1 and n.sons[i].kind == nkExceptBranch: - addf(p.body, "} catch (EXC) {$n lastJSError = EXC;$n", []) + var generalCatchBranchExists = false + if p.target == targetJS and catchBranchesExist: + addf(p.body, "} catch (EXC) {$n var prevJSError = lastJSError;$n" & + " lastJSError = EXC;$n --excHandler;$n", []) elif p.target == targetLua: addf(p.body, "end)$n", []) while i < length and n.sons[i].kind == nkExceptBranch: let blen = sonsLen(n.sons[i]) if blen == 1: # general except section: + generalCatchBranchExists = true if i > 1: addf(p.body, "else {$n" | "else$n", []) gen(p, n.sons[i].sons[0], a) moveInto(p, a, r) @@ -593,17 +564,22 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = if n.sons[i].sons[j].kind != nkType: internalError(n.info, "genTryStmt") if orExpr != nil: add(orExpr, "||" | " or ") - addf(orExpr, "isObj($1.exc.m_type, $2)", - [safePoint, genTypeInfo(p, n.sons[i].sons[j].typ)]) + addf(orExpr, "isObj(lastJSError.m_type, $1)", + [genTypeInfo(p, n.sons[i].sons[j].typ)]) if i > 1: add(p.body, "else ") - addf(p.body, "if ($1.exc && ($2)) {$n" | "if $1.exc and ($2) then$n", + addf(p.body, "if (lastJSError && ($2)) {$n" | "if $1.exc and ($2) then$n", [safePoint, orExpr]) gen(p, n.sons[i].sons[blen - 1], a) moveInto(p, a, r) addf(p.body, "}$n" | "end$n", []) inc(i) if p.target == targetJS: - add(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl) + if catchBranchesExist: + if not generalCatchBranchExists: + useMagic(p, "reraiseException") + add(p.body, "else {" & tnl & "reraiseException();" & tnl & "}" & tnl) + add(p.body, "lastJSError = prevJSError;" & tnl) + add(p.body, "} finally {" & tnl) if i < length and n.sons[i].kind == nkFinally: genStmt(p, n.sons[i].sons[0]) if p.target == targetJS: @@ -822,7 +798,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = addf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc]) else: useMagic(p, "nimCopy") - addf(p.body, "$1 = nimCopy($2, $3);$n", + addf(p.body, "$1 = nimCopy($1, $2, $3);$n", [a.res, b.res, genTypeInfo(p, y.typ)]) of etyBaseIndex: if a.typ != etyBaseIndex or b.typ != etyBaseIndex: @@ -885,7 +861,7 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) = if skipTypes(n.sons[0].typ, abstractVarRange).kind == tyTuple: r.res = "$1.Field$2" % [r.res, getFieldPosition(n.sons[1]).rope] else: - if n.sons[1].kind != nkSym: internalError(n.sons[1].info, "genFieldAddr") + if n.sons[1].kind != nkSym: internalError(n.sons[1].info, "genFieldAccess") var f = n.sons[1].sym if f.loc.r == nil: f.loc.r = mangleName(f) r.res = "$1.$2" % [r.res, f.loc.r] @@ -937,6 +913,13 @@ proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) = r.address = nil r.kind = resExpr +proc isIndirect(v: PSym): bool = + result = {sfAddrTaken, sfGlobal} * v.flags != {} and + #(mapType(v.typ) != etyObject) and + {sfImportc, sfVolatile, sfExportc} * v.flags == {} and + v.kind notin {skProc, skConverter, skMethod, skIterator, skClosureIterator, + skConst, skTemp, skLet} + proc genAddr(p: PProc, n: PNode, r: var TCompRes) = case n.sons[0].kind of nkSym: @@ -945,12 +928,16 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) = case s.kind of skVar, skLet, skResult: r.kind = resExpr - if mapType(n.sons[0].typ) == etyObject: + let jsType = mapType(n.typ) + if jsType == etyObject: # make addr() a no-op: r.typ = etyNone - r.res = s.loc.r + if isIndirect(s): + r.res = s.loc.r & "[0]" + else: + r.res = s.loc.r r.address = nil - elif {sfGlobal, sfAddrTaken} * s.flags != {}: + elif {sfGlobal, sfAddrTaken} * s.flags != {} or jsType == etyBaseIndex: # for ease of code generation, we do not distinguish between # sfAddrTaken and sfGlobal. r.typ = etyBaseIndex @@ -964,18 +951,35 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) = of nkCheckedFieldExpr: genCheckedFieldAddr(p, n, r) of nkDotExpr: - genFieldAddr(p, n.sons[0], r) + if mapType(n.typ) == etyBaseIndex: + genFieldAddr(p, n.sons[0], r) + else: + genFieldAccess(p, n.sons[0], r) of nkBracketExpr: var ty = skipTypes(n.sons[0].typ, abstractVarRange) - if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange) - case ty.kind - of tyArray, tyArrayConstr, tyOpenArray, tySequence, tyString, tyCString, - tyVarargs, tyChar: - genArrayAddr(p, n.sons[0], r) - of tyTuple: - genFieldAddr(p, n.sons[0], r) - else: internalError(n.sons[0].info, "expr(nkBracketExpr, " & $ty.kind & ')') - else: internalError(n.sons[0].info, "genAddr") + if ty.kind in MappedToObject: + gen(p, n.sons[0], r) + else: + let kindOfIndexedExpr = skipTypes(n.sons[0].sons[0].typ, abstractVarRange).kind + case kindOfIndexedExpr + of tyArray, tyArrayConstr, tyOpenArray, tySequence, tyString, tyCString, + tyVarargs: + genArrayAddr(p, n.sons[0], r) + of tyTuple: + genFieldAddr(p, n.sons[0], r) + else: internalError(n.sons[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')') + of nkObjDownConv: + gen(p, n.sons[0], r) + else: internalError(n.sons[0].info, "genAddr: " & $n.sons[0].kind) + +proc genProcForSymIfNeeded(p: PProc, s: PSym) = + if not p.g.generatedSyms.containsOrIncl(s.id): + let newp = genProc(p, s) + var owner = p + while owner != nil and owner.prc != s.owner: + owner = owner.up + if owner != nil: add(owner.locals, newp) + else: add(p.g.code, newp) proc genSym(p: PProc, n: PNode, r: var TCompRes) = var s = n.sym @@ -992,7 +996,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) = else: r.address = s.loc.r r.res = s.loc.r & "_Idx" - elif k != etyObject and {sfAddrTaken, sfGlobal} * s.flags != {}: + elif isIndirect(s): r.res = "$1[0]" % [s.loc.r] else: r.res = s.loc.r @@ -1012,13 +1016,8 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) = discard elif sfForward in s.flags: p.g.forwarded.add(s) - elif not p.g.generatedSyms.containsOrIncl(s.id): - let newp = genProc(p, s) - var owner = p - while owner != nil and owner.prc != s.owner: - owner = owner.up - if owner != nil: add(owner.locals, newp) - else: add(p.g.code, newp) + else: + genProcForSymIfNeeded(p, s) else: if s.loc.r == nil: internalError(n.info, "symbol has no generated name: " & s.name.s) @@ -1046,11 +1045,22 @@ proc genArg(p: PProc, n: PNode, r: var TCompRes) = proc genArgs(p: PProc, n: PNode, r: var TCompRes) = add(r.res, "(") + var hasArgs = false + + var typ = skipTypes(n.sons[0].typ, abstractInst) + assert(typ.kind == tyProc) + assert(sonsLen(typ) == sonsLen(typ.n)) + for i in countup(1, sonsLen(n) - 1): let it = n.sons[i] - if it.typ.isCompileTimeOnly: continue - if i > 1: add(r.res, ", ") + if i < sonsLen(typ): + assert(typ.n.sons[i].kind == nkSym) + let paramType = typ.n.sons[i] + if paramType.typ.isCompileTimeOnly: continue + + if hasArgs: add(r.res, ", ") genArg(p, it, r) + hasArgs = true add(r.res, ")") r.kind = resExpr @@ -1079,6 +1089,7 @@ proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) = r.kind = resExpr proc genEcho(p: PProc, n: PNode, r: var TCompRes) = + useMagic(p, "toJSStr") # Used in rawEcho useMagic(p, "rawEcho") add(r.res, "rawEcho(") let n = n[1].skipConv @@ -1096,24 +1107,32 @@ proc putToSeq(s: string, indirect: bool): Rope = if indirect: result = "[$1]" % [result] proc createVar(p: PProc, typ: PType, indirect: bool): Rope -proc createRecordVarAux(p: PProc, rec: PNode, c: var int): Rope = - result = nil +proc createRecordVarAux(p: PProc, rec: PNode, excludedFieldIDs: IntSet, output: var Rope) = case rec.kind of nkRecList: for i in countup(0, sonsLen(rec) - 1): - add(result, createRecordVarAux(p, rec.sons[i], c)) + createRecordVarAux(p, rec.sons[i], excludedFieldIDs, output) of nkRecCase: - add(result, createRecordVarAux(p, rec.sons[0], c)) + createRecordVarAux(p, rec.sons[0], excludedFieldIDs, output) for i in countup(1, sonsLen(rec) - 1): - add(result, createRecordVarAux(p, lastSon(rec.sons[i]), c)) + createRecordVarAux(p, lastSon(rec.sons[i]), excludedFieldIDs, output) of nkSym: - if c > 0: add(result, ", ") - add(result, mangleName(rec.sym)) - add(result, ": ") - add(result, createVar(p, rec.sym.typ, false)) - inc(c) + if rec.sym.id notin excludedFieldIDs: + if output.len > 0: output.add(", ") + output.add(mangleName(rec.sym)) + output.add(": ") + output.add(createVar(p, rec.sym.typ, false)) else: internalError(rec.info, "createRecordVarAux") +proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: var Rope) = + var t = typ + if tfFinal notin t.flags or t.sons[0] != nil: + if output.len > 0: output.add(", ") + addf(output, "m_type: $1" | "m_type = $#", [genTypeInfo(p, t)]) + while t != nil: + createRecordVarAux(p, t.n, excludedFieldIDs, output) + t = t.sons[0] + proc createVar(p: PProc, typ: PType, indirect: bool): Rope = var t = skipTypes(typ, abstractInst) case t.kind @@ -1124,7 +1143,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = of tyRange, tyGenericInst: result = createVar(p, lastSon(typ), indirect) of tySet: - result = rope("{}") + result = putToSeq("{}", indirect) of tyBool: result = putToSeq("false", indirect) of tyArray, tyArrayConstr: @@ -1144,6 +1163,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = add(result, createVar(p, e, false)) inc(i) add(result, "]") + if indirect: result = "[$1]" % [result] of tyTuple: result = rope("{") for i in 0.. <t.sonsLen: @@ -1151,16 +1171,12 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = addf(result, "Field$1: $2" | "Field$# = $#", [i.rope, createVar(p, t.sons[i], false)]) add(result, "}") + if indirect: result = "[$1]" % [result] of tyObject: - result = rope("{") - var c = 0 - if tfFinal notin t.flags or t.sons[0] != nil: - inc(c) - addf(result, "m_type: $1" | "m_type = $#", [genTypeInfo(p, t)]) - while t != nil: - add(result, createRecordVarAux(p, t.n, c)) - t = t.sons[0] - add(result, "}") + var initList : Rope + createObjInitList(p, t, initIntSet(), initList) + result = "{$1}" % [initList] + if indirect: result = "[$1]" % [result] of tyVar, tyPtr, tyRef: if mapType(t) == etyBaseIndex: result = putToSeq("[null, 0]" | "{nil, 0}", indirect) @@ -1172,11 +1188,6 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = internalError("createVar: " & $t.kind) result = nil -proc isIndirect(v: PSym): bool = - result = {sfAddrTaken, sfGlobal} * v.flags != {} and - (mapType(v.typ) != etyObject) and - v.kind notin {skProc, skConverter, skMethod, skIterator, skClosureIterator} - proc genVarInit(p: PProc, v: PSym, n: PNode) = var a: TCompRes @@ -1193,7 +1204,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = s = a.res else: useMagic(p, "nimCopy") - s = "nimCopy($1, $2)" % [a.res, genTypeInfo(p, n.typ)] + s = "nimCopy(null, $1, $2)" % [a.res, genTypeInfo(p, n.typ)] of etyBaseIndex: if (a.typ != etyBaseIndex): internalError(n.info, "genVarInit") if {sfAddrTaken, sfGlobal} * v.flags != {}: @@ -1207,7 +1218,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = else: s = a.res if isIndirect(v): - addf(p.body, "var $1 = [$2];$n" | "local $1 = {$2};$n", [v.loc.r, s]) + addf(p.body, "var $1 = /**/[$2];$n" | "local $1 = {$2};$n", [v.loc.r, s]) else: addf(p.body, "var $1 = $2;$n" | "local $1 = $2;$n", [v.loc.r, s]) @@ -1239,7 +1250,7 @@ proc genNew(p: PProc, n: PNode) = var a: TCompRes gen(p, n.sons[1], a) var t = skipTypes(n.sons[1].typ, abstractVar).sons[0] - addf(p.body, "$1 = $2;$n", [a.res, createVar(p, t, true)]) + addf(p.body, "$1 = $2;$n", [a.res, createVar(p, t, false)]) proc genNewSeq(p: PProc, n: PNode) = var x, y: TCompRes @@ -1325,14 +1336,17 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = # XXX: range checking? if not (optOverflowCheck in p.options): unaryExpr(p, n, r, "", "$1 - 1") else: unaryExpr(p, n, r, "subInt", "subInt($1, 1)") - of mAppendStrCh: binaryExpr(p, n, r, "addChar", "addChar($1, $2)") + of mAppendStrCh: binaryExpr(p, n, r, "addChar", + "if ($1 != null) { addChar($1, $2); } else { $1 = [$2, 0]; }") of mAppendStrStr: if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyCString: - binaryExpr(p, n, r, "", "$1 += $2") + binaryExpr(p, n, r, "", "if ($1 != null) { $1 += $2; } else { $1 = $2; }") else: - binaryExpr(p, n, r, "", "$1 = ($1.slice(0, -1)).concat($2)") + binaryExpr(p, n, r, "", + "if ($1 != null) { $1 = ($1.slice(0, -1)).concat($2); } else { $1 = $2;}") # XXX: make a copy of $2, because of Javascript's sucking semantics - of mAppendSeqElem: binaryExpr(p, n, r, "", "$1.push($2)") + of mAppendSeqElem: binaryExpr(p, n, r, "", + "if ($1 != null) { $1.push($2); } else { $1 = [$2]; }") of mConStrStr: genConStrStr(p, n, r) of mEqStr: binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)") of mLeStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) <= 0)") @@ -1343,14 +1357,17 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mSizeOf: r.res = rope(getSize(n.sons[1].typ)) of mChr, mArrToSeq: gen(p, n.sons[1], r) # nothing to do of mOrd: genOrd(p, n, r) - of mLengthStr: unaryExpr(p, n, r, "", "($1.length-1)") + of mLengthStr: unaryExpr(p, n, r, "", "($1 != null ? $1.length-1 : 0)") + of mXLenStr: unaryExpr(p, n, r, "", "$1.length-1") of mLengthSeq, mLengthOpenArray, mLengthArray: + unaryExpr(p, n, r, "", "($1 != null ? $1.length : 0)") + of mXLenSeq: unaryExpr(p, n, r, "", "$1.length") of mHigh: if skipTypes(n.sons[1].typ, abstractVar).kind == tyString: - unaryExpr(p, n, r, "", "($1.length-2)") + unaryExpr(p, n, r, "", "($1 != null ? ($1.length-2) : -1)") else: - unaryExpr(p, n, r, "", "($1.length-1)") + unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)") of mInc: if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2") else: binaryExpr(p, n, r, "addInt", "$1 = addInt($1, $2)") @@ -1379,6 +1396,9 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mCopyStrLast: ternaryExpr(p, n, r, "", "($1.slice($2, ($3)+1).concat(0))") of mNewString: unaryExpr(p, n, r, "mnewString", "mnewString($1)") of mNewStringOfCap: unaryExpr(p, n, r, "mnewString", "mnewString(0)") + of mDotDot: + genProcForSymIfNeeded(p, n.sons[0].sym) + genCall(p, n, r) else: genCall(p, n, r) #else internalError(e.info, 'genMagic: ' + magicToStr[op]); @@ -1424,19 +1444,22 @@ proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) = r.res.add("}") proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = - # XXX inheritance? var a: TCompRes - r.res = rope("{") r.kind = resExpr + var initList : Rope + var fieldIDs = initIntSet() for i in countup(1, sonsLen(n) - 1): - if i > 1: add(r.res, ", ") + if i > 1: add(initList, ", ") var it = n.sons[i] internalAssert it.kind == nkExprColonExpr gen(p, it.sons[1], a) var f = it.sons[0].sym if f.loc.r == nil: f.loc.r = mangleName(f) - addf(r.res, "$#: $#" | "$# = $#" , [f.loc.r, a.res]) - r.res.add("}") + fieldIDs.incl(f.id) + addf(initList, "$#: $#" | "$# = $#" , [f.loc.r, a.res]) + let t = skipTypes(n.typ, abstractInst + skipPtrs) + createObjInitList(p, t, fieldIDs, initList) + r.res = "{$1}" % [initList] proc genConv(p: PProc, n: PNode, r: var TCompRes) = var dest = skipTypes(n.typ, abstractVarRange) @@ -1681,7 +1704,7 @@ proc genHeader(): Rope = result = ("/* Generated by the Nim Compiler v$1 */$n" & "/* (c) 2015 Andreas Rumpf */$n$n" & "var framePtr = null;$n" & - "var excHandler = null;$n" & + "var excHandler = 0;$n" & "var lastJSError = null;$n") % [rope(VersionAsString)] |