big compiler refactoring; avoid globals for multi method dispatcher generation
This commit is contained in:
parent
311253ef2f
commit
46efaf294b
29 changed files with 225 additions and 215 deletions
|
|
@ -35,7 +35,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)
|
||||
|
|
@ -366,11 +366,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) =
|
||||
|
|
@ -621,7 +623,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:
|
||||
|
|
@ -635,7 +637,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):
|
||||
|
|
@ -745,7 +747,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:
|
||||
|
|
@ -769,11 +771,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
|
||||
|
|
@ -782,7 +784,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:
|
||||
|
|
@ -793,7 +795,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
|
||||
|
||||
|
|
@ -927,7 +929,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)
|
||||
|
|
@ -1002,12 +1004,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:
|
||||
|
|
@ -1047,7 +1049,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 =
|
||||
|
|
@ -1081,7 +1083,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)
|
||||
|
|
@ -1089,7 +1091,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):
|
||||
|
|
@ -1193,6 +1195,42 @@ type
|
|||
|
||||
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 =
|
||||
|
|
@ -1207,7 +1245,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:
|
||||
|
|
@ -1224,7 +1262,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
|
||||
|
|
@ -1233,7 +1271,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:
|
||||
|
|
@ -1299,8 +1337,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 {'.', '('}:
|
||||
|
|
@ -1317,6 +1355,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
|||
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:
|
||||
pushProcCon(c, s)
|
||||
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
|
||||
|
|
@ -1324,6 +1363,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
|||
|
||||
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]))
|
||||
|
|
@ -1333,15 +1374,18 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
|||
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)
|
||||
|
|
@ -1349,7 +1393,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
|
||||
|
|
@ -1368,7 +1412,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
|
||||
|
|
@ -1395,46 +1439,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")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue