summary refs log tree commit diff stats
diff options
context:
space:
mode:
authordom96 <dominikpicheta@googlemail.com>2011-09-23 21:43:24 +0100
committerdom96 <dominikpicheta@googlemail.com>2011-09-23 21:43:24 +0100
commit6deda5a973312e86fe58e319e97afd93bc07c82d (patch)
tree0769b2871024febab389c8bc72d01cd770b52cfb
parent2359b8b1073cfd027ac14a147aba06cc18d61010 (diff)
downloadNim-6deda5a973312e86fe58e319e97afd93bc07c82d.tar.gz
Fixed string concatenation and other bugs in the JS backend. Fixed a small bug in the IRC module.
-rwxr-xr-xcompiler/ecmasgen.nim108
-rwxr-xr-xdoc/lib.txt6
-rwxr-xr-xlib/ecmas/dom.nim1
-rw-r--r--lib/pure/irc.nim8
-rwxr-xr-xlib/pure/times.nim8
-rwxr-xr-xlib/system.nim3
-rwxr-xr-xlib/system/ecmasys.nim2
-rw-r--r--lib/system/reprjs.nim23
-rwxr-xr-xweb/nimrod.ini2
9 files changed, 117 insertions, 44 deletions
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim
index 4347bd283..d597da193 100755
--- a/compiler/ecmasgen.nim
+++ b/compiler/ecmasgen.nim
@@ -778,9 +778,10 @@ proc genSwap(p: var TProc, n: PNode, r: var TCompRes) =
 proc genFieldAddr(p: var TProc, n: PNode, r: var TCompRes) = 
   var a: TCompRes
   r.kind = etyBaseIndex
-  gen(p, n.sons[0], a)
-  if n.sons[1].kind != nkSym: InternalError(n.sons[1].info, "genFieldAddr")
-  var f = n.sons[1].sym
+  var b = if n.kind == nkHiddenAddr: n.sons[0] else: n
+  gen(p, b.sons[0], a)
+  if b.sons[1].kind != nkSym: InternalError(b.sons[1].info, "genFieldAddr")
+  var f = b.sons[1].sym
   if f.loc.r == nil: f.loc.r = mangleName(f)
   r.res = makeCString(ropeToStr(f.loc.r))
   r.com = mergeExpr(a)
@@ -1030,42 +1031,68 @@ proc genVarStmt(p: var TProc, n: PNode, r: var TCompRes) =
     genLineDir(p, a, r)
     genVarInit(p, v, a.sons[2], r)
 
-proc genConstStmt(p: var TProc, n: PNode, r: var TCompRes) = 
+proc genConstStmt(p: var TProc, n: PNode, r: var TCompRes) =
   genLineDir(p, n, r)
-  for i in countup(0, sonsLen(n) - 1): 
+  for i in countup(0, sonsLen(n) - 1):
     if n.sons[i].kind == nkCommentStmt: continue 
     assert(n.sons[i].kind == nkConstDef)
     var c = n.sons[i].sons[0].sym
     if (c.ast != nil) and (c.typ.kind in ConstantDataTypes) and
-        not (lfNoDecl in c.loc.flags): 
+        not (lfNoDecl in c.loc.flags):
       genLineDir(p, n.sons[i], r)
       genVarInit(p, c, c.ast, r)
 
-proc genNew(p: var TProc, n: PNode, r: var TCompRes) = 
+proc genNew(p: var TProc, n: PNode, r: var TCompRes) =
   var a: TCompRes
   gen(p, n.sons[1], a)
   var t = skipTypes(n.sons[1].typ, abstractVar).sons[0]
   if a.com != nil: appf(r.com, "$1;$n", [a.com])
   appf(r.com, "$1 = $2;$n", [a.res, createVar(p, t, true)])
 
-proc genOrd(p: var TProc, n: PNode, r: var TCompRes) = 
+proc genOrd(p: var TProc, 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)")
   else: InternalError(n.info, "genOrd")
   
-proc genConStrStr(p: var TProc, n: PNode, r: var TCompRes) = 
-  var a, b: TCompRes
+proc genConStrStr(p: var TProc, n: PNode, r: var TCompRes) =
+  var a: TCompRes
+
   gen(p, n.sons[1], a)
-  gen(p, n.sons[2], b)
-  r.com = mergeExpr(a.com, b.com)
-  if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyChar: 
-    a.res = ropef("[$1, 0]", [a.res])
-  if skipTypes(n.sons[2].typ, abstractVarRange).kind == tyChar: 
-    b.res = ropef("[$1, 0]", [b.res])
-  r.res = ropef("($1.slice(0,-1)).concat($2)", [a.res, b.res])
-
-proc genMagic(p: var TProc, n: PNode, r: var TCompRes) = 
+  r.com = mergeExpr(r.com, a.com)
+  if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyChar:
+    r.res.app(ropef("[$1].concat(", [a.res]))
+  else:
+    r.res.app(ropef("($1.slice(0,-1)).concat(", [a.res]))
+
+  for i in countup(2, sonsLen(n) - 2):
+    gen(p, n.sons[i], a)
+    r.com = mergeExpr(r.com, a.com)
+
+    if skipTypes(n.sons[i].typ, abstractVarRange).kind == tyChar:
+      r.res.app(ropef("[$1],", [a.res]))
+    else:
+      r.res.app(ropef("$1.slice(0,-1),", [a.res]))
+
+  gen(p, n.sons[sonsLen(n) - 1], a)
+  r.com = mergeExpr(r.com, a.com)
+  if skipTypes(n.sons[sonsLen(n) - 1].typ, abstractVarRange).kind == tyChar:
+    r.res.app(ropef("[$1, 0])", [a.res]))
+  else:
+    r.res.app(ropef("$1)", [a.res]))
+
+proc genRepr(p: var TProc, n: PNode, r: var TCompRes) =
+  var t = skipTypes(n.sons[1].typ, abstractVarRange)
+  case t.kind
+  of tyInt..tyInt64:
+    unaryExpr(p, n, r, "", "reprInt($1)")
+  of tyEnum, tyOrdinal:
+    binaryExpr(p, n, r, "", "reprEnum($1, $2)")
+  else:
+    # XXX:
+    internalError(n.info, "genRepr: Not implemented")
+
+proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
   var 
     a: TCompRes
     line, filen: PRope
@@ -1073,54 +1100,59 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
   case op
   of mOr: genOr(p, n.sons[1], n.sons[2], r)
   of mAnd: genAnd(p, n.sons[1], n.sons[2], r)
-  of mAddi..mStrToStr: arith(p, n, r, op)        #mRepr: genRepr(p, n, r);
+  of mAddi..mStrToStr: arith(p, n, r, op)
+  of mRepr: genRepr(p, n, r)
   of mSwap: genSwap(p, n, r)
-  of mUnaryLt: 
+  of mUnaryLt:
     # XXX: range checking?
     if not (optOverflowCheck in p.Options): unaryExpr(p, n, r, "", "$1 - 1")
     else: unaryExpr(p, n, r, "subInt", "subInt($1, 1)")
-  of mPred: 
+  of mPred:
     # XXX: range checking?
     if not (optOverflowCheck in p.Options): binaryExpr(p, n, r, "", "$1 - $2")
     else: binaryExpr(p, n, r, "subInt", "subInt($1, $2)")
-  of mSucc: 
+  of mSucc:
     # XXX: range checking?
     if not (optOverflowCheck in p.Options): binaryExpr(p, n, r, "", "$1 - $2")
     else: binaryExpr(p, n, r, "addInt", "addInt($1, $2)")
   of mAppendStrCh: binaryStmt(p, n, r, "addChar", "$1 = addChar($1, $2)")
-  of mAppendStrStr: 
-    binaryStmt(p, n, r, "", "$1 = ($1.slice(0,-1)).concat($2)") 
-    # XXX: make a copy of $2, because of EMCAScript's sucking semantics
+  of mAppendStrStr:
+    if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyCString:
+        binaryStmt(p, n, r, "", "$1 += $2")
+    else:
+      binaryStmt(p, n, r, "", "$1 = ($1.slice(0,-1)).concat($2)")
+    # XXX: make a copy of $2, because of ECMAScript's sucking semantics
   of mAppendSeqElem: binaryStmt(p, n, r, "", "$1.push($2)")
   of mConStrStr: genConStrStr(p, n, r)
   of mEqStr: binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)")
   of mLeStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) <= 0)")
   of mLtStr: binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) < 0)")
   of mIsNil: unaryExpr(p, n, r, "", "$1 == null")
-  of mAssert: 
-    if (optAssert in p.Options): 
+  of mEnumToStr: genRepr(p, n, r)
+  of mAssert:
+    if (optAssert in p.Options):
       useMagic(p, "internalAssert")
       gen(p, n.sons[1], a)
       line = toRope(toLinenumber(n.info))
       filen = makeCString(ToFilename(n.info))
-      appf(r.com, "if (!($3)) internalAssert($1, $2)", 
+      appf(r.com, "if (!($3)) internalAssert($1, $2)",
            [filen, line, mergeExpr(a)])
   of mNew, mNewFinalize: genNew(p, n, r)
   of mSizeOf: r.res = toRope(getSize(n.sons[1].typ))
   of mChr: gen(p, n.sons[1], r)      # nothing to do
   of mOrd: genOrd(p, n, r)
   of mLengthStr: unaryExpr(p, n, r, "", "($1.length-1)")
-  of mLengthSeq, mLengthOpenArray, mLengthArray: 
+  of mLengthSeq, mLengthOpenArray, mLengthArray:
     unaryExpr(p, n, r, "", "$1.length")
-  of mHigh: 
-    if skipTypes(n.sons[0].typ, abstractVar).kind == tyString: 
+  of mHigh:
+    if skipTypes(n.sons[0].typ, abstractVar).kind == tyString:
       unaryExpr(p, n, r, "", "($1.length-2)")
-    else: 
+    else:
       unaryExpr(p, n, r, "", "($1.length-1)")
-  of mInc: 
+  of mInc:
     if not (optOverflowCheck in p.Options): binaryStmt(p, n, r, "", "$1 += $2")
     else: binaryStmt(p, n, r, "addInt", "$1 = addInt($1, $2)")
-  of ast.mDec: 
+  of ast.mDec:
     if not (optOverflowCheck in p.Options): binaryStmt(p, n, r, "", "$1 -= $2")
     else: binaryStmt(p, n, r, "subInt", "$1 = subInt($1, $2)")
   of mSetLengthStr: binaryStmt(p, n, r, "", "$1.length = ($2)-1")
@@ -1135,12 +1167,12 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
   of mIncl: binaryStmt(p, n, r, "", "$1[$2] = true")
   of mExcl: binaryStmt(p, n, r, "", "delete $1[$2]")
   of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)")
-  of mNLen..mNError: 
+  of mNLen..mNError:
     localError(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
   of mNewSeq: binaryStmt(p, n, r, "", "$1 = new Array($2)")
   of mEcho: genEcho(p, n, r)
-  else: 
-    genCall(p, n, r)          
+  else:
+    genCall(p, n, r)
     #else internalError(e.info, 'genMagic: ' + magicToStr[op]);
   
 proc genSetConstr(p: var TProc, n: PNode, r: var TCompRes) = 
diff --git a/doc/lib.txt b/doc/lib.txt
index 0b30056ee..179861d01 100755
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -274,6 +274,12 @@ Database support
   redis-server instance, send commands and receive replies.
 
 
+Modules for JS backend
+---------------------------
+
+* `dom <dom.html>`_
+  Declaration of the Document Object Model for the ECMAScript backend.
+
 
 Impure libraries
 ================
diff --git a/lib/ecmas/dom.nim b/lib/ecmas/dom.nim
index e9c587928..3a1caecbe 100755
--- a/lib/ecmas/dom.nim
+++ b/lib/ecmas/dom.nim
@@ -227,6 +227,7 @@ type
     getAttributeNode*: proc (attr: cstring): ref TNode
     getElementsByTagName*: proc (): seq[ref TNode]
     hasChildNodes*: proc (): bool
+    innerHTML*: cstring
     insertBefore*: proc (newNode, before: ref TNode)
     insertData*: proc (position: int, data: cstring)
     removeAttribute*: proc (attr: cstring)
diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim
index 5a4c815f6..0397502cd 100644
--- a/lib/pure/irc.nim
+++ b/lib/pure/irc.nim
@@ -70,7 +70,12 @@ type
   
 proc send*(irc: var TIRC, message: string) =
   ## Sends ``message`` as a raw command. It adds ``\c\L`` for you.
-  irc.sock.send(message & "\c\L")
+  try:
+    irc.sock.send(message & "\c\L")
+  except EOS:
+    # Assuming disconnection of every EOS could be bad,
+    # but I can't exactly check for EBrokenPipe.
+    irc.connected = false
 
 proc privmsg*(irc: var TIRC, target, message: string) =
   ## Sends ``message`` to ``target``. ``Target`` can be a channel, or a user.
@@ -199,6 +204,7 @@ proc poll*(irc: var TIRC, ev: var TIRCEvent,
   ##
   ## This function should be called often as it also handles pinging
   ## the server.
+  if not irc.connected: ev.typ = EvDisconnected
   var line = ""
   var socks = @[irc.sock]
   var ret = socks.select(timeout)
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index da23d4615..378d6ae80 100755
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -52,7 +52,7 @@ elif defined(windows):
 
 elif defined(ECMAScript):
   type
-    TTime* {.final.} = object
+    TTime* {.final, importc.} = object
       getDay: proc (): int
       getFullYear: proc (): int
       getHours: proc (): int
@@ -62,6 +62,7 @@ elif defined(ECMAScript):
       getSeconds: proc (): int
       getTime: proc (): int
       getTimezoneOffset: proc (): int
+      getDate: proc (): int
       getUTCDate: proc (): int
       getUTCFullYear: proc (): int
       getUTCHours: proc (): int
@@ -310,7 +311,8 @@ when not defined(ECMAScript):
       result = toFloat(int(clock())) / toFloat(clocksPerSec)
     
 else:
-  proc getTime(): TTime {.importc: "new Date", nodecl.}
+  proc newDate(): TTime {.importc: "new Date", nodecl.}
+  proc getTime(): TTime = return newDate()
 
   const
     weekDays: array [0..6, TWeekDay] = [
@@ -346,7 +348,7 @@ else:
     result.setDate(timeInfo.monthday)
   
   proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo))
-  proc `$`(time: TTime): string = $time.toLocaleString()
+  proc `$`(time: TTime): string = return $time.toLocaleString()
     
   proc `-` (a, b: TTime): int64 = 
     return a.getTime() - b.getTime()
diff --git a/lib/system.nim b/lib/system.nim
index ea004b925..644202d8c 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1495,6 +1495,8 @@ else:
       `x`[0][len] = 0
     """
 
+  proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".}
+
 proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo", noSideEffect.}
   ## special built-in that takes a variable number of arguments. Each argument
   ## is converted to a string via ``$``, so it works for user-defined
@@ -1886,6 +1888,7 @@ elif defined(ecmaScript) or defined(NimrodVM):
 
   when defined(ecmaScript):
     include "system/ecmasys"
+    include "system/reprjs"
   elif defined(NimrodVM):
     proc cmp(x, y: string): int =
       if x == y: return 0
diff --git a/lib/system/ecmasys.nim b/lib/system/ecmasys.nim
index ece33d9dc..5dc01f46e 100755
--- a/lib/system/ecmasys.nim
+++ b/lib/system/ecmasys.nim
@@ -228,7 +228,7 @@ proc cmp(x, y: string): int = return cmpStrings(x, y)
 
 proc eqStrings(a, b: string): bool {.noStackFrame, compilerProc.} =
   asm """
-    if (`a == `b`) return true;
+    if (`a` == `b`) return true;
     if ((!`a`) || (!`b`)) return false;
     var alen = `a`.length;
     if (alen != `b`.length) return false;
diff --git a/lib/system/reprjs.nim b/lib/system/reprjs.nim
new file mode 100644
index 000000000..b6b6ffe9c
--- /dev/null
+++ b/lib/system/reprjs.nim
@@ -0,0 +1,23 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2011 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+proc reprInt(x: int64): string {.compilerproc.} = return $x
+
+proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
+  if ntfEnumHole notin typ.flags:
+    if e <% typ.node.len:
+      return $typ.node.sons[e].name
+  else:
+    # ugh we need a slow linear search:
+    var n = typ.node
+    var s = n.sons
+    for i in 0 .. n.len-1:
+      if s[i].offset == e: return $s[i].name
+  result = $e & " (invalid data!)"
+
diff --git a/web/nimrod.ini b/web/nimrod.ini
index 93fa0bfc2..f2719ae4f 100755
--- a/web/nimrod.ini
+++ b/web/nimrod.ini
@@ -41,7 +41,7 @@ srcdoc: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics"
 srcdoc: "impure/rdstdin;wrappers/zmq;wrappers/sphinx"
 srcdoc: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
 srcdoc: "pure/collections/intsets;pure/collections/queues;pure/encodings"
-srcdoc: "pure/events;pure/collections/sequtils;pure/irc"
+srcdoc: "pure/events;pure/collections/sequtils;pure/irc;ecmas/dom"
 
 webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
 webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"