summary refs log tree commit diff stats
path: root/compiler/jsgen.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/jsgen.nim')
-rw-r--r--compiler/jsgen.nim90
1 files changed, 55 insertions, 35 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index f6ec256d2..ede759426 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -505,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) {
@@ -518,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)
@@ -558,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:
@@ -957,7 +968,9 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
       of tyTuple:
         genFieldAddr(p, n.sons[0], r)
       else: internalError(n.sons[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
-  else: internalError(n.sons[0].info, "genAddr")
+  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):
@@ -1067,6 +1080,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
@@ -1084,24 +1098,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
@@ -1142,15 +1164,9 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
     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:
@@ -1423,6 +1439,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
   var a: TCompRes
   r.res = rope("{")
   r.kind = resExpr
+  var fieldIDs = initIntSet()
   for i in countup(1, sonsLen(n) - 1):
     if i > 1: add(r.res, ", ")
     var it = n.sons[i]
@@ -1430,7 +1447,10 @@ 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)
+    fieldIDs.incl(f.id)
     addf(r.res, "$#: $#" | "$# = $#" , [f.loc.r, a.res])
+  let t = skipTypes(n.typ, abstractInst + skipPtrs)
+  createObjInitList(p, t, fieldIDs, r.res)
   r.res.add("}")
 
 proc genConv(p: PProc, n: PNode, r: var TCompRes) =
@@ -1676,7 +1696,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)]