summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-06-02 19:52:06 +0300
committerZahary Karadjov <zahary@gmail.com>2012-06-02 19:52:06 +0300
commit88f7b7bc500325cc7399022c3dc137539d0f2640 (patch)
treed9e0d97895dc413b52c3eb9f9b523618fe76bfdc
parenta1da1f987b28ed041c3f3ad2317e756e2125aa30 (diff)
parent232ab71f208e341da327e54afa8a6d287141836b (diff)
downloadNim-88f7b7bc500325cc7399022c3dc137539d0f2640.tar.gz
Merge branch 'master' of github.com:Araq/Nimrod into upstream
-rwxr-xr-xcompiler/ast.nim3
-rw-r--r--compiler/ccgcalls.nim15
-rwxr-xr-xcompiler/ccgexprs.nim36
-rwxr-xr-xcompiler/ccgstmts.nim31
-rwxr-xr-xcompiler/ccgtypes.nim11
-rwxr-xr-xcompiler/ccgutils.nim9
-rwxr-xr-xcompiler/ecmasgen.nim3
-rwxr-xr-xcompiler/evals.nim2
-rwxr-xr-xcompiler/lookups.nim21
-rwxr-xr-xcompiler/renderer.nim2
-rwxr-xr-xcompiler/semgnrc.nim2
-rwxr-xr-xcompiler/semstmts.nim8
-rwxr-xr-xcompiler/transf.nim6
-rwxr-xr-xcompiler/types.nim13
-rwxr-xr-xconfig/nimrod.cfg1
-rwxr-xr-xlib/core/macros.nim23
-rwxr-xr-xlib/core/typeinfo.nim3
-rwxr-xr-xlib/pure/times.nim174
-rwxr-xr-xlib/system.nim41
-rwxr-xr-xlib/system/assign.nim12
-rwxr-xr-xlib/system/excpt.nim9
-rwxr-xr-xpackages/docutils/rst.nim9
-rwxr-xr-xtests/compile/ttempl3.nim15
-rw-r--r--tests/reject/tenummix.nim11
-rw-r--r--tests/run/tdumptree.nim27
-rw-r--r--tests/run/tgenericprocvar.nim19
-rw-r--r--tests/run/tsequtils.nim2
-rwxr-xr-xtodo.txt17
-rwxr-xr-xtools/niminst/buildsh.tmpl7
-rwxr-xr-xtools/niminst/install.tmpl36
-rwxr-xr-xweb/news.txt5
31 files changed, 459 insertions, 114 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index c59c47453..d9ec70450 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -145,6 +145,7 @@ type
     nkIfStmt,             # an if statement
     nkWhenStmt,           # a when expression or statement
     nkForStmt,            # a for statement
+    nkParForStmt,         # a parallel for statement
     nkWhileStmt,          # a while statement
     nkCaseStmt,           # a case statement
     nkTypeSection,        # a type section (consists of type definitions)
@@ -396,7 +397,7 @@ type
     mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, 
     mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, 
     mConTArr, mConTT, mSlice, 
-    mFields, mFieldPairs,
+    mFields, mFieldPairs, mOmpParFor,
     mAppendStrCh, mAppendStrStr, mAppendSeqElem, 
     mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, 
     mIsPartOf, mAstToStr, mRand, 
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index f2fa6a280..17139f055 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -20,7 +20,8 @@ proc hasNoInit(call: PNode): bool {.inline.} =
 
 proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
   var pl = pl
-  var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
+  # getUniqueType() is too expensive here:
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   if typ.sons[0] != nil:
     if isInvalidReturnType(typ.sons[0]):
       if sonsLen(ri) > 1: app(pl, ", ")
@@ -124,7 +125,8 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
   # this is a hotspot in the compiler
   initLocExpr(p, ri.sons[0], op)
   var pl = con(op.r, "(")
-  var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
+  # getUniqueType() is too expensive here:
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   for i in countup(1, length - 1):
@@ -150,7 +152,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
   var op: TLoc
   initLocExpr(p, ri.sons[0], op)
   var pl: PRope
-  var typ = ri.sons[0].typ
+  
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   for i in countup(1, length - 1):
@@ -201,7 +204,8 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
   var op, a: TLoc
   initLocExpr(p, ri.sons[0], op)
   var pl: PRope = nil
-  var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
+  # getUniqueType() is too expensive here:
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   assert(sonsLen(typ) == sonsLen(typ.n))
@@ -228,7 +232,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
   var op, a: TLoc
   initLocExpr(p, ri.sons[0], op)
   var pl = toRope"["
-  var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
+  # getUniqueType() is too expensive here:
+  var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   assert(sonsLen(typ) == sonsLen(typ.n))
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index eb20153fc..7a0face5e 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -283,7 +283,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
 
 proc expr(p: BProc, e: PNode, d: var TLoc)
 proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
-  initLoc(result, locNone, getUniqueType(e.typ), OnUnknown)
+  initLoc(result, locNone, e.typ, OnUnknown)
   expr(p, e, result)
 
 proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
@@ -543,17 +543,17 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
 
 proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
   initLocExpr(p, e.sons[0], a)
-  if (e.sons[1].kind != nkSym): InternalError(e.info, "genRecordFieldAux")
+  if e.sons[1].kind != nkSym: InternalError(e.info, "genRecordFieldAux")
   if d.k == locNone: d.s = a.s
   discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
-  result = getUniqueType(a.t)
+  result = a.t
 
 proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
   var a: TLoc
   var ty = genRecordFieldAux(p, e, d, a)
   var r = rdLoc(a)
   var f = e.sons[1].sym
-  if ty.n == nil:
+  if ty.kind == tyTuple:
     # we found a unique tuple type which lacks field information
     # so we use Field$i
     appf(r, ".Field$1", [toRope(f.position)])
@@ -561,14 +561,14 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
   else:
     var field: PSym = nil
     while ty != nil:
-      if not (ty.kind in {tyTuple, tyObject}):
+      if ty.kind notin {tyTuple, tyObject}:
         InternalError(e.info, "genRecordField")
       field = lookupInRecord(ty.n, f.name)
       if field != nil: break
       if gCmd != cmdCompileToCpp: app(r, ".Sup")
       ty = GetUniqueType(ty.sons[0])
-    if field == nil: InternalError(e.info, "genRecordField")
-    if field.loc.r == nil: InternalError(e.info, "genRecordField")
+    if field == nil: InternalError(e.info, "genRecordField 2 ")
+    if field.loc.r == nil: InternalError(e.info, "genRecordField 3")
     appf(r, ".$1", [field.loc.r])
     putIntoDest(p, d, field.typ, r)
 
@@ -579,16 +579,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
   initLocExpr(p, e.sons[0], a)
   if d.k == locNone: d.s = a.s
   discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
-  var ty = getUniqueType(a.t)
+  var ty = a.t
   var r = rdLoc(a)
   case e.sons[1].kind
   of nkIntLit..nkInt64Lit: i = int(e.sons[1].intVal)
   else: internalError(e.info, "genTupleElem")
-  if ty.n != nil:
-    var field = ty.n.sons[i].sym
-    if field == nil: InternalError(e.info, "genTupleElem")
-    if field.loc.r == nil: InternalError(e.info, "genTupleElem")
-    appf(r, ".$1", [field.loc.r])
+  when false:
+    if ty.n != nil:
+      var field = ty.n.sons[i].sym
+      if field == nil: InternalError(e.info, "genTupleElem")
+      if field.loc.r == nil: InternalError(e.info, "genTupleElem")
+      appf(r, ".$1", [field.loc.r])
   else:
     appf(r, ".Field$1", [toRope(i)])
   putIntoDest(p, d, ty.sons[i], r)
@@ -1510,11 +1511,10 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
     for i in countup(0, sonsLen(n) - 1):
       var it = n.sons[i]
       if it.kind == nkExprColonExpr: it = it.sons[1]
-      if t.n == nil:
-        initLoc(rec, locExpr, it.typ, d.s)
-        rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)])
-        expr(p, it, rec)
-      else:
+      initLoc(rec, locExpr, it.typ, d.s)
+      rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)])
+      expr(p, it, rec)
+      when false:
         initLoc(rec, locExpr, it.typ, d.s)
         if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genTupleConstr")
         rec.r = ropef("$1.$2",
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index db6d5bd67..46e4f75df 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -32,7 +32,7 @@ proc genVarTuple(p: BProc, n: PNode) =
       assignLocalVar(p, v)
       initLocalVar(p, v, immediateAsgn=true)
     initLoc(field, locExpr, t.sons[i], tup.s)
-    if t.n == nil: 
+    if t.kind == tyTuple: 
       field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
     else: 
       if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genVarTuple")
@@ -258,6 +258,34 @@ proc genBlock(p: BProc, t: PNode, d: var TLoc) =
     else: genStmts(p, t.sons[1])
     endBlock(p)
   
+proc genParForStmt(p: BProc, t: PNode) =
+  assert(sonsLen(t) == 3)
+  inc(p.withinLoop)
+  genLineDir(p, t)
+
+  preserveBreakIdx:
+    let forLoopVar = t.sons[0].sym
+    var rangeA, rangeB: TLoc
+    assignLocalVar(P, forLoopVar)
+    #initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
+    #discard mangleName(forLoopVar)
+    let call = t.sons[1]
+    initLocExpr(p, call.sons[1], rangeA)
+    initLocExpr(p, call.sons[2], rangeB)
+    
+    appf(p.s(cpsStmts), "#pragma omp parallel for $4$n" &
+                        "for ($1 = $2; $1 <= $3; ++$1)", 
+                        forLoopVar.loc.rdLoc,
+                        rangeA.rdLoc, rangeB.rdLoc,
+                        call.sons[3].getStr.toRope)
+    
+    p.breakIdx = startBlock(p)
+    p.blocks[p.breakIdx].isLoop = true
+    genStmts(p, t.sons[2])
+    endBlock(p)
+
+  dec(p.withinLoop)
+  
 proc genBreakStmt(p: BProc, t: PNode) = 
   var idx = p.breakIdx
   if t.sons[0].kind != nkEmpty: 
@@ -815,5 +843,6 @@ proc genStmts(p: BProc, t: PNode) =
         # we have not only the header: 
         if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags: 
           genProc(p.module, prc)
+  of nkParForStmt: genParForStmt(p, t)
   else: internalError(t.info, "genStmts(" & $t.kind & ')')
   
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 1b3e84cc4..4492c2fea 100755
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -144,7 +144,7 @@ proc mapSetType(typ: PType): TCTypeKind =
 
 proc mapType(typ: PType): TCTypeKind = 
   case typ.kind
-  of tyNone: result = ctVoid
+  of tyNone, tyStmt: result = ctVoid
   of tyBool: result = ctBool
   of tyChar: result = ctChar
   of tySet: result = mapSetType(typ)
@@ -561,7 +561,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
         appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result])
       IdTablePut(m.forwTypeCache, t, result)
     IdTablePut(m.typeCache, t, result) # always call for sideeffects:
-    if t.n != nil: recdesc = getRecordDesc(m, t, result, check)
+    if t.kind != tyTuple: recdesc = getRecordDesc(m, t, result, check)
     else: recdesc = getTupleDesc(m, t, result, check)
     if not isImportedType(t): app(m.s[cfsTypes], recdesc)
   of tySet: 
@@ -889,8 +889,11 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
   of tyEnum: genEnumInfo(gNimDat, t, result)
   of tyObject: genObjectInfo(gNimDat, t, result)
   of tyTuple: 
-    if t.n != nil: genObjectInfo(gNimDat, t, result)
-    else: genTupleInfo(gNimDat, t, result)
+    # if t.n != nil: genObjectInfo(gNimDat, t, result)
+    # else:
+    # BUGFIX: use consistently RTTI without proper field names; otherwise
+    # results are not deterministic!
+    genTupleInfo(gNimDat, t, result)
   else: InternalError("genTypeInfo(" & $t.kind & ')')
 
 proc genTypeSection(m: BModule, n: PNode) = 
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 12795358a..5ba523070 100755
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -87,14 +87,19 @@ proc GetUniqueType*(key: PType): PType =
   of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
     result = GetUniqueType(lastSon(key))
   of tyArrayConstr, tyGenericInvokation, tyGenericBody,
-     tyOpenArray, tyArray, tyTuple, tySet, tyRange, 
+     tyOpenArray, tyArray, tySet, tyRange, tyTuple,
      tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar:
+    # tuples are quite horrible as C does not support them directly and
+    # tuple[string, string] is a (strange) subtype of
+    # tuple[nameA, nameB: string]. This bites us here, so we 
+    # use 'sameBackendType' instead of 'sameType'.
+
     # we have to do a slow linear search because types may need
     # to be compared by their structure:
     if IdTableHasObjectAsKey(gTypeTable[k], key): return key 
     for h in countup(0, high(gTypeTable[k].data)): 
       var t = PType(gTypeTable[k].data[h].key)
