completed expr/stmt unification
This commit is contained in:
parent
8e5d6834cc
commit
fa0a327dd6
10 changed files with 642 additions and 673 deletions
|
|
@ -19,24 +19,6 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
|||
|
||||
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
|
||||
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
|
||||
var smoduleId = getModule(s).id
|
||||
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
||||
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
||||
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
||||
|
||||
proc semProcvarCheck(c: PContext, n: PNode) =
|
||||
let n = n.skipConv
|
||||
if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skIterator,
|
||||
skConverter}:
|
||||
performProcvarCheck(c, n, n.sym)
|
||||
|
||||
proc semDestructorCheck(c: PContext, n: PNode, flags: TExprFlags) {.inline.} =
|
||||
if efAllowDestructor notin flags and n.kind in nkCallKinds+{nkObjConstr}:
|
||||
if instantiateDestructor(c, n.typ):
|
||||
LocalError(n.info, errGenerated,
|
||||
"usage of a type with a destructor in a non destructible context")
|
||||
|
||||
proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
# same as 'semExprWithType' but doesn't check for proc vars
|
||||
result = semExpr(c, n, flags)
|
||||
|
|
@ -781,16 +763,6 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
|
|||
# and check 'arg' for semantics again:
|
||||
addSon(result, semExpr(c, arg))
|
||||
|
||||
proc discardCheck(result: PNode) =
|
||||
if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
|
||||
if result.kind == nkNilLit:
|
||||
# XXX too much work and fixing would break bootstrapping:
|
||||
#Message(n.info, warnNilStatement)
|
||||
result.typ = nil
|
||||
elif not ImplicitlyDiscardable(result) and result.typ.kind != tyError and
|
||||
gCmd != cmdInteractive:
|
||||
localError(result.info, errDiscardValue)
|
||||
|
||||
proc semExprNoType(c: PContext, n: PNode): PNode =
|
||||
result = semExpr(c, n, {efWantStmt})
|
||||
discardCheck(result)
|
||||
|
|
@ -1125,14 +1097,16 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
|||
var
|
||||
rhs = semExprWithType(c, n.sons[1],
|
||||
if lhsIsResult: {efAllowDestructor} else: {})
|
||||
if lhsIsResult and lhs.sym.typ.kind == tyGenericParam:
|
||||
if matchTypeClass(lhs.typ, rhs.typ):
|
||||
InternalAssert c.p.resultSym != nil
|
||||
lhs.typ = rhs.typ
|
||||
c.p.resultSym.typ = rhs.typ
|
||||
c.p.owner.typ.sons[0] = rhs.typ
|
||||
else:
|
||||
typeMismatch(n, lhs.typ, rhs.typ)
|
||||
if lhsIsResult:
|
||||
n.typ = EnforceVoidContext
|
||||
if lhs.sym.typ.kind == tyGenericParam:
|
||||
if matchTypeClass(lhs.typ, rhs.typ):
|
||||
InternalAssert c.p.resultSym != nil
|
||||
lhs.typ = rhs.typ
|
||||
c.p.resultSym.typ = rhs.typ
|
||||
c.p.owner.typ.sons[0] = rhs.typ
|
||||
else:
|
||||
typeMismatch(n, lhs.typ, rhs.typ)
|
||||
|
||||
n.sons[1] = fitNode(c, le, rhs)
|
||||
fixAbstractType(c, n)
|
||||
|
|
@ -1481,52 +1455,13 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
|||
if result == nil:
|
||||
setResult(it.sons[0])
|
||||
else: illFormedAst(n)
|
||||
if result == nil:
|
||||
result = newNodeI(nkNilLit, n.info)
|
||||
if result == nil:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
# The ``when`` statement implements the mechanism for platform dependent
|
||||
# code. Thus we try to ensure here consistent ID allocation after the
|
||||
# ``when`` statement.
|
||||
IDsynchronizationPoint(200)
|
||||
|
||||
|
||||
proc semExprBranch(c: PContext, n: PNode): PNode =
|
||||
result = semExpr(c, n)
|
||||
if result.typ != nil:
|
||||
# XXX tyGenericInst here?
|
||||
semProcvarCheck(c, result)
|
||||
if result.typ.kind == tyVar: result = newDeref(result)
|
||||
semDestructorCheck(c, result, {})
|
||||
|
||||
proc semIf(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
var typ = CommonTypeBegin
|
||||
var hasElse = false
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
if it.len == 2:
|
||||
when newScopeForIf: openScope(c.tab)
|
||||
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
|
||||
when not newScopeForIf: openScope(c.tab)
|
||||
it.sons[1] = semExprBranch(c, it.sons[1])
|
||||
typ = commonType(typ, it.sons[1].typ)
|
||||
closeScope(c.tab)
|
||||
elif it.len == 1:
|
||||
hasElse = true
|
||||
openScope(c.tab)
|
||||
it.sons[0] = semExprBranch(c, it.sons[0])
|
||||
typ = commonType(typ, it.sons[0].typ)
|
||||
closeScope(c.tab)
|
||||
else: illFormedAst(it)
|
||||
if isEmptyType(typ) or not hasElse:
|
||||
for it in n: discardCheck(it.lastSon)
|
||||
result.kind = nkIfStmt
|
||||
else:
|
||||
for it in n:
|
||||
let j = it.len-1
|
||||
it.sons[j] = fitNode(c, typ, it.sons[j])
|
||||
result.kind = nkIfExpr
|
||||
result.typ = typ
|
||||
|
||||
proc semSetConstr(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkCurly, n.info)
|
||||
result.typ = newTypeS(tySet, c)
|
||||
|
|
@ -1692,26 +1627,21 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
it.sons[1] = e
|
||||
# XXX object field name check for 'case objects' if the kind is static?
|
||||
|
||||
proc semStmtListExpr(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
checkMinSonsLen(n, 1)
|
||||
var length = sonsLen(n)
|
||||
for i in countup(0, length - 2):
|
||||
n.sons[i] = semStmt(c, n.sons[i])
|
||||
if length > 0:
|
||||
n.sons[length - 1] = semExprWithType(c, n.sons[length - 1])
|
||||
n.typ = n.sons[length - 1].typ
|
||||
|
||||
proc semBlockExpr(c: PContext, n: PNode): PNode =
|
||||
proc semBlock(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
Inc(c.p.nestedBlockCounter)
|
||||
checkSonsLen(n, 2)
|
||||
openScope(c.tab) # BUGFIX: label is in the scope of block!
|
||||
if n.sons[0].kind notin {nkEmpty, nkSym}:
|
||||
# nkSym for gensym'ed labels:
|
||||
addDecl(c, newSymS(skLabel, n.sons[0], c))
|
||||
n.sons[1] = semStmtListExpr(c, n.sons[1])
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
var labl = newSymG(skLabel, n.sons[0], c)
|
||||
if sfGenSym notin labl.flags:
|
||||
addDecl(c, labl)
|
||||
n.sons[0] = newSymNode(labl, n.sons[0].info)
|
||||
suggestSym(n.sons[0], labl)
|
||||
n.sons[1] = semExpr(c, n.sons[1])
|
||||
n.typ = n.sons[1].typ
|
||||
if isEmptyType(n.typ): n.kind = nkBlockStmt
|
||||
else: n.kind = nkBlockExpr
|
||||
closeScope(c.tab)
|
||||
Dec(c.p.nestedBlockCounter)
|
||||
|
||||
|
|
@ -1731,57 +1661,6 @@ proc buildCall(n: PNode): PNode =
|
|||
else:
|
||||
result = n
|
||||
|
||||
proc semCaseExpr(c: PContext, caseStmt: PNode): PNode =
|
||||
# The case expression is simply rewritten to a StmtListExpr:
|
||||
# var res {.noInit, genSym.}: type(values)
|
||||
#
|
||||
# case E
|
||||
# of X: res = value1
|
||||
# of Y: res = value2
|
||||
#
|
||||
# res
|
||||
var
|
||||
info = caseStmt.info
|
||||
resVar = newSym(skVar, idAnon, getCurrOwner(), info)
|
||||
resNode = newSymNode(resVar, info)
|
||||
resType: PType
|
||||
|
||||
resVar.flags = { sfGenSym, sfNoInit }
|
||||
|
||||
for i in countup(1, caseStmt.len - 1):
|
||||
var cs = caseStmt[i]
|
||||
case cs.kind
|
||||
of nkOfBranch, nkElifBranch, nkElse:
|
||||
# the value is always the last son regardless of the branch kind
|
||||
cs.checkMinSonsLen 1
|
||||
var value = cs{-1}
|
||||
if value.kind == nkStmtList: value.kind = nkStmtListExpr
|
||||
|
||||
value = semExprWithType(c, value)
|
||||
if resType == nil:
|
||||
resType = value.typ
|
||||
elif not sameType(resType, value.typ):
|
||||
# XXX: semeType is a bit too harsh.
|
||||
# work on finding a common base type.
|
||||
# this will be useful for arrays/seq too:
|
||||
# [ref DerivedA, ref DerivedB, ref Base]
|
||||
typeMismatch(cs, resType, value.typ)
|
||||
|
||||
cs{-1} = newNode(nkAsgn, cs.info, @[resNode, value])
|
||||
else:
|
||||
IllFormedAst(caseStmt)
|
||||
|
||||
result = newNode(nkStmtListExpr, info, @[
|
||||
newNode(nkVarSection, info, @[
|
||||
newNode(nkIdentDefs, info, @[
|
||||
resNode,
|
||||
symNodeFromType(c, resType, info),
|
||||
emptyNode])]),
|
||||
caseStmt,
|
||||
resNode])
|
||||
|
||||
result = semStmtListExpr(c, result)
|
||||
|
||||
proc fixImmediateParams(n: PNode): PNode =
|
||||
# XXX: Temporary work-around until we carry out
|
||||
# the planned overload resolution reforms
|
||||
|
|
@ -1946,7 +1825,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
of nkObjConstr: result = semObjConstr(c, n, flags)
|
||||
of nkLambdaKinds: result = semLambda(c, n, flags)
|
||||
of nkDerefExpr: result = semDeref(c, n)
|
||||
of nkAddr:
|
||||
of nkAddr:
|
||||
result = n
|
||||
checkSonsLen(n, 1)
|
||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
|
|
@ -1958,8 +1837,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
n.sons[0] = semExpr(c, n.sons[0], flags)
|
||||
of nkCast: result = semCast(c, n)
|
||||
of nkIfExpr, nkIfStmt: result = semIf(c, n)
|
||||
of nkStmtListExpr: result = semStmtListExpr(c, n)
|
||||
of nkBlockExpr: result = semBlockExpr(c, n)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv:
|
||||
checkSonsLen(n, 2)
|
||||
of nkStringToCString, nkCStringToString, nkObjDownConv, nkObjUpConv:
|
||||
|
|
@ -1976,8 +1853,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
of nkStaticExpr:
|
||||
result = semStaticExpr(c, n)
|
||||
of nkAsgn: result = semAsgn(c, n)
|
||||
of nkBlockStmt: result = semBlock(c, n)
|
||||
of nkStmtList: result = semStmtList(c, n)
|
||||
of nkBlockStmt, nkBlockExpr: result = semBlock(c, n)
|
||||
of nkStmtList, nkStmtListExpr: result = semStmtList(c, n)
|
||||
of nkRaiseStmt: result = semRaise(c, n)
|
||||
of nkVarSection: result = semVarOrLet(c, n, skVar)
|
||||
of nkLetSection: result = semVarOrLet(c, n, skLet)
|
||||
|
|
@ -1988,9 +1865,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
of nkTryStmt: result = semTry(c, n)
|
||||
of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
|
||||
of nkForStmt, nkParForStmt: result = semFor(c, n)
|
||||
of nkCaseStmt:
|
||||
if efWantStmt in flags: result = semCase(c, n)
|
||||
else: result = semCaseExpr(c, n)
|
||||
of nkCaseStmt: result = semCase(c, n)
|
||||
of nkReturnStmt: result = semReturn(c, n)
|
||||
of nkAsmStmt: result = semAsm(c, n)
|
||||
of nkYieldStmt: result = semYield(c, n)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue