diff options
author | Araq <rumpf_a@web.de> | 2015-03-12 10:55:55 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-03-12 11:08:03 +0100 |
commit | f88678bed474b27854c883b386a52a159a57bfeb (patch) | |
tree | 3fc59782587d74c90df8a81df2aacbc23d119819 | |
parent | b97207a74ce7d827160e02a6e0194a569608dcb5 (diff) | |
download | Nim-f88678bed474b27854c883b386a52a159a57bfeb.tar.gz |
fixes #2298
-rw-r--r-- | compiler/jsgen.nim | 408 |
1 files changed, 205 insertions, 203 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 87847204f..75c4ddfa0 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -62,13 +62,13 @@ type res: PRope # result part; index if this is an # (address, index)-tuple address: PRope # address of an (address, index)-tuple - - TBlock = object + + TBlock = object id: int # the ID of the label; positive means that it # has been used (i.e. the label should be emitted) isLoop: bool # whether it's a 'block' or 'while' - - TGlobals = object + + TGlobals = object typeInfo, code: PRope forwarded: seq[PSym] generatedSyms: IntSet @@ -98,7 +98,7 @@ proc newGlobals(): PGlobals = result.generatedSyms = initIntSet() result.typeInfoGenerated = initIntSet() -proc initCompRes(r: var TCompRes) = +proc initCompRes(r: var TCompRes) = r.address = nil r.res = nil r.typ = etyNone @@ -112,7 +112,7 @@ proc rdLoc(a: TCompRes): PRope {.inline.} = else: result = ropef("$1[$2]", a.address, a.res) -proc newProc(globals: PGlobals, module: BModule, procDef: PNode, +proc newProc(globals: PGlobals, module: BModule, procDef: PNode, options: TOptions): PProc = result = PProc( blocks: @[], @@ -121,30 +121,30 @@ proc newProc(globals: PGlobals, module: BModule, procDef: PNode, procDef: procDef, g: globals) if procDef != nil: result.prc = procDef.sons[namePos].sym - -const - MappedToObject = {tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, + +const + MappedToObject = {tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tySet, tyVar, tyRef, tyPtr, tyBigNum, tyVarargs} -proc mapType(typ: PType): TJSTypeKind = +proc mapType(typ: PType): TJSTypeKind = let t = skipTypes(typ, abstractInst) case t.kind - of tyVar, tyRef, tyPtr: - if skipTypes(t.lastSon, abstractInst).kind in MappedToObject: + of tyVar, tyRef, tyPtr: + if skipTypes(t.lastSon, abstractInst).kind in MappedToObject: result = etyObject - else: + else: result = etyBaseIndex of tyPointer: # treat a tyPointer like a typed pointer to an array of bytes result = etyInt - of tyRange, tyDistinct, tyOrdinal, tyConst, tyMutable, tyIter, tyProxy: + of tyRange, tyDistinct, tyOrdinal, tyConst, tyMutable, tyIter, tyProxy: result = mapType(t.sons[0]) of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt of tyBool: result = etyBool of tyFloat..tyFloat128: result = etyFloat of tySet: result = etyObject # map a set to a table of tyString, tySequence: result = etyInt # little hack to get right semantics - of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tyBigNum, + of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tyBigNum, tyVarargs: result = etyObject of tyNil: result = etyNull @@ -154,10 +154,10 @@ proc mapType(typ: PType): TJSTypeKind = result = etyNone of tyProc: result = etyProc of tyCString: result = etyString - -proc mangleName(s: PSym): PRope = + +proc mangleName(s: PSym): PRope = result = s.loc.r - if result == nil: + if result == nil: result = toRope(mangle(s.name.s)) app(result, "_") app(result, toRope(s.id)) @@ -166,7 +166,7 @@ proc mangleName(s: PSym): PRope = proc makeJSString(s: string): PRope = strutils.escape(s).toRope include jstypes - + proc gen(p: PProc, n: PNode, r: var TCompRes) proc genStmt(p: PProc, n: PNode) proc genProc(oldProc: PProc, prc: PSym): PRope @@ -341,14 +341,14 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["", "", "$1", "$1"], # ToBiggestFloat ["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt ["", "", "Math.floor($1)", "Math.floor($1)"], # ToBiggestInt - ["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"], + ["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"], ["nimBoolToStr", "nimBoolToStr", "nimBoolToStr($1)", "nimBoolToStr($1)"], [ - "cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")", - "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", "cstrToNimstr", - "cstrToNimstr(($1)+\"\")", - "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", - "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"], - ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"], + "cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")", + "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", "cstrToNimstr", + "cstrToNimstr(($1)+\"\")", + "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", + "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"], + ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"], ["", "", "$1", "$1"]] luaOps: TMagicOps = [ @@ -441,14 +441,14 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["", "", "$1", "$1"], # ToBiggestFloat ["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt ["", "", "Math.floor($1)", "Math.floor($1)"], # ToBiggestInt - ["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"], + ["nimCharToStr", "nimCharToStr", "nimCharToStr($1)", "nimCharToStr($1)"], ["nimBoolToStr", "nimBoolToStr", "nimBoolToStr($1)", "nimBoolToStr($1)"], [ - "cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")", - "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", "cstrToNimstr", - "cstrToNimstr(($1)+\"\")", - "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", - "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"], - ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"], + "cstrToNimstr", "cstrToNimstr", "cstrToNimstr(($1)+\"\")", + "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", "cstrToNimstr", + "cstrToNimstr(($1)+\"\")", + "cstrToNimstr(($1)+\"\")"], ["cstrToNimstr", + "cstrToNimstr", "cstrToNimstr(($1)+\"\")", "cstrToNimstr(($1)+\"\")"], + ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"], ["", "", "$1", "$1"]] proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) = @@ -502,9 +502,9 @@ proc genLineDir(p: PProc, n: PNode) = appf(p.body, "endb($1);$n", [toRope(line)]) elif ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and - ((p.prc == nil) or not (sfPure in p.prc.flags)): + ((p.prc == nil) or not (sfPure in p.prc.flags)): appf(p.body, "F.line = $1;$n", [toRope(line)]) - + proc genWhileStmt(p: PProc, n: PNode) = var cond: TCompRes @@ -533,7 +533,7 @@ proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) = src.kind = resNone src.res = nil -proc genTry(p: PProc, n: PNode, r: var TCompRes) = +proc genTry(p: PProc, n: PNode, r: var TCompRes) = # code to generate: # # var sp = {prev: excHandler, exc: null}; @@ -560,8 +560,8 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = inc(p.unique) var safePoint = ropef("Tmp$1", [toRope(p.unique)]) appf(p.body, - "var $1 = {prev: excHandler, exc: null};$nexcHandler = $1;$n" | - "local $1 = pcall(", + "var $1 = {prev: excHandler, exc: null};$nexcHandler = $1;$n" | + "local $1 = pcall(", [safePoint]) if optStackTrace in p.options: app(p.body, "framePtr = F;" & tnl) appf(p.body, "try {$n" | "function()$n") @@ -574,9 +574,9 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = appf(p.body, "} catch (EXC) {$n lastJSError = EXC;$n") elif p.target == targetLua: appf(p.body, "end)$n") - while i < length and n.sons[i].kind == nkExceptBranch: + while i < length and n.sons[i].kind == nkExceptBranch: let blen = sonsLen(n.sons[i]) - if blen == 1: + if blen == 1: # general except section: if i > 1: appf(p.body, "else {$n" | "else$n") gen(p, n.sons[i].sons[0], a) @@ -585,11 +585,11 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = else: var orExpr: PRope = nil useMagic(p, "isObj") - for j in countup(0, blen - 2): - if n.sons[i].sons[j].kind != nkType: + for j in countup(0, blen - 2): + if n.sons[i].sons[j].kind != nkType: internalError(n.info, "genTryStmt") if orExpr != nil: app(orExpr, "||" | " or ") - appf(orExpr, "isObj($1.exc.m_type, $2)", + appf(orExpr, "isObj($1.exc.m_type, $2)", [safePoint, genTypeInfo(p, n.sons[i].sons[j].typ)]) if i > 1: app(p.body, "else ") appf(p.body, "if ($1.exc && ($2)) {$n" | "if $1.exc and ($2) then$n", @@ -622,13 +622,13 @@ proc genRaiseStmt(p: PProc, n: PNode) = useMagic(p, "reraiseException") app(p.body, "reraiseException();" & tnl) -proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = +proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = var cond, stmt: TCompRes genLineDir(p, n) gen(p, n.sons[0], cond) let stringSwitch = skipTypes(n.sons[0].typ, abstractVar).kind == tyString - if stringSwitch: + if stringSwitch: useMagic(p, "toJSStr") appf(p.body, "switch (toJSStr($1)) {$n", [cond.rdLoc]) else: @@ -636,25 +636,25 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = if not isEmptyType(n.typ): r.kind = resVal r.res = getTemp(p) - for i in countup(1, sonsLen(n) - 1): + for i in countup(1, sonsLen(n) - 1): let it = n.sons[i] case it.kind - of nkOfBranch: - for j in countup(0, sonsLen(it) - 2): + of nkOfBranch: + for j in countup(0, sonsLen(it) - 2): let e = it.sons[j] - if e.kind == nkRange: + if e.kind == nkRange: var v = copyNode(e.sons[0]) - while v.intVal <= e.sons[1].intVal: + while v.intVal <= e.sons[1].intVal: gen(p, v, cond) appf(p.body, "case $1: ", [cond.rdLoc]) inc(v.intVal) else: - if stringSwitch: + if stringSwitch: case e.kind - of nkStrLit..nkTripleStrLit: appf(p.body, "case $1: ", + of nkStrLit..nkTripleStrLit: appf(p.body, "case $1: ", [makeJSString(e.strVal)]) else: internalError(e.info, "jsgen.genCaseStmt: 2") - else: + else: gen(p, e, cond) appf(p.body, "case $1: ", [cond.rdLoc]) gen(p, lastSon(it), stmt) @@ -668,7 +668,7 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = else: internalError(it.info, "jsgen.genCaseStmt") appf(p.body, "}$n") -proc genCaseLua(p: PProc, n: PNode, r: var TCompRes) = +proc genCaseLua(p: PProc, n: PNode, r: var TCompRes) = var cond, stmt: TCompRes genLineDir(p, n) @@ -681,13 +681,13 @@ proc genCaseLua(p: PProc, n: PNode, r: var TCompRes) = if not isEmptyType(n.typ): r.kind = resVal r.res = getTemp(p) - for i in countup(1, sonsLen(n) - 1): + for i in countup(1, sonsLen(n) - 1): let it = n.sons[i] case it.kind of nkOfBranch: if i != 1: appf(p.body, "$nelsif ") else: appf(p.body, "if ") - for j in countup(0, sonsLen(it) - 2): + for j in countup(0, sonsLen(it) - 2): if j != 0: app(p.body, " or ") let e = it.sons[j] if e.kind == nkRange: @@ -696,7 +696,7 @@ proc genCaseLua(p: PProc, n: PNode, r: var TCompRes) = gen(p, e.sons[1], ib) appf(p.body, "$1 >= $2 and $1 <= $3", [tmp, ia.rdLoc, ib.rdLoc]) else: - if stringSwitch: + if stringSwitch: case e.kind of nkStrLit..nkTripleStrLit: appf(p.body, "eqStr($1, $2)", [tmp, makeJSString(e.strVal)]) @@ -713,11 +713,11 @@ proc genCaseLua(p: PProc, n: PNode, r: var TCompRes) = moveInto(p, stmt, r) else: internalError(it.info, "jsgen.genCaseStmt") appf(p.body, "$nend$n") - + proc genBlock(p: PProc, n: PNode, r: var TCompRes) = inc(p.unique) let idx = len(p.blocks) - if n.sons[0].kind != nkEmpty: + if n.sons[0].kind != nkEmpty: # named block? if (n.sons[0].kind != nkSym): internalError(n.info, "genBlock") var sym = n.sons[0].sym @@ -731,10 +731,10 @@ proc genBlock(p: PProc, n: PNode, r: var TCompRes) = appf(p.body, "} while(false);$n" | "$n::L$#::$n", labl.toRope) setLen(p.blocks, idx) -proc genBreakStmt(p: PProc, n: PNode) = +proc genBreakStmt(p: PProc, n: PNode) = var idx: int genLineDir(p, n) - if n.sons[0].kind != nkEmpty: + if n.sons[0].kind != nkEmpty: # named break? assert(n.sons[0].kind == nkSym) let sym = n.sons[0].sym @@ -749,24 +749,24 @@ proc genBreakStmt(p: PProc, n: PNode) = p.blocks[idx].id = abs(p.blocks[idx].id) # label is used appf(p.body, "break L$1;$n" | "goto ::L$1::;$n", [toRope(p.blocks[idx].id)]) -proc genAsmStmt(p: PProc, n: PNode) = +proc genAsmStmt(p: PProc, n: PNode) = genLineDir(p, n) assert(n.kind == nkAsmStmt) - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): case n.sons[i].kind of nkStrLit..nkTripleStrLit: app(p.body, n.sons[i].strVal) of nkSym: app(p.body, mangleName(n.sons[i].sym)) else: internalError(n.sons[i].info, "jsgen: genAsmStmt()") - -proc genIf(p: PProc, n: PNode, r: var TCompRes) = + +proc genIf(p: PProc, n: PNode, r: var TCompRes) = var cond, stmt: TCompRes var toClose = 0 if not isEmptyType(n.typ): r.kind = resVal r.res = getTemp(p) - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): let it = n.sons[i] - if sonsLen(it) != 1: + if sonsLen(it) != 1: if i > 0: appf(p.body, "else {$n" | "else$n", []) inc(toClose) @@ -793,18 +793,18 @@ proc generateHeader(p: PProc, typ: PType): PRope = if isCompileTimeOnly(param.typ): continue var name = mangleName(param) app(result, name) - if mapType(param.typ) == etyBaseIndex: + if mapType(param.typ) == etyBaseIndex: app(result, ", ") app(result, name) app(result, "_Idx") -const - nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, - nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString, - nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix, +const + nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, + nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString, + nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix, nkCommand, nkHiddenCallConv, nkCallStrLit} -proc needsNoCopy(y: PNode): bool = +proc needsNoCopy(y: PNode): bool = result = (y.kind in nodeKindsNeedNoCopy) or (skipTypes(y.typ, abstractInst).kind in {tyRef, tyPtr, tyVar}) @@ -820,22 +820,22 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = useMagic(p, "nimCopy") appf(p.body, "$1 = nimCopy($2, $3);$n", [a.res, b.res, genTypeInfo(p, y.typ)]) - of etyBaseIndex: - if a.typ != etyBaseIndex or b.typ != etyBaseIndex: + of etyBaseIndex: + if a.typ != etyBaseIndex or b.typ != etyBaseIndex: internalError(x.info, "genAsgn") appf(p.body, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res]) else: appf(p.body, "$1 = $2;$n", [a.res, b.res]) -proc genAsgn(p: PProc, n: PNode) = +proc genAsgn(p: PProc, n: PNode) = genLineDir(p, n) genAsgnAux(p, n.sons[0], n.sons[1], noCopyNeeded=false) -proc genFastAsgn(p: PProc, n: PNode) = +proc genFastAsgn(p: PProc, n: PNode) = genLineDir(p, n) genAsgnAux(p, n.sons[0], n.sons[1], noCopyNeeded=true) -proc genSwap(p: PProc, n: PNode) = +proc genSwap(p: PProc, n: PNode) = var a, b: TCompRes gen(p, n.sons[1], a) gen(p, n.sons[2], b) @@ -844,7 +844,7 @@ proc genSwap(p: PProc, n: PNode) = if mapType(skipTypes(n.sons[1].typ, abstractVar)) == etyBaseIndex: inc(p.unique) let tmp2 = ropef("Tmp$1", [toRope(p.unique)]) - if a.typ != etyBaseIndex or b.typ != etyBaseIndex: + if a.typ != etyBaseIndex or b.typ != etyBaseIndex: internalError(n.info, "genSwap") appf(p.body, "var $1 = $2; $2 = $3; $3 = $1;$n" | "local $1 = $2; $2 = $3; $3 = $1;$n", [ @@ -859,7 +859,7 @@ proc getFieldPosition(f: PNode): int = of nkSym: result = f.sym.position else: internalError(f.info, "genFieldPosition") -proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) = +proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) = var a: TCompRes r.typ = etyBaseIndex let b = if n.kind == nkHiddenAddr: n.sons[0] else: n @@ -875,7 +875,7 @@ proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) = r.address = a.res r.kind = resExpr -proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) = +proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) = r.typ = etyNone gen(p, n.sons[0], r) if skipTypes(n.sons[0].typ, abstractVarRange).kind == tyTuple: @@ -887,14 +887,16 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) = r.res = ropef("$1.$2", [r.res, f.loc.r]) r.kind = resExpr -proc genCheckedFieldAddr(p: PProc, n: PNode, r: var TCompRes) = - genFieldAddr(p, n.sons[0], r) # XXX - -proc genCheckedFieldAccess(p: PProc, n: PNode, r: var TCompRes) = +proc genCheckedFieldAddr(p: PProc, n: PNode, r: var TCompRes) = + let m = if n.kind == nkHiddenAddr: n.sons[0] else: n + internalAssert m.kind == nkCheckedFieldExpr + genFieldAddr(p, m.sons[0], r) # XXX + +proc genCheckedFieldAccess(p: PProc, n: PNode, r: var TCompRes) = genFieldAccess(p, n.sons[0], r) # XXX - -proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = - var + +proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = + var a, b: TCompRes first: BiggestInt r.typ = etyBaseIndex @@ -908,7 +910,7 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = else: first = 0 if optBoundsCheck in p.options and not isConstExpr(m.sons[1]): useMagic(p, "chckIndx") - r.res = ropef("chckIndx($1, $2, $3.length)-$2", + r.res = ropef("chckIndx($1, $2, $3.length)-$2", [b.res, toRope(first), a.res]) elif first != 0: r.res = ropef("($1)-$2", [b.res, toRope(first)]) @@ -916,14 +918,14 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = r.res = b.res r.kind = resExpr -proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) = +proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) = 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: genArrayAddr(p, n, r) - of tyTuple: + of tyTuple: genFieldAddr(p, n, r) else: internalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')') r.typ = etyNone @@ -967,12 +969,12 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) = of tyArray, tyArrayConstr, tyOpenArray, tySequence, tyString, tyCString, tyVarargs: genArrayAddr(p, n, r) - of tyTuple: + of tyTuple: genFieldAddr(p, n, r) else: internalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')') else: internalError(n.info, "genAddr") - -proc genSym(p: PProc, n: PNode, r: var TCompRes) = + +proc genSym(p: PProc, n: PNode, r: var TCompRes) = var s = n.sym case s.kind of skVar, skLet, skParam, skTemp, skResult: @@ -1019,9 +1021,9 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) = internalError(n.info, "symbol has no generated name: " & s.name.s) r.res = s.loc.r r.kind = resVal - -proc genDeref(p: PProc, n: PNode, r: var TCompRes) = - if mapType(n.sons[0].typ) == etyObject: + +proc genDeref(p: PProc, n: PNode, r: var TCompRes) = + if mapType(n.sons[0].typ) == etyObject: gen(p, n.sons[0], r) else: var a: TCompRes @@ -1041,15 +1043,15 @@ proc genArg(p: PProc, n: PNode, r: var TCompRes) = proc genArgs(p: PProc, n: PNode, r: var TCompRes) = app(r.res, "(") - for i in countup(1, sonsLen(n) - 1): + for i in countup(1, sonsLen(n) - 1): let it = n.sons[i] - if it.typ.isCompileTimeOnly: continue + if it.typ.isCompileTimeOnly: continue if i > 1: app(r.res, ", ") genArg(p, it, r) app(r.res, ")") r.kind = resExpr -proc genCall(p: PProc, n: PNode, r: var TCompRes) = +proc genCall(p: PProc, n: PNode, r: var TCompRes) = gen(p, n.sons[0], r) genArgs(p, n, r) @@ -1065,7 +1067,7 @@ proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) = var op: TCompRes gen(p, n.sons[0], op) app(r.res, op.res) - + app(r.res, "(") for i in countup(2, sonsLen(n) - 1): if i > 2: app(r.res, ", ") @@ -1080,88 +1082,88 @@ proc genEcho(p: PProc, n: PNode, r: var TCompRes) = internalAssert n.kind == nkBracket for i in countup(0, sonsLen(n) - 1): let it = n.sons[i] - if it.typ.isCompileTimeOnly: continue + if it.typ.isCompileTimeOnly: continue if i > 0: app(r.res, ", ") genArg(p, it, r) app(r.res, ")") r.kind = resExpr -proc putToSeq(s: string, indirect: bool): PRope = +proc putToSeq(s: string, indirect: bool): PRope = result = toRope(s) if indirect: result = ropef("[$1]", [result]) - + proc createVar(p: PProc, typ: PType, indirect: bool): PRope -proc createRecordVarAux(p: PProc, rec: PNode, c: var int): PRope = +proc createRecordVarAux(p: PProc, rec: PNode, c: var int): PRope = result = nil case rec.kind - of nkRecList: - for i in countup(0, sonsLen(rec) - 1): + of nkRecList: + for i in countup(0, sonsLen(rec) - 1): app(result, createRecordVarAux(p, rec.sons[i], c)) - of nkRecCase: + of nkRecCase: app(result, createRecordVarAux(p, rec.sons[0], c)) - for i in countup(1, sonsLen(rec) - 1): + for i in countup(1, sonsLen(rec) - 1): app(result, createRecordVarAux(p, lastSon(rec.sons[i]), c)) - of nkSym: + of nkSym: if c > 0: app(result, ", ") app(result, mangleName(rec.sym)) app(result, ": ") app(result, createVar(p, rec.sym.typ, false)) inc(c) else: internalError(rec.info, "createRecordVarAux") - -proc createVar(p: PProc, typ: PType, indirect: bool): PRope = + +proc createVar(p: PProc, typ: PType, indirect: bool): PRope = var t = skipTypes(typ, abstractInst) case t.kind - of tyInt..tyInt64, tyEnum, tyChar: + of tyInt..tyInt64, tyEnum, tyChar: result = putToSeq("0", indirect) - of tyFloat..tyFloat128: + of tyFloat..tyFloat128: result = putToSeq("0.0", indirect) - of tyRange, tyGenericInst: + of tyRange, tyGenericInst: result = createVar(p, lastSon(typ), indirect) - of tySet: + of tySet: result = toRope("{}") - of tyBool: + of tyBool: result = putToSeq("false", indirect) - of tyArray, tyArrayConstr: + of tyArray, tyArrayConstr: var length = int(lengthOrd(t)) var e = elemType(t) - if length > 32: + if length > 32: useMagic(p, "arrayConstr") # XXX: arrayConstr depends on nimCopy. This line shouldn't be necessary. useMagic(p, "nimCopy") - result = ropef("arrayConstr($1, $2, $3)", [toRope(length), + result = ropef("arrayConstr($1, $2, $3)", [toRope(length), createVar(p, e, false), genTypeInfo(p, e)]) - else: + else: result = toRope("[") var i = 0 - while i < length: + while i < length: if i > 0: app(result, ", ") app(result, createVar(p, e, false)) inc(i) app(result, "]") - of tyTuple: + of tyTuple: result = toRope("{") for i in 0.. <t.sonsLen: if i > 0: app(result, ", ") - appf(result, "Field$1: $2" | "Field$# = $#", i.toRope, + appf(result, "Field$1: $2" | "Field$# = $#", i.toRope, createVar(p, t.sons[i], false)) app(result, "}") - of tyObject: + of tyObject: result = toRope("{") var c = 0 if tfFinal notin t.flags or t.sons[0] != nil: inc(c) appf(result, "m_type: $1" | "m_type = $#", [genTypeInfo(p, t)]) - while t != nil: + while t != nil: app(result, createRecordVarAux(p, t.n, c)) t = t.sons[0] app(result, "}") - of tyVar, tyPtr, tyRef: + of tyVar, tyPtr, tyRef: if mapType(t) == etyBaseIndex: result = putToSeq("[null, 0]" | "{nil, 0}", indirect) else: result = putToSeq("null" | "nil", indirect) - of tySequence, tyString, tyCString, tyPointer, tyProc: + of tySequence, tyString, tyCString, tyPointer, tyProc: result = putToSeq("null" | "nil", indirect) else: internalError("createVar: " & $t.kind) @@ -1172,42 +1174,42 @@ proc isIndirect(v: PSym): bool = (mapType(v.typ) != etyObject) and v.kind notin {skProc, skConverter, skMethod, skIterator, skClosureIterator} -proc genVarInit(p: PProc, v: PSym, n: PNode) = - var +proc genVarInit(p: PProc, v: PSym, n: PNode) = + var a: TCompRes s: PRope - if n.kind == nkEmpty: - appf(p.body, "var $1 = $2;$n" | "local $1 = $2;$n", + if n.kind == nkEmpty: + appf(p.body, "var $1 = $2;$n" | "local $1 = $2;$n", [mangleName(v), createVar(p, v.typ, isIndirect(v))]) - else: + else: discard mangleName(v) gen(p, n, a) case mapType(v.typ) - of etyObject: - if needsNoCopy(n): + of etyObject: + if needsNoCopy(n): s = a.res - else: + else: useMagic(p, "nimCopy") s = ropef("nimCopy($1, $2)", [a.res, genTypeInfo(p, n.typ)]) - of etyBaseIndex: + of etyBaseIndex: if (a.typ != etyBaseIndex): internalError(n.info, "genVarInit") - if {sfAddrTaken, sfGlobal} * v.flags != {}: - appf(p.body, "var $1 = [$2, $3];$n" | "local $1 = {$2, $3};$n", + if {sfAddrTaken, sfGlobal} * v.flags != {}: + appf(p.body, "var $1 = [$2, $3];$n" | "local $1 = {$2, $3};$n", [v.loc.r, a.address, a.res]) else: - appf(p.body, "var $1 = $2; var $1_Idx = $3;$n" | + appf(p.body, "var $1 = $2; var $1_Idx = $3;$n" | "local $1 = $2; local $1_Idx = $3;$n", [ v.loc.r, a.address, a.res]) return else: s = a.res - if isIndirect(v): + if isIndirect(v): appf(p.body, "var $1 = [$2];$n" | "local $1 = {$2};$n", [v.loc.r, s]) - else: + else: appf(p.body, "var $1 = $2;$n" | "local $1 = $2;$n", [v.loc.r, s]) - -proc genVarStmt(p: PProc, n: PNode) = - for i in countup(0, sonsLen(n) - 1): + +proc genVarStmt(p: PProc, n: PNode) = + for i in countup(0, sonsLen(n) - 1): var a = n.sons[i] if a.kind != nkCommentStmt: if a.kind == nkVarTuple: @@ -1249,7 +1251,7 @@ proc genOrd(p: PProc, n: PNode, r: var TCompRes) = of tyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r) of tyBool: unaryExpr(p, n, r, "", "($1 ? 1:0)" | "toBool($#)") else: internalError(n.info, "genOrd") - + proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) = var a: TCompRes @@ -1282,7 +1284,7 @@ proc genRepr(p: PProc, n: PNode, r: var TCompRes) = gen(p, n.sons[1], r) useMagic(p, "cstrToNimstr") r.kind = resExpr - r.res = ropef("cstrToNimstr($1.node.sons[$2].name)", + r.res = ropef("cstrToNimstr($1.node.sons[$2].name)", [genTypeInfo(p, t), r.res]) else: # XXX: @@ -1303,11 +1305,11 @@ proc genReset(p: PProc, n: PNode) = var x: TCompRes useMagic(p, "genericReset") gen(p, n.sons[1], x) - appf(p.body, "$1 = genericReset($1, $2);$n", [x.res, + appf(p.body, "$1 = genericReset($1, $2);$n", [x.res, genTypeInfo(p, n.sons[1].typ)]) proc genMagic(p: PProc, n: PNode, r: var TCompRes) = - var + var a: TCompRes line, filen: PRope var op = n.sons[0].sym.magic @@ -1384,34 +1386,34 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mCopyStr: binaryExpr(p, n, r, "", "($1.slice($2))") 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 mNewStringOfCap: unaryExpr(p, n, r, "mnewString", "mnewString(0)") else: genCall(p, n, r) #else internalError(e.info, 'genMagic: ' + magicToStr[op]); - -proc genSetConstr(p: PProc, n: PNode, r: var TCompRes) = + +proc genSetConstr(p: PProc, n: PNode, r: var TCompRes) = var a, b: TCompRes useMagic(p, "SetConstr") r.res = toRope("SetConstr(") r.kind = resExpr - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): if i > 0: app(r.res, ", ") var it = n.sons[i] - if it.kind == nkRange: + if it.kind == nkRange: gen(p, it.sons[0], a) gen(p, it.sons[1], b) appf(r.res, "[$1, $2]", [a.res, b.res]) - else: + else: gen(p, it, a) app(r.res, a.res) app(r.res, ")") -proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) = +proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) = var a: TCompRes r.res = toRope("[") r.kind = resExpr - for i in countup(0, sonsLen(n) - 1): + for i in countup(0, sonsLen(n) - 1): if i > 0: app(r.res, ", ") gen(p, n.sons[i], a) app(r.res, a.res) @@ -1444,7 +1446,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = appf(r.res, "$#: $#" | "$# = $#" , [f.loc.r, a.res]) r.res.app("}") -proc genConv(p: PProc, n: PNode, r: var TCompRes) = +proc genConv(p: PProc, n: PNode, r: var TCompRes) = var dest = skipTypes(n.typ, abstractVarRange) var src = skipTypes(n.sons[1].typ, abstractVarRange) gen(p, n.sons[1], r) @@ -1460,24 +1462,24 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) = else: # TODO: What types must we handle here? discard - -proc upConv(p: PProc, n: PNode, r: var TCompRes) = + +proc upConv(p: PProc, n: PNode, r: var TCompRes) = gen(p, n.sons[0], r) # XXX - -proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) = + +proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) = var a, b: TCompRes gen(p, n.sons[0], r) - if optRangeCheck in p.options: + if optRangeCheck in p.options: gen(p, n.sons[1], a) gen(p, n.sons[2], b) useMagic(p, "chckRange") r.res = ropef("chckRange($1, $2, $3)", [r.res, a.res, b.res]) r.kind = resExpr -proc convStrToCStr(p: PProc, n: PNode, r: var TCompRes) = +proc convStrToCStr(p: PProc, n: PNode, r: var TCompRes) = # we do an optimization here as this is likely to slow down # much of the code otherwise: - if n.sons[0].kind == nkCStringToString: + if n.sons[0].kind == nkCStringToString: gen(p, n.sons[0].sons[0], r) else: gen(p, n.sons[0], r) @@ -1486,22 +1488,22 @@ proc convStrToCStr(p: PProc, n: PNode, r: var TCompRes) = r.res = ropef("toJSStr($1)", [r.res]) r.kind = resExpr -proc convCStrToStr(p: PProc, n: PNode, r: var TCompRes) = +proc convCStrToStr(p: PProc, n: PNode, r: var TCompRes) = # we do an optimization here as this is likely to slow down # much of the code otherwise: - if n.sons[0].kind == nkStringToCString: + if n.sons[0].kind == nkStringToCString: gen(p, n.sons[0].sons[0], r) - else: + else: gen(p, n.sons[0], r) if r.res == nil: internalError(n.info, "convCStrToStr") useMagic(p, "cstrToNimstr") r.res = ropef("cstrToNimstr($1)", [r.res]) r.kind = resExpr -proc genReturnStmt(p: PProc, n: PNode) = +proc genReturnStmt(p: PProc, n: PNode) = if p.procDef == nil: internalError(n.info, "genReturnStmt") p.beforeRetNeeded = true - if (n.sons[0].kind != nkEmpty): + if (n.sons[0].kind != nkEmpty): genStmt(p, n.sons[0]) else: genLineDir(p, n) @@ -1517,22 +1519,22 @@ proc genProcBody(p: PProc, prc: PSym): PRope = else: result = nil if p.beforeRetNeeded: - appf(result, "BeforeRet: do {$n$1} while (false); $n" | + appf(result, "BeforeRet: do {$n$1} while (false); $n" | "$#;::BeforeRet::$n", [p.body]) else: app(result, p.body) - if prc.typ.callConv == ccSysCall and p.target == targetJS: + if prc.typ.callConv == ccSysCall and p.target == targetJS: result = ropef("try {$n$1} catch (e) {$n" & " alert(\"Unhandled exception:\\n\" + e.message + \"\\n\"$n}", [result]) - if optStackTrace in prc.options: + if optStackTrace in prc.options: app(result, "framePtr = framePtr.prev;" & tnl) -proc genProc(oldProc: PProc, prc: PSym): PRope = +proc genProc(oldProc: PProc, prc: PSym): PRope = var resultSym: PSym name, returnStmt, resultAsgn, header: PRope a: TCompRes - #if gVerbosity >= 3: + #if gVerbosity >= 3: # echo "BEGIN generating code for: " & prc.name.s var p = newProc(oldProc.g, oldProc.module, prc.ast, prc.options) p.target = oldProc.target @@ -1541,17 +1543,17 @@ proc genProc(oldProc: PProc, prc: PSym): PRope = resultAsgn = nil name = mangleName(prc) header = generateHeader(p, prc.typ) - if prc.typ.sons[0] != nil and sfPure notin prc.flags: + if prc.typ.sons[0] != nil and sfPure notin prc.flags: resultSym = prc.ast.sons[resultPos].sym resultAsgn = ropef("var $# = $#;$n" | "local $# = $#;$n", [ - mangleName(resultSym), + mangleName(resultSym), createVar(p, resultSym.typ, isIndirect(resultSym))]) gen(p, prc.ast.sons[resultPos], a) returnStmt = ropef("return $#;$n", [a.res]) genStmt(p, prc.getBody) result = ropef("function $#($#) {$n$#$#$#$#}$n" | "function $#($#) $n$#$#$#$#$nend$n", - [name, header, p.locals, resultAsgn, + [name, header, p.locals, resultAsgn, genProcBody(p, prc), returnStmt]) #if gVerbosity >= 3: # echo "END generated code for: " & prc.name.s @@ -1584,28 +1586,28 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = r.res = toRope"null" | toRope"nil" r.kind = resExpr of nkStrLit..nkTripleStrLit: - if skipTypes(n.typ, abstractVarRange).kind == tyString: + if skipTypes(n.typ, abstractVarRange).kind == tyString: useMagic(p, "cstrToNimstr") r.res = ropef("cstrToNimstr($1)", [makeJSString(n.strVal)]) - else: + else: r.res = makeJSString(n.strVal) r.kind = resExpr - of nkFloatLit..nkFloat64Lit: + of nkFloatLit..nkFloat64Lit: let f = n.floatVal if f != f: r.res = toRope"NaN" elif f == 0.0: r.res = toRope"0.0" - elif f == 0.5 * f: + elif f == 0.5 * f: if f > 0.0: r.res = toRope"Infinity" else: r.res = toRope"-Infinity" else: r.res = toRope(f.toStrMaxPrecision) r.kind = resExpr of nkCallKinds: - if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone): + if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone): genMagic(p, n, r) elif n.sons[0].kind == nkSym and sfInfixCall in n.sons[0].sym.flags and n.len >= 2: genInfixCall(p, n, r) - else: + else: genCall(p, n, r) of nkCurly: genSetConstr(p, n, r) of nkBracket: genArrayConstr(p, n, r) @@ -1626,7 +1628,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = of nkStringToCString: convStrToCStr(p, n, r) of nkCStringToString: convCStrToStr(p, n, r) of nkEmpty: discard - of nkLambdaKinds: + of nkLambdaKinds: let s = n.sons[namePos].sym discard mangleName(s) r.res = s.loc.r @@ -1647,9 +1649,9 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = of nkWhileStmt: genWhileStmt(p, n) of nkVarSection, nkLetSection: genVarStmt(p, n) of nkConstSection: discard - of nkForStmt, nkParForStmt: + of nkForStmt, nkParForStmt: internalError(n.info, "for statement not eliminated") - of nkCaseStmt: + of nkCaseStmt: if p.target == targetJS: genCaseJS(p, n, r) else: genCaseLua(p, n, r) of nkReturnStmt: genReturnStmt(p, n) @@ -1663,8 +1665,8 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = of nkAsmStmt: genAsmStmt(p, n) of nkTryStmt: genTry(p, n, r) of nkRaiseStmt: genRaiseStmt(p, n) - of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt, - nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, + of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt, + nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: discard of nkProcDef, nkMethodDef, nkConverterDef: var s = n.sons[namePos].sym @@ -1675,33 +1677,33 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = internalError(n.info, "first class iterators not implemented") of nkPragmaBlock: gen(p, n.lastSon, r) else: internalError(n.info, "gen: unknown node type: " & $n.kind) - + var globals: PGlobals -proc newModule(module: PSym): BModule = +proc newModule(module: PSym): BModule = new(result) result.module = module if globals == nil: globals = newGlobals() - + proc genHeader(): PRope = result = ropef("/* Generated by the Nim Compiler v$1 */$n" & "/* (c) 2015 Andreas Rumpf */$n$n" & - "var framePtr = null;$n" & + "var framePtr = null;$n" & "var excHandler = null;$n" & - "var lastJSError = null;$n", + "var lastJSError = null;$n", [toRope(VersionAsString)]) -proc genModule(p: PProc, n: PNode) = +proc genModule(p: PProc, n: PNode) = if optStackTrace in p.options: appf(p.body, "var F = {procname:$1,prev:framePtr,filename:$2,line:0};$n" & "framePtr = F;$n", [ - makeJSString("module " & p.module.module.name.s), + makeJSString("module " & p.module.module.name.s), makeJSString(toFilename(p.module.module.info))]) genStmt(p, n) if optStackTrace in p.options: appf(p.body, "framePtr = framePtr.prev;$n") -proc myProcess(b: PPassContext, n: PNode): PNode = +proc myProcess(b: PPassContext, n: PNode): PNode = if passes.skipCodegen(n): return n result = n var m = BModule(b) @@ -1716,17 +1718,17 @@ proc wholeCode*(m: BModule): PRope = if not globals.generatedSyms.containsOrIncl(prc.id): var p = newProc(globals, m, nil, m.module.options) app(p.g.code, genProc(p, prc)) - + var disp = generateMethodDispatchers() - for i in 0..sonsLen(disp)-1: + for i in 0..sonsLen(disp)-1: let prc = disp.sons[i].sym if not globals.generatedSyms.containsOrIncl(prc.id): var p = newProc(globals, m, nil, m.module.options) app(p.g.code, genProc(p, prc)) result = con(globals.typeInfo, globals.code) - -proc myClose(b: PPassContext, n: PNode): PNode = + +proc myClose(b: PPassContext, n: PNode): PNode = if passes.skipCodegen(n): return n result = myProcess(b, n) var m = BModule(b) @@ -1740,11 +1742,11 @@ proc myClose(b: PPassContext, n: PNode): PNode = changeFileExt(completeCFilePath(m.module.filename), "js") discard writeRopeIfNotEqual(con(genHeader(), code), outfile) -proc myOpenCached(s: PSym, rd: PRodReader): PPassContext = +proc myOpenCached(s: PSym, rd: PRodReader): PPassContext = internalError("symbol files are not possible with the JS code generator") result = nil -proc myOpen(s: PSym): PPassContext = +proc myOpen(s: PSym): PPassContext = result = newModule(s) const JSgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose) |