-      if t != nil and sameType(t, key): 
+      if t != nil and sameBackendType(t, key): 
         return t
     IdTablePut(gTypeTable[k], key, key)
     result = key
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim
index 9c9c01734..07754ee13 100755
--- a/compiler/ecmasgen.nim
+++ b/compiler/ecmasgen.nim
@@ -1343,7 +1343,8 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
   of nkWhileStmt: genWhileStmt(p, n, r)
   of nkVarSection, nkLetSection: genVarStmt(p, n, r)
   of nkConstSection: genConstStmt(p, n, r)
-  of nkForStmt: internalError(n.info, "for statement not eliminated")
+  of nkForStmt, nkParForStmt: 
+    internalError(n.info, "for statement not eliminated")
   of nkCaseStmt: genCaseStmt(p, n, r)
   of nkReturnStmt: genReturnStmt(p, n, r)
   of nkBreakStmt: genBreakStmt(p, n, r)
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 002fed194..5c77a4d94 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -1331,7 +1331,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
   of nkPragmaBlock:
     result = evalAux(c, n.sons[1], flags)
   of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, 
-     nkLambdaKinds, nkContinueStmt, nkIdent: 
+     nkLambdaKinds, nkContinueStmt, nkIdent, nkParForStmt: 
     result = raiseCannotEval(c, n.info)
   of nkRefTy:
     result = evalAux(c, n.sons[0], flags)
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 62f4a3391..d9725eedf 100755
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -21,18 +21,19 @@ proc considerAcc*(n: PNode): PIdent =
     case n.len
     of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n))
     of 1: result = considerAcc(n.sons[0])
-    of 2:
-      if n[0].ident.id == ord(wStar):
+    else:
+      if n.len == 2 and n[0].kind == nkIdent and n[0].ident.id == ord(wStar):
+        # XXX find a better way instead of `*x` for 'genSym'
         result = genSym(n[1].ident.s)
       else:
-        result = getIdent(n[0].ident.s & n[1].ident.s)
-    else:
-      var id = ""
-      for i in 0.. <n.len:
-        if n.sons[i].kind != nkIdent:
-          GlobalError(n.info, errIdentifierExpected, renderTree(n))
-        id.add(n.sons[i].ident.s)
-      result = getIdent(id)
+        var id = ""
+        for i in 0.. <n.len:
+          let x = n.sons[i]
+          case x.kind
+          of nkIdent: id.add(x.ident.s)
+          of nkSym: id.add(x.sym.name.s)
+          else: GlobalError(n.info, errIdentifierExpected, renderTree(n))
+        result = getIdent(id)
   else:
     GlobalError(n.info, errIdentifierExpected, renderTree(n))
 
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 67b657657..a5e79762c 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -984,7 +984,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkCaseStmt, nkRecCase: gcase(g, n)
   of nkMacroStmt: gmacro(g, n)
   of nkTryStmt: gtry(g, n)
-  of nkForStmt: gfor(g, n)
+  of nkForStmt, nkParForStmt: gfor(g, n)
   of nkBlockStmt, nkBlockExpr: gblock(g, n)
   of nkStaticStmt: gstaticStmt(g, n)
   of nkAsmStmt: gasm(g, n)
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index d8f017c4c..f7e64bdee 100755
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -142,7 +142,7 @@ proc semGenericStmt(c: PContext, n: PNode,
         a.sons[j] = semGenericStmt(c, a.sons[j], flags, toBind)
       a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, toBind)
     closeScope(c.tab)
-  of nkForStmt: 
+  of nkForStmt, nkParForStmt: 
     var L = sonsLen(n)
     openScope(c.tab)
     n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, toBind)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 943c49bad..82f43e787 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -465,7 +465,11 @@ proc semFor(c: PContext, n: PNode): PNode =
     else:
       GlobalError(n.sons[length - 2].info, errIteratorExpected)
   elif call.sons[0].sym.magic != mNone:
-    result = semForFields(c, n, call.sons[0].sym.magic)
+    if call.sons[0].sym.magic == mOmpParFor:
+      result = semForVars(c, n)
+      result.kind = nkParForStmt
+    else:
+      result = semForFields(c, n, call.sons[0].sym.magic)
   else:
     result = semForVars(c, n)
   closeScope(c.tab)
@@ -979,7 +983,7 @@ proc SemStmt(c: PContext, n: PNode): PNode =
   of nkWhileStmt: result = semWhile(c, n)
   of nkTryStmt: result = semTry(c, n)
   of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
-  of nkForStmt: result = semFor(c, n)
+  of nkForStmt, nkParForStmt: result = semFor(c, n)
   of nkCaseStmt: result = semCase(c, n)
   of nkReturnStmt: result = semReturn(c, n)
   of nkAsmStmt: result = semAsm(c, n)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 9e0d4051f..0ab8bc8d3 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -247,7 +247,7 @@ proc transformConstSection(c: PTransf, v: PNode): PTransNode =
 
 proc hasContinue(n: PNode): bool = 
   case n.kind
-  of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil
+  of nkEmpty..nkNilLit, nkForStmt, nkParForStmt, nkWhileStmt: nil
   of nkContinueStmt: result = true
   else: 
     for i in countup(0, sonsLen(n) - 1): 
@@ -659,6 +659,10 @@ proc transform(c: PTransf, n: PNode): PTransNode =
     inc c.inLoop
     result = transformFor(c, n)
     dec c.inLoop
+  of nkParForStmt:
+    inc c.inLoop
+    result = transformSons(c, n)
+    dec c.inLoop
   of nkCaseStmt: result = transformCase(c, n)
   of nkContinueStmt:
     result = PTransNode(newNode(nkBreakStmt))
diff --git a/compiler/types.nim b/compiler/types.nim
index 633524eff..2f201b9de 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -550,6 +550,7 @@ type
 
   TSameTypeClosure = object {.pure.}
     cmp: TDistinctCompare
+    ignoreTupleFields: bool
     recCheck: int
     s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster
                             # (few elements expected)
@@ -645,7 +646,7 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
     for i in countup(0, sonsLen(a) - 1): 
       result = SameTypeAux(a.sons[i], b.sons[i], c)
       if not result: return 
-    if a.n != nil and b.n != nil: 
+    if a.n != nil and b.n != nil and not c.ignoreTupleFields: 
       for i in countup(0, sonsLen(a.n) - 1): 
         # check field names: 
         if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "sameTuple")
@@ -787,6 +788,11 @@ proc SameType*(x, y: PType): bool =
   var c = initSameTypeClosure()
   result = sameTypeAux(x, y, c)
   
+proc sameBackendType*(x, y: PType): bool =
+  var c = initSameTypeClosure()
+  c.ignoreTupleFields = true
+  result = sameTypeAux(x, y, c)
+  
 proc compareTypes*(x, y: PType, cmp: TDistinctCompare): bool =
   ## compares two type for equality (modulo type distinction)
   var c = initSameTypeClosure()
@@ -863,8 +869,9 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
       result = typeAllowedAux(marker, t.sons[0], skResult)
   of tyExpr, tyStmt, tyTypeDesc: 
     result = true
-  of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation, tyTypeClass:
-    result = false            #InternalError('shit found');
+  of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation, 
+      tyTypeClass:
+    result = false
   of tyEmpty, tyNil:
     result = kind == skConst
   of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer: 
diff --git a/config/nimrod.cfg b/config/nimrod.cfg
index 21cf55ec9..c98f30f02 100755
--- a/config/nimrod.cfg
+++ b/config/nimrod.cfg
@@ -60,6 +60,7 @@ hint[LineTooLong]=off
 
 @if unix:
   @if not bsd:
+    # -fopenmp
     gcc.options.linker = "-ldl"
     clang.options.linker = "-ldl"
     tcc.options.linker = "-ldl"
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 8b08952f0..b0f237924 100755
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -36,7 +36,7 @@ type
     nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch, 

     nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt, 

     nnkAsmStmt, nnkPragma, nnkPragmaBlock, nnkIfStmt, nnkWhenStmt, 

-    nnkForStmt, nnkWhileStmt, nnkCaseStmt, 

+    nnkForStmt, nnkParForStmt, nnkWhileStmt, nnkCaseStmt, 

     nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection, 

     nnkConstDef, nnkTypeDef, 

     nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt, 

@@ -217,10 +217,19 @@ template emit*(s: expr): stmt =
   ## Example:

   ## 

   ##   emit("echo " & '"' & "hello world".toUpper & '"')

-  ##

-  block:

-    const evaluated = s

-    eval: result = evaluated.parseStmt

+  ##
+  block:
+    const evaluated = s
+    eval: result = evaluated.parseStmt
+  when false:

+    template once(x: expr): expr =
+      block:
+        const y = x
+        y
+
+    macro `payload`(x: stmt): stmt = result = once(s).parseStmt
+    `payload`()
+
 

 proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =

   ## checks that `n` is of kind `k`. If this is not the case,

@@ -323,7 +332,7 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
 

 macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr

   ## Accepts a block of nimrod code and prints the parsed abstract syntax

-  ## tree using the `toTree` function.

+  ## tree using the `toTree` function. Printing is done *at compile time*.

   ##

   ## You can use this as a tool to explore the Nimrod's abstract syntax 

   ## tree and to discover what kind of nodes must be created to represent

@@ -331,7 +340,7 @@ macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr
 

 macro dumpLisp*(s: stmt): stmt = echo s[1].lispRepr

   ## Accepts a block of nimrod code and prints the parsed abstract syntax

-  ## tree using the `toLisp` function.

+  ## tree using the `toLisp` function. Printing is done *at compile time*.

   ##

   ## See `dumpTree`.

 

diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index 9cc8e4dfd..ca2b68cc3 100755
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -479,7 +479,8 @@ proc setBiggestFloat*(x: TAny, y: biggestFloat) =
 proc getString*(x: TAny): string = 
   ## retrieve the string value out of `x`. `x` needs to represent a string.
   assert x.rawtype.kind == tyString
-  result = cast[ptr string](x.value)[]
+  if not isNil(cast[ptr pointer](x.value)[]):
+    result = cast[ptr string](x.value)[]
 
 proc setString*(x: TAny, y: string) = 
   ## sets the string value of `x`. `x` needs to represent a string.
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 968b317d6..4cb873b1c 100755
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -24,7 +24,11 @@ type
     mJan, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec
   TWeekDay* = enum ## represents a weekday
     dMon, dTue, dWed, dThu, dFri, dSat, dSun
-    
+
+var
+  timezone {.importc, header: "<time.h>".}: int
+  tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
+
 when defined(posix): 
   type
     TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int
@@ -112,6 +116,20 @@ type
     yearday*: range[0..365]   ## The number of days since January 1,
                               ## in the range 0 to 365.
                               ## Always 0 if the target is ECMAScript.
+    isDST*: bool              ## Determines whether DST is in effect. Always
+                              ## ``False`` if time is UTC.
+    tzname*: string           ## The timezone this time is in. E.g. GMT
+    timezone*: int            ## The offset of the (non-DST) timezone in seconds
+                              ## west of UTC.
+
+  TTimeInterval* = object
+    miliseconds*: int ## The number of miliseconds
+    seconds*: int     ## The number of seconds
+    minutes*: int     ## The number of minutes
+    hours*: int       ## The number of hours
+    days*: int        ## The number of days
+    months*: int      ## The number of months
+    years*: int       ## The number of years
 
 proc getTime*(): TTime ## gets the current calendar time
 proc getLocalTime*(t: TTime): TTimeInfo
@@ -122,7 +140,7 @@ proc getGMTime*(t: TTime): TTimeInfo
   ## expressed in Coordinated Universal Time (UTC).
 
 proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
-  ## converts a broken-down time structure, expressed as local time, to
+  ## converts a broken-down time structure to
   ## calendar time representation. The function ignores the specified
   ## contents of the structure members `weekday` and `yearday` and recomputes
   ## them from the other information in the broken-down time structure.
