tester should work again; documented (;)

This commit is contained in:
Araq 2013-04-30 23:54:02 +02:00
commit 427f84b4ec
4 changed files with 43 additions and 7 deletions

View file

@ -214,12 +214,12 @@ proc genConstStmt(p: BProc, t: PNode) =
proc genIfStmt(p: BProc, n: PNode) = proc genIfStmt(p: BProc, n: PNode) =
# #
# if (!expr1) goto L1; # { if (!expr1) goto L1;
# { thenPart } # thenPart }
# goto LEnd # goto LEnd
# L1: # L1:
# if (!expr2) goto L2; # { if (!expr2) goto L2;
# { thenPart2 } # thenPart2 }
# goto LEnd # goto LEnd
# L2: # L2:
# { elsePart } # { elsePart }
@ -232,13 +232,15 @@ proc genIfStmt(p: BProc, n: PNode) =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i] var it = n.sons[i]
if it.len == 2: if it.len == 2:
startBlock(p)
initLocExpr(p, it.sons[0], a) initLocExpr(p, it.sons[0], a)
Lelse = getLabel(p) Lelse = getLabel(p)
inc(p.labels) inc(p.labels)
lineFF(p, cpsStmts, "if (!$1) goto $2;$n", lineFF(p, cpsStmts, "if (!$1) goto $2;$n",
"br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n", "br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n",
[rdLoc(a), Lelse, toRope(p.labels)]) [rdLoc(a), Lelse, toRope(p.labels)])
genSimpleBlock(p, it.sons[1]) genStmts(p, it.sons[1])
endBlock(p)
if sonsLen(n) > 1: if sonsLen(n) > 1:
lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [Lend]) lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [Lend])
fixLabel(p, Lelse) fixLabel(p, Lelse)

View file

@ -25,6 +25,9 @@ The language constructs are explained using an extended BNF, in
which ``(a)*`` means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and which ``(a)*`` means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and
``(a)?`` means an optional *a*. Parentheses may be used to group elements. ``(a)?`` means an optional *a*. Parentheses may be used to group elements.
``&`` is the lookahead operator; ``&a`` means that an ``a`` is expected but
not consumed. It will be consumed in the following rule.
The ``|``, ``/`` symbols are used to mark alternatives and have the lowest The ``|``, ``/`` symbols are used to mark alternatives and have the lowest
precedence. ``/`` is the ordered choice that requires the parser to try the precedence. ``/`` is the ordered choice that requires the parser to try the
alternatives in the given order. ``/`` is often used to ensure the grammar alternatives in the given order. ``/`` is often used to ensure the grammar
@ -1726,6 +1729,17 @@ contain other statements. To avoid the `dangling else problem`:idx:, complex
statements always have to be intended. The details can be found in the grammar. statements always have to be intended. The details can be found in the grammar.
Statement list expression
-------------------------
Statements can also occur in an expression context that looks
like ``(stmt1; stmt2; ...; ex)``. This is called
an `statement list expression`:idx: or ``(;)``. The type
of ``(stmt1; stmt2; ...; ex)`` is the type of ``ex``. All the other statements
must be of type ``void``. (One can use ``discard`` to produce a ``void`` type.)
``(;)`` does not introduce a new scope.
Discard statement Discard statement
----------------- -----------------
@ -1892,6 +1906,20 @@ the ``:`` are executed. This goes on until the last ``elif``. If all
conditions fail, the ``else`` part is executed. If there is no ``else`` conditions fail, the ``else`` part is executed. If there is no ``else``
part, execution continues with the statement after the ``if`` statement. part, execution continues with the statement after the ``if`` statement.
The scoping for an ``if`` statement is slightly subtle to support an important
use case. A new scope starts for the ``if``/``elif`` condition and ends after
the corresponding *then* block:
.. code-block:: nimrod
if {| (let m = input =~ re"(\w+)=\w+"; m.isMatch):
echo "key ", m[0], " value ", m[1] |}
elif {| (let m = input =~ re""; m.isMatch):
echo "new m in this scope" |}
else:
# 'm' not declared here
In the example the scopes have been enclosed in ``{| |}``.
Case statement Case statement
-------------- --------------

View file

@ -515,6 +515,13 @@ contain indentation at certain places for better readability:
As a rule of thumb, indentation within expressions is allowed after operators, As a rule of thumb, indentation within expressions is allowed after operators,
an open parenthesis and after commas. an open parenthesis and after commas.
With parenthesis and semicolons ``(;)`` you can use statements where only
an expression is allowed:
.. code-block:: nimrod
# computes fac(4) at compile time:
const fac4 = (var x = 1; for i in 1..4: x *= i; x)
Procedures Procedures
========== ==========

View file

@ -7,8 +7,6 @@ version 0.9.2
- acyclic vs prunable; introduce GC hints - acyclic vs prunable; introduce GC hints
- CGEN: ``restrict`` pragma + backend support; computed goto support - CGEN: ``restrict`` pragma + backend support; computed goto support
- document NimMain and check whether it works for threading - document NimMain and check whether it works for threading
- parser/grammar:
* document (var x = 12; for i in ... ; x) construct
- make use of commonType relation in expressions - make use of commonType relation in expressions
- further expr/stmt unification: - further expr/stmt unification:
- rewrite nkCaseExpr handling - rewrite nkCaseExpr handling
@ -59,6 +57,7 @@ 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!