summary refs log tree commit diff stats
path: root/compiler/jsgen.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-06-02 21:50:56 +0200
committerAraq <rumpf_a@web.de>2013-06-02 21:50:56 +0200
commitfa062ca0c4510e3cdb043daa790f0e29fa5f4ca1 (patch)
tree46b736d31af5b8b4d027b9744d17f1a784935287 /compiler/jsgen.nim
parent2ec3e6b49ecd65dce42a0332af9b4e816d87afcd (diff)
downloadNim-fa062ca0c4510e3cdb043daa790f0e29fa5f4ca1.tar.gz
next steps to a luajit codegen
Diffstat (limited to 'compiler/jsgen.nim')
-rw-r--r--compiler/jsgen.nim319
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) =