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.nim85
1 files changed, 75 insertions, 10 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 41e42b825..a60b0cc5e 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -48,6 +48,7 @@ type
     etyNull,                  # null type
     etyProc,                  # proc type
     etyBool,                  # bool type
+    etySeq,                   # Nim seq or string type
     etyInt,                   # JavaScript's int
     etyFloat,                 # JavaScript's float
     etyString,                # JavaScript's string
@@ -156,15 +157,18 @@ proc mapType(typ: PType): TJSTypeKind =
   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 tyString, tySequence: result = etySeq
   of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tyBigNum,
      tyVarargs:
     result = etyObject
   of tyNil: result = etyNull
   of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
      tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
-     tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses:
+     tyExpr, tyStmt, tyTypeDesc, tyTypeClasses, tyVoid:
     result = etyNone
+  of tyStatic:
+    if t.n != nil: result = mapType(lastSon t)
+    else: result = etyNone
   of tyProc: result = etyProc
   of tyCString: result = etyString
 
@@ -817,7 +821,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
     addf(p.body, "$#[$#] = chr($#);$n", [a.rdLoc, b.rdLoc, c.rdLoc])
     return
 
-  let xtyp = mapType(p, x.typ)
+  var xtyp = mapType(p, x.typ)
 
   if x.kind == nkHiddenDeref and x.sons[0].kind == nkCall and xtyp != etyObject:
     gen(p, x.sons[0], a)
@@ -829,7 +833,18 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
 
   gen(p, y, b)
 
+  # we don't care if it's an etyBaseIndex (global) of a string, it's
+  # still a string that needs to be copied properly:
+  if x.typ.skipTypes(abstractInst).kind in {tySequence, tyString}:
+    xtyp = etySeq
   case xtyp
+  of etySeq:
+    if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
+      addf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
+    else:
+      useMagic(p, "nimCopy")
+      addf(p.body, "$1 = nimCopy(null, $2, $3);$n",
+           [a.rdLoc, b.res, genTypeInfo(p, y.typ)])
   of etyObject:
     if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
       addf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
@@ -1049,6 +1064,8 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
       else: internalError(n.sons[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
   of nkObjDownConv:
     gen(p, n.sons[0], r)
+  of nkHiddenDeref:
+    gen(p, n.sons[0].sons[0], r)
   else: internalError(n.sons[0].info, "genAddr: " & $n.sons[0].kind)
 
 proc thisParam(p: PProc; typ: PType): PType =
@@ -1215,11 +1232,13 @@ proc genOtherArg(p: PProc; n: PNode; i: int; typ: PType;
     genArgNoParam(p, it, r)
   else:
     genArg(p, it, paramType.sym, r)
+  inc generated
 
 proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType;
                     r: var TCompRes) =
   var i = 0
   var j = 1
+  r.kind = resExpr
   while i < pat.len:
     case pat[i]
     of '@':
@@ -1233,10 +1252,18 @@ proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType;
       genOtherArg(p, n, j, typ, generated, r)
       inc j
       inc i
+    of '\31':
+      # unit separator
+      add(r.res, "#")
+      inc i
+    of '\29':
+      # group separator
+      add(r.res, "@")
+      inc i
     else:
       let start = i
       while i < pat.len:
-        if pat[i] notin {'@', '#'}: inc(i)
+        if pat[i] notin {'@', '#', '\31', '\29'}: inc(i)
         else: break
       if i - 1 >= start:
         add(r.res, substr(pat, start, i - 1))
@@ -1403,6 +1430,12 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
       result = putToSeq("null", indirect)
   of tySequence, tyString, tyCString, tyPointer, tyProc:
     result = putToSeq("null", indirect)
+  of tyStatic:
+    if t.n != nil:
+      result = createVar(p, lastSon t, indirect)
+    else:
+      internalError("createVar: " & $t.kind)
+      result = nil
   else:
     internalError("createVar: " & $t.kind)
     result = nil
@@ -1418,7 +1451,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
     discard mangleName(v, p.target)
     gen(p, n, a)
     case mapType(p, v.typ)
-    of etyObject:
+    of etyObject, etySeq:
       if needsNoCopy(p, n):
         s = a.res
       else:
@@ -1557,8 +1590,16 @@ proc genRepr(p: PProc, n: PNode, r: var TCompRes) =
   of tyEnum, tyOrdinal:
     gen(p, n.sons[1], r)
     useMagic(p, "cstrToNimstr")
+    var offset = ""
+    if t.kind == tyEnum:
+      let firstFieldOffset = t.n.sons[0].sym.position
+      if firstFieldOffset < 0:
+        offset = "+" & $(-firstFieldOffset)
+      elif firstFieldOffset > 0:
+        offset = "-" & $firstFieldOffset
+
     r.kind = resExpr
-    r.res = "cstrToNimstr($1.node.sons[$2].name)" % [genTypeInfo(p, t), r.res]
+    r.res = "cstrToNimstr($1.node.sons[$2$3].name)" % [genTypeInfo(p, t), r.res, rope(offset)]
   else:
     # XXX:
     internalError(n.info, "genRepr: Not implemented")
@@ -1678,8 +1719,9 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
     else:
       if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
       else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
-  of mSetLengthStr: binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0" | "")
-  of mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2" | "")
+  of mSetLengthStr:
+    binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0" | "$1 = substr($1, 0, $2)")
+  of mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2" | "$1 = array_slice($1, 0, $2)")
   of mCard: unaryExpr(p, n, r, "SetCard", "SetCard($1)")
   of mLtSet: binaryExpr(p, n, r, "SetLt", "SetLt($1, $2)")
   of mLeSet: binaryExpr(p, n, r, "SetLe", "SetLe($1, $2)")
@@ -1689,8 +1731,31 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
   of mMinusSet: binaryExpr(p, n, r, "SetMinus", "SetMinus($1, $2)")
   of mIncl: binaryExpr(p, n, r, "", "$1[$2] = true")
   of mExcl: binaryExpr(p, n, r, "", "delete $1[$2]" | "unset $1[$2]")
-  of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)" | "isset($1[$2])")
+  of mInSet:
+    if p.target == targetJS:
+      binaryExpr(p, n, r, "", "($1[$2] != undefined)")
+    else:
+      let s = n.sons[1]
+      if s.kind == nkCurly:
+        var a, b, x: TCompRes
+        gen(p, n.sons[2], x)
+        r.res = rope("(")
+        r.kind = resExpr
+        for i in countup(0, sonsLen(s) - 1):
+          if i > 0: add(r.res, " || ")
+          var it = s.sons[i]
+          if it.kind == nkRange:
+            gen(p, it.sons[0], a)
+            gen(p, it.sons[1], b)
+            addf(r.res, "($1 >= $2 && $1 <= $3)", [x.res, a.res, b.res,])
+          else:
+            gen(p, it, a)
+            addf(r.res, "($1 == $2)", [x.res, a.res])
+        add(r.res, ")")
+      else:
+        binaryExpr(p, n, r, "", "isset($1[$2])")
   of mNewSeq: genNewSeq(p, n)
+  of mNewSeqOfCap: unaryExpr(p, n, r, "", "[]" | "array()")
   of mOf: genOf(p, n, r)
   of mReset: genReset(p, n)
   of mEcho: genEcho(p, n, r)
@@ -1989,7 +2054,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
     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:
+        n.len >= 1:
       genInfixCall(p, n, r)
     else:
       genCall(p, n, r)