diff options
Diffstat (limited to 'compiler/semstmts.nim')
-rw-r--r-- | compiler/semstmts.nim | 184 |
1 files changed, 103 insertions, 81 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 282d4da88..5ecba3ab0 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -36,7 +36,7 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode = x.info = n.info incl(s.flags, sfUsed) n.sons[0] = x - suggestSym(x.info, s) + suggestSym(x.info, s, c.graph.usageSym) styleCheckUse(x.info, s) else: localError(n.info, errInvalidControlFlowX, s.name.s) @@ -367,11 +367,13 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym = if isTopLevel(c): result = semIdentWithPragma(c, kind, n, {sfExported}) incl(result.flags, sfGlobal) + #if kind in {skVar, skLet}: + # echo "global variable here ", n.info, " ", result.name.s else: result = semIdentWithPragma(c, kind, n, {}) if result.owner.kind == skModule: incl(result.flags, sfGlobal) - suggestSym(n.info, result) + suggestSym(n.info, result, c.graph.usageSym) styleCheckDef(result) proc checkNilable(v: PSym) = @@ -622,7 +624,7 @@ proc semForVars(c: PContext, n: PNode): PNode = if iter.kind != tyTuple or length == 3: if length == 3: var v = symForVar(c, n.sons[0]) - if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) + if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal) # BUGFIX: don't use `iter` here as that would strip away # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim`` # for an example: @@ -636,7 +638,7 @@ proc semForVars(c: PContext, n: PNode): PNode = else: for i in countup(0, length - 3): var v = symForVar(c, n.sons[i]) - if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) + if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal) v.typ = iter.sons[i] n.sons[i] = newSymNode(v) if sfGenSym notin v.flags and not isDiscardUnderscore(v): @@ -746,7 +748,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = # We have a generic type declaration here. In generic types, # symbol lookup needs to be done here. openScope(c) - pushOwner(s) + pushOwner(c, s) if s.magic == mNone: s.typ.kind = tyGenericBody # XXX for generic type aliases this is not correct! We need the # underlying Id really: @@ -770,11 +772,11 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = body.sym = s body.size = -1 # could not be computed properly s.typ.sons[sonsLen(s.typ) - 1] = body - popOwner() + popOwner(c) closeScope(c) elif a.sons[2].kind != nkEmpty: # process the type's body: - pushOwner(s) + pushOwner(c, s) var t = semTypeNode(c, a.sons[2], s.typ) if s.typ == nil: s.typ = t @@ -783,7 +785,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = assignType(s.typ, t) #debug s.typ s.ast = a - popOwner() + popOwner(c) let aa = a.sons[2] if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and aa.sons[0].kind == nkObjectTy: @@ -794,7 +796,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = internalAssert st.lastSon.sym == nil incl st.flags, tfRefsAnonObj let obj = newSym(skType, getIdent(s.name.s & ":ObjectType"), - getCurrOwner(), s.info) + getCurrOwner(c), s.info) obj.typ = st.lastSon st.lastSon.sym = obj @@ -928,7 +930,7 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) = proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) = if t != nil: - var s = newSym(skResult, getIdent"result", getCurrOwner(), info) + var s = newSym(skResult, getIdent"result", getCurrOwner(c), info) s.typ = t incl(s.flags, sfUsed) addParamOrResult(c, s, owner) @@ -1003,12 +1005,12 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = checkSonsLen(n, bodyPos + 1) var s: PSym if n[namePos].kind != nkSym: - s = newSym(skProc, c.cache.idAnon, getCurrOwner(), n.info) + s = newSym(skProc, c.cache.idAnon, getCurrOwner(c), n.info) s.ast = n n.sons[namePos] = newSymNode(s) else: s = n[namePos].sym - pushOwner(s) + pushOwner(c, s) openScope(c) var gp: PNode if n.sons[genericParamsPos].kind != nkEmpty: @@ -1048,7 +1050,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = else: localError(n.info, errImplOfXexpected, s.name.s) closeScope(c) # close scope for parameters - popOwner() + popOwner(c) result.typ = s.typ proc semDo(c: PContext, n: PNode, flags: TExprFlags): PNode = @@ -1082,7 +1084,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = params[i].sym.name.s) #params[i].sym.owner = s openScope(c) - pushOwner(s) + pushOwner(c, s) addParams(c, params, skProc) pushProcCon(c, s) addResult(c, n.typ.sons[0], n.info, skProc) @@ -1090,7 +1092,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) n.sons[bodyPos] = transformBody(c.module, semBody, s) popProcCon(c) - popOwner() + popOwner(c) closeScope(c) # alternative variant (not quite working): @@ -1178,11 +1180,58 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = localError(n.info, errGenerated, "'destroy' or 'deepCopy' expected for 'override'") +proc cursorInProcAux(n: PNode): bool = + if inCheckpoint(n.info) != cpNone: return true + for i in 0..<n.safeLen: + if cursorInProcAux(n[i]): return true + +proc cursorInProc(n: PNode): bool = + if n.info.fileIndex == gTrackPos.fileIndex: + result = cursorInProcAux(n) + type TProcCompilationSteps = enum stepRegisterSymbol, stepDetermineType, +import compilerlog + +proc hasObjParam(s: PSym): bool = + var t = s.typ + for col in countup(1, sonsLen(t)-1): + if skipTypes(t.sons[col], skipPtrs).kind == tyObject: + return true + +proc finishMethod(c: PContext, s: PSym) = + if hasObjParam(s): + methodDef(c.graph, s, false) + +proc semMethodPrototype(c: PContext; s: PSym; n: PNode) = + if isGenericRoutine(s): + let tt = s.typ + var foundObj = false + # we start at 1 for now so that tparsecombnum continues to compile. + # XXX Revisit this problem later. + for col in countup(1, sonsLen(tt)-1): + let t = tt.sons[col] + if t != nil and t.kind == tyGenericInvocation: + var x = skipTypes(t.sons[0], {tyVar, tyPtr, tyRef, tyGenericInst, + tyGenericInvocation, tyGenericBody, + tyAlias}) + if x.kind == tyObject and t.len-1 == n.sons[genericParamsPos].len: + foundObj = true + x.methods.safeAdd((col,s)) + if not foundObj: + message(n.info, warnDeprecated, "generic method not attachable to object type") + else: + # why check for the body? bug #2400 has none. Checking for sfForward makes + # no sense either. + # and result.sons[bodyPos].kind != nkEmpty: + if hasObjParam(s): + methodDef(c.graph, s, fromCache=false) + else: + localError(n.info, errXNeedsParamObjectType, "method") + proc semProcAux(c: PContext, n: PNode, kind: TSymKind, validPragmas: TSpecialWords, phase = stepRegisterSymbol): PNode = @@ -1197,7 +1246,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, assert phase == stepRegisterSymbol if n[namePos].kind == nkEmpty: - s = newSym(kind, c.cache.idAnon, getCurrOwner(), n.info) + s = newSym(kind, c.cache.idAnon, getCurrOwner(c), n.info) incl(s.flags, sfUsed) isAnon = true else: @@ -1214,7 +1263,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, return else: s = n[namePos].sym - s.owner = getCurrOwner() + s.owner = getCurrOwner(c) typeIsDetermined = s.typ == nil s.ast = n #s.scope = c.currentScope @@ -1223,7 +1272,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, # where the proc was declared let oldScope = c.currentScope #c.currentScope = s.scope - pushOwner(s) + pushOwner(c, s) openScope(c) var gp: PNode if n.sons[genericParamsPos].kind != nkEmpty: @@ -1289,8 +1338,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, if importantComments() and not isNil(proto.ast.comment): n.comment = proto.ast.comment proto.ast = n # needed for code generation - popOwner() - pushOwner(s) + popOwner(c) + pushOwner(c, s) s.options = gOptions if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n) if s.name.s[0] in {'.', '('}: @@ -1304,30 +1353,40 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, # Macros and Templates can have generic parameters, but they are # only used for overload resolution (there is no instantiation of # the symbol, so we must process the body now) - pushProcCon(c, s) - if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics: - if not usePseudoGenerics: paramsTypeCheck(c, s.typ) - - c.p.wasForwarded = proto != nil - maybeAddResult(c, s, n) - if lfDynamicLib notin s.loc.flags: - # no semantic checking for importc: - let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) - # unfortunately we cannot skip this step when in 'system.compiles' - # context as it may even be evaluated in 'system.compiles': - n.sons[bodyPos] = transformBody(c.module, semBody, s) + if not usePseudoGenerics and gIdeCmd in {ideSug, ideCon} and not + cursorInProc(n.sons[bodyPos]): + discard "speed up nimsuggest" + if s.kind == skMethod: semMethodPrototype(c, s, n) else: - if s.typ.sons[0] != nil and kind != skIterator: - addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info)) - openScope(c) - n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos]) - closeScope(c) - fixupInstantiatedSymbols(c, s) - if sfImportc in s.flags: - # so we just ignore the body after semantic checking for importc: - n.sons[bodyPos] = ast.emptyNode - popProcCon(c) + pushProcCon(c, s) + if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics: + if not usePseudoGenerics: paramsTypeCheck(c, s.typ) + + c.p.wasForwarded = proto != nil + maybeAddResult(c, s, n) + if s.kind == skMethod: semMethodPrototype(c, s, n) + + if lfDynamicLib notin s.loc.flags: + # no semantic checking for importc: + let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) + # unfortunately we cannot skip this step when in 'system.compiles' + # context as it may even be evaluated in 'system.compiles': + n.sons[bodyPos] = transformBody(c.module, semBody, s) + else: + if s.typ.sons[0] != nil and kind != skIterator: + addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info)) + + openScope(c) + n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos]) + closeScope(c) + fixupInstantiatedSymbols(c, s) + if s.kind == skMethod: semMethodPrototype(c, s, n) + if sfImportc in s.flags: + # so we just ignore the body after semantic checking for importc: + n.sons[bodyPos] = ast.emptyNode + popProcCon(c) else: + if s.kind == skMethod: semMethodPrototype(c, s, n) if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s) if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone: incl(s.flags, sfForward) @@ -1335,7 +1394,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, sideEffectsCheck(c, s) closeScope(c) # close scope for parameters # c.currentScope = oldScope - popOwner() + popOwner(c) if n.sons[patternPos].kind != nkEmpty: c.patterns.add(s) if isAnon: result.typ = s.typ @@ -1354,7 +1413,7 @@ proc semIterator(c: PContext, n: PNode): PNode = let isAnon = n[namePos].kind == nkEmpty if n[namePos].kind == nkSym: # gensym'ed iterators might need to become closure iterators: - n[namePos].sym.owner = getCurrOwner() + n[namePos].sym.owner = getCurrOwner(c) n[namePos].sym.kind = skIterator result = semProcAux(c, n, skIterator, iteratorPragmas) var s = result.sons[namePos].sym @@ -1381,46 +1440,9 @@ proc semIterator(c: PContext, n: PNode): PNode = proc semProc(c: PContext, n: PNode): PNode = result = semProcAux(c, n, skProc, procPragmas) -proc hasObjParam(s: PSym): bool = - var t = s.typ - for col in countup(1, sonsLen(t)-1): - if skipTypes(t.sons[col], skipPtrs).kind == tyObject: - return true - -proc finishMethod(c: PContext, s: PSym) = - if hasObjParam(s): - methodDef(s, false) - proc semMethod(c: PContext, n: PNode): PNode = if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method") result = semProcAux(c, n, skMethod, methodPragmas) - # macros can transform methods to nothing: - if namePos >= result.safeLen: return result - var s = result.sons[namePos].sym - if isGenericRoutine(s): - let tt = s.typ - var foundObj = false - # we start at 1 for now so that tparsecombnum continues to compile. - # XXX Revisit this problem later. - for col in countup(1, sonsLen(tt)-1): - let t = tt.sons[col] - if t != nil and t.kind == tyGenericInvocation: - var x = skipTypes(t.sons[0], {tyVar, tyPtr, tyRef, tyGenericInst, - tyGenericInvocation, tyGenericBody, - tyAlias}) - if x.kind == tyObject and t.len-1 == result.sons[genericParamsPos].len: - foundObj = true - x.methods.safeAdd((col,s)) - if not foundObj: - message(n.info, warnDeprecated, "generic method not attachable to object type") - else: - # why check for the body? bug #2400 has none. Checking for sfForward makes - # no sense either. - # and result.sons[bodyPos].kind != nkEmpty: - if hasObjParam(s): - methodDef(s, fromCache=false) - else: - localError(n.info, errXNeedsParamObjectType, "method") proc semConverterDef(c: PContext, n: PNode): PNode = if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "converter") |