more intuitive behaviour for 'discardable' in expression bodies

This commit is contained in:
Araq 2013-05-04 18:58:58 +02:00
commit f8af7ed6b4
6 changed files with 99 additions and 22 deletions

View file

@ -1146,10 +1146,9 @@ proc semProcBody(c: PContext, n: PNode): PNode =
# ``result``: # ``result``:
if result.kind == nkSym and result.sym == c.p.resultSym: if result.kind == nkSym and result.sym == c.p.resultSym:
nil nil
elif result.kind == nkNilLit or ImplicitlyDiscardable(result): elif result.kind == nkNilLit:
# intended semantic: if it's 'discardable' and the context allows for it, # or ImplicitlyDiscardable(result):
# discard it. This is bad for chaining but nicer for C wrappers. # new semantic: 'result = x' triggers the void context
# ambiguous :-(
result.typ = nil result.typ = nil
elif result.kind == nkStmtListExpr and result.typ.kind == tyNil: elif result.kind == nkStmtListExpr and result.typ.kind == tyNil:
# to keep backwards compatibility bodies like: # to keep backwards compatibility bodies like:

View file

@ -120,7 +120,7 @@ proc fixNilType(n: PNode) =
if isAtom(n): if isAtom(n):
if n.kind != nkNilLit and n.typ != nil: if n.kind != nkNilLit and n.typ != nil:
localError(n.info, errDiscardValue) localError(n.info, errDiscardValue)
else: elif n.kind in {nkStmtList, nkStmtListExpr}:
for it in n: fixNilType(it) for it in n: fixNilType(it)
n.typ = nil n.typ = nil
@ -165,6 +165,7 @@ proc semIf(c: PContext, n: PNode): PNode =
let j = it.len-1 let j = it.len-1
it.sons[j] = fitNode(c, typ, it.sons[j]) it.sons[j] = fitNode(c, typ, it.sons[j])
result.kind = nkIfExpr result.kind = nkIfExpr
# propagate any enforced VoidContext:
result.typ = typ result.typ = typ
proc semCase(c: PContext, n: PNode): PNode = proc semCase(c: PContext, n: PNode): PNode =
@ -220,6 +221,7 @@ proc semCase(c: PContext, n: PNode): PNode =
var it = n.sons[i] var it = n.sons[i]
let j = it.len-1 let j = it.len-1
it.sons[j] = fitNode(c, typ, it.sons[j]) it.sons[j] = fitNode(c, typ, it.sons[j])
# propagate any enforced VoidContext:
result.typ = typ result.typ = typ
proc semTry(c: PContext, n: PNode): PNode = proc semTry(c: PContext, n: PNode): PNode =
@ -264,6 +266,7 @@ proc semTry(c: PContext, n: PNode): PNode =
var it = n.sons[i] var it = n.sons[i]
let j = it.len-1 let j = it.len-1
it.sons[j] = fitNode(c, typ, it.sons[j]) it.sons[j] = fitNode(c, typ, it.sons[j])
# propagate any enforced VoidContext:
result.typ = typ result.typ = typ
proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode = proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
@ -623,6 +626,8 @@ proc semFor(c: PContext, n: PNode): PNode =
result = semForFields(c, n, call.sons[0].sym.magic) result = semForFields(c, n, call.sons[0].sym.magic)
else: else:
result = semForVars(c, n) result = semForVars(c, n)
# propagate any enforced VoidContext:
result.typ = n.sons[length-1].typ
closeScope(c.tab) closeScope(c.tab)
proc semRaise(c: PContext, n: PNode): PNode = proc semRaise(c: PContext, n: PNode): PNode =
@ -1079,9 +1084,13 @@ proc semStmtList(c: PContext, n: PNode): PNode =
var length = sonsLen(n) var length = sonsLen(n)
var voidContext = false var voidContext = false
var last = length-1 var last = length-1
while last > 0 and n.sons[last].kind in {nkPragma, nkCommentStmt, # by not allowing for nkCommentStmt etc. we ensure nkStmtListExpr actually
nkNilLit, nkEmpty}: # really *ends* in the expression that produces the type: The compiler now
dec last # relies on this fact and it's too much effort to change that. And arguably
# 'R(); #comment' shouldn't produce R's type anyway.
#while last > 0 and n.sons[last].kind in {nkPragma, nkCommentStmt,
# nkNilLit, nkEmpty}:
# dec last
for i in countup(0, length - 1): for i in countup(0, length - 1):
case n.sons[i].kind case n.sons[i].kind
of nkFinally, nkExceptBranch: of nkFinally, nkExceptBranch:

View file

@ -35,7 +35,14 @@ qualifiedIdent = symbol ('.' optInd ('type' | 'addr' | symbol))?
exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)? exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}' setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}'
castExpr = 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')' castExpr = 'cast' '[' optInd typeDesc optPar ']' '(' optInd expr optPar ')'
generalizedLit ::= GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT parKeyw = 'discard' | 'include' | 'if' | 'while' | 'case' | 'try'
| 'finally' | 'except' | 'for' | 'block' | 'const' | 'let'
| 'when' | 'var' | 'mixin'
par = '(' optInd (&parKeyw complexOrSimpleStmt ^+ ';'
| simpleExpr ('=' expr (';' complexOrSimpleStmt ^+ ';' )? )?
| (':' expr)? (',' (exprColonEqExpr comma?)*)? )?
optPar ')'
generalizedLit = GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
identOrLiteral = generalizedLit | symbol identOrLiteral = generalizedLit | symbol
| INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
| UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT | UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
@ -43,7 +50,7 @@ identOrLiteral = generalizedLit | symbol
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
| CHAR_LIT | CHAR_LIT
| NIL | NIL
| tupleConstr | arrayConstr | setOrTableConstr | par | arrayConstr | setOrTableConstr
| castExpr | castExpr
tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')' tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']' arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']'
@ -76,7 +83,8 @@ doBlocks = doBlock ^* IND{=}
procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)? procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
expr = (ifExpr expr = (ifExpr
| whenExpr | whenExpr
| caseExpr) | caseExpr
| tryStmt)
/ simpleExpr / simpleExpr
typeKeyw = 'var' | 'ref' | 'ptr' | 'shared' | 'type' | 'tuple' typeKeyw = 'var' | 'ref' | 'ptr' | 'shared' | 'type' | 'tuple'
| 'proc' | 'iterator' | 'distinct' | 'object' | 'enum' | 'proc' | 'iterator' | 'distinct' | 'object' | 'enum'

66
tests/run/tstmtexprs.nim Normal file
View file

@ -0,0 +1,66 @@
discard """
output: '''(bar: bar)
1244
6
abcdefghijklmnopqrstuvwxyz
145 23'''
"""
import strutils
when true:
proc test(foo: proc (x, y: int): bool) =
echo foo(5, 5)
type Foo = object
bar: string
proc newfoo(): Foo =
result.bar = "bar"
echo($newfoo())
proc retInt(x, y: int): int =
if (var yy = 0; yy != 0):
echo yy
else:
echo(try: parseInt("1244") except EINvalidValue: -1)
result = case x
of 23: 3
of 64:
case y
of 1: 2
of 2: 3
of 3: 6
else: 8
else: 1
echo retInt(64, 3)
proc buildString(): string =
result = ""
for x in 'a'..'z':
result.add(x)
echo buildString()
#test(
# proc (x, y: int): bool =
# if x == 5: return true
# if x == 2: return false
# if y == 78: return true
#)
proc q(): int {.discardable.} = 145
proc p(): int =
q()
proc p2(a: int): int =
# result enforces a void context:
if a == 2:
result = 23
q()
echo p(), " ", p2(2)

View file

@ -28,6 +28,7 @@ version 0.9.4
============= =============
- macros as type pragmas - macros as type pragmas
- effect propagation for callbacks
- provide tool/API to track leaks/object counts - provide tool/API to track leaks/object counts
- hybrid GC - hybrid GC
- use big blocks in the allocator - use big blocks in the allocator
@ -52,7 +53,6 @@ version 0.9.X
- improve the compiler as a service - improve the compiler as a service
- better support for macros that rewrite procs - better support for macros that rewrite procs
- macros need access to types and symbols (partially implemented) - macros need access to types and symbols (partially implemented)
- effect propagation for callbacks
- perhaps: change comment handling in the AST - perhaps: change comment handling in the AST
- enforce 'simpleExpr' more often --> doesn't work; tkProc is - enforce 'simpleExpr' more often --> doesn't work; tkProc is
part of primary! part of primary!

View file

@ -100,12 +100,7 @@ Nimrod plays nice with others
Roadmap to 1.0 Roadmap to 1.0
============== ==============
Version 0.9.2
* better interaction between macros, templates and overloading
* the symbol binding rules for generics and templates may change again
Version 0.9.x Version 0.9.x
* message passing performance will be greatly improved * the symbol binding rules for templates will change
* the syntactic distinction between statements and expressions will be * a shared memory garbage collected heap will be provided
removed
* the need for forward declarations may be removed * the need for forward declarations may be removed