switch to a linked list of scopes

This commit is contained in:
Zahary Karadjov 2013-05-11 23:45:20 +03:00
commit 9a6f47ae69
11 changed files with 96 additions and 88 deletions

View file

@ -1080,6 +1080,9 @@ proc initStrTable(x: var TStrTable) =
x.counter = 0 x.counter = 0
newSeq(x.data, startSize) newSeq(x.data, startSize)
proc newStrTable*: TStrTable =
initStrTable(result)
proc initTable(x: var TTable) = proc initTable(x: var TTable) =
x.counter = 0 x.counter = 0
newSeq(x.data, startSize) newSeq(x.data, startSize)

View file

@ -84,9 +84,15 @@ proc NextIdentIter*(ti: var TIdentIter, tab: TStrTable): PSym
# ... # ...
# #
type type
TScope = object
symbols*: TStrTable
parent*: PScope
PScope = ref TScope
TSymTab*{.final.} = object TSymTab*{.final.} = object
tos*: Natural # top of stack tos*: Natural # top of stack
stack*: seq[TStrTable] stack*: seq[PScope]
proc InitSymTab*(tab: var TSymTab) proc InitSymTab*(tab: var TSymTab)
@ -98,10 +104,6 @@ proc SymTabAdd*(tab: var TSymTab, e: PSym)
proc SymTabAddAt*(tab: var TSymTab, e: PSym, at: Natural) proc SymTabAddAt*(tab: var TSymTab, e: PSym, at: Natural)
proc SymTabAddUnique*(tab: var TSymTab, e: PSym): TResult proc SymTabAddUnique*(tab: var TSymTab, e: PSym): TResult
proc SymTabAddUniqueAt*(tab: var TSymTab, e: PSym, at: Natural): TResult proc SymTabAddUniqueAt*(tab: var TSymTab, e: PSym, at: Natural): TResult
proc OpenScope*(tab: var TSymTab)
proc RawCloseScope*(tab: var TSymTab)
# the real "closeScope" adds some
# checks in parsobj
# these are for debugging only: They are not really deprecated, but I want # these are for debugging only: They are not really deprecated, but I want
# the warning so that release versions do not contain debugging statements: # the warning so that release versions do not contain debugging statements:
@ -746,14 +748,6 @@ proc SymTabAddUniqueAt(tab: var TSymTab, e: PSym, at: Natural): TResult =
proc SymTabAddUnique(tab: var TSymTab, e: PSym): TResult = proc SymTabAddUnique(tab: var TSymTab, e: PSym): TResult =
result = SymTabAddUniqueAt(tab, e, tab.tos - 1) result = SymTabAddUniqueAt(tab, e, tab.tos - 1)
proc OpenScope(tab: var TSymTab) =
if tab.tos >= len(tab.stack): setlen(tab.stack, tab.tos + 1)
initStrTable(tab.stack[tab.tos])
Inc(tab.tos)
proc RawCloseScope(tab: var TSymTab) =
Dec(tab.tos)
iterator items*(tab: TStrTable): PSym = iterator items*(tab: TStrTable): PSym =
var it: TTabIter var it: TTabIter
var s = InitTabIter(it, tab) var s = InitTabIter(it, tab)

View file

@ -64,13 +64,10 @@ proc getSymRepr*(s: PSym): string =
of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s) of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s)
else: result = s.name.s else: result = s.name.s
proc CloseScope*(tab: var TSymTab) = proc ensureNoMissingOrUnusedSymbols*(scope: PScope) =
# check if all symbols have been used and defined: # check if all symbols have been used and defined:
if tab.tos > len(tab.stack):
InternalError("CloseScope")
return
var it: TTabIter var it: TTabIter
var s = InitTabIter(it, tab.stack[tab.tos-1]) var s = InitTabIter(it, scope.symbols)
var missingImpls = 0 var missingImpls = 0
while s != nil: while s != nil:
if sfForward in s.flags: if sfForward in s.flags:
@ -83,8 +80,7 @@ proc CloseScope*(tab: var TSymTab) =
# BUGFIX: check options in s! # BUGFIX: check options in s!
if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}: if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s)) Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
s = NextIter(it, tab.stack[tab.tos-1]) s = NextIter(it, scope.symbols)
astalgo.rawCloseScope(tab)
proc WrongRedefinition*(info: TLineInfo, s: string) = proc WrongRedefinition*(info: TLineInfo, s: string) =
if gCmd != cmdInteractive: if gCmd != cmdInteractive:

View file

@ -247,7 +247,7 @@ proc myOpen(module: PSym): PPassContext =
c.semTypeNode = semTypeNode c.semTypeNode = semTypeNode
pushProcCon(c, module) pushProcCon(c, module)
pushOwner(c.module) pushOwner(c.module)
openScope(c.tab) # scope for imported symbols openScope(c) # scope for imported symbols
SymTabAdd(c.tab, module) # a module knows itself SymTabAdd(c.tab, module) # a module knows itself
if sfSystemModule in module.flags: if sfSystemModule in module.flags:
magicsys.SystemModule = module # set global variable! magicsys.SystemModule = module # set global variable!
@ -255,7 +255,7 @@ proc myOpen(module: PSym): PPassContext =
else: else:
SymTabAdd(c.tab, magicsys.SystemModule) # import the "System" identifier SymTabAdd(c.tab, magicsys.SystemModule) # import the "System" identifier
importAllSymbols(c, magicsys.SystemModule) importAllSymbols(c, magicsys.SystemModule)
openScope(c.tab) # scope for the module's symbols closeScope(c) # scope for the module's symbols
result = c result = c
proc myOpenCached(module: PSym, rd: PRodReader): PPassContext = proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
@ -310,8 +310,8 @@ proc checkThreads(c: PContext) =
proc myClose(context: PPassContext, n: PNode): PNode = proc myClose(context: PPassContext, n: PNode): PNode =
var c = PContext(context) var c = PContext(context)
closeScope(c.tab) # close module's scope closeScope(c) # close module's scope
rawCloseScope(c.tab) # imported symbols; don't check for unused ones! rawCloseScope(c) # imported symbols; don't check for unused ones!
result = newNode(nkStmtList) result = newNode(nkStmtList)
if n != nil: if n != nil:
InternalError(n.info, "n is not nil") #result := n; InternalError(n.info, "n is not nil") #result := n;

View file

@ -48,6 +48,7 @@ type
PContext* = ref TContext PContext* = ref TContext
TContext* = object of TPassContext # a context represents a module TContext* = object of TPassContext # a context represents a module
module*: PSym # the module sym belonging to the context module*: PSym # the module sym belonging to the context
currentScope*: PScope
p*: PProcCon # procedure context p*: PProcCon # procedure context
friendModule*: PSym # current friend module; may access private data; friendModule*: PSym # current friend module; may access private data;
# this is used so that generic instantiations # this is used so that generic instantiations
@ -111,6 +112,20 @@ proc PopOwner*()
var gOwners*: seq[PSym] = @[] 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 = proc getCurrOwner(): PSym =
# owner stack (used for initializing the # owner stack (used for initializing the
# owner field of syms) # owner field of syms)

View file

@ -1139,7 +1139,7 @@ proc SemReturn(c: PContext, n: PNode): PNode =
LocalError(n.info, errXNotAllowedHere, "\'return\'") LocalError(n.info, errXNotAllowedHere, "\'return\'")
proc semProcBody(c: PContext, n: PNode): PNode = proc semProcBody(c: PContext, n: PNode): PNode =
openScope(c.tab) openScope(c)
result = semExpr(c, n) result = semExpr(c, n)
if c.p.resultSym != nil and not isEmptyType(result.typ): if c.p.resultSym != nil and not isEmptyType(result.typ):
# transform ``expr`` to ``result = expr``, but not if the expr is already # transform ``expr`` to ``result = expr``, but not if the expr is already
@ -1163,7 +1163,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
result = semAsgn(c, a) result = semAsgn(c, a)
else: else:
discardCheck(result) discardCheck(result)
closeScope(c.tab) closeScope(c)
proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) = proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
var t = skipTypes(restype, {tyGenericInst}) var t = skipTypes(restype, {tyGenericInst})
@ -1375,7 +1375,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# open a scope for temporary symbol inclusions: # open a scope for temporary symbol inclusions:
let oldTos = c.tab.tos let oldTos = c.tab.tos
openScope(c.tab) openScope(c)
let oldOwnerLen = len(gOwners) let oldOwnerLen = len(gOwners)
let oldGenerics = c.generics let oldGenerics = c.generics
let oldContextLen = msgs.getInfoContextLen() let oldContextLen = msgs.getInfoContextLen()
@ -1398,7 +1398,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
c.p = oldProcCon c.p = oldProcCon
msgs.setInfoContextLen(oldContextLen) msgs.setInfoContextLen(oldContextLen)
setlen(gOwners, oldOwnerLen) setlen(gOwners, oldOwnerLen)
while c.tab.tos > oldTos: rawCloseScope(c.tab) while c.tab.tos > oldTos: rawCloseScope(c)
dec c.InCompilesContext dec c.InCompilesContext
dec msgs.gSilence dec msgs.gSilence
msgs.gErrorCounter = oldErrorCount msgs.gErrorCounter = oldErrorCount
@ -1641,7 +1641,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
result = n result = n
Inc(c.p.nestedBlockCounter) Inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2) checkSonsLen(n, 2)
openScope(c.tab) # BUGFIX: label is in the scope of block! openScope(c) # BUGFIX: label is in the scope of block!
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
var labl = newSymG(skLabel, n.sons[0], c) var labl = newSymG(skLabel, n.sons[0], c)
if sfGenSym notin labl.flags: if sfGenSym notin labl.flags:
@ -1652,7 +1652,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
n.typ = n.sons[1].typ n.typ = n.sons[1].typ
if isEmptyType(n.typ): n.kind = nkBlockStmt if isEmptyType(n.typ): n.kind = nkBlockStmt
else: n.kind = nkBlockExpr else: n.kind = nkBlockExpr
closeScope(c.tab) closeScope(c)
Dec(c.p.nestedBlockCounter) Dec(c.p.nestedBlockCounter)
proc buildCall(n: PNode): PNode = proc buildCall(n: PNode): PNode =

View file

@ -36,9 +36,9 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags,
proc semGenericStmtScope(c: PContext, n: PNode, proc semGenericStmtScope(c: PContext, n: PNode,
flags: TSemGenericFlags, flags: TSemGenericFlags,
ctx: var TIntSet): PNode = ctx: var TIntSet): PNode =
openScope(c.tab) openScope(c)
result = semGenericStmt(c, n, flags, ctx) result = semGenericStmt(c, n, flags, ctx)
closeScope(c.tab) closeScope(c)
template macroToExpand(s: expr): expr = template macroToExpand(s: expr): expr =
s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags) s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfImmediate in s.flags)
@ -180,12 +180,12 @@ proc semGenericStmt(c: PContext, n: PNode,
for i in countup(0, sonsLen(n)-1): for i in countup(0, sonsLen(n)-1):
n.sons[i] = semGenericStmt(c, n.sons[i], flags+{withinMixin}, ctx) n.sons[i] = semGenericStmt(c, n.sons[i], flags+{withinMixin}, ctx)
of nkWhileStmt: of nkWhileStmt:
openScope(c.tab) openScope(c)
for i in countup(0, sonsLen(n)-1): for i in countup(0, sonsLen(n)-1):
n.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx) n.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
closeScope(c.tab) closeScope(c)
of nkCaseStmt: of nkCaseStmt:
openScope(c.tab) openScope(c)
n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx) n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx)
for i in countup(1, sonsLen(n)-1): for i in countup(1, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
@ -194,22 +194,22 @@ proc semGenericStmt(c: PContext, n: PNode,
for j in countup(0, L-2): for j in countup(0, L-2):
a.sons[j] = semGenericStmt(c, a.sons[j], flags, ctx) a.sons[j] = semGenericStmt(c, a.sons[j], flags, ctx)
a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx) a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx)
closeScope(c.tab) closeScope(c)
of nkForStmt, nkParForStmt: of nkForStmt, nkParForStmt:
var L = sonsLen(n) var L = sonsLen(n)
openScope(c.tab) openScope(c)
n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx) n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
for i in countup(0, L - 3): for i in countup(0, L - 3):
addPrelimDecl(c, newSymS(skUnknown, n.sons[i], c)) addPrelimDecl(c, newSymS(skUnknown, n.sons[i], c))
n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx) n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx)
closeScope(c.tab) closeScope(c)
of nkBlockStmt, nkBlockExpr, nkBlockType: of nkBlockStmt, nkBlockExpr, nkBlockType:
checkSonsLen(n, 2) checkSonsLen(n, 2)
openScope(c.tab) openScope(c)
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
addPrelimDecl(c, newSymS(skUnknown, n.sons[0], c)) addPrelimDecl(c, newSymS(skUnknown, n.sons[0], c))
n.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx) n.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
closeScope(c.tab) closeScope(c)
of nkTryStmt: of nkTryStmt:
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
n.sons[0] = semGenericStmtScope(c, n.sons[0], flags, ctx) n.sons[0] = semGenericStmtScope(c, n.sons[0], flags, ctx)
@ -265,10 +265,10 @@ proc semGenericStmt(c: PContext, n: PNode,
if (a.kind != nkTypeDef): IllFormedAst(a) if (a.kind != nkTypeDef): IllFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
if a.sons[1].kind != nkEmpty: if a.sons[1].kind != nkEmpty:
openScope(c.tab) openScope(c)
a.sons[1] = semGenericStmt(c, a.sons[1], flags, ctx) a.sons[1] = semGenericStmt(c, a.sons[1], flags, ctx)
a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx) a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx)
closeScope(c.tab) closeScope(c)
else: else:
a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx) a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx)
of nkEnumTy: of nkEnumTy:
@ -303,7 +303,7 @@ proc semGenericStmt(c: PContext, n: PNode,
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1)
if n.kind notin nkLambdaKinds: if n.kind notin nkLambdaKinds:
addPrelimDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c)) addPrelimDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c))
openScope(c.tab) openScope(c)
n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos], n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos],
flags, ctx) flags, ctx)
if n.sons[paramsPos].kind != nkEmpty: if n.sons[paramsPos].kind != nkEmpty:
@ -315,7 +315,7 @@ proc semGenericStmt(c: PContext, n: PNode,
if n.sons[namePos].kind == nkSym: body = n.sons[namePos].sym.getBody if n.sons[namePos].kind == nkSym: body = n.sons[namePos].sym.getBody
else: body = n.sons[bodyPos] else: body = n.sons[bodyPos]
n.sons[bodyPos] = semGenericStmtScope(c, body, flags, ctx) n.sons[bodyPos] = semGenericStmtScope(c, body, flags, ctx)
closeScope(c.tab) closeScope(c)
of nkPragma, nkPragmaExpr: nil of nkPragma, nkPragmaExpr: nil
of nkExprColonExpr: of nkExprColonExpr:
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)

View file

@ -106,13 +106,13 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
if c.generics[i].genericSym.id == s.id: if c.generics[i].genericSym.id == s.id:
var oldPrc = c.generics[i].inst.sym var oldPrc = c.generics[i].inst.sym
pushInfoContext(oldPrc.info) pushInfoContext(oldPrc.info)
openScope(c.tab) openScope(c)
var n = oldPrc.ast var n = oldPrc.ast
n.sons[bodyPos] = copyTree(s.getBody) n.sons[bodyPos] = copyTree(s.getBody)
if n.sons[paramsPos].kind != nkEmpty: if n.sons[paramsPos].kind != nkEmpty:
addParams(c, oldPrc.typ.n, oldPrc.kind) addParams(c, oldPrc.typ.n, oldPrc.kind)
instantiateBody(c, n, oldPrc) instantiateBody(c, n, oldPrc)
closeScope(c.tab) closeScope(c)
popInfoContext() popInfoContext()
proc sideEffectsCheck(c: PContext, s: PSym) = proc sideEffectsCheck(c: PContext, s: PSym) =
@ -144,7 +144,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
result.owner = getCurrOwner().owner result.owner = getCurrOwner().owner
result.ast = n result.ast = n
pushOwner(result) pushOwner(result)
openScope(c.tab) openScope(c)
if n.sons[genericParamsPos].kind == nkEmpty: if n.sons[genericParamsPos].kind == nkEmpty:
InternalError(n.info, "generateInstance") InternalError(n.info, "generateInstance")
n.sons[namePos] = newSymNode(result) n.sons[namePos] = newSymNode(result)
@ -177,7 +177,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
else: else:
result = oldPrc result = oldPrc
popInfoContext() popInfoContext()
closeScope(c.tab) # close scope for parameters closeScope(c) # close scope for parameters
popOwner() popOwner()
c.friendModule = oldFriend c.friendModule = oldFriend
dec(c.InstCounter) dec(c.InstCounter)

