summary refs log tree commit diff stats
path: root/nim
diff options
context:
space:
mode:
authorAndreas Rumpf <andreas@andreas-desktop>2009-11-12 19:34:21 +0100
committerAndreas Rumpf <andreas@andreas-desktop>2009-11-12 19:34:21 +0100
commitac421c37ba9a973155dc5600e38d7a40553d8de6 (patch)
tree5ede0dfe1c02aa547f788a39f070614a64a3b9ab /nim
parentd5acb88cccecf54bcc9a7c13f4fbaa095a8b37d4 (diff)
downloadNim-ac421c37ba9a973155dc5600e38d7a40553d8de6.tar.gz
bind table
Diffstat (limited to 'nim')
-rwxr-xr-xnim/llvmdata.pas139
-rwxr-xr-xnim/pbraces.pas122
-rwxr-xr-xnim/pendx.pas36
-rwxr-xr-xnim/pnimsyn.pas47
-rwxr-xr-xnim/semgnrc.pas287
-rwxr-xr-xnim/semtempl.pas14
-rwxr-xr-xnim/syntaxes.pas10
-rwxr-xr-xnim/vis.pas35
8 files changed, 570 insertions, 120 deletions
diff --git a/nim/llvmdata.pas b/nim/llvmdata.pas
new file mode 100755
index 000000000..a8ae0f311
--- /dev/null
+++ b/nim/llvmdata.pas
@@ -0,0 +1,139 @@
+//
+//
+//           The Nimrod Compiler
+//        (c) Copyright 2009 Andreas Rumpf
+//
+//    See the file "copying.txt", included in this
+//    distribution, for details about the copyright.
+//
+unit llvmdata;
+
+// this module implements data structures for emitting LLVM.
+
+interface
+
+{$include 'config.inc'}
+
+uses
+  nsystem, ast, astalgo, idents, lists, passes;
+
+type
+  VTypeKind = (
+    VoidTyID,        ///<  0: type with no size
+    FloatTyID,       ///<  1: 32 bit floating point type
+    DoubleTyID,      ///<  2: 64 bit floating point type
+    X86_FP80TyID,    ///<  3: 80 bit floating point type (X87)
+    FP128TyID,       ///<  4: 128 bit floating point type (112-bit mantissa)
+    PPC_FP128TyID,   ///<  5: 128 bit floating point type (two 64-bits)
+    LabelTyID,       ///<  6: Labels
+    MetadataTyID,    ///<  7: Metadata
+
+    // Derived types... see DerivedTypes.h file...
+    // Make sure FirstDerivedTyID stays up to date!!!
+    IntegerTyID,     ///<  8: Arbitrary bit width integers
+    FunctionTyID,    ///<  9: Functions
+    StructTyID,      ///< 10: Structures
+    ArrayTyID,       ///< 11: Arrays
+    PointerTyID,     ///< 12: Pointers
+    OpaqueTyID,      ///< 13: Opaque: type with unknown structure
+    VectorTyID,      ///< 14: SIMD 'packed' format, or other vector type
+  );
+  VType = ^VTypeDesc;
+  VTypeSeq = array of VType;
+  VTypeDesc = object(TIdObj)
+    k: VTypeKind;
+    s: VTypeSeq;
+    arrayLen: int;
+    name: string;
+  end;
+  
+  VInstrKind = (
+    iNone, 
+    iAdd,
+    iSub,
+    iMul,
+    iDiv,
+    iMod,
+  
+  );
+  VLocalVar = record
+    
+  
+  end;
+  VInstr = record
+    k: VInstrKind;
+    
+  end;
+
+/// This represents a single basic block in LLVM. A basic block is simply a
+/// container of instructions that execute sequentially. Basic blocks are Values
+/// because they are referenced by instructions such as branches and switch
+/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block
+/// represents a label to which a branch can jump.
+///
+  VBlock = ^VBlockDesc;
+  VBlockDesc = record // LLVM basic block
+    // list of instructions
+  end;
+
+  VLinkage = (
+    ExternalLinkage, // Externally visible function
+    LinkOnceLinkage, // Keep one copy of function when linking (inline)
+    WeakLinkage, // Keep one copy of function when linking (weak)
+    AppendingLinkage, // Special purpose, only applies to global arrays
+    InternalLinkage, // Rename collisions when linking (static functions)
+    DLLImportLinkage, // Function to be imported from DLL
+    DLLExportLinkage, // Function to be accessible from DLL
+    ExternalWeakLinkage, // ExternalWeak linkage description
+    GhostLinkage // Stand-in functions for streaming fns from bitcode
+  );
+  VVisibility = (
+    DefaultVisibility, // The GV is visible
+    HiddenVisibility, // The GV is hidden
+    ProtectedVisibility // The GV is protected
+  );
+  TLLVMCallConv = (
+    CCallConv = 0,
+    FastCallConv = 8,
+    ColdCallConv = 9,
+    X86StdcallCallConv = 64,
+    X86FastcallCallConv = 65
+  );
+  
+  VProc = ^VProcDesc;
+  VProcDesc = record
+    b: VBlock;
+    name: string;
+    sym: PSym; // proc that is generated
+    linkage: VLinkage;
+    vis: VVisibility;
+    callConv: VCallConv;
+    next: VProc;
+  end;
+  VModule = ^VModuleDesc;
+  VModuleDesc = object(TPassContext) // represents a C source file
+    sym: PSym;
+    filename: string;
+    typeCache: TIdTable;     // cache the generated types
+    forwTypeCache: TIdTable; // cache for forward declarations of types
+    declaredThings: TIntSet; // things we have declared in this file
+    declaredProtos: TIntSet; // prototypes we have declared in this file
+    headerFiles: TLinkedList; // needed headers to include
+    typeInfoMarker: TIntSet; // needed for generating type information
+    initProc: VProc;         // code for init procedure
+    typeStack: TTypeSeq;     // used for type generation
+    dataCache: TNodeTable;
+    forwardedProcs: TSymSeq; // keep forwarded procs here
+    typeNodes, nimTypes: int;// used for type info generation
+    typeNodesName, nimTypesName: PRope; // used for type info generation
+    labels: natural;         // for generating unique module-scope names
+    next: VModule; // to stack modules
+  end;
+  
+
+
+implementation
+
+
+end.
+
diff --git a/nim/pbraces.pas b/nim/pbraces.pas
index d362fac65..2e10c50f2 100755
--- a/nim/pbraces.pas
+++ b/nim/pbraces.pas
@@ -146,8 +146,7 @@ begin
   end;
 end;
 
-procedure qualifiedIdentListAux(var p: TParser; endTok: TTokType;
-                                result: PNode);
+procedure qualifiedIdentListAux(var p: TParser; endTok: TTokType; result: PNode);
 var
   a: PNode;
 begin
@@ -216,16 +215,6 @@ begin
   eat(p, tkParRi);
 end;
 
-procedure setBaseFlags(n: PNode; base: TNumericalBase);
-begin
-  case base of
-    base10: begin end;
-    base2: include(n.flags, nfBase2);
-    base8: include(n.flags, nfBase8);
-    base16: include(n.flags, nfBase16);
-  end
-end;
-
 function identOrLiteral(var p: TParser): PNode;
 begin
   case p.tok.tokType of
@@ -542,7 +531,7 @@ begin
   optInd(p, result);
   while (p.tok.tokType = tkSymbol) or (p.tok.tokType = tkAccent) do begin
     a := parseIdentColonEquals(p, {@set}[]);
-    addSon(result, a);        
+    addSon(result, a);
     if p.tok.tokType <> tkComma then break;
     getTok(p);
     optInd(p, a)
@@ -729,12 +718,12 @@ begin
   end
 end;
 
-function parseImportStmt(var p: TParser): PNode;
+function parseImportOrIncludeStmt(var p: TParser; kind: TNodeKind): PNode;
 var
   a: PNode;
 begin
-  result := newNodeP(nkImportStmt, p);
-  getTok(p); // skip `import`
+  result := newNodeP(kind, p);
+  getTok(p); // skip `import` or `include`
   optInd(p, result);
   while true do begin
     case p.tok.tokType of
@@ -764,41 +753,6 @@ begin
   end;
 end;
 
-function parseIncludeStmt(var p: TParser): PNode;
-var
-  a: PNode;
-begin
-  result := newNodeP(nkIncludeStmt, p);
-  getTok(p); // skip `include`
-  optInd(p, result);
-  while true do begin
-    case p.tok.tokType of
-      tkEof, tkSad, tkDed: break;
-      tkSymbol, tkAccent:   a := parseSymbol(p);
-      tkRStrLit:  begin
-        a := newStrNodeP(nkRStrLit, p.tok.literal, p);
-        getTok(p)
-      end;
-      tkStrLit: begin
-        a := newStrNodeP(nkStrLit, p.tok.literal, p);
-        getTok(p);
-      end;
-      tkTripleStrLit: begin
-        a := newStrNodeP(nkTripleStrLit, p.tok.literal, p);
-        getTok(p)
-      end;
-      else begin
-        parMessage(p, errIdentifierExpected, tokToStr(p.tok));
-        break
-      end;
-    end;
-    addSon(result, a);
-    if p.tok.tokType <> tkComma then break;
-    getTok(p);
-    optInd(p, a)
-  end;
-end;
-
 function parseFromStmt(var p: TParser): PNode;
 var
   a: PNode;
