more intuitive behaviour for 'discardable' in expression bodies

This commit is contained in:
Araq
2013-05-04 18:58:58 +02:00
parent af441e607f
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``:
if result.kind == nkSym and result.sym == c.p.resultSym:
nil
elif result.kind == nkNilLit or ImplicitlyDiscardable(result):
# intended semantic: if it's 'discardable' and the context allows for it,
# discard it. This is bad for chaining but nicer for C wrappers.
# ambiguous :-(
elif result.kind == nkNilLit:
# or ImplicitlyDiscardable(result):
# new semantic: 'result = x' triggers the void context
result.typ = nil
elif result.kind == nkStmtListExpr and result.typ.kind == tyNil:
# to keep backwards compatibility bodies like:

View File

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

View File

@@ -35,7 +35,14 @@ qualifiedIdent = symbol ('.' optInd ('type' | 'addr' | symbol))?
exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}'
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
| INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
| UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
@@ -43,7 +50,7 @@ identOrLiteral = generalizedLit | symbol
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT
| CHAR_LIT
| NIL
| tupleConstr | arrayConstr | setOrTableConstr
| par | arrayConstr | setOrTableConstr
| castExpr
tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']'
@@ -76,7 +83,8 @@ doBlocks = doBlock ^* IND{=}
procExpr = 'proc' paramListColon pragmas? ('=' COMMENT? stmt)?
expr = (ifExpr
| whenExpr
| caseExpr)
| caseExpr
| tryStmt)
/ simpleExpr
typeKeyw = 'var' | 'ref' | 'ptr' | 'shared' | 'type' | 'tuple'
| '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
- effect propagation for callbacks
- provide tool/API to track leaks/object counts
- hybrid GC
- use big blocks in the allocator
@@ -52,7 +53,6 @@ version 0.9.X
- improve the compiler as a service
- better support for macros that rewrite procs
- macros need access to types and symbols (partially implemented)
- effect propagation for callbacks
- perhaps: change comment handling in the AST
- enforce 'simpleExpr' more often --> doesn't work; tkProc is
part of primary!

View File

@@ -100,12 +100,7 @@ Nimrod plays nice with others
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
* message passing performance will be greatly improved
* the syntactic distinction between statements and expressions will be
removed
* the symbol binding rules for templates will change
* a shared memory garbage collected heap will be provided
* the need for forward declarations may be removed