summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/cgen.nim2
-rwxr-xr-xcompiler/sem.nim10
-rwxr-xr-xcompiler/semcall.nim8
-rwxr-xr-xcompiler/semdata.nim12
-rwxr-xr-xcompiler/seminst.nim54
-rwxr-xr-xcompiler/semthreads.nim13
-rwxr-xr-xcompiler/trees.nim33
7 files changed, 53 insertions, 79 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 02fcce980..68e377f8b 100755
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -15,7 +15,7 @@ import
   options, intsets,
   nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, 
   times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
-  rodutils
+  rodutils, renderer
 
 when options.hasTinyCBackend:
   import tccgen
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 19b3cc9e2..c2fbfff72 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -134,15 +134,13 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode =
 include semtypes, semexprs, semgnrc, semstmts
 
 proc addCodeForGenerics(c: PContext, n: PNode) = 
-  for i in countup(c.lastGenericIdx, sonsLen(c.generics) - 1): 
-    var it = c.generics.sons[i].sons[1]
-    if it.kind != nkSym: InternalError("addCodeForGenerics")
-    var prc = it.sym
+  for i in countup(lastGenericIdx, Len(generics) - 1):
+    var prc = generics[i].instSym
     if prc.kind in {skProc, skMethod, skConverter} and prc.magic == mNone: 
       if prc.ast == nil or prc.ast.sons[codePos] == nil: 
         InternalError(prc.info, "no code for " & prc.name.s)
       addSon(n, prc.ast)
-  c.lastGenericIdx = sonsLen(c.generics)
+  lastGenericIdx = Len(generics)
 
 proc semExprNoFlags(c: PContext, n: PNode): PNode = 
   result = semExpr(c, n, {})
@@ -174,7 +172,7 @@ proc myOpenCached(module: PSym, filename: string,
 proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = 
   result = semStmt(c, n)
   # BUGFIX: process newly generated generics here, not at the end!
-  if sonsLen(c.generics) > 0: 
+  if lastGenericIdx < Len(generics):
     var a = newNodeI(nkStmtList, n.info)
     addCodeForGenerics(c, a)
     if sonsLen(a) > 0: 
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index cf277728d..f20349c0f 100755
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -119,12 +119,4 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     # candidateCount != 1: return explicitGenericInstError(n)
   else:
     assert false
-  
-  when false:
-    var x: TCandidate
-    initCandidate(x, s, n)
-    var newInst = generateInstance(c, s, x.bindings, n.info)
-    
-    markUsed(n, s)
-    result = newSymNode(newInst, n.info)
 
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 9051e4726..306638d6c 100755
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -33,16 +33,17 @@ type
     nestedBlockCounter*: int  # whether we are in a block or not
     next*: PProcCon           # used for stacking procedure contexts
   
+  TInstantiatedSymbol* {.final.} = object
+    genericSym*, instSym*: PSym
+    concreteTypes*: seq[PType]
+  
   PContext* = ref TContext
   TContext* = object of TPassContext # a context represents a module
     module*: PSym             # the module sym belonging to the context
     p*: PProcCon              # procedure context
     InstCounter*: int         # to prevent endless instantiations
-    generics*: PNode          # a list of the things to compile; list of
-                              # nkExprEqExpr nodes which contain the
-                              # generic symbol and the instantiated symbol
+   
     threadEntries*: TSymSeq   # list of thread entries to check
-    lastGenericIdx*: int      # used for the generics stack
     tab*: TSymTab             # each module has its own symbol table
     AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
                                # store this info in the syms themselves!)
@@ -58,6 +59,8 @@ type
   
 
 var gInstTypes*: TIdTable # map PType to PType
+var generics*: seq[TInstantiatedSymbol] = @[] # a list of the things to compile
+var lastGenericIdx*: int      # used for the generics stack
 
 proc newContext*(module: PSym, nimfile: string): PContext
 
@@ -124,7 +127,6 @@ proc newContext(module: PSym, nimfile: string): PContext =
   initLinkedList(result.libs)
   append(result.optionStack, newOptionEntry())
   result.module = module
-  result.generics = newNode(nkStmtList)
   result.threadEntries = @[]
   result.converters = @[]
   result.filename = nimfile
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 3d0b672bc..6cb325290 100755
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -9,15 +9,17 @@
 
 # This module implements the instantiation of generic procs.
 
-proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) = 
-  if (n.kind != nkGenericParams): 
+proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
+                                 entry: var TInstantiatedSymbol) = 
+  if n.kind != nkGenericParams: 
     InternalError(n.info, "instantiateGenericParamList; no generic params")
-  for i in countup(0, sonsLen(n) - 1): 
+  newSeq(entry.concreteTypes, n.len)
+  for i in countup(0, n.len - 1):
     var a = n.sons[i]
     if a.kind != nkSym: 
       InternalError(a.info, "instantiateGenericParamList; no symbol")
     var q = a.sym
-    if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue 
+    if q.typ.kind notin {tyTypeDesc, tyGenericParam}: continue 
     var s = newSym(skType, q.name, getCurrOwner())
     s.info = q.info
     incl(s.flags, sfUsed)
@@ -29,24 +31,23 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
       InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
     s.typ = t
     addDecl(c, s)
+    entry.concreteTypes[i] = t
 
-proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym = 
-  result = nil
-  for i in countup(0, sonsLen(c.generics) - 1): 
-    if c.generics.sons[i].kind != nkExprEqExpr: 
-      InternalError(genericSym.info, "GenericCacheGet")
-    var a = c.generics.sons[i].sons[0].sym
-    if genericSym.id == a.id: 
-      var b = c.generics.sons[i].sons[1].sym
-      if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
-        #echo "found in cache: ", getProcHeader(instSym)
-        return b
+proc sameInstantiation(a, b: TInstantiatedSymbol): bool =
+  if a.genericSym.id == b.genericSym.id and 
+      a.concreteTypes.len == b.concreteTypes.len:
+    for i in 0 .. < a.concreteTypes.len:
+      if not sameType(a.concreteTypes[i], b.concreteTypes[i]): return
+    result = true
 
-proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) = 
-  var n = newNode(nkExprEqExpr)
-  addSon(n, newSymNode(genericSym))
-  addSon(n, newSymNode(instSym))
-  addSon(c.generics, n)
+proc GenericCacheGet(c: PContext, entry: var TInstantiatedSymbol): PSym = 
+  for i in countup(0, Len(generics) - 1):
+    if sameInstantiation(entry, generics[i]):
+      result = generics[i].instSym
+      # checking for the concrete parameter list is wrong and unnecessary!
+      #if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
+      #echo "found in cache: ", getProcHeader(result)
+      return
 
 proc removeDefaultParamValues(n: PNode) = 
   # we remove default params, because they cannot be instantiated properly
@@ -81,11 +82,14 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   result.ast = n
   pushOwner(result)
   openScope(c.tab)
-  if (n.sons[genericParamsPos].kind == nkEmpty): 
+  if n.sons[genericParamsPos].kind == nkEmpty: 
     InternalError(n.info, "generateInstance")
   n.sons[namePos] = newSymNode(result)
   pushInfoContext(info)
-  instantiateGenericParamList(c, n.sons[genericParamsPos], pt)
+  var entry: TInstantiatedSymbol
+  entry.instSym = result
+  entry.genericSym = fn
+  instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry)
   n.sons[genericParamsPos] = ast.emptyNode
   # semantic checking for the parameters:
   if n.sons[paramsPos].kind != nkEmpty: 
@@ -96,10 +100,10 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
     result.typ = newTypeS(tyProc, c)
     addSon(result.typ, nil)
   result.typ.callConv = fn.typ.callConv
-  var oldPrc = GenericCacheGet(c, fn, result)
-  if oldPrc == nil: 
+  var oldPrc = GenericCacheGet(c, entry)
+  if oldPrc == nil:
     # add it here, so that recursive generic procs are possible:
-    GenericCacheAdd(c, fn, result)
+    generics.add(entry)
     addDecl(c, result)
     if n.sons[codePos].kind != nkEmpty: 
       pushProcCon(c, result)
diff --git a/compiler/semthreads.nim b/compiler/semthreads.nim
index b6bdc9e60..5e52aea72 100755
--- a/compiler/semthreads.nim
+++ b/compiler/semthreads.nim
@@ -358,6 +358,8 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
   of nkAsmStmt, nkPragma, nkIteratorDef, nkProcDef, nkMethodDef,
      nkConverterDef, nkMacroDef, nkTemplateDef: 
       result = toVoid
+  of nkExprColonExpr:
+    result = analyse(c, n.sons[1])
   else: InternalError(n.info, "analysis not implemented for: " & $n.kind)
 
 proc analyseThreadProc*(prc: PSym) =
@@ -368,17 +370,6 @@ proc analyseThreadProc*(prc: PSym) =
     c.mapping[formal.id] = toTheirs # thread receives foreign data!
   discard analyse(c, prc.ast.sons[codePos])
 
-when false:
-  proc analyseThreadCreationCall(n: PNode) =
-    # thread proc is second param of ``createThread``:
-    if n[2].kind != nkSym or n[2].sym.kind != skProc:
-      Message(n.info, warnAnalysisLoophole, renderTree(n))
-      return
-    analyseProc(n[2].sym)
-
-  proc AnalyseThread*(threadCreation: PNode) =
-    analyseThreadCreationCall(threadCreation)
-
 proc needsGlobalAnalysis*: bool =
   result = gGlobalOptions * {optThreads, optThreadAnalysis} == 
                             {optThreads, optThreadAnalysis}
diff --git a/compiler/trees.nim b/compiler/trees.nim
index 76a30e3ac..7b90296ad 100755
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -12,19 +12,6 @@
 import 
   ast, astalgo, lexer, msgs, strutils, wordrecg
 
-proc getMagic*(op: PNode): TMagic
-
-proc isConstExpr*(n: PNode): bool
-proc flattenTree*(root: PNode, op: TMagic): PNode
-proc TreeToSym*(t: PNode): PSym
-proc SwapOperands*(op: PNode)
-proc getOpSym*(op: PNode): PSym
-proc getProcSym*(call: PNode): PSym
-proc ExprStructuralEquivalent*(a, b: PNode): bool
-proc sameTree*(a, b: PNode): bool
-proc cyclicTree*(n: PNode): bool
-# implementation
-
 proc hasSon(father, son: PNode): bool = 
   for i in countup(0, sonsLen(father) - 1): 
     if father.sons[i] == son: 
@@ -45,11 +32,11 @@ proc cyclicTreeAux(n, s: PNode): bool =
   result = false
   delSon(s, m)
 
-proc cyclicTree(n: PNode): bool = 
+proc cyclicTree*(n: PNode): bool = 
   var s = newNodeI(nkEmpty, n.info)
   result = cyclicTreeAux(n, s)
 
-proc ExprStructuralEquivalent(a, b: PNode): bool = 
+proc ExprStructuralEquivalent*(a, b: PNode): bool = 
   result = false
   if a == b: 
     result = true
@@ -69,7 +56,7 @@ proc ExprStructuralEquivalent(a, b: PNode): bool =
           if not ExprStructuralEquivalent(a.sons[i], b.sons[i]): return 
         result = true
   
-proc sameTree(a, b: PNode): bool = 
+proc sameTree*(a, b: PNode): bool = 
   result = false
   if a == b: 
     result = true
@@ -93,10 +80,10 @@ proc sameTree(a, b: PNode): bool =
           if not sameTree(a.sons[i], b.sons[i]): return 
         result = true
   
-proc getProcSym(call: PNode): PSym = 
+proc getProcSym*(call: PNode): PSym = 
   result = call.sons[0].sym
 
-proc getOpSym(op: PNode): PSym = 
+proc getOpSym*(op: PNode): PSym = 
   if not (op.kind in {nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit}): 
     result = nil
   else: 
@@ -104,7 +91,7 @@ proc getOpSym(op: PNode): PSym =
     if op.sons[0].Kind == nkSym: result = op.sons[0].sym
     else: result = nil
   
-proc getMagic(op: PNode): TMagic = 
+proc getMagic*(op: PNode): TMagic = 
   case op.kind
   of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkPrefix, nkPostfix,
      nkInfix: 
@@ -113,10 +100,10 @@ proc getMagic(op: PNode): TMagic =
     else: result = mNone
   else: result = mNone
   
-proc TreeToSym(t: PNode): PSym = 
+proc TreeToSym*(t: PNode): PSym = 
   result = t.sym
 
-proc isConstExpr(n: PNode): bool = 
+proc isConstExpr*(n: PNode): bool = 
   result = (n.kind in
       {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, 
        nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags)
@@ -128,14 +115,14 @@ proc flattenTreeAux(d, a: PNode, op: TMagic) =
   else: 
     addSon(d, copyTree(a))
   
-proc flattenTree(root: PNode, op: TMagic): PNode = 
+proc flattenTree*(root: PNode, op: TMagic): PNode = 
   result = copyNode(root)
   if (getMagic(root) == op): 
     # BUGFIX: forget to copy prc
     addSon(result, copyNode(root.sons[0]))
     flattenTreeAux(result, root, op)
 
-proc SwapOperands(op: PNode) = 
+proc SwapOperands*(op: PNode) = 
   var tmp = op.sons[1]
   op.sons[1] = op.sons[2]
   op.sons[2] = tmp