diff options
Diffstat (limited to 'compiler/semstmts.nim')
-rw-r--r-- | compiler/semstmts.nim | 130 |
1 files changed, 84 insertions, 46 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 2c3adfeda..efe5c9217 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -52,12 +52,12 @@ proc semAsm(con: PContext, n: PNode): PNode = proc semWhile(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 2) - openScope(c.tab) + openScope(c) n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0])) inc(c.p.nestedLoopCounter) n.sons[1] = semStmt(c, n.sons[1]) dec(c.p.nestedLoopCounter) - closeScope(c.tab) + closeScope(c) if n.sons[1].typ == EnforceVoidContext: result.typ = EnforceVoidContext @@ -103,9 +103,9 @@ proc semExprBranch(c: PContext, n: PNode): PNode = semDestructorCheck(c, result, {}) proc semExprBranchScope(c: PContext, n: PNode): PNode = - openScope(c.tab) + openScope(c) result = semExprBranch(c, n) - closeScope(c.tab) + closeScope(c) const skipForDiscardable = {nkIfStmt, nkIfExpr, nkCaseStmt, nkOfBranch, @@ -150,12 +150,12 @@ proc semIf(c: PContext, n: PNode): PNode = for i in countup(0, sonsLen(n) - 1): var it = n.sons[i] if it.len == 2: - when newScopeForIf: openScope(c.tab) + when newScopeForIf: openScope(c) 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]) typ = commonType(typ, it.sons[1].typ) - closeScope(c.tab) + closeScope(c) elif it.len == 1: hasElse = true 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 = result = n checkMinSonsLen(n, 2) - openScope(c.tab) + openScope(c) n.sons[0] = semExprWithType(c, n.sons[0]) var chckCovered = false var covered: biggestint = 0 @@ -202,12 +202,12 @@ proc semCase(c: PContext, n: PNode): PNode = of nkElifBranch: chckCovered = false checkSonsLen(x, 2) - when newScopeForIf: openScope(c.tab) + when newScopeForIf: openScope(c) 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]) typ = commonType(typ, x.sons[1].typ) - closeScope(c.tab) + closeScope(c) of nkElse: chckCovered = false checkSonsLen(x, 1) @@ -221,7 +221,7 @@ proc semCase(c: PContext, n: PNode): PNode = hasElse = true else: localError(n.info, errNotAllCasesCovered) - closeScope(c.tab) + closeScope(c) if isEmptyType(typ) or typ.kind == tyNil or not hasElse: for i in 1..n.len-1: discardCheck(n.sons[i].lastSon) # propagate any enforced VoidContext: @@ -289,8 +289,9 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode = changeType(result, typ, check=false) proc findShadowedVar(c: PContext, v: PSym): PSym = - for i in countdown(c.tab.tos - 2, ModuleTablePos+1): - let shadowed = StrTableGet(c.tab.stack[i], v.name) + for scope in walkScopes(c.currentScope.parent): + if scope == c.topLevelScope: break + let shadowed = StrTableGet(scope.symbols, v.name) if shadowed != nil and shadowed.kind in skLocalVars: return shadowed @@ -472,12 +473,12 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) = var fc: TFieldInstCtx # either 'tup[i]' or 'field' is valid fc.field = typ.sym fc.replaceByFieldName = c.m == mFieldPairs - openScope(c.c.tab) + openScope(c.c) inc c.c.InUnrolledContext let body = instFieldLoopBody(fc, lastSon(forLoop), forLoop) father.add(SemStmt(c.c, body)) dec c.c.InUnrolledContext - closeScope(c.c.tab) + closeScope(c.c) of nkNilLit: nil of nkRecCase: let L = forLoop.len @@ -541,7 +542,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = if tupleTypeA.kind == tyTuple: var loopBody = n.sons[length-1] for i in 0..sonsLen(tupleTypeA)-1: - openScope(c.tab) + openScope(c) var fc: TFieldInstCtx fc.tupleType = tupleTypeA fc.tupleIndex = i @@ -550,7 +551,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = inc c.InUnrolledContext stmts.add(SemStmt(c, body)) dec c.InUnrolledContext - closeScope(c.tab) + closeScope(c) else: var fc: TFieldsCtx fc.m = m @@ -614,7 +615,7 @@ proc semFor(c: PContext, n: PNode): PNode = result = n checkMinSonsLen(n, 3) var length = sonsLen(n) - openScope(c.tab) + openScope(c) n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator}) var call = n.sons[length-2] if call.kind in nkCallKinds and call.sons[0].typ.callConv == ccClosure: @@ -640,7 +641,7 @@ proc semFor(c: PContext, n: PNode): PNode = # propagate any enforced VoidContext: if n.sons[length-1].typ == EnforceVoidContext: result.typ = EnforceVoidContext - closeScope(c.tab) + closeScope(c) proc semRaise(c: PContext, n: PNode): PNode = result = n @@ -690,7 +691,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = if a.sons[1].kind != nkEmpty: # We have a generic type declaration here. In generic types, # symbol lookup needs to be done here. - openScope(c.tab) + openScope(c) pushOwner(s) if s.magic == mNone: s.typ.kind = tyGenericBody # XXX for generic type aliases this is not correct! We need the @@ -715,7 +716,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = body.size = -1 # could not be computed properly s.typ.sons[sonsLen(s.typ) - 1] = body popOwner() - closeScope(c.tab) + closeScope(c) elif a.sons[2].kind != nkEmpty: # process the type's body: pushOwner(s) @@ -772,7 +773,7 @@ proc addParams(c: PContext, n: PNode, kind: TSymKind) = proc semBorrow(c: PContext, n: PNode, s: PSym) = # search for the correct alias: - var b = SearchForBorrowProc(c, s, c.tab.tos - 2) + var b = SearchForBorrowProc(c, c.currentScope.parent, s) if b != nil: # store the alias: n.sons[bodyPos] = newSymNode(b) @@ -800,7 +801,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] @@ -835,7 +836,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = else: s = n[namePos].sym pushOwner(s) - openScope(c.tab) + openScope(c) if n.sons[genericParamsPos].kind != nkEmpty: illFormedAst(n) # process parameters: if n.sons[paramsPos].kind != nkEmpty: @@ -861,7 +862,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = sideEffectsCheck(c, s) else: LocalError(n.info, errImplOfXexpected, s.name.s) - closeScope(c.tab) # close scope for parameters + closeScope(c) # close scope for parameters popOwner() result.typ = s.typ @@ -884,17 +885,48 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) = addResult(c, s.typ.sons[0], n.info, s.kind) addResultNode(c, n) -proc semProcAux(c: PContext, n: PNode, kind: TSymKind, - validPragmas: TSpecialWords): PNode = +type + TProcCompilationSteps = enum + stepRegisterSymbol, + stepDetermineType, + stepCompileBody + +proc isForwardDecl(s: PSym): bool = + InternalAssert s.kind == skProc + result = s.ast[bodyPos].kind != nkEmpty + +proc semProcAux(c: PContext, n: PNode, kind: TSymKind, + validPragmas: TSpecialWords, + phase = stepRegisterSymbol): PNode = result = semProcAnnotation(c, n) if result != nil: return result result = n checkSonsLen(n, bodyPos + 1) - var s = semIdentDef(c, n.sons[0], kind) - n.sons[namePos] = newSymNode(s) - s.ast = n + var s: PSym + var typeIsDetermined = false + if n[namePos].kind != nkSym: + assert phase == stepRegisterSymbol + s = semIdentDef(c, n.sons[0], kind) + n.sons[namePos] = newSymNode(s) + s.ast = n + s.scope = c.currentScope + + if sfNoForward in c.module.flags and + sfSystemModule notin c.module.flags: + addInterfaceOverloadableSymAt(c, c.currentScope, s) + s.flags.incl sfForward + return + else: + s = n[namePos].sym + typeIsDetermined = s.typ == nil + # if typeIsDetermined: assert phase == stepCompileBody + # else: assert phase == stepDetermineType + # before compiling the proc body, set as current the scope + # where the proc was declared + let oldScope = c.currentScope + c.currentScope = s.scope pushOwner(s) - openScope(c.tab) + openScope(c) var gp: PNode if n.sons[genericParamsPos].kind != nkEmpty: n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos]) @@ -917,17 +949,17 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, n.sons[patternPos] = semPattern(c, n.sons[patternPos]) if s.kind == skIterator: s.typ.flags.incl(tfIterator) - var proto = SearchForProc(c, s, c.tab.tos-2) # -2 because we have a scope - # open for parameters + var proto = SearchForProc(c, s.scope, s) 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) - else: - addInterfaceDeclAt(c, s, c.tab.tos - 2) + elif kind in OverloadableSyms: + if not typeIsDetermined: + addInterfaceOverloadableSymAt(c, s.scope, s) + else: + if not typeIsDetermined: + addInterfaceDeclAt(c, s.scope, s) if n.sons[pragmasPos].kind != nkEmpty: pragma(c, s, n.sons[pragmasPos], validPragmas) else: @@ -938,8 +970,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, if sfForward notin proto.flags: WrongRedefinition(n.info, proto.name.s) excl(proto.flags, sfForward) - closeScope(c.tab) # close scope with wrong parameter symbols - openScope(c.tab) # open scope for old (correct) parameter symbols + closeScope(c) # close scope with wrong parameter symbols + openScope(c) # open scope for old (correct) parameter symbols if proto.ast.sons[genericParamsPos].kind != nkEmpty: addGenericParamListToScope(c, proto.ast.sons[genericParamsPos]) addParams(c, proto.typ.n, proto.kind) @@ -988,11 +1020,17 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, incl(s.flags, sfForward) elif sfBorrow in s.flags: semBorrow(c, n, s) sideEffectsCheck(c, s) - closeScope(c.tab) # close scope for parameters + closeScope(c) # close scope for parameters + c.currentScope = oldScope popOwner() if n.sons[patternPos].kind != nkEmpty: c.patterns.add(s) - + +proc determineType(c: PContext, s: PSym) = + if s.typ != nil: return + #if s.magic != mNone: return + discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType) + proc semIterator(c: PContext, n: PNode): PNode = result = semProcAux(c, n, skIterator, iteratorPragmas) var s = result.sons[namePos].sym @@ -1055,7 +1093,7 @@ proc semMacroDef(c: PContext, n: PNode): PNode = if n.sons[bodyPos].kind == nkEmpty: LocalError(n.info, errImplOfXexpected, s.name.s) -proc evalInclude(c: PContext, n: PNode): PNode = +proc evalInclude(c: PContext, n: PNode): PNode = result = newNodeI(nkStmtList, n.info) addSon(result, n) for i in countup(0, sonsLen(n) - 1): @@ -1179,6 +1217,6 @@ proc SemStmt(c: PContext, n: PNode): PNode = result = semExprNoType(c, n) proc semStmtScope(c: PContext, n: PNode): PNode = - openScope(c.tab) + openScope(c) result = semStmt(c, n) - closeScope(c.tab) + closeScope(c) |