@@ -146,10 +164,90 @@ proc `<=` * (a, b: TTime): bool {.
   ## returns true iff ``a <= b``.
   result = a - b <= 0
 
+proc getTzname*(): tuple[nonDST, DST: string]
+  ## returns the local timezone; ``nonDST`` is the name of the local non-DST
+  ## timezone, ``DST`` is the name of the local DST timezone.
+
+proc getTimezone*(): int
+  ## returns the offset of the local (non-DST) timezone in seconds west of UTC.
+
 proc getStartMilsecs*(): int {.deprecated.}
   ## get the miliseconds from the start of the program. **Deprecated since
   ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
 
+proc newInterval*(miliseconds, seconds, minutes, hours, days, months, 
+                  years: int = 0): TTimeInterval =
+  ## creates a new ``TTimeInterval``.
+  result.miliseconds = miliseconds
+  result.seconds = seconds
+  result.minutes = minutes
+  result.hours = hours
+  result.days = days
+  result.months = months
+  result.years = years
+
+proc isLeapYear(year: int): bool =
+  if year mod 400 == 0:
+     return true
+  elif year mod 100 == 0: 
+     return false
+  elif year mod 4 == 0: 
+     return true
+  else:
+     return false
+
+proc getDaysInMonth(month: TMonth, year: int): int =
+  # http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month
+  if month == mFeb: # Feb
+    if isLeapYear(year):
+      result = 29
+    else:
+      result = 28
+  elif month in [mApr, mJun, mSep, mNov]: result = 30
+  else: result = 31  
+
+proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float =
+  var anew = a
+  var newinterv = interval
+  result = 0.0
+  
+  newinterv.months += interval.years * 12
+  var curMonth = anew.month
+  for mth in 1 .. newinterv.months:
+    result += float(getDaysInMonth(curMonth, anew.year) * 24 * 60 * 60)
+    if curMonth == mDec:
+      curMonth = mJan
+      anew.year.inc()
+    else:
+      curMonth.inc()
+  result += float(newinterv.days * 24 * 60 * 60)
+  result += float(newinterv.minutes * 60 * 60)
+  result += newinterv.seconds.float
+  result += newinterv.miliseconds / 1000
+
+proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
+  ## adds ``interval`` time.
+  ##
+  ## **Note:** This has been only briefly tested and it may not be very accurate.
+  let t = timeInfoToTime(a)
+  var secs = calculateSeconds(a, interval)
+  if a.tzname == "UTC":
+    result = getGMTime(TTime(float(t) + secs))
+  else:
+    result = getLocalTime(TTime(float(t) + secs))
+
+proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
+  ## subtracts ``interval`` time.
+  ##
+  ## **Note:** This has been only briefly tested, it is inaccurate especially
+  ## when you subtract so much that you reach the Julian calendar.
+  let t = timeInfoToTime(a)
+  var secs = calculateSeconds(a, interval)
+  if a.tzname == "UTC":
+    result = getGMTime(TTime(float(t) - secs))
+  else:
+    result = getLocalTime(TTime(float(t) - secs))
+
 when not defined(ECMAScript):  
   proc epochTime*(): float {.rtl, extern: "nt$1".}
     ## gets time after the UNIX epoch (1970) in seconds. It is a float
@@ -169,7 +267,8 @@ when not defined(ECMAScript):
     ##   doWork()
     ##   echo "CPU time [s] ", cpuTime() - t0
 
-when not defined(ECMAScript):  
+when not defined(ECMAScript):
+  
   # C wrapper:
   type
     structTM {.importc: "struct tm", final.} = object
@@ -205,7 +304,7 @@ when not defined(ECMAScript):
     clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
     
   # our own procs on top of that:
-  proc tmToTimeInfo(tm: structTM): TTimeInfo =
+  proc tmToTimeInfo(tm: structTM, local: bool): TTimeInfo =
     const
       weekDays: array [0..6, TWeekDay] = [
         dSun, dMon, dTue, dWed, dThu, dFri, dSat]
@@ -217,6 +316,18 @@ when not defined(ECMAScript):
     result.year = tm.year + 1900'i32
     result.weekday = weekDays[int(tm.weekDay)]
     result.yearday = int(tm.yearday)
+    result.isDST = tm.isDST > 0
+    #result.tzname = if local: getTzname()[if result.isDST: 0 else: 1] else: "UTC"
+    # TODO: ^^^ Crashes the compiler.
+    if local:
+      if result.isDST:
+        result.tzname = getTzname()[0]
+      if not result.isDST:
+        result.tzname = getTzname()[1]
+    else:
+      result.tzname = "UTC"
+    
+    result.timezone = if local: getTimezone() else: 0
   
   proc timeInfoToTM(t: TTimeInfo): structTM =
     const
@@ -229,7 +340,7 @@ when not defined(ECMAScript):
     result.year = t.year - 1900
     result.weekday = weekDays[t.weekDay]
     result.yearday = t.yearday
-    result.isdst = -1
+    result.isdst = if t.isDST: 1 else: 0
   
   when not defined(useNimRtl):
     proc `-` (a, b: TTime): int64 =
@@ -251,13 +362,13 @@ when not defined(ECMAScript):
   proc getTime(): TTime = return timec(nil)
   proc getLocalTime(t: TTime): TTimeInfo =
     var a = t
-    result = tmToTimeInfo(localtime(addr(a))[])
+    result = tmToTimeInfo(localtime(addr(a))[], true)
     # copying is needed anyway to provide reentrancity; thus
     # the convertion is not expensive
   
   proc getGMTime(t: TTime): TTimeInfo =
     var a = t
-    result = tmToTimeInfo(gmtime(addr(a))[])
+    result = tmToTimeInfo(gmtime(addr(a))[], false)
     # copying is needed anyway to provide reentrancity; thus
     # the convertion is not expensive
   
@@ -294,7 +405,13 @@ when not defined(ECMAScript):
   proc winTimeToUnixTime*(t: int64): TTime = 
     ## converts a Windows time to a UNIX `TTime` (``time_t``)
     result = TTime((t - epochDiff) div rateDiff)
-    
+ 
+  proc getTzname(): tuple[nonDST, DST: string] =
+    return ($tzname[0], $tzname[1])
+  
+  proc getTimezone(): int =
+    return timezone
+  
   when not defined(useNimRtl):
     proc epochTime(): float = 
       when defined(posix):
@@ -417,18 +534,21 @@ proc format*(info: TTimeInfo, f: string): string =
   ##    tt       Same as above, but ``AM`` and ``PM`` instead of ``A`` and ``P`` respectively.
   ##    y(yyyy)  This displays the year to different digits. You most likely only want 2 or 4 'y's
   ##    yy       Displays the year to two digits.                                                   ``2012 -> 12``
-  ##    yyyy     Displays the year to four digits.                                                  ``2012 -> 2012``                                
+  ##    yyyy     Displays the year to four digits.                                                  ``2012 -> 2012``
+  ##    z        Displays the timezone offset from UTC.                                             ``GMT+7 -> +7``, ``GMT-5 -> -5``
+  ##    zz       Same as above but with leading 0.                                                  ``GMT+7 -> +07``, ``GMT-5 -> -05``
+  ##    zzz      Same as above but with ``:00``.                                                    ``GMT+7 -> +07:00``, ``GMT-5 -> -05:00``
+  ##    ZZZ      Displays the name of the timezone.                                                 ``GMT -> GMT``, ``EST -> EST``
   ## ==========  =================================================================================  ================================================
-
+  ##
+  ## Other strings can be inserted by putting them in ``''``. For example ``hh'->'mm`` will give ``01->56``.
 
   result = ""
   var i = 0
   var currentF = ""
   while True:
     case f[i]
-    of '\0':
-      break
-    of ' ', '-', '/', ':', '\'':
+    of ' ', '-', '/', ':', '\'', '\0':
       case currentF
       of "d":
         result.add($info.monthday)
@@ -437,9 +557,9 @@ proc format*(info: TTimeInfo, f: string): string =
           result.add("0")
         result.add($info.monthday)
       of "ddd":
-        result.add(($info.month)[0 .. 2])
+        result.add(($info.monthday)[0 .. 2])
       of "dddd":
-        result.add($info.month)
+        result.add($info.monthday)
       of "h":
         result.add($(info.hour - 12))
       of "hh":
@@ -460,11 +580,11 @@ proc format*(info: TTimeInfo, f: string): string =
           result.add('0')
         result.add($info.minute)
       of "M":
-        result.add($(int(info.month)))
+        result.add($(int(info.month)+1))
       of "MM":
         if int(info.month) < 10:
           result.add('0')
-        result.add($(int(info.month)))
+        result.add($(int(info.month)+1))
       of "MMM":
         result.add(($info.month)[0..2])
       of "MMMM":
@@ -500,12 +620,32 @@ proc format*(info: TTimeInfo, f: string): string =
       of "yyyyy":
         result.add('0')
         result.add($info.year)
+      of "z":
+        let hrs = (info.timezone div 60) div 60
+        result.add($hrs)
+      of "zz":
+        let hrs = (info.timezone div 60) div 60
+        
+        result.add($hrs)
+        if hrs.abs < 10:
+          var atIndex = result.len-(($hrs).len-(if hrs < 0: 1 else: 0))
+          result.insert("0", atIndex)
+      of "zzz":
+        let hrs = (info.timezone div 60) div 60
+        
+        result.add($hrs & ":00")
+        if hrs.abs < 10:
+          var atIndex = result.len-(($hrs & ":00").len-(if hrs < 0: 1 else: 0))
+          result.insert("0", atIndex)
+      of "ZZZ":
+        result.add(info.tzname)
       of "":
         nil # Do nothing.
       else:
         raise newException(EInvalidValue, "Invalid format string: " & currentF)
       
       currentF = ""
+      if f[i] == '\0': break
       
       if f[i] == '\'':
         inc(i) # Skip '
diff --git a/lib/system.nim b/lib/system.nim
index 4a7ac0654..449b56c2f 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -49,9 +49,13 @@ type
                                 ## a type description (for templates)
   void* {.magic: "VoidType".}  ## meta type to denote the absense of any type
   
-  TInteger* = int|char|int8|int16|int32|int64|bool|enum
+  TInteger* = int|int8|int16|int32|int64
     ## type class matching all integer types
 
+  TOrdinal* = TInteger|bool|enum
+    ## type class matching all ordinal types; however this includes enums with
+    ## holes.
+
   TNumber* = TInteger|float|float32|float64
     ## type class matching all number types
 
@@ -190,6 +194,7 @@ type
     msg* {.exportc: "message".}: string ## the exception's message. Not
                                         ## providing an exception message 
                                         ## is bad style.
+    trace: string
 
   EAsynch* = object of E_Base ## Abstract exception class for
                               ## *asynchronous exceptions* (interrupts).
@@ -1195,6 +1200,15 @@ iterator `..`*[S, T](a: S, b: T): T {.inline.} =
     yield res
     inc res
 
+iterator `||`*[S, T](a: S, b: T, annotation=""): T {.
+  inline, magic: "OmpParFor", sideEffect.} =
+  ## parallel loop iterator. Same as `..` but the loop may run in parallel.
+  ## `annotation` is an additional annotation for the code generator to use.
+  ## Note that the compiler maps that to
+  ## the ``#pragma omp parallel for`` construct of `OpenMP`:idx: and as
+  ## such isn't aware of the parallelism in your code. Be careful.
+  nil
+
 proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
 proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.}
 proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.}
@@ -1900,6 +1914,10 @@ when not defined(EcmaScript) and not defined(NimrodVM):
   when hostOS != "standalone":
     proc getStackTrace*(): string
       ## gets the current stack trace. This is only works for debug builds.
+
+    proc getStackTrace*(e: ref E_Base): string
+      ## gets the stack trace associated with `e`, which is the stack that
+      ## lead to the ``raise`` statement. This is only works for debug builds.
       
   {.push stack_trace: off.}
   when hostOS == "standalone":
@@ -2177,19 +2195,19 @@ proc `*=`*[T](x: var ordinal[T], y: ordinal[T]) {.inline, noSideEffect.} =
   ## Binary `*=` operator for ordinals
   x = x * y
 
-proc `+=` *(x: var float, y:float) {.inline, noSideEffect.} =
+proc `+=`*[T: float|float32|float64] (x: var T, y: T) {.inline, noSideEffect.} =
   ## Increments in placee a floating point number
   x = x + y
 
-proc `-=` *(x: var float, y:float) {.inline, noSideEffect.} =
+proc `-=`*[T: float|float32|float64] (x: var T, y: T) {.inline, noSideEffect.} =
   ## Decrements in place a floating point number
   x = x - y
 
-proc `*=` *(x: var float, y:float) {.inline, noSideEffect.} =
+proc `*=`*[T: float|float32|float64] (x: var T, y: T) {.inline, noSideEffect.} =
   ## Multiplies in place a floating point number
   x = x * y
 
-proc `/=` *(x: var float, y:float) {.inline, noSideEffect.} =
+proc `/=`*[T: float|float32|float64] (x: var T, y: T) {.inline, noSideEffect.} =
   ## Divides in place a floating point number
   x = x / y
 
@@ -2283,5 +2301,18 @@ template eval*(blk: stmt): stmt =
     macro payload(x: stmt): stmt = blk
     payload()
 
+proc insert*(x: var string, item: string, i = 0) {.noSideEffect.} = 
+  ## inserts `item` into `x` at position `i`.
+  var xl = x.len
+  setLen(x, xl+item.len)
+  var j = xl-1
+  while j >= i:
+    shallowCopy(x[j+item.len], x[j])
+    dec(j)
+  j = 0
+  while j < item.len:
+    x[j+i] = item[j]
+    inc(j)
+
 when defined(initDebugger):
   initDebugger()
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index d1055fbb5..59c44a6cc 100755
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -7,6 +7,8 @@
 #    distribution, for details about the copyright.
 #
 
+proc genericResetAux(dest: Pointer, n: ptr TNimNode)
+
 proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool)
 proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
   var
@@ -20,10 +22,16 @@ proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
     for i in 0..n.len-1:
       genericAssignAux(dest, src, n.sons[i], shallow)
   of nkCase:
