implements 'defer'

This commit is contained in:
Araq 2014-12-04 10:12:32 +01:00
commit e27ab36731
12 changed files with 45 additions and 20 deletions

View file

@ -160,6 +160,7 @@ type
nkConstDef, # a const definition
nkTypeDef, # a type definition
nkYieldStmt, # the yield statement as a tree
nkDefer, # the 'defer' statement
nkTryStmt, # a try statement
nkFinally, # a finally section
nkRaiseStmt, # a raise statement
@ -566,7 +567,7 @@ type
mBool, mChar, mString, mCstring,
mPointer, mEmptySet, mIntSetBaseType, mNil, mExpr, mStmt, mTypeDesc,
mVoidType, mPNimrodNode, mShared, mGuarded, mLock, mSpawn, mDeepCopy,
mIsMainModule, mCompileDate, mCompileTime, mProcCall,
mIsMainModule, mCompileDate, mCompileTime, mProcCall,
mCpuEndian, mHostOS, mHostCPU, mAppType,
mNaN, mInf, mNegInf,
mCompileOption, mCompileOptionArg,

View file

@ -35,7 +35,8 @@ type
tkSymbol, # keywords:
tkAddr, tkAnd, tkAs, tkAsm, tkAtomic,
tkBind, tkBlock, tkBreak, tkCase, tkCast,
tkConst, tkContinue, tkConverter, tkDiscard, tkDistinct, tkDiv, tkDo,
tkConst, tkContinue, tkConverter,
tkDefer, tkDiscard, tkDistinct, tkDiv, tkDo,
tkElif, tkElse, tkEnd, tkEnum, tkExcept, tkExport,
tkFinally, tkFor, tkFrom,
tkGeneric, tkIf, tkImport, tkIn, tkInclude, tkInterface,
@ -71,7 +72,8 @@ const
"tkSymbol",
"addr", "and", "as", "asm", "atomic",
"bind", "block", "break", "case", "cast",
"const", "continue", "converter", "discard", "distinct", "div", "do",
"const", "continue", "converter",
"defer", "discard", "distinct", "div", "do",
"elif", "else", "end", "enum", "except", "export",
"finally", "for", "from", "generic", "if",
"import", "in", "include", "interface", "is", "isnot", "iterator",

View file

@ -1423,9 +1423,10 @@ proc parseBlock(p: var TParser): PNode =
colcom(p, result)
addSon(result, parseStmt(p))
proc parseStatic(p: var TParser): PNode =
proc parseStaticOrDefer(p: var TParser; k: TNodeKind): PNode =
#| staticStmt = 'static' colcom stmt
result = newNodeP(nkStaticStmt, p)
#| deferStmt = 'defer' colcom stmt
result = newNodeP(k, p)
getTokNoInd(p)
colcom(p, result)
addSon(result, parseStmt(p))
@ -1863,7 +1864,7 @@ proc simpleStmt(p: var TParser): PNode =
proc complexOrSimpleStmt(p: var TParser): PNode =
#| complexOrSimpleStmt = (ifStmt | whenStmt | whileStmt
#| | tryStmt | finallyStmt | exceptStmt | forStmt
#| | blockStmt | staticStmt | asmStmt
#| | blockStmt | staticStmt | deferStmt | asmStmt
#| | 'proc' routine
#| | 'method' routine
#| | 'iterator' routine
@ -1884,7 +1885,8 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
of tkExcept: result = parseExceptBlock(p, nkExceptBranch)
of tkFor: result = parseFor(p)
of tkBlock: result = parseBlock(p)
of tkStatic: result = parseStatic(p)
of tkStatic: result = parseStaticOrDefer(p, nkStaticStmt)
of tkDefer: result = parseStaticOrDefer(p, nkDefer)
of tkAsm: result = parseAsm(p)
of tkProc: result = parseRoutine(p, nkProcDef)
of tkMethod: result = parseRoutine(p, nkMethodDef)

View file

@ -1362,8 +1362,9 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
# nkNilLit, nkEmpty}:
# dec last
for i in countup(0, length - 1):
case n.sons[i].kind
of nkFinally, nkExceptBranch:
let k = n.sons[i].kind
case k
of nkFinally, nkExceptBranch, nkDefer:
# stand-alone finally and except blocks are
# transformed into regular try blocks:
#
@ -1372,12 +1373,24 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
# ... | ...
# | finally:
# | fclose(f)
var deferPart: PNode
if k == nkDefer:
deferPart = newNodeI(nkFinally, n.sons[i].info)
deferPart.add n.sons[i].sons[0]
elif k == nkFinally:
message(n.info, warnDeprecated,
"use 'defer'; standalone 'finally'")
deferPart = n.sons[i]
else:
message(n.info, warnDeprecated,
"use an explicit 'try'; standalone 'except'")
deferPart = n.sons[i]
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])
tryStmt.addSon(deferPart)
n.sons[i] = semTry(c, tryStmt)
n.sons.setLen(i+1)
return
@ -1424,7 +1437,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
# a statement list (s; e) has the type 'e':
if result.kind == nkStmtList and result.len > 0:
var lastStmt = lastSon(result)
if lastStmt.kind != nkNilLit and not ImplicitlyDiscardable(lastStmt):
if lastStmt.kind != nkNilLit and not implicitlyDiscardable(lastStmt):
result.typ = lastStmt.typ
#localError(lastStmt.info, errGenerated,
# "Last expression must be explicitly returned if it " &

View file

@ -24,7 +24,7 @@ type
wAddr, wAnd, wAs, wAsm, wAtomic,
wBind, wBlock, wBreak, wCase, wCast, wConst,
wContinue, wConverter, wDiscard, wDistinct, wDiv, wDo,
wContinue, wConverter, wDefer, wDiscard, wDistinct, wDiv, wDo,
wElif, wElse, wEnd, wEnum, wExcept, wExport,
wFinally, wFor, wFrom, wGeneric, wIf, wImport, wIn,
wInclude, wInterface, wIs, wIsnot, wIterator, wLet,
@ -103,7 +103,7 @@ const
"addr", "and", "as", "asm", "atomic",
"bind", "block", "break", "case", "cast",
"const", "continue", "converter",
"discard", "distinct", "div", "do",
"defer", "discard", "distinct", "div", "do",
"elif", "else", "end", "enum", "except", "export",
"finally", "for", "from", "generic", "if",
"import", "in", "include", "interface", "is", "isnot", "iterator",