get rid of the SymTab* procs in astalgo

This commit is contained in:
Zahary Karadjov
2013-05-12 00:49:00 +03:00
parent 9a6f47ae69
commit 3d1c6de638
11 changed files with 91 additions and 133 deletions

View File

@@ -72,39 +72,6 @@ type
proc InitIdentIter*(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym
proc NextIdentIter*(ti: var TIdentIter, tab: TStrTable): PSym
# -------------- symbol table ----------------------------------------------
# Each TParser object (which represents a module being compiled) has its own
# symbol table. A symbol table is organized as a stack of str tables. The
# stack represents the different scopes.
# Stack pointer:
# 0 imported symbols from other modules
# 1 module level
# 2 proc level
# 3 nested statements
# ...
#
type
TScope = object
symbols*: TStrTable
parent*: PScope
PScope = ref TScope
TSymTab*{.final.} = object
tos*: Natural # top of stack
stack*: seq[PScope]
proc InitSymTab*(tab: var TSymTab)
proc DeinitSymTab*(tab: var TSymTab)
proc SymTabGet*(tab: TSymTab, s: PIdent): PSym
proc SymTabGet*(tab: TSymTab, s: PIdent, filter: TSymKinds): PSym
proc SymTabLocalGet*(tab: TSymTab, s: PIdent): PSym
proc SymTabAdd*(tab: var TSymTab, e: PSym)
proc SymTabAddAt*(tab: var TSymTab, e: PSym, at: Natural)
proc SymTabAddUnique*(tab: var TSymTab, e: PSym): TResult
proc SymTabAddUniqueAt*(tab: var TSymTab, e: PSym, at: Natural): TResult
# these are for debugging only: They are not really deprecated, but I want
# the warning so that release versions do not contain debugging statements:
proc debug*(n: PSym) {.deprecated.}
@@ -710,44 +677,7 @@ proc NextIter(ti: var TTabIter, tab: TStrTable): PSym =
result = tab.data[ti.h]
Inc(ti.h) # ... and increment by one always
if result != nil: break
proc InitSymTab(tab: var TSymTab) =
tab.tos = 0
tab.stack = EmptySeq
proc DeinitSymTab(tab: var TSymTab) =
tab.stack = nil
proc SymTabLocalGet(tab: TSymTab, s: PIdent): PSym =
result = StrTableGet(tab.stack[tab.tos - 1], s)
proc SymTabGet(tab: TSymTab, s: PIdent): PSym =
for i in countdown(tab.tos - 1, 0):
result = StrTableGet(tab.stack[i], s)
if result != nil: return
result = nil
proc SymTabGet*(tab: TSymTab, s: PIdent, filter: TSymKinds): PSym =
for i in countdown(tab.tos - 1, 0):
result = StrTableGet(tab.stack[i], s)
if result != nil and result.kind in filter: return
result = nil
proc SymTabAddAt(tab: var TSymTab, e: PSym, at: Natural) =
StrTableAdd(tab.stack[at], e)
proc SymTabAdd(tab: var TSymTab, e: PSym) =
StrTableAdd(tab.stack[tab.tos - 1], e)
proc SymTabAddUniqueAt(tab: var TSymTab, e: PSym, at: Natural): TResult =
if StrTableIncl(tab.stack[at], e):
result = Failure
else:
result = Success
proc SymTabAddUnique(tab: var TSymTab, e: PSym): TResult =
result = SymTabAddUniqueAt(tab, e, tab.tos - 1)
iterator items*(tab: TStrTable): PSym =
var it: TTabIter
var s = InitTabIter(it, tab)
@@ -755,10 +685,6 @@ iterator items*(tab: TStrTable): PSym =
yield s
s = NextIter(it, tab)
iterator items*(tab: TSymTab): PSym =
for i in countdown(tab.tos-1, 0):
for it in items(tab.stack[i]): yield it
proc hasEmptySlot(data: TIdPairSeq): bool =
for h in countup(0, high(data)):
if data[h].key == nil:

View File

@@ -46,7 +46,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
result.typ = errorType(c)
incl(result.flags, sfDiscardable)
# pretend it's imported from some unknown module to prevent cascading errors:
SymTabAddAt(c.tab, result, ast.ImportTablePos)
c.importTable.addSym(result)
type
TOverloadIterMode* = enum
@@ -63,8 +63,8 @@ proc getSymRepr*(s: PSym): string =
case s.kind
of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s)
else: result = s.name.s
proc ensureNoMissingOrUnusedSymbols*(scope: PScope) =
proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
# check if all symbols have been used and defined:
var it: TTabIter
var s = InitTabIter(it, scope.symbols)
@@ -89,15 +89,15 @@ proc WrongRedefinition*(info: TLineInfo, s: string) =
proc AddSym*(t: var TStrTable, n: PSym) =
if StrTableIncl(t, n): WrongRedefinition(n.info, n.name.s)
proc addDecl*(c: PContext, sym: PSym) =
if SymTabAddUnique(c.tab, sym) == Failure:
proc addDecl*(c: PContext, sym: PSym) =
if c.currentScope.addUnique(sym) == Failure:
WrongRedefinition(sym.info, sym.Name.s)
proc addPrelimDecl*(c: PContext, sym: PSym) =
discard SymTabAddUnique(c.tab, sym)
discard c.currentScope.addUnique(sym)
proc addDeclAt*(c: PContext, sym: PSym, at: Natural) =
if SymTabAddUniqueAt(c.tab, sym, at) == Failure:
proc addDeclAt*(scope: PScope, sym: PSym) =
if scope.addUnique(sym) == Failure:
WrongRedefinition(sym.info, sym.Name.s)
proc AddInterfaceDeclAux(c: PContext, sym: PSym) =
@@ -106,35 +106,35 @@ proc AddInterfaceDeclAux(c: PContext, sym: PSym) =
if c.module != nil: StrTableAdd(c.module.tab, sym)
else: InternalError(sym.info, "AddInterfaceDeclAux")
proc addInterfaceDeclAt*(c: PContext, sym: PSym, at: Natural) =
addDeclAt(c, sym, at)
proc addInterfaceDeclAt*(c: PContext, scope: PScope, sym: PSym) =
addDeclAt(scope, sym)
AddInterfaceDeclAux(c, sym)
proc addOverloadableSymAt*(c: PContext, fn: PSym, at: Natural) =
proc addOverloadableSymAt*(scope: PScope, fn: PSym) =
if fn.kind notin OverloadableSyms:
InternalError(fn.info, "addOverloadableSymAt")
return
var check = StrTableGet(c.tab.stack[at], fn.name)
var check = StrTableGet(scope.symbols, fn.name)
if check != nil and check.Kind notin OverloadableSyms:
WrongRedefinition(fn.info, fn.Name.s)
else:
SymTabAddAt(c.tab, fn, at)
scope.addSym(fn)
proc addInterfaceDecl*(c: PContext, sym: PSym) =
# it adds the symbol to the interface if appropriate
addDecl(c, sym)
AddInterfaceDeclAux(c, sym)
proc addInterfaceOverloadableSymAt*(c: PContext, sym: PSym, at: int) =
proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
# it adds the symbol to the interface if appropriate
addOverloadableSymAt(c, sym, at)
addOverloadableSymAt(scope, sym)
AddInterfaceDeclAux(c, sym)
proc lookUp*(c: PContext, n: PNode): PSym =
# Looks up a symbol. Generates an error in case of nil.
case n.kind
of nkIdent:
result = SymtabGet(c.Tab, n.ident)
result = searchInScopes(c, n.ident)
if result == nil:
LocalError(n.info, errUndeclaredIdentifier, n.ident.s)
result = errorSym(c, n)
@@ -142,7 +142,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
result = n.sym
of nkAccQuoted:
var ident = considerAcc(n)
result = SymtabGet(c.Tab, ident)
result = searchInScopes(c, ident)
if result == nil:
LocalError(n.info, errUndeclaredIdentifier, ident.s)
result = errorSym(c, n)
@@ -161,7 +161,7 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
case n.kind
of nkIdent, nkAccQuoted:
var ident = considerAcc(n)
result = SymtabGet(c.Tab, ident)
result = searchInScopes(c, ident)
if result == nil and checkUndeclared in flags:
LocalError(n.info, errUndeclaredIdentifier, ident.s)
result = errorSym(c, n)
@@ -239,6 +239,47 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
else: nil
if result != nil and result.kind == skStub: loadStub(result)
proc openScope*(c: PContext): PScope {.discardable.} =
c.currentScope = PScope(parent: c.currentScope, symbols: newStrTable())
result = c.currentScope
proc rawCloseScope*(c: PContext) =
c.currentScope = c.currentScope.parent
proc closeScope*(c: PContext) =
ensureNoMissingOrUnusedSymbols(c.currentScope)
rawCloseScope(c)
template addSym*(scope: PScope, s: PSym) =
StrTableAdd(scope.symbols, s)
proc addUniqueSym*(scope: PScope, s: PSym): TResult =
if StrTableIncl(scope.symbols, s):
result = Failure
else:
result = Success
iterator walkScopes*(scope: PScope): PScope =
var current = scope
while current != nil:
yield current
current = current.parent
proc localSearchInScope*(c: PContext, s: PIdent): PSym =
result = StrTableGet(c.currentScope.symbols, s)
proc searchInScopes*(c: PContext, s: PIdent): PSym =
for scope in walkScopes(c.currentScope):
result = StrTableGet(scope.symbols, s)
if result != nil: return
result = nil
proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym =
for scope in walkScopes(c.currentScope):
result = StrTableGet(scope.symbols, s)
if result != nil and result.kind in filter: return
result = nil
proc lastOverloadScope*(o: TOverloadIter): int =
case o.mode
of oimNoQualifier: result = o.stackPtr