+    var dd = selectBranch(dest, n)
+    var m = selectBranch(src, n)
+    # reset if different branches are in use; note different branches also
+    # imply that's not self-assignment (``x = x``)!
+    if m != dd and dd != nil: 
+      genericResetAux(dest, dd)
     copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
             n.typ.size)
-    var m = selectBranch(src, n)
-    if m != nil: genericAssignAux(dest, src, m, shallow)
+    if m != nil:
+      genericAssignAux(dest, src, m, shallow)
   of nkNone: sysAssert(false, "genericAssignAux")
   #else:
   #  echo "ugh memory corruption! ", n.kind
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index a523e4e04..204fba376 100755
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -194,6 +194,9 @@ proc quitOrDebug() {.inline.} =
 
 proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
   e.name = ename
+  when hasSomeStackTrace:
+    e.trace = ""
+    rawWriteStackTrace(e.trace)
   if localRaiseHook != nil:
     if not localRaiseHook(e): return
   if globalRaiseHook != nil:
@@ -253,6 +256,12 @@ proc getStackTrace(): string =
   else:
     result = "No stack traceback available\n"
 
+proc getStackTrace(e: ref E_Base): string =
+  if not isNil(e) and not isNil(e.trace):
+    result = e.trace
+  else:
+    result = ""
+
 when defined(endb):
   var
     dbgAborting: bool # whether the debugger wants to abort
diff --git a/packages/docutils/rst.nim b/packages/docutils/rst.nim
index 16572abb4..126b21bd6 100755
--- a/packages/docutils/rst.nim
+++ b/packages/docutils/rst.nim
@@ -608,9 +608,16 @@ proc parseSmiley(p: var TRstParser): PRstNode =
       result.text = val
       return
 
+when false:
+  const
+    urlChars = {'A'..'Z', 'a'..'z', '0'..'9', ':', '#', '@', '%', '/', ';',
+                 '$', '(', ')', '~', '_', '?', '+', '-', '=', '\\', '.', '&',
+                 '\128'..'\255'}
+
 proc isURL(p: TRstParser, i: int): bool =
   result = (p.tok[i+1].symbol == ":") and (p.tok[i+2].symbol == "//") and
-          (p.tok[i+3].kind == tkWord) and (p.tok[i+4].symbol == ".")
+          (p.tok[i+3].kind == tkWord) and 
+          (p.tok[i].symbol in ["http", "ftp", "gopher", "telnet", "file"])
 
 proc parseURL(p: var TRstParser, father: PRstNode) = 
   #if p.tok[p.idx].symbol[strStart] == '<':
diff --git a/tests/compile/ttempl3.nim b/tests/compile/ttempl3.nim
index d8e67cc3e..a2e95ab03 100755
--- a/tests/compile/ttempl3.nim
+++ b/tests/compile/ttempl3.nim
@@ -40,3 +40,18 @@ template typedef(name: expr, typ: typeDesc) {.immediate.} =
 typedef(myint, int)
 var x: PMyInt
 
+
+# Test UFCS
+
+type
+  Foo = object
+    arg: int
+
+proc initFoo(arg: int): Foo =
+  result.arg = arg
+
+template create(typ: typeDesc, arg: expr): expr = `init typ`(arg)
+
+var ff = Foo.create(12)
+
+echo ff.arg
diff --git a/tests/reject/tenummix.nim b/tests/reject/tenummix.nim
new file mode 100644
index 000000000..f32eb82a7
--- /dev/null
+++ b/tests/reject/tenummix.nim
@@ -0,0 +1,11 @@
+discard """
+  file: "system.nim"
+  line: 640
+  errormsg: "type mismatch"
+"""
+
+type
+  TE1 = enum eA, eB
+  TE2 = enum eC, eD
+  
+assert eA != eC
diff --git a/tests/run/tdumptree.nim b/tests/run/tdumptree.nim
new file mode 100644
index 000000000..5299a94e3
--- /dev/null
+++ b/tests/run/tdumptree.nim
@@ -0,0 +1,27 @@
+discard """
+disabled: true
+output: '''StmtList
+  VarSection
+    IdentDefs
+      Ident !"x"
+      nil
+      Call
+        DotExpr
+          Ident !"foo"
+          Ident !"create"
+        IntLit 56'''
+"""
+
+# disabled; can't work as the output is done by the compiler
+
+import macros
+
+#emit("type\n  TFoo = object\n    bar: int")
+
+#var f: TFoo
+#f.bar = 5
+#echo(f.bar)
+
+dumpTree:
+  var x = foo.create(56)
+
diff --git a/tests/run/tgenericprocvar.nim b/tests/run/tgenericprocvar.nim
index 7fdc58ca4..088909d58 100644
--- a/tests/run/tgenericprocvar.nim
+++ b/tests/run/tgenericprocvar.nim
@@ -1,5 +1,5 @@
 discard """
-  output: "0false"
+  output: "0false12"
 """
 
 # Test multiple generic instantiation of generic proc vars:
@@ -17,3 +17,20 @@ proc threadProcWrapper[TMsg]() =
 threadProcWrapper[int]()
 threadProcWrapper[bool]()
 
+type
+  TFilterProc[T,D] = proc (item: T, env:D): bool
+
+proc filter[T,D](data: seq[T], env:D, pred: TFilterProc[T,D]): seq[T] =
+  result = @[]
+  for e in data:
+    if pred(e, env): result.add(e)
+
+proc predTest(item: int, value: int): Bool =
+  return item <= value
+
+proc test(data: seq[int], value: int): seq[int] =
+  return filter(data, value, predTest)
+
+for x in items(test(@[1,2,3], 2)):
+  stdout.write(x)
+
diff --git a/tests/run/tsequtils.nim b/tests/run/tsequtils.nim
index 2982ca612..7bc15ef9c 100644
--- a/tests/run/tsequtils.nim
+++ b/tests/run/tsequtils.nim
@@ -1,6 +1,6 @@
 discard """
 file: "tsequtils.nim"
-output: '''Zip: [{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}]
+output: '''Zip: [{"Field0": 1, "Field1": 2}, {"Field0": 3, "Field1": 4}, {"Field0": 5, "Field1": 6}]
 Filter Iterator: 3
 Filter Iterator: 5
 Filter Iterator: 7
diff --git a/todo.txt b/todo.txt
index 6267e3497..6bdfefc0d 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,8 +1,10 @@
 version 0.9.0
 =============
 
-- make stack traces part of the exception in debug builds
-- make templates hygienic by default
+- implement 'gorge'
+- implement a warning message for shadowed 'result' variable
+- make templates hygienic by default: try to gensym() everything in the 'block'
+  of a template
 - ``bind`` for overloaded symbols does not work apparently
 - ``=`` should be overloadable; requires specialization for ``=``
 - fix remaining generics bugs
@@ -24,6 +26,7 @@ version 0.9.0
 - we need to support iteration of 2 different data structures in parallel
 - make exceptions compatible with C++ exceptions
 - change how comments are part of the AST
+- find a better solution for gensym instead of `*ident`
 - extract nimdoc properly and document it finally
 - rethink the syntax: distinction between expr and stmt is unfortunate; 
   indentation handling is quite complex too; problem with exception handling
@@ -32,17 +35,9 @@ version 0.9.0
   error handling more light-weight
   people also want ``inc a; inc b``
 
+
 Bugs
 ----
-- bug: generic assign still buggy
-  - special case the generic assign that needs to care about case objects
-
-- bug: returning a tyVar does not mean it is save to return it:
-  proc forward[T](x: var T): var T = result = x
-  proc p(): var int = 
-    var x: int
-    # reject this call via alias analysis:
-    result = forward(x)
 
 - bug: stress testing basic method example (eval example) 
   without ``-d:release`` leaks memory?
diff --git a/tools/niminst/buildsh.tmpl b/tools/niminst/buildsh.tmpl
index 936378de2..a9c99a404 100755
--- a/tools/niminst/buildsh.tmpl
+++ b/tools/niminst/buildsh.tmpl
@@ -3,6 +3,9 @@
 #  result = "#! /bin/sh\n# Generated from niminst\n" &
 #           "# Template is in tools/buildsh.tmpl\n" &
 #           "# To regenerate run ``niminst csource`` or ``koch csource``\n"
+
+set -e
+
 while :
 do
     case "$1" in
@@ -108,11 +111,11 @@ case $myos in
 #      var linkCmd = ""
 #      for f in items(c.cfiles[osA][cpuA]):
     echo "$CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")}"
-    $CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")} || exit 1
+    $CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")}
 #        add(linkCmd, " \\\n" & changeFileExt(f, "o"))
 #      end for    
     echo "$LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd"
-    $LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd || exit 1
+    $LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd
     ;;
 #    end for
   *)
diff --git a/tools/niminst/install.tmpl b/tools/niminst/install.tmpl
index 9dea6887b..bfba024c7 100755
--- a/tools/niminst/install.tmpl
+++ b/tools/niminst/install.tmpl
@@ -3,6 +3,8 @@
 #  result = "#! /bin/sh\n# Generated by niminst\n"
 #  var proj = c.name.toLower
 
+set -e
+
 if [ $# -eq 1 ] ; then
 # if c.cat[fcUnixBin].len > 0:
   if test -f ?{c.cat[fcUnixBin][0]}
@@ -47,13 +49,13 @@ if [ $# -eq 1 ] ; then
       docdir="$1/?proj/doc"
       datadir="$1/?proj/data"
       
-      mkdir -p $1/?proj || exit 1
-      mkdir -p $bindir || exit 1
-      mkdir -p $configdir || exit 1
+      mkdir -p $1/?proj
+      mkdir -p $bindir
+      mkdir -p $configdir
       ;;
   esac
-  mkdir -p $libdir || exit 1
-  mkdir -p $docdir || exit 1
+  mkdir -p $libdir
+  mkdir -p $docdir
   echo "copying files..."
 #var createdDirs = newStringTable()
 #for cat in fcConfig..fcLib:
@@ -63,30 +65,34 @@ if [ $# -eq 1 ] ; then
 #      mk = unixDirVars[cat] & "/" & mk
 #      if not createdDirs.hasKey(mk):
 #        createdDirs[mk] = "true"
-  mkdir -p ?mk || exit 1
+  mkdir -p ?mk
 #      end if
 #    end if
 #  end for
 #end for
 
 #for f in items(c.cat[fcUnixBin]):
-  cp ?f $bindir/?f.skipRoot || exit 1
+  cp ?f $bindir/?f.skipRoot
   chmod 755 $bindir/?f.skipRoot
 #end for
 #for f in items(c.cat[fcConfig]): 
-  cp ?f $configdir/?f.skipRoot || exit 1
+  cp ?f $configdir/?f.skipRoot
   chmod 644 $configdir/?f.skipRoot
 #end for
 #for f in items(c.cat[fcData]): 
-  cp ?f $datadir/?f.skipRoot || exit 1
-  chmod 644 $datadir/?f.skipRoot
+  if [ -f ?f ]; then
+    cp ?f $datadir/?f.skipRoot
+    chmod 644 $datadir/?f.skipRoot
+  fi
 #end for
-#for f in items(c.cat[fcDoc]): 
-  cp ?f $docdir/?f.skipRoot || exit 1
-  chmod 644 $docdir/?f.skipRoot
+#for f in items(c.cat[fcDoc]):
+  if [ -f ?f ]; then
+    cp ?f $docdir/?f.skipRoot
+    chmod 644 $docdir/?f.skipRoot
+  fi
 #end for
-#for f in items(c.cat[fcLib]): 
-  cp ?f $libdir/?f.skipRoot || exit 1
+#for f in items(c.cat[fcLib]):
+  cp ?f $libdir/?f.skipRoot
   chmod 644 $libdir/?f.skipRoot
 #end for
   
diff --git a/web/news.txt b/web/news.txt
index cdc318a6a..847c36561 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -48,6 +48,7 @@ Library Additions
 - Added ``system.clamp`` to limit a value within an interval ``[a, b]``.
 - Added ``strutils.continuesWith``.
 - Added ``system.getStackTrace``.
+- Added ``system.||`` for parallel for loop support.
 - The GC supports (soft) realtime systems via ``GC_setMaxPause`` 
   and ``GC_step`` procs.
 
@@ -73,6 +74,9 @@ Changes affecting backwards compatibility
 - Deprecated ``system.GC_setStrategy``.
 - ``re.findAll`` and ``pegs.findAll`` don't return *captures* anymore but
   matching *substrings*.
+- RTTI and thus the ``marshall`` module don't contain the proper field names
+  of tuples anymore. This had to be changed as the old behaviour never
+  produced consistent results.
 
 
 Compiler Additions
@@ -86,6 +90,7 @@ Compiler Additions
   option or pragma.
 - The compiler now generates marker procs that the GC can use instead of RTTI.
   This speeds up the GC quite a bit.
+- The compiler now supports OpenMP's parallel for loop.
 
 
 Language Additions