View file

@ -52,12 +52,12 @@ proc semAsm(con: PContext, n: PNode): PNode =
proc semWhile(c: PContext, n: PNode): PNode = proc semWhile(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 2) checkSonsLen(n, 2)
openScope(c.tab) openScope(c)
n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0])) n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0]))
inc(c.p.nestedLoopCounter) inc(c.p.nestedLoopCounter)
n.sons[1] = semStmt(c, n.sons[1]) n.sons[1] = semStmt(c, n.sons[1])
dec(c.p.nestedLoopCounter) dec(c.p.nestedLoopCounter)
closeScope(c.tab) closeScope(c)
if n.sons[1].typ == EnforceVoidContext: if n.sons[1].typ == EnforceVoidContext:
result.typ = EnforceVoidContext result.typ = EnforceVoidContext
@ -103,9 +103,9 @@ proc semExprBranch(c: PContext, n: PNode): PNode =
semDestructorCheck(c, result, {}) semDestructorCheck(c, result, {})
proc semExprBranchScope(c: PContext, n: PNode): PNode = proc semExprBranchScope(c: PContext, n: PNode): PNode =
openScope(c.tab) openScope(c)
result = semExprBranch(c, n) result = semExprBranch(c, n)
closeScope(c.tab) closeScope(c)
const const
skipForDiscardable = {nkIfStmt, nkIfExpr, nkCaseStmt, nkOfBranch, skipForDiscardable = {nkIfStmt, nkIfExpr, nkCaseStmt, nkOfBranch,
@ -150,12 +150,12 @@ proc semIf(c: PContext, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i] var it = n.sons[i]
if it.len == 2: if it.len == 2:
when newScopeForIf: openScope(c.tab) when newScopeForIf: openScope(c)
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0])) it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
when not newScopeForIf: openScope(c.tab) when not newScopeForIf: openScope(c)
it.sons[1] = semExprBranch(c, it.sons[1]) it.sons[1] = semExprBranch(c, it.sons[1])
typ = commonType(typ, it.sons[1].typ) typ = commonType(typ, it.sons[1].typ)
closeScope(c.tab) closeScope(c)
elif it.len == 1: elif it.len == 1:
hasElse = true hasElse = true
it.sons[0] = semExprBranchScope(c, it.sons[0]) it.sons[0] = semExprBranchScope(c, it.sons[0])
@ -176,7 +176,7 @@ proc semIf(c: PContext, n: PNode): PNode =
proc semCase(c: PContext, n: PNode): PNode = proc semCase(c: PContext, n: PNode): PNode =
result = n result = n
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
openScope(c.tab) openScope(c)
n.sons[0] = semExprWithType(c, n.sons[0]) n.sons[0] = semExprWithType(c, n.sons[0])
var chckCovered = false var chckCovered = false
var covered: biggestint = 0 var covered: biggestint = 0
@ -202,12 +202,12 @@ proc semCase(c: PContext, n: PNode): PNode =
of nkElifBranch: of nkElifBranch:
chckCovered = false chckCovered = false
checkSonsLen(x, 2) checkSonsLen(x, 2)
when newScopeForIf: openScope(c.tab) when newScopeForIf: openScope(c)
x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0])) x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0]))
when not newScopeForIf: openScope(c.tab) when not newScopeForIf: openScope(c)
x.sons[1] = semExprBranch(c, x.sons[1]) x.sons[1] = semExprBranch(c, x.sons[1])
typ = commonType(typ, x.sons[1].typ) typ = commonType(typ, x.sons[1].typ)
closeScope(c.tab) closeScope(c)
of nkElse: of nkElse:
chckCovered = false chckCovered = false
checkSonsLen(x, 1) checkSonsLen(x, 1)
@ -221,7 +221,7 @@ proc semCase(c: PContext, n: PNode): PNode =
hasElse = true hasElse = true
else: else:
localError(n.info, errNotAllCasesCovered) localError(n.info, errNotAllCasesCovered)
closeScope(c.tab) closeScope(c)
if isEmptyType(typ) or typ.kind == tyNil or not hasElse: if isEmptyType(typ) or typ.kind == tyNil or not hasElse:
for i in 1..n.len-1: discardCheck(n.sons[i].lastSon) for i in 1..n.len-1: discardCheck(n.sons[i].lastSon)
# propagate any enforced VoidContext: # propagate any enforced VoidContext:
@ -472,12 +472,12 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
var fc: TFieldInstCtx # either 'tup[i]' or 'field' is valid var fc: TFieldInstCtx # either 'tup[i]' or 'field' is valid
fc.field = typ.sym fc.field = typ.sym
fc.replaceByFieldName = c.m == mFieldPairs fc.replaceByFieldName = c.m == mFieldPairs
openScope(c.c.tab) openScope(c.c)
inc c.c.InUnrolledContext inc c.c.InUnrolledContext
let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop) let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop)
father.add(SemStmt(c.c, body)) father.add(SemStmt(c.c, body))
dec c.c.InUnrolledContext dec c.c.InUnrolledContext
closeScope(c.c.tab) closeScope(c.c)
of nkNilLit: nil of nkNilLit: nil
of nkRecCase: of nkRecCase:
let L = forLoop.len let L = forLoop.len
@ -541,7 +541,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
if tupleTypeA.kind == tyTuple: if tupleTypeA.kind == tyTuple:
var loopBody = n.sons[length-1] var loopBody = n.sons[length-1]
for i in 0..sonsLen(tupleTypeA)-1: for i in 0..sonsLen(tupleTypeA)-1:
openScope(c.tab) openScope(c)
var fc: TFieldInstCtx var fc: TFieldInstCtx
fc.tupleType = tupleTypeA fc.tupleType = tupleTypeA
fc.tupleIndex = i fc.tupleIndex = i
@ -550,7 +550,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
inc c.InUnrolledContext inc c.InUnrolledContext
stmts.add(SemStmt(c, body)) stmts.add(SemStmt(c, body))
dec c.InUnrolledContext dec c.InUnrolledContext
closeScope(c.tab) closeScope(c)
else: else:
var fc: TFieldsCtx var fc: TFieldsCtx
fc.m = m fc.m = m
@ -614,7 +614,7 @@ proc semFor(c: PContext, n: PNode): PNode =
result = n result = n
checkMinSonsLen(n, 3) checkMinSonsLen(n, 3)
var length = sonsLen(n) var length = sonsLen(n)
openScope(c.tab) openScope(c)
n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator}) n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator})
var call = n.sons[length-2] var call = n.sons[length-2]
if call.kind in nkCallKinds and call.sons[0].typ.callConv == ccClosure: if call.kind in nkCallKinds and call.sons[0].typ.callConv == ccClosure:
@ -640,7 +640,7 @@ proc semFor(c: PContext, n: PNode): PNode =
# propagate any enforced VoidContext: # propagate any enforced VoidContext:
if n.sons[length-1].typ == EnforceVoidContext: if n.sons[length-1].typ == EnforceVoidContext:
result.typ = EnforceVoidContext result.typ = EnforceVoidContext
closeScope(c.tab) closeScope(c)
proc semRaise(c: PContext, n: PNode): PNode = proc semRaise(c: PContext, n: PNode): PNode =
result = n result = n
@ -690,7 +690,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
if a.sons[1].kind != nkEmpty: if a.sons[1].kind != nkEmpty:
# We have a generic type declaration here. In generic types, # We have a generic type declaration here. In generic types,
# symbol lookup needs to be done here. # symbol lookup needs to be done here.
openScope(c.tab) openScope(c)
pushOwner(s) pushOwner(s)
if s.magic == mNone: s.typ.kind = tyGenericBody if s.magic == mNone: s.typ.kind = tyGenericBody
# XXX for generic type aliases this is not correct! We need the # XXX for generic type aliases this is not correct! We need the
@ -715,7 +715,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
body.size = -1 # could not be computed properly body.size = -1 # could not be computed properly
s.typ.sons[sonsLen(s.typ) - 1] = body s.typ.sons[sonsLen(s.typ) - 1] = body
popOwner() popOwner()
closeScope(c.tab) closeScope(c)
elif a.sons[2].kind != nkEmpty: elif a.sons[2].kind != nkEmpty:
# process the type's body: # process the type's body:
pushOwner(s) pushOwner(s)
@ -835,7 +835,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
else: else:
s = n[namePos].sym s = n[namePos].sym
pushOwner(s) pushOwner(s)
openScope(c.tab) openScope(c)
if n.sons[genericParamsPos].kind != nkEmpty: if n.sons[genericParamsPos].kind != nkEmpty:
illFormedAst(n) # process parameters: illFormedAst(n) # process parameters:
if n.sons[paramsPos].kind != nkEmpty: if n.sons[paramsPos].kind != nkEmpty:
@ -861,7 +861,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
sideEffectsCheck(c, s) sideEffectsCheck(c, s)
else: else:
LocalError(n.info, errImplOfXexpected, s.name.s) LocalError(n.info, errImplOfXexpected, s.name.s)
closeScope(c.tab) # close scope for parameters closeScope(c) # close scope for parameters
popOwner() popOwner()
result.typ = s.typ result.typ = s.typ
@ -894,7 +894,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
n.sons[namePos] = newSymNode(s) n.sons[namePos] = newSymNode(s)
s.ast = n s.ast = n
pushOwner(s) pushOwner(s)
openScope(c.tab) openScope(c)
var gp: PNode var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty: if n.sons[genericParamsPos].kind != nkEmpty:
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos]) n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
@ -938,8 +938,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if sfForward notin proto.flags: if sfForward notin proto.flags:
WrongRedefinition(n.info, proto.name.s) WrongRedefinition(n.info, proto.name.s)
excl(proto.flags, sfForward) excl(proto.flags, sfForward)
closeScope(c.tab) # close scope with wrong parameter symbols closeScope(c) # close scope with wrong parameter symbols
openScope(c.tab) # open scope for old (correct) parameter symbols openScope(c) # open scope for old (correct) parameter symbols
if proto.ast.sons[genericParamsPos].kind != nkEmpty: if proto.ast.sons[genericParamsPos].kind != nkEmpty:
addGenericParamListToScope(c, proto.ast.sons[genericParamsPos]) addGenericParamListToScope(c, proto.ast.sons[genericParamsPos])
addParams(c, proto.typ.n, proto.kind) addParams(c, proto.typ.n, proto.kind)
@ -988,7 +988,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
incl(s.flags, sfForward) incl(s.flags, sfForward)
elif sfBorrow in s.flags: semBorrow(c, n, s) elif sfBorrow in s.flags: semBorrow(c, n, s)
sideEffectsCheck(c, s) sideEffectsCheck(c, s)
closeScope(c.tab) # close scope for parameters closeScope(c) # close scope for parameters
popOwner() popOwner()
if n.sons[patternPos].kind != nkEmpty: if n.sons[patternPos].kind != nkEmpty:
c.patterns.add(s) c.patterns.add(s)
@ -1179,6 +1179,6 @@ proc SemStmt(c: PContext, n: PNode): PNode =
result = semExprNoType(c, n) result = semExprNoType(c, n)
proc semStmtScope(c: PContext, n: PNode): PNode = proc semStmtScope(c: PContext, n: PNode): PNode =
openScope(c.tab) openScope(c)
result = semStmt(c, n) result = semStmt(c, n)
closeScope(c.tab) closeScope(c)

