semExpr/semStmt merged
This commit is contained in:
parent
8c8400ea3a
commit
23c3af80f6
6 changed files with 187 additions and 166 deletions
|
|
@ -1197,3 +1197,7 @@ iterator items*(n: PNode): PNode =
|
||||||
|
|
||||||
proc isAtom*(n: PNode): bool {.inline.} =
|
proc isAtom*(n: PNode): bool {.inline.} =
|
||||||
result = n.kind >= nkNone and n.kind <= nkNilLit
|
result = n.kind >= nkNone and n.kind <= nkNilLit
|
||||||
|
|
||||||
|
proc isEmptyType*(t: PType): bool {.inline.} =
|
||||||
|
## 'void' and 'stmt' types are often equivalent to 'nil' these days:
|
||||||
|
result = t == nil or t.kind in {tyEmpty, tyStmt}
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ const
|
||||||
errOrdXMustNotBeNegative: "ord($1) must not be negative",
|
errOrdXMustNotBeNegative: "ord($1) must not be negative",
|
||||||
errLenXinvalid: "len($1) must be less than 32768",
|
errLenXinvalid: "len($1) must be less than 32768",
|
||||||
errWrongNumberOfVariables: "wrong number of variables",
|
errWrongNumberOfVariables: "wrong number of variables",
|
||||||
errExprCannotBeRaised: "only objects can be raised",
|
errExprCannotBeRaised: "only a 'ref object' can be raised",
|
||||||
errBreakOnlyInLoop: "'break' only allowed in loop construct",
|
errBreakOnlyInLoop: "'break' only allowed in loop construct",
|
||||||
errTypeXhasUnknownSize: "type \'$1\' has unknown size",
|
errTypeXhasUnknownSize: "type \'$1\' has unknown size",
|
||||||
errConstNeedsConstExpr: "a constant can only be initialized with a constant expression",
|
errConstNeedsConstExpr: "a constant can only be initialized with a constant expression",
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,17 @@ proc semPass*(): TPass
|
||||||
|
|
||||||
type
|
type
|
||||||
TExprFlag = enum
|
TExprFlag = enum
|
||||||
efLValue, efWantIterator, efInTypeof
|
efLValue, efWantIterator, efInTypeof, efWantStmt
|
||||||
TExprFlags = set[TExprFlag]
|
TExprFlags = set[TExprFlag]
|
||||||
|
|
||||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||||
|
proc semExprNoType(c: PContext, n: PNode): PNode
|
||||||
|
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||||
|
|
||||||
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode
|
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode
|
||||||
|
proc changeType(n: PNode, newType: PType)
|
||||||
|
|
||||||
proc semLambda(c: PContext, n: PNode): PNode
|
proc semLambda(c: PContext, n: PNode): PNode
|
||||||
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
|
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType
|
||||||
proc semStmt(c: PContext, n: PNode): PNode
|
proc semStmt(c: PContext, n: PNode): PNode
|
||||||
|
|
@ -83,6 +88,8 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
|
||||||
|
|
||||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
semCheck: bool = true): PNode
|
semCheck: bool = true): PNode
|
||||||
|
proc semMacroStmt(c: PContext, n: PNode, flags: TExprFlags,
|
||||||
|
semCheck = true): PNode
|
||||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||||
|
|
||||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||||
|
|
@ -156,7 +163,7 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode =
|
||||||
LocalError(n.info, errConstExprExpected)
|
LocalError(n.info, errConstExprExpected)
|
||||||
result = nn
|
result = nn
|
||||||
|
|
||||||
include semtypes, semtempl, semexprs, semgnrc, semstmts
|
include semtypes, semtempl, semgnrc, semstmts, semexprs
|
||||||
|
|
||||||
proc addCodeForGenerics(c: PContext, n: PNode) =
|
proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||||
for i in countup(c.generics.lastGenericIdx, Len(c.generics.generics) - 1):
|
for i in countup(c.generics.lastGenericIdx, Len(c.generics.generics) - 1):
|
||||||
|
|
|
||||||
|
|
@ -706,10 +706,14 @@ proc semExprNoType(c: PContext, n: PNode): PNode =
|
||||||
proc ImplicitelyDiscardable(n: PNode): bool {.inline.} =
|
proc ImplicitelyDiscardable(n: PNode): bool {.inline.} =
|
||||||
result = isCallExpr(n) and n.sons[0].kind == nkSym and
|
result = isCallExpr(n) and n.sons[0].kind == nkSym and
|
||||||
sfDiscardable in n.sons[0].sym.flags
|
sfDiscardable in n.sons[0].sym.flags
|
||||||
result = semExpr(c, n)
|
result = semExpr(c, n, {efWantStmt})
|
||||||
if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
|
if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
|
||||||
if gCmd == cmdInteractive:
|
if gCmd == cmdInteractive:
|
||||||
result = buildEchoStmt(c, result)
|
result = buildEchoStmt(c, result)
|
||||||
|
elif result.kind == nkNilLit:
|
||||||
|
# XXX too much work and fixing would break bootstrapping:
|
||||||
|
#Message(n.info, warnNilStatement)
|
||||||
|
result.typ = nil
|
||||||
elif not ImplicitelyDiscardable(result) and result.typ.kind != tyError:
|
elif not ImplicitelyDiscardable(result) and result.typ.kind != tyError:
|
||||||
localError(n.info, errDiscardValue)
|
localError(n.info, errDiscardValue)
|
||||||
|
|
||||||
|
|
@ -1041,6 +1045,60 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
asgnToResultVar(c, n, n.sons[0], n.sons[1])
|
asgnToResultVar(c, n, n.sons[0], n.sons[1])
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
|
proc SemReturn(c: PContext, n: PNode): PNode =
|
||||||
|
result = n
|
||||||
|
checkSonsLen(n, 1)
|
||||||
|
if c.p.owner.kind notin {skConverter, skMethod, skProc, skMacro}:
|
||||||
|
LocalError(n.info, errXNotAllowedHere, "\'return\'")
|
||||||
|
elif n.sons[0].kind != nkEmpty:
|
||||||
|
# transform ``return expr`` to ``result = expr; return``
|
||||||
|
if c.p.resultSym != nil:
|
||||||
|
var a = newNodeI(nkAsgn, n.sons[0].info)
|
||||||
|
addSon(a, newSymNode(c.p.resultSym))
|
||||||
|
addSon(a, n.sons[0])
|
||||||
|
n.sons[0] = semAsgn(c, a)
|
||||||
|
# optimize away ``result = result``:
|
||||||
|
if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult:
|
||||||
|
n.sons[0] = ast.emptyNode
|
||||||
|
else:
|
||||||
|
LocalError(n.info, errNoReturnTypeDeclared)
|
||||||
|
|
||||||
|
proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||||
|
var t = skipTypes(restype, {tyGenericInst})
|
||||||
|
case t.kind
|
||||||
|
of tyVar:
|
||||||
|
n.sons[0] = takeImplicitAddr(c, n.sons[0])
|
||||||
|
of tyTuple:
|
||||||
|
for i in 0.. <t.sonsLen:
|
||||||
|
var e = skipTypes(t.sons[i], {tyGenericInst})
|
||||||
|
if e.kind == tyVar:
|
||||||
|
if n.sons[0].kind == nkPar:
|
||||||
|
n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i])
|
||||||
|
elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
|
||||||
|
n.sons[0].sons[1].kind == nkPar:
|
||||||
|
var a = n.sons[0].sons[1]
|
||||||
|
a.sons[i] = takeImplicitAddr(c, a.sons[i])
|
||||||
|
else:
|
||||||
|
localError(n.sons[0].info, errXExpected, "tuple constructor")
|
||||||
|
else: nil
|
||||||
|
|
||||||
|
proc SemYield(c: PContext, n: PNode): PNode =
|
||||||
|
result = n
|
||||||
|
checkSonsLen(n, 1)
|
||||||
|
if c.p.owner == nil or c.p.owner.kind != skIterator:
|
||||||
|
LocalError(n.info, errYieldNotAllowedHere)
|
||||||
|
elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
|
||||||
|
LocalError(n.info, errYieldNotAllowedInTryStmt)
|
||||||
|
elif n.sons[0].kind != nkEmpty:
|
||||||
|
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
|
||||||
|
var restype = c.p.owner.typ.sons[0]
|
||||||
|
if restype != nil:
|
||||||
|
n.sons[0] = fitNode(c, restype, n.sons[0])
|
||||||
|
if n.sons[0].typ == nil: InternalError(n.info, "semYield")
|
||||||
|
SemYieldVarResult(c, n, restype)
|
||||||
|
else:
|
||||||
|
localError(n.info, errCannotReturnExpr)
|
||||||
|
|
||||||
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
|
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
|
||||||
if onlyCurrentScope:
|
if onlyCurrentScope:
|
||||||
result = SymtabLocalGet(c.tab, i)
|
result = SymtabLocalGet(c.tab, i)
|
||||||
|
|
@ -1417,7 +1475,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
# because of the changed symbol binding, this does not mean that we
|
# because of the changed symbol binding, this does not mean that we
|
||||||
# don't have to check the symbol for semantics here again!
|
# don't have to check the symbol for semantics here again!
|
||||||
result = semSym(c, n, n.sym, flags)
|
result = semSym(c, n, n.sym, flags)
|
||||||
of nkEmpty, nkNone:
|
of nkEmpty, nkNone, nkCommentStmt:
|
||||||
nil
|
nil
|
||||||
of nkNilLit:
|
of nkNilLit:
|
||||||
result.typ = getSysType(tyNil)
|
result.typ = getSysType(tyNil)
|
||||||
|
|
@ -1505,10 +1563,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = semIndirectOp(c, n, flags)
|
result = semIndirectOp(c, n, flags)
|
||||||
of nkMacroStmt:
|
of nkMacroStmt:
|
||||||
result = semMacroStmt(c, n, flags)
|
result = semMacroStmt(c, n, flags)
|
||||||
of nkWhenExpr:
|
of nkWhen:
|
||||||
result = semWhen(c, n, false)
|
if efWantStmt in flags:
|
||||||
result = semExpr(c, result)
|
result = semWhen(c, n, true)
|
||||||
of nkBracketExpr:
|
else:
|
||||||
|
result = semWhen(c, n, false)
|
||||||
|
result = semExpr(c, result, flags)
|
||||||
|
of nkBracketExpr:
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
|
var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
|
||||||
if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}:
|
if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}:
|
||||||
|
|
@ -1562,6 +1623,45 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = n.sons[0]
|
result = n.sons[0]
|
||||||
of nkStaticExpr:
|
of nkStaticExpr:
|
||||||
result = semStaticExpr(c, n)
|
result = semStaticExpr(c, n)
|
||||||
|
|
||||||
|
of nkAsgn: result = semAsgn(c, n)
|
||||||
|
of nkBlockStmt: result = semBlock(c, n)
|
||||||
|
of nkStmtList: result = semStmtList(c, n)
|
||||||
|
of nkRaiseStmt: result = semRaise(c, n)
|
||||||
|
of nkVarSection: result = semVarOrLet(c, n, skVar)
|
||||||
|
of nkLetSection: result = semVarOrLet(c, n, skLet)
|
||||||
|
of nkConstSection: result = semConst(c, n)
|
||||||
|
of nkTypeSection: result = SemTypeSection(c, n)
|
||||||
|
of nkIfStmt: result = SemIf(c, n)
|
||||||
|
of nkDiscardStmt: result = semDiscard(c, n)
|
||||||
|
of nkWhileStmt: result = semWhile(c, n)
|
||||||
|
of nkTryStmt: result = semTry(c, n)
|
||||||
|
of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
|
||||||
|
of nkForStmt, nkParForStmt: result = semFor(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)
|
||||||
|
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas)
|
||||||
|
of nkIteratorDef: result = semIterator(c, n)
|
||||||
|
of nkProcDef: result = semProc(c, n)
|
||||||
|
of nkMethodDef: result = semMethod(c, n)
|
||||||
|
of nkConverterDef: result = semConverterDef(c, n)
|
||||||
|
of nkMacroDef: result = semMacroDef(c, n)
|
||||||
|
of nkTemplateDef: result = semTemplateDef(c, n)
|
||||||
|
of nkImportStmt:
|
||||||
|
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
|
||||||
|
result = evalImport(c, n)
|
||||||
|
of nkFromStmt:
|
||||||
|
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from")
|
||||||
|
result = evalFrom(c, n)
|
||||||
|
of nkIncludeStmt:
|
||||||
|
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "include")
|
||||||
|
result = evalInclude(c, n)
|
||||||
|
of nkPragmaBlock:
|
||||||
|
result = semPragmaBlock(c, n)
|
||||||
|
of nkStaticStmt:
|
||||||
|
result = semStaticStmt(c, n)
|
||||||
else:
|
else:
|
||||||
LocalError(n.info, errInvalidExpressionX,
|
LocalError(n.info, errInvalidExpressionX,
|
||||||
renderTree(n, {renderNoComments}))
|
renderTree(n, {renderNoComments}))
|
||||||
|
|
|
||||||
22
compiler/sempass2.nim
Normal file
22
compiler/sempass2.nim
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The Nimrod Compiler
|
||||||
|
# (c) Copyright 2012 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
# included from sem.nim
|
||||||
|
|
||||||
|
# Second semantic checking pass over the AST. Necessary because the old
|
||||||
|
# way had some inherent problems. Performs:
|
||||||
|
#
|
||||||
|
# * procvar checks
|
||||||
|
# * effect tracking
|
||||||
|
# * closure analysis
|
||||||
|
# * checks for invalid usages of compiletime magics
|
||||||
|
# * checks for invalid usages of PNimNode
|
||||||
|
# * later: will do an escape analysis for closures at least
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ proc semDiscard(c: PContext, n: PNode): PNode =
|
||||||
checkSonsLen(n, 1)
|
checkSonsLen(n, 1)
|
||||||
if n.sons[0].kind != nkEmpty:
|
if n.sons[0].kind != nkEmpty:
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||||
if n.sons[0].typ == nil: localError(n.info, errInvalidDiscard)
|
if isEmptyType(n.sons[0].typ): localError(n.info, errInvalidDiscard)
|
||||||
|
|
||||||
proc semBreakOrContinue(c: PContext, n: PNode): PNode =
|
proc semBreakOrContinue(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -162,60 +162,6 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||||
if chckCovered and (covered != toCover(n.sons[0].typ)):
|
if chckCovered and (covered != toCover(n.sons[0].typ)):
|
||||||
localError(n.info, errNotAllCasesCovered)
|
localError(n.info, errNotAllCasesCovered)
|
||||||
closeScope(c.tab)
|
closeScope(c.tab)
|
||||||
|
|
||||||
proc SemReturn(c: PContext, n: PNode): PNode =
|
|
||||||
result = n
|
|
||||||
checkSonsLen(n, 1)
|
|
||||||
if c.p.owner.kind notin {skConverter, skMethod, skProc, skMacro}:
|
|
||||||
LocalError(n.info, errXNotAllowedHere, "\'return\'")
|
|
||||||
elif n.sons[0].kind != nkEmpty:
|
|
||||||
# transform ``return expr`` to ``result = expr; return``
|
|
||||||
if c.p.resultSym != nil:
|
|
||||||
var a = newNodeI(nkAsgn, n.sons[0].info)
|
|
||||||
addSon(a, newSymNode(c.p.resultSym))
|
|
||||||
addSon(a, n.sons[0])
|
|
||||||
n.sons[0] = semAsgn(c, a)
|
|
||||||
# optimize away ``result = result``:
|
|
||||||
if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult:
|
|
||||||
n.sons[0] = ast.emptyNode
|
|
||||||
else:
|
|
||||||
LocalError(n.info, errNoReturnTypeDeclared)
|
|
||||||
|
|
||||||
proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
|
||||||
var t = skipTypes(restype, {tyGenericInst})
|
|
||||||
case t.kind
|
|
||||||
of tyVar:
|
|
||||||
n.sons[0] = takeImplicitAddr(c, n.sons[0])
|
|
||||||
of tyTuple:
|
|
||||||
for i in 0.. <t.sonsLen:
|
|
||||||
var e = skipTypes(t.sons[i], {tyGenericInst})
|
|
||||||
if e.kind == tyVar:
|
|
||||||
if n.sons[0].kind == nkPar:
|
|
||||||
n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i])
|
|
||||||
elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and
|
|
||||||
n.sons[0].sons[1].kind == nkPar:
|
|
||||||
var a = n.sons[0].sons[1]
|
|
||||||
a.sons[i] = takeImplicitAddr(c, a.sons[i])
|
|
||||||
else:
|
|
||||||
localError(n.sons[0].info, errXExpected, "tuple constructor")
|
|
||||||
else: nil
|
|
||||||
|
|
||||||
proc SemYield(c: PContext, n: PNode): PNode =
|
|
||||||
result = n
|
|
||||||
checkSonsLen(n, 1)
|
|
||||||
if c.p.owner == nil or c.p.owner.kind != skIterator:
|
|
||||||
LocalError(n.info, errYieldNotAllowedHere)
|
|
||||||
elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
|
|
||||||
LocalError(n.info, errYieldNotAllowedInTryStmt)
|
|
||||||
elif n.sons[0].kind != nkEmpty:
|
|
||||||
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
|
|
||||||
var restype = c.p.owner.typ.sons[0]
|
|
||||||
if restype != nil:
|
|
||||||
n.sons[0] = fitNode(c, restype, n.sons[0])
|
|
||||||
if n.sons[0].typ == nil: InternalError(n.info, "semYield")
|
|
||||||
SemYieldVarResult(c, n, restype)
|
|
||||||
else:
|
|
||||||
localError(n.info, errCannotReturnExpr)
|
|
||||||
|
|
||||||
proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
|
proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
|
||||||
result = fitNode(c, typ, n)
|
result = fitNode(c, typ, n)
|
||||||
|
|
@ -1125,111 +1071,53 @@ proc insertDestructors(c: PContext, varSection: PNode):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
proc SemStmt(c: PContext, n: PNode): PNode =
|
proc semStmtList(c: PContext, n: PNode): PNode =
|
||||||
const # must be last statements in a block:
|
# these must be last statements in a block:
|
||||||
|
const
|
||||||
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
|
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
|
||||||
result = n
|
result = n
|
||||||
if gCmd == cmdIdeTools:
|
var length = sonsLen(n)
|
||||||
suggestStmt(c, n)
|
for i in countup(0, length - 1):
|
||||||
if nfSem in n.flags: return
|
case n.sons[i].kind
|
||||||
case n.kind
|
of nkFinally, nkExceptBranch:
|
||||||
of nkAsgn: result = semAsgn(c, n)
|
# stand-alone finally and except blocks are
|
||||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkMacroStmt, nkCallStrLit:
|
# transformed into regular try blocks:
|
||||||
result = semCommand(c, n)
|
#
|
||||||
of nkEmpty, nkCommentStmt: nil
|
# var f = fopen("somefile") | var f = fopen("somefile")
|
||||||
of nkNilLit:
|
# finally: fclose(f) | try:
|
||||||
# XXX too much work and fixing would break bootstrapping:
|
# ... | ...
|
||||||
#Message(n.info, warnNilStatement)
|
# | finally:
|
||||||
of nkBlockStmt: result = semBlock(c, n)
|
# | fclose(f)
|
||||||
of nkStmtList:
|
var tryStmt = newNodeI(nkTryStmt, n.sons[i].info)
|
||||||
var length = sonsLen(n)
|
var body = newNodeI(nkStmtList, n.sons[i].info)
|
||||||
for i in countup(0, length - 1):
|
if i < n.sonsLen - 1:
|
||||||
case n.sons[i].kind
|
body.sons = n.sons[(i+1)..(-1)]
|
||||||
of nkFinally, nkExceptBranch:
|
tryStmt.addSon(body)
|
||||||
# stand-alone finally and except blocks are
|
tryStmt.addSon(n.sons[i])
|
||||||
# transformed into regular try blocks:
|
n.sons[i] = semTry(c, tryStmt)
|
||||||
#
|
n.sons.setLen(i+1)
|
||||||
# var f = fopen("somefile") | var f = fopen("somefile")
|
return
|
||||||
# finally: fclose(f) | try:
|
|
||||||
# ... | ...
|
|
||||||
# | finally:
|
|
||||||
# | fclose(f)
|
|
||||||
var tryStmt = newNodeI(nkTryStmt, n.sons[i].info)
|
|
||||||
var body = newNodeI(nkStmtList, n.sons[i].info)
|
|
||||||
if i < n.sonsLen - 1:
|
|
||||||
body.sons = n.sons[(i+1)..(-1)]
|
|
||||||
tryStmt.addSon(body)
|
|
||||||
tryStmt.addSon(n.sons[i])
|
|
||||||
n.sons[i] = semTry(c, tryStmt)
|
|
||||||
n.sons.setLen(i+1)
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
n.sons[i] = semStmt(c, n.sons[i])
|
|
||||||
case n.sons[i].kind
|
|
||||||
of nkVarSection, nkLetSection:
|
|
||||||
let (outer, inner) = insertDestructors(c, n.sons[i])
|
|
||||||
if outer != nil:
|
|
||||||
n.sons[i] = outer
|
|
||||||
for j in countup(i+1, length-1):
|
|
||||||
inner.addSon(SemStmt(c, n.sons[j]))
|
|
||||||
n.sons.setLen(i+1)
|
|
||||||
return
|
|
||||||
of LastBlockStmts:
|
|
||||||
for j in countup(i + 1, length - 1):
|
|
||||||
case n.sons[j].kind
|
|
||||||
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: nil
|
|
||||||
else: localError(n.sons[j].info, errStmtInvalidAfterReturn)
|
|
||||||
else: nil
|
|
||||||
of nkRaiseStmt: result = semRaise(c, n)
|
|
||||||
of nkVarSection: result = semVarOrLet(c, n, skVar)
|
|
||||||
of nkLetSection: result = semVarOrLet(c, n, skLet)
|
|
||||||
of nkConstSection: result = semConst(c, n)
|
|
||||||
of nkTypeSection: result = SemTypeSection(c, n)
|
|
||||||
of nkIfStmt: result = SemIf(c, n)
|
|
||||||
of nkWhenStmt: result = semWhen(c, n)
|
|
||||||
of nkDiscardStmt: result = semDiscard(c, n)
|
|
||||||
of nkWhileStmt: result = semWhile(c, n)
|
|
||||||
of nkTryStmt: result = semTry(c, n)
|
|
||||||
of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
|
|
||||||
of nkForStmt, nkParForStmt: result = semFor(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)
|
|
||||||
of nkPragma: pragma(c, c.p.owner, n, stmtPragmas)
|
|
||||||
of nkIteratorDef: result = semIterator(c, n)
|
|
||||||
of nkProcDef: result = semProc(c, n)
|
|
||||||
of nkMethodDef: result = semMethod(c, n)
|
|
||||||
of nkConverterDef: result = semConverterDef(c, n)
|
|
||||||
of nkMacroDef: result = semMacroDef(c, n)
|
|
||||||
of nkTemplateDef: result = semTemplateDef(c, n)
|
|
||||||
of nkImportStmt:
|
|
||||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
|
|
||||||
result = evalImport(c, n)
|
|
||||||
of nkFromStmt:
|
|
||||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from")
|
|
||||||
result = evalFrom(c, n)
|
|
||||||
of nkIncludeStmt:
|
|
||||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "include")
|
|
||||||
result = evalInclude(c, n)
|
|
||||||
of nkPragmaBlock:
|
|
||||||
result = semPragmaBlock(c, n)
|
|
||||||
of nkStaticStmt:
|
|
||||||
result = semStaticStmt(c, n)
|
|
||||||
else:
|
|
||||||
# in interactive mode, we embed the expression in an 'echo':
|
|
||||||
if gCmd == cmdInteractive:
|
|
||||||
result = buildEchoStmt(c, semExpr(c, n))
|
|
||||||
else:
|
else:
|
||||||
result = semExprNoType(c, n)
|
n.sons[i] = semStmt(c, n.sons[i])
|
||||||
#LocalError(n.info, errStmtExpected)
|
case n.sons[i].kind
|
||||||
#result = ast.emptyNode
|
of nkVarSection, nkLetSection:
|
||||||
if result == nil:
|
let (outer, inner) = insertDestructors(c, n.sons[i])
|
||||||
InternalError(n.info, "SemStmt: result = nil")
|
if outer != nil:
|
||||||
# error correction:
|
n.sons[i] = outer
|
||||||
result = emptyNode
|
for j in countup(i+1, length-1):
|
||||||
else:
|
inner.addSon(SemStmt(c, n.sons[j]))
|
||||||
incl(result.flags, nfSem)
|
n.sons.setLen(i+1)
|
||||||
|
return
|
||||||
|
of LastBlockStmts:
|
||||||
|
for j in countup(i + 1, length - 1):
|
||||||
|
case n.sons[j].kind
|
||||||
|
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: nil
|
||||||
|
else: localError(n.sons[j].info, errStmtInvalidAfterReturn)
|
||||||
|
else: nil
|
||||||
|
|
||||||
|
proc SemStmt(c: PContext, n: PNode): PNode =
|
||||||
|
# now: simply an alias:
|
||||||
|
result = semExprNoType(c, n)
|
||||||
|
|
||||||
proc semStmtScope(c: PContext, n: PNode): PNode =
|
proc semStmtScope(c: PContext, n: PNode): PNode =
|
||||||
openScope(c.tab)
|
openScope(c.tab)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue