summary refs log tree commit diff stats
path: root/nim/sem.pas
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2009-05-08 16:36:06 +0200
committerAndreas Rumpf <rumpf_a@web.de>2009-05-08 16:36:06 +0200
commitdb4f617afcd095db087dcb52e3ea603cca111da7 (patch)
treeeeffcc8fb523171dc394c136acf9b8006ec4138f /nim/sem.pas
parent08bc9ac03c49db7bfcdee82f46aadf95a324e015 (diff)
downloadNim-db4f617afcd095db087dcb52e3ea603cca111da7.tar.gz
version 0.7.8
Diffstat (limited to 'nim/sem.pas')
-rw-r--r--nim/sem.pas43
1 files changed, 37 insertions, 6 deletions
diff --git a/nim/sem.pas b/nim/sem.pas
index 3494754fd..09f9bf49b 100644
--- a/nim/sem.pas
+++ b/nim/sem.pas
@@ -112,6 +112,23 @@ begin
   end
 end;
 
+function semAfterMacroCall(c: PContext; n, p: PNode): PNode;
+begin
+  result := n;
+  if (p = nil) or (p.kind <> nkIdent) then
+    liMessage(n.info, errInvalidParamKindX, renderTree(p))
+  else begin
+    case p.ident.id of
+      ord(wExpr): result := semExprWithType(c, result);
+      ord(wStmt): result := semStmt(c, result);
+      ord(wTypeDesc): 
+        result.typ := semTypeNode(c, result, nil);
+      else
+        liMessage(p.info, errInvalidParamKindX, p.ident.s)
+    end
+  end
+end;
+
 function semMacroExpr(c: PContext; n: PNode; sym: PSym): PNode;
 var
   p: PEvalContext;
@@ -128,7 +145,7 @@ begin
   result := s.params[0];
   popStackFrame(p);
   if cyclicTree(result) then liMessage(n.info, errCyclicTree);
-  result := semStmt(c, result);
+  result := semAfterMacroCall(c, result, sym.ast.sons[paramsPos].sons[0]);
   // now, that was easy ...
   // and we get more flexibility than in any other programming language
 end;
@@ -137,14 +154,12 @@ end;
 {$include 'seminst.pas'}
 {$include 'sigmatch.pas'}
 
-
 procedure CheckBool(t: PNode);
 begin
   if (t.Typ = nil) or (skipVarGeneric(t.Typ).kind <> tyBool) then
     liMessage(t.Info, errExprMustBeBool);
 end;
 
-
 procedure typeMismatch(n: PNode; formal, actual: PType);
 begin
   liMessage(n.Info, errGenerated,
@@ -167,13 +182,17 @@ var
   prc: PSym;
   it: PNode;
 begin
-  for i := 0 to sonsLen(c.generics)-1 do begin
+  for i := c.lastGenericIdx to sonsLen(c.generics)-1 do begin
     it := c.generics.sons[i].sons[1];
     if it.kind <> nkSym then InternalError('addCodeForGenerics');
     prc := it.sym;
-    if (prc.kind in [skProc, skConverter]) and (prc.magic = mNone) then 
+    if (prc.kind in [skProc, skConverter]) and (prc.magic = mNone) then begin
+      if (prc.ast = nil) or (prc.ast.sons[codePos] = nil) then 
+        InternalError(prc.info, 'no code for ' + prc.name.s);
       addSon(n, prc.ast);
+    end
   end;
+  c.lastGenericIdx := sonsLen(c.generics);
 end;
 
 function myOpen(module: PSym; const filename: string): PPassContext;
@@ -212,10 +231,21 @@ end;
 function myProcess(context: PPassContext; n: PNode): PNode;
 var
   c: PContext;
+  a: PNode;
 begin
   result := nil;
   c := PContext(context);
   result := semStmt(c, n);
+  // BUGFIX: process newly generated generics here, not at the end!
+  if sonsLen(c.generics) > 0 then begin
+    a := newNodeI(nkStmtList, n.info);
+    addCodeForGenerics(c, a);
+    if sonsLen(a) > 0 then begin
+      // a generic has been added to `a`:
+      addSonIfNotNil(a, result);
+      result := a
+    end
+  end
 end;
 
 function myClose(context: PPassContext; n: PNode): PNode;
@@ -226,7 +256,8 @@ begin
   closeScope(c.tab);    // close module's scope
   rawCloseScope(c.tab); // imported symbols; don't check for unused ones!
   if n = nil then result := newNode(nkStmtList)
-  else result := n;
+  else InternalError(n.info, 'n is not nil');
+  //result := n;
   addCodeForGenerics(c, result);
   popOwner();
   c.p := nil;