summary refs log tree commit diff stats
path: root/rod
diff options
context:
space:
mode:
Diffstat (limited to 'rod')
-rwxr-xr-xrod/cgen.nim14
-rwxr-xr-xrod/commands.nim29
-rwxr-xr-xrod/lookups.nim89
-rwxr-xr-xrod/options.nim8
-rwxr-xr-xrod/semexprs.nim10
-rwxr-xr-xrod/semgnrc.nim36
-rwxr-xr-xrod/seminst.nim8
-rwxr-xr-xrod/semstmts.nim16
-rwxr-xr-xrod/semtypes.nim2
-rwxr-xr-xrod/sigmatch.nim32
-rwxr-xr-xrod/types.nim4
-rwxr-xr-xrod/wordrecg.nim6
12 files changed, 136 insertions, 118 deletions
diff --git a/rod/cgen.nim b/rod/cgen.nim
index f99a06a97..685d912c4 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -380,14 +380,20 @@ proc assignLocalVar(p: BProc, s: PSym) =
     appf(p.s[cpsLocals], " $1;$n", [s.loc.r])
   localDebugInfo(p, s)
 
+proc declareThreadVar(m: BModule, s: PSym) =
+  if optThreads in gGlobalOptions:
+    app(m.s[cfsVars], "NIM_THREADVAR ")
+  app(m.s[cfsVars], getTypeDesc(m, s.loc.t))
+  
+
 proc assignGlobalVar(p: BProc, s: PSym) = 
   if s.loc.k == locNone: 
     fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap)
   useHeader(p.module, s)
   if lfNoDecl in s.loc.flags: return 
   if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
-  if sfThreadVar in s.flags: app(p.module.s[cfsVars], "NIM_THREADVAR ")
-  app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
+  if sfThreadVar in s.flags: declareThreadVar(p.module, s)
+  else: app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
   if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
   if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
   appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
@@ -686,8 +692,8 @@ proc genVarPrototype(m: BModule, sym: PSym) =
            [sym.loc.r, getTypeDesc(m, sym.loc.t)])
     else: 
       app(m.s[cfsVars], "extern ")
-      if sfThreadVar in sym.flags: app(m.s[cfsVars], "NIM_THREADVAR ")
-      app(m.s[cfsVars], getTypeDesc(m, sym.loc.t))
+      if sfThreadVar in sym.flags: declareThreadVar(m, sym)
+      else: app(m.s[cfsVars], getTypeDesc(m, sym.loc.t))
       if sfRegister in sym.flags: app(m.s[cfsVars], " register")
       if sfVolatile in sym.flags: app(m.s[cfsVars], " volatile")
       appf(m.s[cfsVars], " $1;$n", [sym.loc.r])
diff --git a/rod/commands.nim b/rod/commands.nim
index ffd117cd8..7a74cac7f 100755
--- a/rod/commands.nim
+++ b/rod/commands.nim
@@ -25,7 +25,7 @@ proc ProcessCommand*(switch: string, pass: TCmdLinePass)
 proc processSwitch*(switch, arg: string, pass: TCmdlinePass, info: TLineInfo)
 # implementation
 
-const 
+const
   HelpMessage = "Nimrod Compiler Version $1 (" & compileDate & ") [$2: $3]\n" &
       "Copyright (c) 2004-2011 by Andreas Rumpf\n"
 
@@ -49,7 +49,7 @@ Options:
   -f, --forceBuild          force rebuilding of all modules
   --stackTrace:on|off       turn stack tracing on|off
   --lineTrace:on|off        turn line tracing on|off
-  --debugger:on|off         turn Embedded Nimrod Debugger on|off
+  --threads:on|off          turn support for multi-threading on|off
   -x, --checks:on|off       turn all runtime checks on|off
   --objChecks:on|off        turn obj conversion checks on|off
   --fieldChecks:on|off      turn case variant field checks on|off
@@ -92,6 +92,7 @@ Advanced options:
   --os:SYMBOL               set the target operating system (cross-compilation)
   --cpu:SYMBOL              set the target processor (cross-compilation)
   --debuginfo               enables debug information
+  --debugger:on|off         turn Embedded Nimrod Debugger on|off
   -t, --passc:OPTION        pass an option to the C compiler
   -l, --passl:OPTION        pass an option to the linker
   --genMapping              generate a mapping file containing
@@ -212,9 +213,6 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
   of wOn: incl(gNotes, n)
   of wOff: excl(gNotes, n)
   else: liMessage(info, errOnOrOffExpectedButXFound, arg)
-  
-proc processPath(path: string): string = 
-  result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath])
 
 proc processCompile(filename: string) = 
   var found = findFile(filename)
@@ -269,20 +267,32 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
   of wRun, wR: result = contains(gGlobalOptions, optRun)
   of wSymbolFiles: result = contains(gGlobalOptions, optSymbolFiles)
   of wGenScript: result = contains(gGlobalOptions, optGenScript)
+  of wThreads: result = contains(gGlobalOptions, optThreads)
   else: InvalidCmdLineOption(passCmd1, switch, info)
+  
+proc processPath(path: string): string = 
+  result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath,
+    "home", removeTrailingDirSep(os.getHomeDir())])
+
+proc addPath(path: string) = 
+  if not contains(options.searchPaths, path): 
+    lists.PrependStr(options.searchPaths, path)
 
 proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = 
   var 
     theOS: TSystemOS
     cpu: TSystemCPU
-    key, val, path: string
+    key, val: string
   case whichKeyword(switch)
   of wPath, wP: 
     expectArg(switch, arg, pass, info)
-    path = processPath(arg)
-    if not contains(options.searchPaths, path): 
-      lists.PrependStr(options.searchPaths, path)
+    addPath(processPath(arg))
     #discard lists.IncludeStr(options.searchPaths, path)
+  of wRecursivePath:
+    expectArg(switch, arg, pass, info)
+    var path = processPath(arg)
+    for p in os.walkDirRec(path, {pcDir}): addPath(p)
+    addPath(path)
   of wOut, wO: 
     expectArg(switch, arg, pass, info)
     options.outFile = arg
@@ -356,6 +366,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
   of wLineDir: ProcessOnOffSwitch({optLineDir}, arg, pass, info)
   of wAssertions, wA: ProcessOnOffSwitch({optAssert}, arg, pass, info)
   of wDeadCodeElim: ProcessOnOffSwitchG({optDeadCodeElim}, arg, pass, info)
+  of wThreads: ProcessOnOffSwitchG({optThreads}, arg, pass, info)
   of wOpt: 
     expectArg(switch, arg, pass, info)
     case whichKeyword(arg)
diff --git a/rod/lookups.nim b/rod/lookups.nim
index 474933604..f872224c0 100755
--- a/rod/lookups.nim
+++ b/rod/lookups.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -21,28 +21,12 @@ type
     m*: PSym
     mode*: TOverloadIterMode
 
-
-proc getSymRepr*(s: PSym): string
-proc CloseScope*(tab: var TSymTab)
-proc AddSym*(t: var TStrTable, n: PSym)
-proc addDecl*(c: PContext, sym: PSym)
-proc addDeclAt*(c: PContext, sym: PSym, at: Natural)
-proc addOverloadableSymAt*(c: PContext, fn: PSym, at: Natural)
-proc addInterfaceDecl*(c: PContext, sym: PSym)
-proc addInterfaceOverloadableSymAt*(c: PContext, sym: PSym, at: int)
-proc lookUp*(c: PContext, n: PNode): PSym
-  # Looks up a symbol. Generates an error in case of nil.
-proc QualifiedLookUp*(c: PContext, n: PNode, ambiguousCheck: bool): PSym
-proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym
-proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym
-# implementation
-
-proc getSymRepr(s: PSym): string = 
+proc getSymRepr*(s: PSym): string = 
   case s.kind
   of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s)
   else: result = s.name.s
   
-proc CloseScope(tab: var TSymTab) = 
+proc CloseScope*(tab: var TSymTab) = 
   var 
     it: TTabIter
     s: PSym
@@ -59,14 +43,14 @@ proc CloseScope(tab: var TSymTab) =
     s = NextIter(it, tab.stack[tab.tos - 1])
   astalgo.rawCloseScope(tab)
 
-proc AddSym(t: var TStrTable, n: PSym) = 
+proc AddSym*(t: var TStrTable, n: PSym) = 
   if StrTableIncl(t, n): liMessage(n.info, errAttemptToRedefine, n.name.s)
   
-proc addDecl(c: PContext, sym: PSym) = 
+proc addDecl*(c: PContext, sym: PSym) = 
   if SymTabAddUnique(c.tab, sym) == Failure: 
     liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
   
-proc addDeclAt(c: PContext, sym: PSym, at: Natural) = 
+proc addDeclAt*(c: PContext, sym: PSym, at: Natural) = 
   if SymTabAddUniqueAt(c.tab, sym, at) == Failure: 
     liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
 
@@ -81,7 +65,7 @@ proc addInterfaceDeclAt*(c: PContext, sym: PSym, at: Natural) =
   addDeclAt(c, sym, at)
   AddInterfaceDeclAux(c, sym)
   
-proc addOverloadableSymAt(c: PContext, fn: PSym, at: Natural) = 
+proc addOverloadableSymAt*(c: PContext, fn: PSym, at: Natural) = 
   if not (fn.kind in OverloadableSyms): 
     InternalError(fn.info, "addOverloadableSymAt")
   var check = StrTableGet(c.tab.stack[at], fn.name)
@@ -89,17 +73,17 @@ proc addOverloadableSymAt(c: PContext, fn: PSym, at: Natural) =
     liMessage(fn.info, errAttemptToRedefine, fn.Name.s)
   SymTabAddAt(c.tab, fn, at)
   
-proc addInterfaceDecl(c: PContext, sym: PSym) = 
+proc addInterfaceDecl*(c: PContext, sym: PSym) = 
   # it adds the symbol to the interface if appropriate
   addDecl(c, sym)
   AddInterfaceDeclAux(c, sym)
 
-proc addInterfaceOverloadableSymAt(c: PContext, sym: PSym, at: int) = 
+proc addInterfaceOverloadableSymAt*(c: PContext, sym: PSym, at: int) = 
   # it adds the symbol to the interface if appropriate
   addOverloadableSymAt(c, sym, at)
   AddInterfaceDeclAux(c, sym)
 
-proc lookUp(c: PContext, n: PNode): PSym = 
+proc lookUp*(c: PContext, n: PNode): PSym = 
   # Looks up a symbol. Generates an error in case of nil.
   case n.kind
   of nkAccQuoted: 
@@ -118,26 +102,32 @@ proc lookUp(c: PContext, n: PNode): PSym =
     liMessage(n.info, errUseQualifier, result.name.s)
   if result.kind == skStub: loadStub(result)
   
-proc QualifiedLookUp(c: PContext, n: PNode, ambiguousCheck: bool): PSym = 
+type 
+  TLookupFlag* = enum 
+    checkAmbiguity, checkUndeclared
+  
+proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = 
   case n.kind
   of nkIdent: 
     result = SymtabGet(c.Tab, n.ident)
-    if result == nil: 
+    if result == nil and checkUndeclared in flags: 
       liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
-    elif ambiguousCheck and IntSetContains(c.AmbiguousSymbols, result.id): 
+    elif checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols, 
+                                                    result.id): 
       liMessage(n.info, errUseQualifier, n.ident.s)
   of nkSym: 
     #
-    #      result := SymtabGet(c.Tab, n.sym.name);
-    #      if result = nil then
+    #      result = SymtabGet(c.Tab, n.sym.name)
+    #      if result == nil:
     #        liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s)
     #      else 
     result = n.sym
-    if ambiguousCheck and IntSetContains(c.AmbiguousSymbols, result.id): 
+    if checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols, 
+                                                  result.id): 
       liMessage(n.info, errUseQualifier, n.sym.name.s)
   of nkDotExpr: 
     result = nil
-    var m = qualifiedLookUp(c, n.sons[0], false)
+    var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
     if (m != nil) and (m.kind == skModule): 
       var ident: PIdent = nil
       if (n.sons[1].kind == nkIdent): 
@@ -150,17 +140,17 @@ proc QualifiedLookUp(c: PContext, n: PNode, ambiguousCheck: bool): PSym =
           result = StrTableGet(c.tab.stack[ModuleTablePos], ident)
         else: 
           result = StrTableGet(m.tab, ident)
-        if result == nil: 
+        if result == nil and checkUndeclared in flags: 
           liMessage(n.sons[1].info, errUndeclaredIdentifier, ident.s)
-      else: 
+      elif checkUndeclared in flags: 
         liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
   of nkAccQuoted: 
-    result = QualifiedLookup(c, n.sons[0], ambiguousCheck)
+    result = QualifiedLookup(c, n.sons[0], flags)
   else: 
-    result = nil              #liMessage(n.info, errIdentifierExpected, '')
+    result = nil
   if (result != nil) and (result.kind == skStub): loadStub(result)
   
-proc InitOverloadIter(o: var TOverloadIter, c: PContext, n: PNode): PSym = 
+proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = 
   var ident: PIdent
   result = nil
   case n.kind
@@ -173,17 +163,16 @@ proc InitOverloadIter(o: var TOverloadIter, c: PContext, n: PNode): PSym =
       result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident)
   of nkSym: 
     result = n.sym
-    o.mode = oimDone #
-                     #      o.stackPtr := c.tab.tos;
-                     #      o.mode := oimNoQualifier;
-                     #      while (result = nil) do begin
-                     #        dec(o.stackPtr);
-                     #        if o.stackPtr < 0 then break;
-                     #        result := InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name);
-                     #      end; 
+    o.mode = oimDone 
+    #      o.stackPtr = c.tab.tos
+    #      o.mode = oimNoQualifier
+    #      while result == nil:
+    #        dec(o.stackPtr)
+    #        if o.stackPtr < 0: break
+    #        result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name)
   of nkDotExpr: 
     o.mode = oimOtherModule
-    o.m = qualifiedLookUp(c, n.sons[0], false)
+    o.m = qualifiedLookUp(c, n.sons[0])
     if (o.m != nil) and (o.m.kind == skModule): 
       ident = nil
       if (n.sons[1].kind == nkIdent): 
@@ -210,7 +199,7 @@ proc InitOverloadIter(o: var TOverloadIter, c: PContext, n: PNode): PSym =
     nil
   if (result != nil) and (result.kind == skStub): loadStub(result)
   
-proc nextOverloadIter(o: var TOverloadIter, c: PContext, n: PNode): PSym = 
+proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = 
   case o.mode
   of oimDone: 
     result = nil
@@ -222,8 +211,8 @@ proc nextOverloadIter(o: var TOverloadIter, c: PContext, n: PNode): PSym =
       while (result == nil): 
         dec(o.stackPtr)
         if o.stackPtr < 0: break 
-        result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], o.it.name) # BUGFIX: 
-                                                                         # o.it.name <-> n.ident
+        result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], o.it.name) 
+        # BUGFIX: o.it.name <-> n.ident
     else: 
       result = nil
   of oimSelfModule: 
diff --git a/rod/options.nim b/rod/options.nim
index cdba2fcdc..1503770c3 100755
--- a/rod/options.nim
+++ b/rod/options.nim
@@ -30,7 +30,8 @@ type                          # please make sure we have under 32 options
   TOptions* = set[TOption]
   TGlobalOption* = enum 
     gloptNone, optForceFullMake, optBoehmGC, optRefcGC, optDeadCodeElim, 
-    optListCmd, optCompileOnly, optNoLinking, optSafeCode, # only allow safe code
+    optListCmd, optCompileOnly, optNoLinking, 
+    optSafeCode,              # only allow safe code
     optCDebug,                # turn on debugging information
     optGenDynLib,             # generate a dynamic library
     optGenGuiApp,             # generate a GUI application
@@ -40,7 +41,8 @@ type                          # please make sure we have under 32 options
     optSymbolFiles,           # use symbol files for speeding up compilation
     optSkipConfigFile,        # skip the general config file
     optSkipProjConfigFile,    # skip the project's config file
-    optNoMain                 # do not generate a "main" proc
+    optNoMain,                # do not generate a "main" proc
+    optThreads                # support for multi-threading
   TGlobalOptions* = set[TGlobalOption]
   TCommands* = enum           # Nimrod's commands
     cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, 
@@ -142,7 +144,7 @@ proc shortenDir(dir: string): string =
     return copy(dir, len(prefix))
   result = dir
 
-proc removeTrailingDirSep(path: string): string = 
+proc removeTrailingDirSep*(path: string): string = 
   if (len(path) > 0) and (path[len(path) - 1] == dirSep): 
     result = copy(path, 0, len(path) - 2)
   else: 
diff --git a/rod/semexprs.nim b/rod/semexprs.nim
index e6cf097e5..cdcf09d3e 100755
--- a/rod/semexprs.nim
+++ b/rod/semexprs.nim
@@ -631,7 +631,7 @@ proc makeDeref(n: PNode): PNode =
 
 proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   ## returns nil if it's not a built-in field access
-  var s = qualifiedLookup(c, n, true) # check for ambiguity
+  var s = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
   if s != nil:
     return semSym(c, n, s, flags)
 
@@ -940,7 +940,7 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck: bool = true): PNode =
   var a: PNode
   if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
   else: a = n.sons[0]
-  var s = qualifiedLookup(c, a, false)
+  var s = qualifiedLookup(c, a, {checkUndeclared})
   if s != nil: 
     case s.kind
     of skMacro: 
@@ -1014,7 +1014,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: 
     # check if it is an expression macro:
     checkMinSonsLen(n, 1)
-    var s = qualifiedLookup(c, n.sons[0], false)
+    var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
     if s != nil: 
       case s.kind
       of skMacro: result = semMacroExpr(c, n, s)
@@ -1037,10 +1037,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result = semMacroStmt(c, n)
   of nkBracketExpr: 
     checkMinSonsLen(n, 1)
-    var s = qualifiedLookup(c, n.sons[0], false)
+    var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
     if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}: 
       # type parameters: partial generic specialization
-      result = partialSpecialization(c, n, s)
+      result = explictGenericInstantiation(c, n, s)
     else: 
       result = semArrayAccess(c, n, flags)
   of nkPragmaExpr: 
diff --git a/rod/semgnrc.nim b/rod/semgnrc.nim
index 0a291cd42..3ccd415f9 100755
--- a/rod/semgnrc.nim
+++ b/rod/semgnrc.nim
@@ -21,12 +21,14 @@ type
   TSemGenericFlags = set[TSemGenericFlag]
 
 proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
-proc semGenericStmtScope(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode = 
+proc semGenericStmtScope(c: PContext, n: PNode, 
+                         flags: TSemGenericFlags = {}): PNode = 
   openScope(c.tab)
   result = semGenericStmt(c, n, flags)
   closeScope(c.tab)
 
 proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode = 
+  incl(s.flags, sfUsed)
   case s.kind
   of skUnknown: 
     # Introduced in this pass! Leave it as an identifier.
@@ -55,20 +57,29 @@ proc getIdentNode(n: PNode): PNode =
     illFormedAst(n)
     result = nil
 
+#  of nkAccQuoted: 
+#    s = lookUp(c, n)
+#    if withinBind in flags: result = symChoice(c, n, s)
+#    else: result = semGenericStmtSymbol(c, n, s)
+
 proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode = 
   var 
     L: int
     a: PNode
-    s: PSym
   result = n
   if n == nil: return 
   case n.kind
-  of nkIdent, nkAccQuoted: 
-    s = lookUp(c, n)
-    if withinBind in flags: result = symChoice(c, n, s)
-    else: result = semGenericStmtSymbol(c, n, s)
+  of nkIdent:
+    var s = SymtabGet(c.Tab, n.ident)
+    if s == nil:
+      # no error if symbol cannot be bound, unless in ``bind`` context:
+      if withinBind in flags: 
+        liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
+    else:
+      if withinBind in flags: result = symChoice(c, n, s)
+      else: result = semGenericStmtSymbol(c, n, s)
   of nkDotExpr: 
-    s = QualifiedLookUp(c, n, true)
+    var s = QualifiedLookUp(c, n, {})
     if s != nil: result = semGenericStmtSymbol(c, n, s)
   of nkSym..nkNilLit: 
     nil
@@ -77,8 +88,9 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
   of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit: 
     # check if it is an expression macro:
     checkMinSonsLen(n, 1)
-    s = qualifiedLookup(c, n.sons[0], false)
-    if (s != nil): 
+    var s = qualifiedLookup(c, n.sons[0], {})
+    if s != nil: 
+      incl(s.flags, sfUsed)
       case s.kind
       of skMacro: 
         return semMacroExpr(c, n, s, false)
@@ -100,16 +112,16 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
   of nkMacroStmt: 
     result = semMacroStmt(c, n, false)
   of nkIfStmt: 
-    for i in countup(0, sonsLen(n) - 1): 
+    for i in countup(0, sonsLen(n)-1): 
       n.sons[i] = semGenericStmtScope(c, n.sons[i])
   of nkWhileStmt: 
     openScope(c.tab)
-    for i in countup(0, sonsLen(n) - 1): n.sons[i] = semGenericStmt(c, n.sons[i])
+    for i in countup(0, sonsLen(n)-1): n.sons[i] = semGenericStmt(c, n.sons[i])
     closeScope(c.tab)
   of nkCaseStmt: 
     openScope(c.tab)
     n.sons[0] = semGenericStmt(c, n.sons[0])
-    for i in countup(1, sonsLen(n) - 1): 
+    for i in countup(1, sonsLen(n)-1): 
       a = n.sons[i]
       checkMinSonsLen(a, 1)
       L = sonsLen(a)
diff --git a/rod/seminst.nim b/rod/seminst.nim
index 417922825..7954d2e8f 100755
--- a/rod/seminst.nim
+++ b/rod/seminst.nim
@@ -106,6 +106,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   else: 
     result.typ = newTypeS(tyProc, c)
     addSon(result.typ, nil)
+  result.typ.callConv = fn.typ.callConv
   oldPrc = GenericCacheGet(c, fn, result)
   if oldPrc == nil: 
     # add it here, so that recursive generic procs are possible:
@@ -244,10 +245,3 @@ proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode,
   result = ReplaceTypeVarsT(cl, t)
   popInfoContext()
 
-proc partialSpecialization(c: PContext, n: PNode, s: PSym): PNode = 
-  for i in 1..sonsLen(n)-1:
-    n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
-  # we cannot check for the proper number of type parameters because in
-  # `f[a,b](x, y)` `f` is not resolved yet properly.
-  # XXX: BUG this should be checked somehow!
-  result = n
diff --git a/rod/semstmts.nim b/rod/semstmts.nim
index 0546c24dd..0faf3e5fc 100755
--- a/rod/semstmts.nim
+++ b/rod/semstmts.nim
@@ -162,7 +162,7 @@ proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
   addSon(result, newIdentNode(getIdent(id.s & '='), n.info))
   # a[0] is already checked for semantics, that does ``builtinFieldAccess``
   # this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
-  # nodes!
+  # nodes?
   addSon(result, a[0])
   addSon(result, semExpr(c, n[1]))
   result = semDirectCallAnalyseEffects(c, result, {})
@@ -182,18 +182,6 @@ proc semAsgn(c: PContext, n: PNode): PNode =
     a = builtinFieldAccess(c, a, {efLValue})
     if a == nil: 
       return propertyWriteAccess(c, n, n[0])
-    when false:
-      checkSonsLen(a, 2)
-      var id = considerAcc(a.sons[1])
-      result = newNodeI(nkCall, n.info)
-      addSon(result, newIdentNode(getIdent(id.s & '='), n.info))
-      addSon(result, semExpr(c, a.sons[0]))
-      addSon(result, semExpr(c, n.sons[1]))
-      result = semDirectCallAnalyseEffects(c, result, {})
-      if result != nil: 
-        fixAbstractType(c, result)
-        analyseIfAddressTakenInCall(c, result)
-        return 
   of nkBracketExpr: 
     # a[i..j] = x
     # --> `[..]=`(a, i, j, x)
@@ -204,7 +192,6 @@ proc semAsgn(c: PContext, n: PNode): PNode =
       return semExprNoType(c, result)
   else: 
     a = semExprWithType(c, a, {efLValue})
-  #n.sons[0] = semExprWithType(c, n.sons[0], {efLValue})
   n.sons[0] = a
   n.sons[1] = semExprWithType(c, n.sons[1])
   var le = a.typ
@@ -288,7 +275,6 @@ proc semVar(c: PContext, n: PNode): PNode =
     else: 
       def = nil
     if not typeAllowed(typ, skVar): 
-      #debug(typ);
       liMessage(a.info, errXisNoType, typeToString(typ))
     tup = skipTypes(typ, {tyGenericInst})
     if a.kind == nkVarTuple: 
diff --git a/rod/semtypes.nim b/rod/semtypes.nim
index 52766f174..0fb359170 100755
--- a/rod/semtypes.nim
+++ b/rod/semtypes.nim
@@ -178,7 +178,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
     liMessage(n.info, errXExpectsOneTypeParam, "ordinal")
   
 proc semTypeIdent(c: PContext, n: PNode): PSym = 
-  result = qualifiedLookup(c, n, true)
+  result = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
   if (result != nil): 
     markUsed(n, result)
     if result.kind != skType: liMessage(n.info, errTypeExpected)
diff --git a/rod/sigmatch.nim b/rod/sigmatch.nim
index 5dc9de7b0..bcb9198da 100755
--- a/rod/sigmatch.nim
+++ b/rod/sigmatch.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -82,11 +82,11 @@ proc cmpCandidates(a, b: TCandidate): int =
   result = a.convMatches - b.convMatches
 
 proc writeMatches(c: TCandidate) = 
-  Writeln(stdout, "exact matches: " & $(c.exactMatches))
-  Writeln(stdout, "subtype matches: " & $(c.subtypeMatches))
-  Writeln(stdout, "conv matches: " & $(c.convMatches))
-  Writeln(stdout, "intconv matches: " & $(c.intConvMatches))
-  Writeln(stdout, "generic matches: " & $(c.genericMatches))
+  Writeln(stdout, "exact matches: " & $c.exactMatches)
+  Writeln(stdout, "subtype matches: " & $c.subtypeMatches)
+  Writeln(stdout, "conv matches: " & $c.convMatches)
+  Writeln(stdout, "intconv matches: " & $c.intConvMatches)
+  Writeln(stdout, "generic matches: " & $c.genericMatches)
 
 proc getNotFoundError(c: PContext, n: PNode): string = 
   # Gives a detailed error message; this is separated from semDirectCall,
@@ -710,8 +710,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
   elif y.state == csMatch and cmpCandidates(x, y) == 0 and
       not sameMethodDispatcher(x.calleeSym, y.calleeSym): 
     if x.state != csMatch: 
-      InternalError(n.info, "x.state is not csMatch") #writeMatches(x);
-                                                      #writeMatches(y);
+      InternalError(n.info, "x.state is not csMatch") 
     liMessage(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
       getProcHeader(x.calleeSym), getProcHeader(y.calleeSym), 
       x.calleeSym.Name.s])
@@ -740,3 +739,20 @@ proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
     initialBinding = nil
   result = semDirectCallWithBinding(c, n, f, filter, initialBinding)
 
+proc explictGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = 
+  assert n.kind == nkBracketExpr
+  for i in 1..sonsLen(n)-1:
+    n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
+  # we cannot check for the proper number of type parameters because in
+  # `f[a,b](x, y)` `f` is not resolved yet properly.
+  # XXX: BUG this should be checked somehow!
+  assert n.sons[0].kind == nkSym
+  
+  var x: TCandidate
+  initCandidate(x, s, n)
+  var newInst = generateInstance(c, s, x.bindings, n.info)
+  
+  markUsed(n, s)
+  result = newSymNode(newInst)
+  result.info = n.info
+
diff --git a/rod/types.nim b/rod/types.nim
index d7b956983..d26136aa9 100755
--- a/rod/types.nim
+++ b/rod/types.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -747,7 +747,7 @@ proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind): bool =
   result = true
   if n != nil: 
     result = typeAllowedAux(marker, n.typ, kind)
-    if not result: debug(n.typ)
+    #if not result: debug(n.typ)
     if result: 
       case n.kind
       of nkNone..nkNilLit: 
diff --git a/rod/wordrecg.nim b/rod/wordrecg.nim
index 0b5b48bb2..d4bbb8680 100755
--- a/rod/wordrecg.nim
+++ b/rod/wordrecg.nim
@@ -59,7 +59,8 @@ type
     wPretty, 
     wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs, wOC, 
     wRst2html, wRst2tex, wI,
-    wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit
+    wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads,
+    wRecursivePath
     
   TSpecialWords* = set[TSpecialWord]
 
@@ -107,7 +108,8 @@ const
     "compiletooc",
     "pretty", "doc", "gendepend", "listdef", "check", "parse", "scan", 
     "js", "oc", "rst2html", "rst2tex", "i", 
-    "write", "putenv", "prependenv", "appendenv", "threadvar", "emit"]
+    "write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
+    "threads", "recursivepath"]
 
 proc whichKeyword*(id: PIdent): TSpecialWord
 proc whichKeyword*(id: String): TSpecialWord