@@ -1150,6 +1104,24 @@ begin
   indAndComment(p, result); // XXX: special extension!
 end;
 
+function parseConstSection(var p: TParser): PNode;
+begin
+  result := newNodeP(nkConstSection, p);
+  getTok(p);
+  skipComment(p, result);
+  if p.tok.tokType = tkCurlyLe then begin
+    getTok(p);
+    skipComment(p, result);
+    while (p.tok.tokType <> tkCurlyRi) and (p.tok.tokType <> tkEof) do begin
+      addSon(result, parseConstant(p)) 
+    end;
+    eat(p, tkCurlyRi);
+  end
+  else 
+    addSon(result, parseConstant(p));
+end;
+
+
 function parseEnum(var p: TParser): PNode;
 var
   a, b: PNode;
@@ -1379,9 +1351,9 @@ begin
     tkBreak:    result := parseBreakOrContinue(p, nkBreakStmt);
     tkContinue: result := parseBreakOrContinue(p, nkContinueStmt);
     tkCurlyDotLe: result := parsePragma(p);
-    tkImport: result := parseImportStmt(p);
+    tkImport: result := parseImportOrIncludeStmt(p, nkImportStmt);
     tkFrom: result := parseFromStmt(p);
-    tkInclude: result := parseIncludeStmt(p);
+    tkInclude: result := parseImportOrIncludeStmt(p, nkIncludeStmt);
     tkComment: result := newCommentStmt(p);
     else begin
       if isExprStart(p) then 
@@ -1394,6 +1366,24 @@ begin
     skipComment(p, result);
 end;
 
+function parseType(var p: TParser): PNode;
+begin
+  result := newNodeP(nkTypeSection, p);
+  while true do begin
+    case p.tok.tokType of
+      tkComment: skipComment(p, result);
+      tkType: begin
+        // type alias:
+        
+      end;
+      tkEnum:
+      tkObject:
+      tkTuple:
+      else break;
+    end
+  end
+end;
+
 function complexOrSimpleStmt(var p: TParser): PNode;
 begin
   case p.tok.tokType of
@@ -1410,8 +1400,9 @@ begin
     tkMacro:     result := parseRoutine(p, nkMacroDef);
     tkTemplate:  result := parseRoutine(p, nkTemplateDef);
     tkConverter: result := parseRoutine(p, nkConverterDef);
-    tkType:      result := parseSection(p, nkTypeSection, parseTypeDef);
-    tkConst:     result := parseSection(p, nkConstSection, parseConstant);
+    tkType, tkEnum, tkObject, tkTuple:      
+      result := parseTypeAlias(p, nkTypeSection, parseTypeDef);
+    tkConst:     result := parseConstSection(p);
     tkWhen:      result := parseIfOrWhen(p, nkWhenStmt);
     tkVar:       result := parseSection(p, nkVarSection, parseVariable);
     else         result := simpleStmt(p);
@@ -1422,15 +1413,13 @@ function parseStmt(var p: TParser): PNode;
 var
   a: PNode;
 begin
-  if p.tok.tokType = tkInd then begin
+  if p.tok.tokType = tkCurlyLe then begin
     result := newNodeP(nkStmtList, p);
-    pushInd(p.lex^, p.tok.indent);
     getTok(p);
     while true do begin
       case p.tok.tokType of
-        tkSad: getTok(p);
-        tkEof: break;
-        tkDed: begin getTok(p); break end;
+        tkSad, tkInd, tkDed: getTok(p);
+        tkEof, tkCurlyRi: break;
         else begin
           a := complexOrSimpleStmt(p);
           if a = nil then break;
@@ -1438,7 +1427,7 @@ begin
         end
       end
     end;
-    popInd(p.lex^);
+    eat(p, tkCurlyRi);
   end
   else begin
     // the case statement is only needed for better error messages:
