summary refs log tree commit diff stats
path: root/nim/instgen.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/instgen.pas')
-rw-r--r--nim/instgen.pas76
1 files changed, 53 insertions, 23 deletions
diff --git a/nim/instgen.pas b/nim/instgen.pas
index 2d5abc8b2..e64034f9e 100644
--- a/nim/instgen.pas
+++ b/nim/instgen.pas
@@ -21,11 +21,12 @@ type
     newOwner: PSym;
     instantiator: TLineInfo;
   end;
-  PInstClosure = ^TInstantiateClosure;
+  PInstantiateClosure = ^TInstantiateClosure;
+  PInstClosure = PInstantiateClosure;
 
-function instantiateTree(var c: TInstantiateClosure; t: PNode): PNode; forward;
-
-function instantiateSym(var c: TInstantiateClosure; sym: PSym): PSym; forward;
+function instantiateTree(c: PInstantiateClosure; t: PNode): PNode; forward;
+function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym; forward;
+function instantiateType(c: PInstantiateClosure; typ: PType): PType; forward;
 
 function containsGenericTypeIter(t: PType; closure: PObject): bool;
 begin
@@ -37,35 +38,58 @@ begin
   result := iterOverType(t, containsGenericTypeIter, nil);
 end;
 
+function instTypeNode(c: PInstantiateClosure; n: PNode): PNode;
+var
+  i: int;
+begin
+  result := nil;
+  if n <> nil then begin
+    result := copyNode(n);
+    result.typ := instantiateType(c, n.typ);
+    case n.kind of
+      nkNone..nkNilLit: begin // a leaf
+      end;
+      else begin
+        for i := 0 to sonsLen(n)-1 do
+          addSon(result, instTypeNode(c, n.sons[i]));
+      end
+    end
+  end
+end;
 
-function instantiateTypeMutator(typ: PType; c: PObject): PType;
+function instantiateType(c: PInstantiateClosure; typ: PType): PType;
+var 
+  i: int;
 begin
-  result := PType(idTableGet(PInstClosure(c).mapping, typ));
+  result := PType(idTableGet(c.mapping, typ));
   if result <> nil then exit;
   if containsGenericType(typ) then begin
-    result := copyType(typ, PInstClosure(c).newOwner);
-    idTablePut(PInstClosure(c).mapping, typ, result)
+    result := copyType(typ, c.newOwner);
+    idTablePut(c.mapping, typ, result); // to avoid cycles
+    for i := 0 to sonsLen(result)-1 do 
+      result.sons[i] := instantiateType(c, result.sons[i]);
+    if result.n <> nil then
+      result.n := instTypeNode(c, result.n);
   end
   else
     result := typ;
   if result.Kind in GenericTypes then begin
-    liMessage(PInstClosure(c).instantiator, errCannotInstantiateX,
+    liMessage(c.instantiator, errCannotInstantiateX, 
               TypeToString(typ, preferName));
+  end
+  else if result.kind = tyVar then begin
+    if result.sons[0].kind = tyVar then
+      liMessage(c.instantiator, errVarVarTypeNotAllowed);
   end;
 end;
 
-function instantiateType(var c: TInstantiateClosure; typ: PType): PType;
-begin
-  result := mutateType(typ, instantiateTypeMutator, {@cast}PObject(addr(c)));
-end;
-
-function instantiateSym(var c: TInstantiateClosure; sym: PSym): PSym;
+function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym;
 begin
   if sym = nil then begin result := nil; exit end; // BUGFIX
   result := PSym(idTableGet(c.mapping, sym));
   if (result = nil) then begin
     if (sym.owner.id = c.fn.id) or (sym.id = c.fn.id) then begin
-      result := copySym(sym, nil);
+      result := copySym(sym);
       if sym.id = c.fn.id then c.newOwner := result;
       include(result.flags, sfIsCopy);
       idTablePut(c.mapping, sym, result); // BUGFIX
@@ -83,7 +107,7 @@ begin
   end
 end;
 
-function instantiateTree(var c: TInstantiateClosure; t: PNode): PNode;
+function instantiateTree(c: PInstantiateClosure; t: PNode): PNode;
 var
   len, i: int;
 begin
@@ -124,7 +148,8 @@ begin
     q := n.sons[i].sym;
     s := newSym(skType, q.name, getCurrOwner(c));
     t := PType(IdTableGet(pt, q.typ));
-    if t = nil then liMessage(n.sons[i].info, errCannotInstantiateX, s.name.s);
+    if t = nil then
+      liMessage(n.sons[i].info, errCannotInstantiateX, s.name.s);
     assert(t.kind <> tyGenericParam);
     s.typ := t;
     addDecl(c, s);
@@ -138,7 +163,8 @@ var
 begin
   result := nil;
   for i := 0 to sonsLen(c.generics)-1 do begin
-    assert(c.generics.sons[i].kind = nkExprEqExpr);
+    if c.generics.sons[i].kind <> nkExprEqExpr then
+      InternalError(genericSym.info, 'GenericCacheGet');
     a := c.generics.sons[i].sons[0].sym;
     if genericSym.id = a.id then begin
       b := c.generics.sons[i].sons[1].sym;
@@ -173,8 +199,8 @@ var
   n: PNode;
 begin
   oldP := c.p; // restore later
-  result := copySym(fn, getCurrOwner(c));
-  result.id := getId();
+  result := copySym(fn);
+  result.owner := getCurrOwner(c);
   n := copyTree(fn.ast);
   result.ast := n;
   pushOwner(c, result);
@@ -202,7 +228,7 @@ begin
     addDecl(c, result);
     if n.sons[codePos] <> nil then begin
       c.p := newProcCon(result);
-      if result.kind = skProc then begin
+      if result.kind in [skProc, skConverter] then begin
         addResult(c, result.typ.sons[0], n.info);
         addResultNode(c, n);
       end;
@@ -221,8 +247,12 @@ end;
 function generateTypeInstance(p: PContext; const pt: TIdTable;
                               const instantiator: TLineInfo; t: PType): PType;
 var
-  c: TInstantiateClosure;
+  c: PInstantiateClosure;
 begin
+  new(c);
+{@ignore}
+  fillChar(c^, sizeof(c^), 0);
+{@emit}
   c.mapping := pt; // making a copy is not necessary
   c.fn := nil;
   c.instantiator := instantiator;