diff options
author | Araq <rumpf_a@web.de> | 2013-06-02 21:50:56 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-06-02 21:50:56 +0200 |
commit | fa062ca0c4510e3cdb043daa790f0e29fa5f4ca1 (patch) | |
tree | 46b736d31af5b8b4d027b9744d17f1a784935287 /compiler/jsgen.nim | |
parent | 2ec3e6b49ecd65dce42a0332af9b4e816d87afcd (diff) | |
download | Nim-fa062ca0c4510e3cdb043daa790f0e29fa5f4ca1.tar.gz |
next steps to a luajit codegen
Diffstat (limited to 'compiler/jsgen.nim')
-rw-r--r-- | compiler/jsgen.nim | 319 |
1 files changed, 248 insertions, 71 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index e99c71cb8..8e84f7b6b 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -# This is the EMCAScript (also known as JavaScript) code generator. +# This is the JavaScript code generator. # Soon also a Luajit code generator. ;-) import @@ -70,10 +70,10 @@ type blocks: seq[TBlock] up: PProc # up the call chain; required for closure support -template `|`(a, b: expr): expr {.immediate.} = +template `|`(a, b: expr): expr {.immediate, dirty.} = (if p.target == targetJS: a else: b) -proc newGlobals(): PGlobals = +proc newGlobals(): PGlobals = new(result) result.forwarded = @[] result.generatedSyms = initIntSet() @@ -241,9 +241,10 @@ proc genOr(p: PProc, a, b: PNode, r: var TCompRes) = type TMagicFrmt = array[0..3, string] + TMagicOps = array[mAddi..mStrToStr, TMagicFrmt] const # magic checked op; magic unchecked op; checked op; unchecked op - ops: array[mAddi..mStrToStr, TMagicFrmt] = [ + jsOps: TMagicOps = [ ["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI ["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI ["mulInt", "", "mulInt($1, $2)", "($1 * $2)"], # MulI @@ -343,6 +344,106 @@ const # magic checked op; magic unchecked op; checked op; unchecked op ["cstrToNimstr", "cstrToNimstr", "cstrToNimstr($1)", "cstrToNimstr($1)"], ["", "", "$1", "$1"]] + luaOps: TMagicOps = [ + ["addInt", "", "addInt($1, $2)", "($1 + $2)"], # AddI + ["subInt", "", "subInt($1, $2)", "($1 - $2)"], # SubI + ["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 + ["", "", "($1 + $2)", "($1 + $2)"], # AddF64 + ["", "", "($1 - $2)", "($1 - $2)"], # SubF64 + ["", "", "($1 * $2)", "($1 * $2)"], # MulF64 + ["", "", "($1 / $2)", "($1 / $2)"], # DivF64 + ["", "", "($1 >>> $2)", "($1 >>> $2)"], # ShrI + ["", "", "($1 << $2)", "($1 << $2)"], # ShlI + ["", "", "($1 & $2)", "($1 & $2)"], # BitandI + ["", "", "($1 | $2)", "($1 | $2)"], # BitorI + ["", "", "($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 + ["SubU", "SubU", "SubU($1, $2)", "SubU($1, $2)"], # SubU + ["MulU", "MulU", "MulU($1, $2)", "MulU($1, $2)"], # MulU + ["DivU", "DivU", "DivU($1, $2)", "DivU($1, $2)"], # DivU + ["ModU", "ModU", "ModU($1, $2)", "ModU($1, $2)"], # ModU + ["", "", "($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 + ["LeU", "LeU", "LeU($1, $2)", "LeU($1, $2)"], # LeU + ["LtU", "LtU", "LtU($1, $2)", "LtU($1, $2)"], # LtU + ["LeU64", "LeU64", "LeU64($1, $2)", "LeU64($1, $2)"], # LeU64 + ["LtU64", "LtU64", "LtU64($1, $2)", "LtU64($1, $2)"], # LtU64 + ["", "", "($1 == $2)", "($1 == $2)"], # EqEnum + ["", "", "($1 <= $2)", "($1 <= $2)"], # LeEnum + ["", "", "($1 < $2)", "($1 < $2)"], # LtEnum + ["", "", "($1 == $2)", "($1 == $2)"], # EqCh + ["", "", "($1 <= $2)", "($1 <= $2)"], # LeCh + ["", "", "($1 < $2)", "($1 < $2)"], # LtCh + ["", "", "($1 == $2)", "($1 == $2)"], # EqB + ["", "", "($1 <= $2)", "($1 <= $2)"], # LeB + ["", "", "($1 < $2)", "($1 < $2)"], # LtB + ["", "", "($1 == $2)", "($1 == $2)"], # EqRef + ["", "", "($1 == $2)", "($1 == $2)"], # EqProc + ["", "", "($1 == $2)", "($1 == $2)"], # EqUntracedRef + ["", "", "($1 <= $2)", "($1 <= $2)"], # LePtr + ["", "", "($1 < $2)", "($1 < $2)"], # LtPtr + ["", "", "($1 == $2)", "($1 == $2)"], # EqCString + ["", "", "($1 != $2)", "($1 != $2)"], # Xor + ["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 + ["Ze8ToI", "Ze8ToI", "Ze8ToI($1)", "Ze8ToI($1)"], # mZe8ToI + ["Ze8ToI64", "Ze8ToI64", "Ze8ToI64($1)", "Ze8ToI64($1)"], # mZe8ToI64 + ["Ze16ToI", "Ze16ToI", "Ze16ToI($1)", "Ze16ToI($1)"], # mZe16ToI + ["Ze16ToI64", "Ze16ToI64", "Ze16ToI64($1)", "Ze16ToI64($1)"], # mZe16ToI64 + ["Ze32ToI64", "Ze32ToI64", "Ze32ToI64($1)", "Ze32ToI64($1)"], # mZe32ToI64 + ["ZeIToI64", "ZeIToI64", "ZeIToI64($1)", "ZeIToI64($1)"], # mZeIToI64 + ["ToU8", "ToU8", "ToU8($1)", "ToU8($1)"], # ToU8 + ["ToU16", "ToU16", "ToU16($1)", "ToU16($1)"], # ToU16 + ["ToU32", "ToU32", "ToU32($1)", "ToU32($1)"], # ToU32 + ["", "", "$1", "$1"], # ToFloat + ["", "", "$1", "$1"], # ToBiggestFloat + ["", "", "Math.floor($1)", "Math.floor($1)"], # ToInt + ["", "", "Math.floor($1)", "Math.floor($1)"], # ToBiggestInt + ["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)"], + ["", "", "$1", "$1"]] + proc binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) = var x, y: TCompRes useMagic(p, magic) @@ -357,7 +458,7 @@ proc unaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) = r.res = ropef(frmt, [r.rdLoc]) r.kind = resExpr -proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) = +proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic, ops: TMagicOps) = var x, y: TCompRes let i = ord(optOverflowCheck notin p.options) @@ -371,10 +472,13 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) = r.res = ropef(ops[op][i + 2], [r.rdLoc]) r.kind = resExpr +proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) = + arithAux(p, n, r, op, jsOps | luaOps) + proc genLineDir(p: PProc, n: PNode) = let line = toLinenumber(n.info) if optLineDir in p.Options: - appf(p.body, "// line $2 \"$1\"$n", + appf(p.body, "// line $2 \"$1\"$n" | "-- line $2 \"$1\"$n", [toRope(toFilename(n.info)), toRope(line)]) if {optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb} and ((p.prc == nil) or sfPure notin p.prc.flags): @@ -393,7 +497,7 @@ proc genWhileStmt(p: PProc, n: PNode) = inc(p.unique) var length = len(p.blocks) setlen(p.blocks, length + 1) - p.blocks[length].id = - p.unique + p.blocks[length].id = -p.unique p.blocks[length].isLoop = true let labl = p.unique.toRope appf(p.body, "L$1: while (true) {$n" | "while true do$n", labl) @@ -401,7 +505,7 @@ proc genWhileStmt(p: PProc, n: PNode) = appf(p.body, "if (!$1) break L$2;$n" | "if not $1 then goto ::L$2:: end;$n", [cond.res, labl]) genStmt(p, n.sons[1]) - appf(p.body, "}$n" | "end$n", []) + appf(p.body, "}$n" | "end ::L$#::$n", [labl]) setlen(p.blocks, length) proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) = @@ -434,51 +538,62 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = # excHandler = excHandler.prev; # } genLineDir(p, n) + if not isEmptyType(n.typ): + r.kind = resVal + r.res = getTemp(p) inc(p.unique) var safePoint = ropef("Tmp$1", [toRope(p.unique)]) - appf(p.body, - "var $1 = {prev: excHandler, exc: null};$n" & "excHandler = $1;$n", + appf(p.body, + "var $1 = {prev: excHandler, exc: null};$nexcHandler = $1;$n" | + "local $1 = pcall(", [safePoint]) if optStackTrace in p.Options: app(p.body, "framePtr = F;" & tnl) - app(p.body, "try {" & tnl) + appf(p.body, "try {$n" | "function()$n") var length = sonsLen(n) var a: TCompRes gen(p, n.sons[0], a) - if not isEmptyType(n.typ): - r.kind = resVal - r.res = getTemp(p) moveInto(p, a, r) var i = 1 - if length > 1 and n.sons[i].kind == nkExceptBranch: + if p.target == targetJS and length > 1 and n.sons[i].kind == nkExceptBranch: appf(p.body, "} catch (EXC) {$n") + elif p.target == targetLua: + appf(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: - if i > 1: app(p.body, "else {" & tnl) + if i > 1: appf(p.body, "else {$n" | "else$n") gen(p, n.sons[i].sons[0], a) moveInto(p, a, r) - if i > 1: app(p.body, '}' & tnl) + if i > 1: appf(p.body, "}$n" | "end$n") else: var orExpr: PRope = nil useMagic(p, "isObj") for j in countup(0, blen - 2): if n.sons[i].sons[j].kind != nkType: InternalError(n.info, "genTryStmt") - if orExpr != nil: app(orExpr, "||") + if orExpr != nil: app(orExpr, "||" | " or ") 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", [safePoint, orExpr]) + appf(p.body, "if ($1.exc && ($2)) {$n" | "if $1.exc and ($2) then$n", + [safePoint, orExpr]) gen(p, n.sons[i].sons[blen - 1], a) moveInto(p, a, r) - appf(p.body, "}$n") + appf(p.body, "}$n" | "end$n") inc(i) - app(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl) + if p.target == targetJS: + app(p.body, "} finally {" & tnl & "excHandler = excHandler.prev;" & tnl) if i < length and n.sons[i].kind == nkFinally: gen(p, n.sons[i].sons[0], a) moveInto(p, a, r) - app(p.body, '}' & tnl) + if p.target == targetJS: + app(p.body, "}" & tnl) + if p.target == targetLua: + # we need to repeat the finally block for Lua ... + if i < length and n.sons[i].kind == nkFinally: + gen(p, n.sons[i].sons[0], a) + moveInto(p, a, r) proc genRaiseStmt(p: PProc, n: PNode) = genLineDir(p, n) @@ -493,7 +608,7 @@ proc genRaiseStmt(p: PProc, n: PNode) = useMagic(p, "reraiseException") app(p.body, "reraiseException();" & tnl) -proc genCase(p: PProc, n: PNode, r: var TCompRes) = +proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = var cond, stmt: TCompRes genLineDir(p, n) @@ -539,24 +654,67 @@ proc genCase(p: PProc, n: PNode, r: var TCompRes) = else: internalError(it.info, "jsgen.genCaseStmt") appf(p.body, "}$n") -proc genBlock(p: PProc, n: PNode, r: var TCompRes) = - var - idx, labl: int - sym: PSym +proc genCaseLua(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: + useMagic(p, "eqStr") + let tmp = getTemp(p) + appf(p.body, "$1 = $2;$n", [tmp, cond.rdLoc]) + if not isEmptyType(n.typ): + r.kind = resVal + r.res = getTemp(p) + 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): + if j != 0: app(p.body, " or ") + let e = it.sons[j] + if e.kind == nkRange: + var ia, ib: TCompRes + gen(p, e.sons[0], ia) + gen(p, e.sons[1], ib) + appf(p.body, "$1 >= $2 and $1 <= $3", [tmp, ia.rdLoc, ib.rdLoc]) + else: + if stringSwitch: + case e.kind + of nkStrLit..nkTripleStrLit: appf(p.body, "eqStr($1, $2)", + [tmp, makeJSString(e.strVal)]) + else: InternalError(e.info, "jsgen.genCaseStmt: 2") + else: + gen(p, e, cond) + appf(p.body, "$1 == $2", [tmp, cond.rdLoc]) + appf(p.body, " then$n") + gen(p, lastSon(it), stmt) + moveInto(p, stmt, r) + of nkElse: + appf(p.body, "else$n") + gen(p, it.sons[0], stmt) + 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) - idx = len(p.blocks) + let idx = len(p.blocks) if n.sons[0].kind != nkEmpty: # named block? if (n.sons[0].kind != nkSym): InternalError(n.info, "genBlock") - sym = n.sons[0].sym + var sym = n.sons[0].sym sym.loc.k = locOther sym.loc.a = idx setlen(p.blocks, idx + 1) p.blocks[idx].id = - p.unique # negative because it isn't used yet - labl = p.unique - appf(p.body, "L$1: do {$n", toRope(labl)) + let labl = p.unique + appf(p.body, "L$1: do {$n" | "", labl.toRope) gen(p, n.sons[1], r) - appf(p.body, "} while(false);$n") + appf(p.body, "} while(false);$n" | "$n::L$#::$n", labl.toRope) setlen(p.blocks, idx) proc genBreakStmt(p: PProc, n: PNode) = @@ -575,7 +733,7 @@ proc genBreakStmt(p: PProc, n: PNode) = if idx < 0 or not p.blocks[idx].isLoop: InternalError(n.info, "no loop to break") p.blocks[idx].id = abs(p.blocks[idx].id) # label is used - appf(p.body, "break L$1;$n", [toRope(p.blocks[idx].id)]) + appf(p.body, "break L$1;$n" | "goto ::L$1::;$n", [toRope(p.blocks[idx].id)]) proc genAsmStmt(p: PProc, n: PNode) = genLineDir(p, n) @@ -596,18 +754,21 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) = let it = n.sons[i] if sonsLen(it) != 1: if i > 0: - appf(p.body, "else {$n", []) + appf(p.body, "else {$n" | "else$n", []) inc(toClose) gen(p, it.sons[0], cond) - appf(p.body, "if ($1) {$n", cond.rdLoc) + appf(p.body, "if ($1) {$n" | "if $# then$n", cond.rdLoc) gen(p, it.sons[1], stmt) else: # else part: - appf(p.body, "else {$n") + appf(p.body, "else {$n" | "else$n") gen(p, it.sons[0], stmt) moveInto(p, stmt, r) - appf(p.body, "}$n") - app(p.body, repeatChar(toClose, '}') & tnl) + appf(p.body, "}$n" | "end$n") + if p.target == targetJS: + app(p.body, repeatChar(toClose, '}') & tnl) + else: + for i in 1..toClose: appf(p.body, "end$n") proc generateHeader(p: PProc, typ: PType): PRope = result = nil @@ -957,24 +1118,27 @@ proc createVar(p: PProc, typ: PType, indirect: bool): PRope = result = toRope("{") for i in 0.. <t.sonslen: if i > 0: app(result, ", ") - appf(result, "Field$1: $2", i.toRope, createVar(p, t.sons[i], false)) + appf(result, "Field$1: $2" | "Field$# = $#", i.toRope, + createVar(p, t.sons[i], false)) app(result, "}") of tyObject: result = toRope("{") var c = 0 if tfFinal notin t.flags or t.sons[0] != nil: inc(c) - appf(result, "m_type: $1", [genTypeInfo(p, t)]) + appf(result, "m_type: $1" | "m_type = $#", [genTypeInfo(p, t)]) while t != nil: app(result, createRecordVarAux(p, t.n, c)) t = t.sons[0] app(result, "}") of tyVar, tyPtr, tyRef: - if mapType(t) == etyBaseIndex: result = putToSeq("[null, 0]", indirect) - else: result = putToSeq("null", indirect) + if mapType(t) == etyBaseIndex: + result = putToSeq("[null, 0]" | "{nil, 0}", indirect) + else: + result = putToSeq("null" | "nil", indirect) of tySequence, tyString, tyCString, tyPointer, tyProc: - result = putToSeq("null", indirect) - else: + result = putToSeq("null" | "nil", indirect) + else: internalError("createVar: " & $t.kind) result = nil @@ -987,7 +1151,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = a: TCompRes s: PRope if n.kind == nkEmpty: - appf(p.body, "var $1 = $2;$n", + appf(p.body, "var $1 = $2;$n" | "local $1 = $2;$n", [mangleName(v), createVar(p, v.typ, isIndirect(v))]) else: discard mangleName(v) @@ -1002,15 +1166,19 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = of etyBaseIndex: if (a.typ != etyBaseIndex): InternalError(n.info, "genVarInit") if {sfAddrTaken, sfGlobal} * v.flags != {}: - appf(p.body, "var $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, $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" | + "local $1 = $2; local $1_Idx = $3;$n", [ v.loc.r, a.address, a.res]) return else: s = a.res - if isIndirect(v): appf(p.body, "var $1 = [$2];$n", [v.loc.r, s]) - else: appf(p.body, "var $1 = $2;$n", [v.loc.r, s]) + if isIndirect(v): + appf(p.body, "var $1 = [$2];$n" | "local $1 = {$2};$n", [v.loc.r, s]) + 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): @@ -1049,7 +1217,7 @@ proc genNewSeq(p: PProc, n: PNode) = proc genOrd(p: PProc, n: PNode, r: var TCompRes) = case skipTypes(n.sons[1].typ, abstractVar).kind of tyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r) - of tyBool: unaryExpr(p, n, r, "", "($1 ? 1:0)") + of tyBool: unaryExpr(p, n, r, "", "($1 ? 1:0)" | "toBool($#)") else: InternalError(n.info, "genOrd") proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) = @@ -1215,7 +1383,7 @@ proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) = app(r.res, a.res) app(r.res, "]") -proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) = +proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) = var a: TCompRes r.res = toRope("{") r.kind = resExpr @@ -1224,7 +1392,7 @@ proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) = var it = n.sons[i] if it.kind == nkExprColonExpr: it = it.sons[1] gen(p, it, a) - appf(r.res, "Field$1: $2", [i.toRope, a.res]) + appf(r.res, "Field$#: $#" | "Field$# = $#", [i.toRope, a.res]) r.res.app("}") proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = @@ -1239,7 +1407,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = gen(p, it.sons[1], a) var f = it.sons[0].sym if f.loc.r == nil: f.loc.r = mangleName(f) - appf(r.res, "$1: $2", [f.loc.r, a.res]) + appf(r.res, "$#: $#" | "$# = $#" , [f.loc.r, a.res]) r.res.app("}") proc genConv(p: PProc, n: PNode, r: var TCompRes) = @@ -1247,7 +1415,7 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) = var src = skipTypes(n.sons[1].typ, abstractVarRange) gen(p, n.sons[1], r) if (dest.kind != src.kind) and (src.kind == tyBool): - r.res = ropef("(($1)? 1:0)", [r.res]) + r.res = ropef("(($1)? 1:0)" | "toBool($#)", [r.res]) r.kind = resExpr proc upConv(p: PProc, n: PNode, r: var TCompRes) = @@ -1294,20 +1462,23 @@ proc genReturnStmt(p: PProc, n: PNode) = genStmt(p, n.sons[0]) else: genLineDir(p, n) - app(p.body, "break BeforeRet;" & tnl) + appf(p.body, "break BeforeRet;$n" | "goto ::BeforeRet::;$n") -proc genProcBody(p: PProc, prc: PSym): PRope = +proc genProcBody(p: PProc, prc: PSym): PRope = if optStackTrace in prc.options: - result = ropef("var F={procname:$1,prev:framePtr,filename:$2,line:0};$n" & - "framePtr = F;$n", [makeJSString(prc.owner.name.s & '.' & prc.name.s), - makeJSString(toFilename(prc.info))]) + result = ropef(("var F={procname:$1,prev:framePtr,filename:$2,line:0};$n" | + "local F={procname=$#,prev=framePtr,filename=$#,line=0};$n") & + "framePtr = F;$n", [ + makeJSString(prc.owner.name.s & '.' & prc.name.s), + makeJSString(toFilename(prc.info))]) else: result = nil if p.beforeRetNeeded: - appf(result, "BeforeRet: do {$n$1} while (false); $n", [p.body]) - else: + appf(result, "BeforeRet: do {$n$1} while (false); $n" | + "$#;::BeforeRet::$n", [p.body]) + else: app(result, p.body) - if prc.typ.callConv == ccSysCall: + 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: @@ -1329,12 +1500,14 @@ proc genProc(oldProc: PProc, prc: PSym): PRope = header = generateHeader(p, prc.typ) if prc.typ.sons[0] != nil and sfPure notin prc.flags: resultSym = prc.ast.sons[resultPos].sym - resultAsgn = ropef("var $# = $#;$n", [mangleName(resultSym), + resultAsgn = ropef("var $# = $#;$n" | "local $# = $#;$n", [ + 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", + result = ropef("function $#($#) {$n$#$#$#$#}$n" | + "function $#($#) $n$#$#$#$#$nend$n", [name, header, p.locals, resultAsgn, genProcBody(p, prc), returnStmt]) #if gVerbosity >= 3: @@ -1360,10 +1533,10 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = nil elif mapType(n.typ) == etyBaseIndex: r.typ = etyBaseIndex - r.address = toRope"null" + r.address = toRope"null" | toRope"nil" r.res = toRope"0" else: - r.res = toRope"null" + r.res = toRope"null" | toRope"nil" of nkStrLit..nkTripleStrLit: if skipTypes(n.typ, abstractVarRange).kind == tyString: useMagic(p, "cstrToNimstr") @@ -1430,7 +1603,9 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = of nkConstSection: nil of nkForStmt, nkParForStmt: internalError(n.info, "for statement not eliminated") - of nkCaseStmt: genCase(p, n, r) + of nkCaseStmt: + if p.target == targetJS: genCaseJS(p, n, r) + else: genCaseLua(p, n, r) of nkReturnStmt: genReturnStmt(p, n) of nkBreakStmt: genBreakStmt(p, n) of nkAsgn: genAsgn(p, n) @@ -1461,10 +1636,12 @@ proc newModule(module: PSym): BModule = result.module = module if globals == nil: globals = newGlobals() -proc genHeader(): PRope = +proc genHeader(): PRope = result = ropef("/* Generated by the Nimrod Compiler v$1 */$n" & - "/* (c) 2013 Andreas Rumpf */$n$n" & "$nvar Globals = this;$n" & - "var framePtr = null;$n" & "var excHandler = null;$n", + "/* (c) 2013 Andreas Rumpf */$n$n" & + "$nvar Globals = this;$n" & + "var framePtr = null;$n" & + "var excHandler = null;$n", [toRope(versionAsString)]) proc genModule(p: PProc, n: PNode) = |