diff options
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/cgen.nim | 2 | ||||
-rwxr-xr-x | compiler/sem.nim | 10 | ||||
-rwxr-xr-x | compiler/semcall.nim | 8 | ||||
-rwxr-xr-x | compiler/semdata.nim | 12 | ||||
-rwxr-xr-x | compiler/seminst.nim | 54 | ||||
-rwxr-xr-x | compiler/semthreads.nim | 13 | ||||
-rwxr-xr-x | compiler/trees.nim | 33 |
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 |