summary refs log tree commit diff stats
path: root/compiler/semstmts.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semstmts.nim')
-rw-r--r--compiler/semstmts.nim130
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)