@@ -1451,7 +1440,7 @@ begin
       else begin
         result := simpleStmt(p);
         if result = nil then parMessage(p, errExprExpected, tokToStr(p.tok));
-        if p.tok.tokType = tkSad then getTok(p);
+        if p.tok.tokType in [tkInd, tkDed, tkSad] then getTok(p);
       end
     end
   end
@@ -1464,8 +1453,7 @@ begin
   result := newNodeP(nkStmtList, p);
   while true do begin
     case p.tok.tokType of
-      tkSad: getTok(p);
-      tkDed, tkInd: parMessage(p, errInvalidIndentation);
+      tkDed, tkInd, tkSad: getTok(p);
       tkEof: break;
       else begin
         a := complexOrSimpleStmt(p);
@@ -1481,11 +1469,7 @@ begin
   result := nil;
   while true do begin
     case p.tok.tokType of
-      tkSad: getTok(p);
-      tkDed, tkInd: begin
-        parMessage(p, errInvalidIndentation);
-        break;
-      end;
+      tkDed, tkInd, tkSad: getTok(p);
       tkEof: break;
       else begin
         result := complexOrSimpleStmt(p);
diff --git a/nim/pendx.pas b/nim/pendx.pas
new file mode 100755
index 000000000..e23229e28
--- /dev/null
+++ b/nim/pendx.pas
@@ -0,0 +1,36 @@
+//
+//
+//           The Nimrod Compiler
+//        (c) Copyright 2009 Andreas Rumpf
+//
+//    See the file "copying.txt", included in this
+//    distribution, for details about the copyright.
+//
+unit pendx;
+
+{$include config.inc}
+
+interface
+
+uses
+  nsystem, llstream, scanner, idents, strutils, ast, msgs, pnimsyn;
+
+function ParseAll(var p: TParser): PNode;
+
+function parseTopLevelStmt(var p: TParser): PNode;
+// implements an iterator. Returns the next top-level statement or nil if end
+// of stream.
+
+implementation
+
+function ParseAll(var p: TParser): PNode;
+begin
+  result := nil
+end;
+
+function parseTopLevelStmt(var p: TParser): PNode;
+begin
+  result := nil
+end;
+
+end.
diff --git a/nim/pnimsyn.pas b/nim/pnimsyn.pas
index bf964fda1..eeaf2a6e9 100755
--- a/nim/pnimsyn.pas
+++ b/nim/pnimsyn.pas
@@ -72,6 +72,7 @@ procedure optSad(var p: TParser);
 procedure optInd(var p: TParser; n: PNode);
 procedure indAndComment(var p: TParser; n: PNode);
 
+procedure setBaseFlags(n: PNode; base: TNumericalBase);
 
 function parseSymbol(var p: TParser): PNode;
 function accExpr(var p: TParser): PNode;
@@ -1069,12 +1070,12 @@ begin
   end
 end;
 
-function parseImportStmt(var p: TParser): PNode;
+function parseImportOrIncludeStmt(var p: TParser; kind: TNodeKind): PNode;
 var
   a: PNode;
 begin
-  result := newNodeP(nkImportStmt, p);
-  getTok(p); // skip `import`
+  result := newNodeP(kind, p);
+  getTok(p); // skip `import` or `include`
   optInd(p, result);
   while true do begin
     case p.tok.tokType of
@@ -1104,42 +1105,6 @@ begin
   end;
 end;
 
-function parseIncludeStmt(var p: TParser): PNode;
-var
-  a: PNode;
-begin
-  result := newNodeP(nkIncludeStmt, p);
-  getTok(p); // skip `include`
-  optInd(p, result);
-  while true do begin
-    case p.tok.tokType of
-      tkEof, tkSad, tkDed: break;
-      tkSymbol, tkAccent:   a := parseSymbol(p);
-      tkRStrLit:  begin
-        a := newStrNodeP(nkRStrLit, p.tok.literal, p);
-        getTok(p)
-      end;
-      tkStrLit: begin
-        a := newStrNodeP(nkStrLit, p.tok.literal, p);
-        getTok(p);
-      end;
-      tkTripleStrLit: begin
-        a := newStrNodeP(nkTripleStrLit, p.tok.literal, p);
-        getTok(p)
-      end;
-      else begin
-        parMessage(p, errIdentifierExpected, tokToStr(p.tok));
-        break
-      end;
-    end;
-    addSon(result, a);
-    //optInd(p, a);
-    if p.tok.tokType <> tkComma then break;
-    getTok(p);
-    optInd(p, a)
-  end;
-end;
-
 function parseFromStmt(var p: TParser): PNode;
 var
   a: PNode;
@@ -1717,9 +1682,9 @@ begin
     tkBreak:    result := parseBreakOrContinue(p, nkBreakStmt);
     tkContinue: result := parseBreakOrContinue(p, nkContinueStmt);
     tkCurlyDotLe: result := parsePragma(p);
-    tkImport: result := parseImportStmt(p);
+    tkImport: result := parseImportOrIncludeStmt(p, nkImportStmt);
     tkFrom: result := parseFromStmt(p);
-    tkInclude: result := parseIncludeStmt(p);
+    tkInclude: result := parseImportOrIncludeStmt(p, nkIncludeStmt);
     tkComment: result := newCommentStmt(p);
     else begin
       if isExprStart(p) then 
diff --git a/nim/semgnrc.pas b/nim/semgnrc.pas
new file mode 100755
index 000000000..ee905d444
--- /dev/null
+++ b/nim/semgnrc.pas
@@ -0,0 +1,287 @@
+//
+//
+//           The Nimrod Compiler
+//        (c) Copyright 2009 Andreas Rumpf
+//
+//    See the file "copying.txt", included in this
+//    distribution, for details about the copyright.
+//
+
+
+// This implements the first pass over the generic body; it resolves some
+// symbols. Thus for generics there is a two-phase symbol lookup just like
+// in C++.
+// A problem is that it cannot be detected if the symbol is introduced
+// as in ``var x = ...`` or used because macros/templates can hide this!
+// So we have to eval templates/macros right here so that symbol
+// lookup can be accurate.
+
+type
+  TSemGenericFlag = (withinBind, withinTypeDesc);
+  TSemGenericFlags = set of TSemGenericFlag;
+
+function semGenericStmt(c: PContext; n: PNode; 
+                        flags: TSemGenericFlags = {@set}[]): PNode; forward;
+
+function semGenericStmtScope(c: PContext; n: PNode; 
+                             flags: TSemGenericFlags = {@set}[]): PNode;
+begin
+  openScope(c.tab);
+  result := semGenericStmt(c, n, flags);
+  closeScope(c.tab);
+end;
+
+function semGenericStmtSymbol(c: PContext; n: PNode; s: PSym): PNode;
+begin
+  case s.kind of
+    skUnknown: begin
+      // Introduced in this pass! Leave it as an identifier.
+      result := n;
+    end;
+    skProc, skMethod, skIterator, skConverter: result := symChoice(c, n, s);
+    skTemplate: result := semTemplateExpr(c, n, s, false);
+    skMacro: result := semMacroExpr(c, n, s, false);
+    skGenericParam: result := newSymNode(s);
+    skParam: result := n;
+    skType: begin
+      if (s.typ <> nil) and (s.typ.kind <> tyGenericParam) then
+        result := newSymNode(s)
+      else    
+        result := n
+    end
+    else result := newSymNode(s)
+  end
+end;
+
+function getIdentNode(n: PNode): PNode;
+begin
+  case n.kind of
+    nkPostfix: result := getIdentNode(n.sons[1]);
+    nkPragmaExpr, nkAccQuoted: result := getIdentNode(n.sons[0]);
+    nkIdent: result := n;
+    else begin
+      illFormedAst(n);
+      result := nil
+    end
+  end
+end;
+
+function semGenericStmt(c: PContext; n: PNode; 
+                        flags: TSemGenericFlags = {@set}[]): PNode;
+var
+  i, j, L: int;
+  a: PNode;
+  s: PSym;
+begin
+  result := n;
+  if n = nil then exit;
+  case n.kind of
+    nkIdent, nkAccQuoted: begin
+      s := lookUp(c, n);
+      if withinBind in flags then
+        result := symChoice(c, n, s)
+      else
+        result := semGenericStmtSymbol(c, n, s);
+    end;
+    nkDotExpr: begin
+      s := QualifiedLookUp(c, n, true);
+      if s <> nil then
+        result := semGenericStmtSymbol(c, n, s);
+    end;
+    nkSym..nkNilLit: begin end;
+    nkBind: result := semGenericStmt(c, n.sons[0], {@set}[withinBind]);
+    
+    nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit: begin
+      // check if it is an expression macro:
+      checkMinSonsLen(n, 1);
+      s := qualifiedLookup(c, n.sons[0], false);
+      if (s <> nil) then begin
+        case s.kind of
+          skMacro: begin result := semMacroExpr(c, n, s, false); exit end;
+          skTemplate: begin result := semTemplateExpr(c, n, s, false); exit end;
+          skUnknown, skParam: begin
+            // Leave it as an identifier.
+          end;
+          skProc, skMethod, skIterator, skConverter: begin
+            n.sons[0] := symChoice(c, n.sons[0], s);
+          end;
+          skGenericParam: n.sons[0] := newSymNode(s);
+          skType: begin
+            // bad hack for generics:
+            if (s.typ <> nil) and (s.typ.kind <> tyGenericParam) then begin
+              n.sons[0] := newSymNode(s);
+            end
+          end;
+          else n.sons[0] := newSymNode(s)
+        end
+      end;
+      for i := 1 to sonsLen(n)-1 do
+        n.sons[i] := semGenericStmt(c, n.sons[i], flags);
+    end;
+    nkMacroStmt: begin
+      result := semMacroStmt(c, n, false);
+    end;
+    nkIfStmt: begin
+      for i := 0 to sonsLen(n)-1 do
+        n.sons[i] := semGenericStmtScope(c, n.sons[i]);
+    end;
+    nkWhileStmt: begin
+      openScope(c.tab);
+      for i := 0 to sonsLen(n)-1 do
+        n.sons[i] := semGenericStmt(c, n.sons[i]);
+      closeScope(c.tab);
+    end;
+    nkCaseStmt: begin
+      openScope(c.tab);
+      n.sons[0] := semGenericStmt(c, n.sons[0]);
+      for i := 1 to sonsLen(n)-1 do begin
+        a := n.sons[i];
+        checkMinSonsLen(a, 1);
+        L := sonsLen(a);
+        for j := 0 to L-2 do
+          a.sons[j] := semGenericStmt(c, a.sons[j]);
+        a.sons[L-1] := semGenericStmtScope(c, a.sons[L-1]);
+      end;
+      closeScope(c.tab);
+    end;
+    nkForStmt: begin
+      L := sonsLen(n);
+      openScope(c.tab);
+      n.sons[L-2] := semGenericStmt(c, n.sons[L-2]);
+      for i := 0 to L-3 do
+        addDecl(c, newSymS(skUnknown, n.sons[i], c));
+      n.sons[L-1] := semGenericStmt(c, n.sons[L-1]);
+      closeScope(c.tab);
+    end;
+    nkBlockStmt, nkBlockExpr, nkBlockType: begin
+      checkSonsLen(n, 2);
+      openScope(c.tab);
+      if n.sons[0] <> nil then 
+        addDecl(c, newSymS(skUnknown, n.sons[0], c));
+      n.sons[1] := semGenericStmt(c, n.sons[1]);
+      closeScope(c.tab);
+    end;
+    nkTryStmt: begin
+      checkMinSonsLen(n, 2);
+      n.sons[0] := semGenericStmtScope(c, n.sons[0]);
+      for i := 1 to sonsLen(n)-1 do begin
+        a := n.sons[i];
+        checkMinSonsLen(a, 1);
+        L := sonsLen(a);
+        for j := 0 to L-2 do 
+          a.sons[j] := semGenericStmt(c, a.sons[j], {@set}[withinTypeDesc]);
+        a.sons[L-1] := semGenericStmtScope(c, a.sons[L-1]);
+      end;    
+    end;
+    nkVarSection: begin
+      for i := 0 to sonsLen(n)-1 do begin
+        a := n.sons[i];
+        if a.kind = nkCommentStmt then continue;
+        if (a.kind <> nkIdentDefs) and (a.kind <> nkVarTuple) then
+          IllFormedAst(a);
+        checkMinSonsLen(a, 3);
+        L := sonsLen(a);
+        a.sons[L-2] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]);
+        a.sons[L-1] := semGenericStmt(c, a.sons[L-1]);
+        for j := 0 to L-3 do
+          addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c));
+      end
+    end;
+    nkGenericParams: begin
+      for i := 0 to sonsLen(n)-1 do begin
+        a := n.sons[i];
+        if (a.kind <> nkIdentDefs) then IllFormedAst(a);
+        checkMinSonsLen(a, 3);
+        L := sonsLen(a);
+        a.sons[L-2] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]);
+        // do not perform symbol lookup for default expressions 
+        for j := 0 to L-3 do
+          addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c));
+      end
+    end;
+    nkConstSection: begin
+      for i := 0 to sonsLen(n)-1 do begin
+        a := n.sons[i];
+        if a.kind = nkCommentStmt then continue;
+        if (a.kind <> nkConstDef) then IllFormedAst(a);
+        checkSonsLen(a, 3);
+        addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c));
+        a.sons[1] := semGenericStmt(c, a.sons[1], {@set}[withinTypeDesc]);
+        a.sons[2] := semGenericStmt(c, a.sons[2]);
+      end
+    end;
+    nkTypeSection: begin
+      for i := 0 to sonsLen(n)-1 do begin
+        a := n.sons[i];
+        if a.kind = nkCommentStmt then continue;
+        if (a.kind <> nkTypeDef) then IllFormedAst(a);
+        checkSonsLen(a, 3);
+        addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c));
+      end;
+      for i := 0 to sonsLen(n)-1 do begin
+        a := n.sons[i];
+        if a.kind = nkCommentStmt then continue;
+        if (a.kind <> nkTypeDef) then IllFormedAst(a);
+        checkSonsLen(a, 3);
+        if a.sons[1] <> nil then begin
+          openScope(c.tab);
+          a.sons[1] := semGenericStmt(c, a.sons[1]);
+          a.sons[2] := semGenericStmt(c, a.sons[2], {@set}[withinTypeDesc]);
+          closeScope(c.tab);
+        end
+        else
+          a.sons[2] := semGenericStmt(c, a.sons[2], {@set}[withinTypeDesc]);
+      end
+    end;
+    nkEnumTy: begin
+      checkMinSonsLen(n, 1);
+      if n.sons[0] <> nil then
+        n.sons[0] := semGenericStmt(c, n.sons[0], {@set}[withinTypeDesc]);
+      for i := 1 to sonsLen(n)-1 do begin
+        case n.sons[i].kind of
+          nkEnumFieldDef: a := n.sons[i].sons[0];
+          nkIdent: a := n.sons[i];
+          else illFormedAst(n);
+        end;
+        addDeclAt(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c),
+                  c.tab.tos-1);
+      end
+    end;
+    nkObjectTy, nkTupleTy: begin end;
+    nkFormalParams: begin
+      checkMinSonsLen(n, 1);
+      if n.sons[0] <> nil then 
+        n.sons[0] := semGenericStmt(c, n.sons[0], {@set}[withinTypeDesc]);
+      for i := 1 to sonsLen(n)-1 do begin
+        a := n.sons[i];
+        if (a.kind <> nkIdentDefs) then IllFormedAst(a);
+        checkMinSonsLen(a, 3);
+        L := sonsLen(a);
+        a.sons[L-1] := semGenericStmt(c, a.sons[L-2], {@set}[withinTypeDesc]);
+        a.sons[L-1] := semGenericStmt(c, a.sons[L-1]);
+        for j := 0 to L-3 do begin
+          addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c));
+        end
+      end
+    end;
+    nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
+    nkIteratorDef, nkLambda: begin
+      checkSonsLen(n, codePos+1);
+      addDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c));
+      openScope(c.tab);
+      n.sons[genericParamsPos] := semGenericStmt(c, n.sons[genericParamsPos]);
+      if n.sons[paramsPos] <> nil then begin
+        if n.sons[paramsPos].sons[0] <> nil then
+          addDecl(c, newSym(skUnknown, getIdent('result'), nil));
+        n.sons[paramsPos] := semGenericStmt(c, n.sons[paramsPos]);
+      end;
+      n.sons[pragmasPos] := semGenericStmt(c, n.sons[pragmasPos]);
+      n.sons[codePos] := semGenericStmtScope(c, n.sons[codePos]);
+      closeScope(c.tab);
+    end
+    else begin
+      for i := 0 to sonsLen(n)-1 do
+        result.sons[i] := semGenericStmt(c, n.sons[i], flags);
+    end
+  end
+end;
diff --git a/nim/semtempl.pas b/nim/semtempl.pas
index e639960d3..fc7e12a73 100755
--- a/nim/semtempl.pas
+++ b/nim/semtempl.pas
@@ -147,7 +147,8 @@ begin
   end
 end;
 
-function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool): PNode;
+function resolveTemplateParams(c: PContext; n: PNode; withinBind: bool;
+                               var toBind: TIntSet): PNode;
 var
   i: int;
   s: PSym;
@@ -155,7 +156,7 @@ begin
   if n = nil then begin result := nil; exit end;
   case n.kind of
     nkIdent: begin
-      if not withinBind then begin
+      if not withinBind and not IntSetContains(toBind, n.ident.id) then begin
         s := SymTabLocalGet(c.Tab, n.ident);
         if (s <> nil) then begin
           result := newSymNode(s);
@@ -165,17 +166,18 @@ begin
           result := n
       end
       else begin
+        IntSetIncl(toBind, n.ident.id);
         result := symChoice(c, n, lookup(c, n))
       end
     end;
     nkSym..nkNilLit: // atom
       result := n;
     nkBind: 
-      result := resolveTemplateParams(c, n.sons[0], true);
+      result := resolveTemplateParams(c, n.sons[0], true, toBind);
     else begin
       result := n;
       for i := 0 to sonsLen(n)-1 do
-        result.sons[i] := resolveTemplateParams(c, n.sons[i], withinBind);
+        result.sons[i] := resolveTemplateParams(c, n.sons[i], withinBind, toBind);
     end
   end
 end;
@@ -211,6 +213,7 @@ end;
 function semTemplateDef(c: PContext; n: PNode): PNode;
 var
   s: PSym;
+  toBind: TIntSet;
 begin
   if c.p.owner.kind = skModule then begin
     s := semIdentVis(c, skTemplate, n.sons[0], {@set}[sfStar]);
@@ -248,7 +251,8 @@ begin
   addParams(c, s.typ.n);
   
   // resolve parameters:
-  n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false);
+  IntSetInit(toBind);
+  n.sons[codePos] := resolveTemplateParams(c, n.sons[codePos], false, toBind);
   if not (s.typ.sons[0].kind in [tyStmt, tyTypeDesc]) then
     n.sons[codePos] := transformToExpr(n.sons[codePos]);
 
diff --git a/nim/syntaxes.pas b/nim/syntaxes.pas
index 19035028e..158ab8ea2 100755
--- a/nim/syntaxes.pas
+++ b/nim/syntaxes.pas
@@ -15,7 +15,7 @@ interface
 
 uses
   nsystem, strutils, llstream, ast, astalgo, idents, scanner, options, msgs, 
-  pnimsyn, ptmplsyn, filters, rnimsyn;
+  pnimsyn, pbraces, ptmplsyn, filters, rnimsyn;
 
 type
   TFilterKind = (filtNone, filtTemplate, filtReplace, filtStrip);