View File

@@ -409,7 +409,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
if c < 0: sub = substr(str, b + 1)
else: sub = substr(str, b + 1, c - 1)
if sub != "":
var e = SymtabGet(con.tab, getIdent(sub))
var e = searchInScopes(con, getIdent(sub))
if e != nil:
if e.kind == skStub: loadStub(e)
addSon(result, newSymNode(e))

View File

@@ -247,15 +247,15 @@ proc myOpen(module: PSym): PPassContext =
c.semTypeNode = semTypeNode
pushProcCon(c, module)
pushOwner(c.module)
openScope(c) # scope for imported symbols
SymTabAdd(c.tab, module) # a module knows itself
c.importTable = openScope(c)
c.importTable.addSym(module) # a module knows itself
if sfSystemModule in module.flags:
magicsys.SystemModule = module # set global variable!
InitSystem(c.tab) # currently does nothing
else:
SymTabAdd(c.tab, magicsys.SystemModule) # import the "System" identifier
c.importTable.addSym magicsys.SystemModule # import the "System" identifier
importAllSymbols(c, magicsys.SystemModule)
closeScope(c) # scope for the module's symbols
c.topLevelScope = openScope(c)
result = c
proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =

View File

@@ -45,10 +45,18 @@ type
efAllowDestructor
TExprFlags* = set[TExprFlag]
TScope* = object
symbols*: TStrTable
parent*: PScope
PScope* = ref TScope
PContext* = ref TContext
TContext* = object of TPassContext # a context represents a module
module*: PSym # the module sym belonging to the context
currentScope*: PScope
currentScope*: PScope # current scope
importTable*: PScope # scope for all imported symbols
topLevelScope*: PScope # scope for all top-level symbols
p*: PProcCon # procedure context
friendModule*: PSym # current friend module; may access private data;
# this is used so that generic instantiations
@@ -56,7 +64,6 @@ type
InstCounter*: int # to prevent endless instantiations
threadEntries*: TSymSeq # list of thread entries to check
tab*: TSymTab # each module has its own symbol table
AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
# store this info in the syms themselves!)
InGenericContext*: int # > 0 if we are in a generic type
@@ -83,8 +90,7 @@ type
# naming it multiple times
generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
lastGenericIdx*: int # used for the generics stack
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
result.genericSym = s
result.inst = inst
@@ -112,20 +118,6 @@ proc PopOwner*()
var gOwners*: seq[PSym] = @[]
proc openScope*(c: PContext) =
c.currentScope = PScope(parent: c.currentScope, symbols: newStrTable())
c.tab.stack.add(c.currentScope)
inc c.tab.stack.tos
proc rawCloseScope*(c: PContext) =
c.currentScope = c.currentScope.parent
c.tab.stack.setLen(c.tab.stack.len - 1)
dec c.tab.stack.tos
proc closeScope*(c: PContext) =
ensureNoMissingOrUnusedSymbols(c.currentScope)
rawExitScope(c)
proc getCurrOwner(): PSym =
# owner stack (used for initializing the
# owner field of syms)
@@ -166,7 +158,6 @@ proc newOptionEntry(): POptionEntry =
proc newContext(module: PSym): PContext =
new(result)
InitSymTab(result.tab)
result.AmbiguousSymbols = initIntset()
initLinkedList(result.optionStack)
initLinkedList(result.libs)

View File

@@ -120,7 +120,7 @@ proc instantiateDestructor(c: PContext, typ: PType): bool =
of tySequence, tyArray, tyArrayConstr, tyOpenArray, tyVarargs:
if instantiateDestructor(c, t.sons[0]):
if rangeDestructorProc == nil:
rangeDestructorProc = SymtabGet(c.tab, getIdent"nimDestroyRange")
rangeDestructorProc = searchInScopes(c, getIdent"nimDestroyRange")
t.destructor = rangeDestructorProc
return true
else:

View File

@@ -328,9 +328,9 @@ proc semOpAux(c: PContext, n: PNode) =
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
# quick check if there is *any* () operator overloaded:
var par = getIdent("()")
if SymtabGet(c.Tab, par) == nil:
if searchInScopes(c, par) == nil:
result = nil
else:
else:
result = newNodeI(nkCall, n.info)
addSon(result, newIdentNode(par, n.info))
for i in countup(0, sonsLen(n) - 1): addSon(result, n.sons[i])
@@ -937,7 +937,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
addSon(result, copyTree(n[0]))
else:
var i = considerAcc(n.sons[1])
var f = SymTabGet(c.tab, i)
var f = searchInScopes(c, i)
# if f != nil and f.kind == skStub: loadStub(f)
# ``loadStub`` is not correct here as we don't care for ``f`` really
if f != nil:
@@ -1205,9 +1205,9 @@ proc SemYield(c: PContext, n: PNode): PNode =
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
if onlyCurrentScope:
result = SymtabLocalGet(c.tab, i)
result = localSearchInScope(c, i)
else:
result = SymtabGet(c.Tab, i) # no need for stub loading
result = searchInScopes(c, i) # no need for stub loading
proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
case n.kind

View File

@@ -82,7 +82,7 @@ proc Lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
ctx: var TIntSet): PNode =
result = n
let ident = considerAcc(n)
var s = SymtabGet(c.Tab, ident)
var s = searchInScopes(c, ident)
if s == nil:
if ident.id notin ctx and withinMixin notin flags:
localError(n.info, errUndeclaredIdentifier, ident.s)
@@ -281,7 +281,7 @@ proc semGenericStmt(c: PContext, n: PNode,
of nkEnumFieldDef: a = n.sons[i].sons[0]
of nkIdent: a = n.sons[i]
else: illFormedAst(n)
addDeclAt(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c), c.tab.tos-1)
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c))
of nkObjectTy, nkTupleTy:
nil
of nkFormalParams:

View File

@@ -800,7 +800,7 @@ proc lookupMacro(c: PContext, n: PNode): PSym =
result = n.sym
if result.kind notin {skMacro, skTemplate}: result = nil
else:
result = SymtabGet(c.Tab, considerAcc(n), {skMacro, skTemplate})
result = searchInScopes(c, considerAcc(n), {skMacro, skTemplate})
proc semProcAnnotation(c: PContext, prc: PNode): PNode =
var n = prc.sons[pragmasPos]
@@ -894,6 +894,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
n.sons[namePos] = newSymNode(s)
s.ast = n
pushOwner(s)
var outerScope = c.currentScope
openScope(c)
var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty:
@@ -922,12 +923,11 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if proto == nil:
s.typ.callConv = lastOptionEntry(c).defaultCC
# add it here, so that recursive procs are possible:
# -2 because we have a scope open for parameters
if sfGenSym in s.flags: nil
elif kind in OverloadableSyms:
addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2)
addInterfaceOverloadableSymAt(c, outerScope, s)
else:
addInterfaceDeclAt(c, s, c.tab.tos - 2)
addInterfaceDeclAt(c, outerScope, s)
if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, s, n.sons[pragmasPos], validPragmas)
else:

View File

@@ -413,7 +413,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
let curScope = c.tab.tos - 1
var proto = SearchForProc(c, s, curScope)
if proto == nil:
addInterfaceOverloadableSymAt(c, s, curScope)
addInterfaceOverloadableSymAt(c, c.currentScope, s)
else:
SymTabReplace(c.tab.stack[curScope], proto, s)
if n.sons[patternPos].kind != nkEmpty:

View File

@@ -79,7 +79,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
incl(e.flags, sfExported)
if not isPure: StrTableAdd(c.module.tab, e)
addSon(result.n, newSymNode(e))
if sfGenSym notin e.flags and not isPure: addDeclAt(c, e, c.tab.tos - 1)
if sfGenSym notin e.flags and not isPure: addDecl(c, e)
inc(counter)
proc semSet(c: PContext, n: PNode, prev: PType): PType =
@@ -616,7 +616,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if genericParams == nil:
# genericParams is nil when the proc is being instantiated
# the resolved type will be in scope then
let s = SymtabGet(c.tab, paramTypId)
let s = searchInScopes(c, paramTypId)
# tests/run/tinterf triggers this:
if s != nil: result = s.typ
else:
@@ -749,7 +749,7 @@ proc semGenericParamInInvokation(c: PContext, n: PNode): PType =
when false:
if n.kind == nkSym:
# for generics we need to lookup the type var again:
var s = SymtabGet(c.Tab, n.sym.name)
var s = searchInScopes(c, n.sym.name)
if s != nil:
if s.kind == skType and s.typ != nil:
var t = n.sym.typ