View file

@ -125,8 +125,8 @@ proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
proc semTemplBody(c: var TemplCtx, n: PNode): PNode proc semTemplBody(c: var TemplCtx, n: PNode): PNode
proc openScope(c: var TemplCtx) = openScope(c.c.tab) proc openScope(c: var TemplCtx) = openScope(c.c)
proc closeScope(c: var TemplCtx) = closeScope(c.c.tab) proc closeScope(c: var TemplCtx) = closeScope(c.c)
proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode = proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
openScope(c) openScope(c)
@ -362,7 +362,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
s = semIdentVis(c, skTemplate, n.sons[0], {}) s = semIdentVis(c, skTemplate, n.sons[0], {})
# check parameter list: # check parameter list:
pushOwner(s) pushOwner(s)
openScope(c.tab) openScope(c)
n.sons[namePos] = newSymNode(s, n.sons[namePos].info) n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
if n.sons[pragmasPos].kind != nkEmpty: if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, s, n.sons[pragmasPos], templatePragmas) pragma(c, s, n.sons[pragmasPos], templatePragmas)
@ -404,7 +404,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}: if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}:
n.sons[bodyPos] = transformToExpr(n.sons[bodyPos]) n.sons[bodyPos] = transformToExpr(n.sons[bodyPos])
# only parameters are resolved, no type checking is performed # only parameters are resolved, no type checking is performed
closeScope(c.tab) closeScope(c)
popOwner() popOwner()
s.ast = n s.ast = n
result = n result = n
@ -533,7 +533,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
result.sons[i] = semPatternBody(c, n.sons[i]) result.sons[i] = semPatternBody(c, n.sons[i])
proc semPattern(c: PContext, n: PNode): PNode = proc semPattern(c: PContext, n: PNode): PNode =
openScope(c.tab) openScope(c)
var ctx: TemplCtx var ctx: TemplCtx
ctx.toBind = initIntSet() ctx.toBind = initIntSet()
ctx.c = c ctx.c = c
@ -544,4 +544,4 @@ proc semPattern(c: PContext, n: PNode): PNode =
result = result.sons[0] result = result.sons[0]
elif result.len == 0: elif result.len == 0:
LocalError(n.info, errInvalidExpression) LocalError(n.info, errInvalidExpression)
closeScope(c.tab) closeScope(c)

View file

@ -734,13 +734,13 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
proc semBlockType(c: PContext, n: PNode, prev: PType): PType = proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
Inc(c.p.nestedBlockCounter) Inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2) checkSonsLen(n, 2)
openScope(c.tab) openScope(c)
if n.sons[0].kind notin {nkEmpty, nkSym}: if n.sons[0].kind notin {nkEmpty, nkSym}:
addDecl(c, newSymS(skLabel, n.sons[0], c)) addDecl(c, newSymS(skLabel, n.sons[0], c))
result = semStmtListType(c, n.sons[1], prev) result = semStmtListType(c, n.sons[1], prev)
n.sons[1].typ = result n.sons[1].typ = result
n.typ = result n.typ = result
closeScope(c.tab) closeScope(c)
Dec(c.p.nestedBlockCounter) Dec(c.p.nestedBlockCounter)
proc semGenericParamInInvokation(c: PContext, n: PNode): PType = proc semGenericParamInInvokation(c: PContext, n: PNode): PType =
@ -910,7 +910,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = newConstraint(c, tyProc) result = newConstraint(c, tyProc)
else: else:
checkSonsLen(n, 2) checkSonsLen(n, 2)
openScope(c.tab) openScope(c)
result = semProcTypeNode(c, n.sons[0], nil, prev, skProc) result = semProcTypeNode(c, n.sons[0], nil, prev, skProc)
# dummy symbol for `pragma`: # dummy symbol for `pragma`:
var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c) var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
@ -922,7 +922,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else: else:
pragma(c, s, n.sons[1], procTypePragmas) pragma(c, s, n.sons[1], procTypePragmas)
when useEffectSystem: SetEffectsForProcType(result, n.sons[1]) when useEffectSystem: SetEffectsForProcType(result, n.sons[1])
closeScope(c.tab) closeScope(c)
if n.kind == nkIteratorTy: if n.kind == nkIteratorTy:
result.flags.incl(tfIterator) result.flags.incl(tfIterator)
result.callConv = ccClosure result.callConv = ccClosure