summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semexprs.nim7
-rw-r--r--compiler/semstmts.nim23
-rw-r--r--doc/grammar.txt14
-rw-r--r--tests/run/tstmtexprs.nim66
-rw-r--r--todo.txt2
-rw-r--r--web/index.txt9
6 files changed, 99 insertions, 22 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 2ac603920..93dfc2f37 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -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:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 4146b69a1..bca77e06a 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -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:
diff --git a/doc/grammar.txt b/doc/grammar.txt
index 59ae5b073..217007281 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -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'
diff --git a/tests/run/tstmtexprs.nim b/tests/run/tstmtexprs.nim
new file mode 100644
index 000000000..a69acd98b
--- /dev/null
+++ b/tests/run/tstmtexprs.nim
@@ -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)
diff --git a/todo.txt b/todo.txt
index 9189e037f..764ba1e13 100644
--- a/todo.txt
+++ b/todo.txt
@@ -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!
diff --git a/web/index.txt b/web/index.txt
index 99beb3743..9b90e94de 100644
--- a/web/index.txt
+++ b/web/index.txt
@@ -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