@@ -68,8 +68,8 @@ function parseAll(var p: TParsers): PNode;
 begin
   case p.skin of
     skinStandard: result := pnimsyn.parseAll(p.parser);
-    skinBraces, skinEndX: InternalError('parser to implement');
-    // skinBraces: result := pbraces.parseAll(p.parser);
+    skinBraces: result := pbraces.parseAll(p.parser);
+    skinEndX: InternalError('parser to implement');
     // skinEndX: result := pendx.parseAll(p.parser);
   end
 end;
@@ -78,8 +78,8 @@ function parseTopLevelStmt(var p: TParsers): PNode;
 begin
   case p.skin of
     skinStandard: result := pnimsyn.parseTopLevelStmt(p.parser);
-    skinBraces, skinEndX: InternalError('parser to implement');
-    //skinBraces: result := pbraces.parseTopLevelStmt(p.parser);
+    skinBraces: result := pbraces.parseTopLevelStmt(p.parser); 
+    skinEndX: InternalError('parser to implement');
     //skinEndX: result := pendx.parseTopLevelStmt(p.parser);
   end
 end;
diff --git a/nim/vis.pas b/nim/vis.pas
new file mode 100755
index 000000000..b8ba0fc5b
--- /dev/null
+++ b/nim/vis.pas
@@ -0,0 +1,35 @@
+//
+//
+//           The Nimrod Compiler
+//        (c) Copyright 2009 Andreas Rumpf
+//
+//    See the file "copying.txt", included in this
+//    distribution, for details about the copyright.
+//
+unit vis;
+
+// Virtual instruction set for Nimrod. This is used for LLVM code generation.
+
+interface
+
+{$include 'config.inc'}
+
+uses
+  nsystem, ast, astalgo, strutils, nhashes, trees, platform, magicsys,
+  extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents,
+  lists, types, ccgutils, nos, ntime, ropes, nmath, passes, rodread,
+  wordrecg, rnimsyn, treetab;
+  
+type
+  TInstrKind = (
+    insAddi,
+  
+  );
+  TInstruction = record
+    
+  end;
+  
+
+implementation
+
+end.