fixes #6609; 'if' expressions support multiple statements; minor breaking change

This commit is contained in:
Araq 2017-11-05 01:25:39 +01:00
commit 742f43e572
5 changed files with 91 additions and 17 deletions

View file

@ -41,3 +41,16 @@
what to return if the environment variable does not exist. what to return if the environment variable does not exist.
- Removed PDCurses wrapper from the stdlib and published it as a separate - Removed PDCurses wrapper from the stdlib and published it as a separate
Nimble package. Nimble package.
- The parsing rules of ``if`` expressions were changed so that multiple
statements are allowed in the branches. We found few code examples that
now fail because of this change, but here is one:
.. code-block:: nim
t[ti] = if exp_negative: '-' else: '+'; inc(ti)
This now needs to be written as:
.. code-block:: nim
t[ti] = (if exp_negative: '-' else: '+'); inc(ti)

View file

@ -785,21 +785,58 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
#| 'else' colcom expr #| 'else' colcom expr
#| ifExpr = 'if' condExpr #| ifExpr = 'if' condExpr
#| whenExpr = 'when' condExpr #| whenExpr = 'when' condExpr
result = newNodeP(kind, p) when true:
while true: result = newNodeP(kind, p)
getTok(p) # skip `if`, `elif` while true:
var branch = newNodeP(nkElifExpr, p) getTok(p) # skip `if`, `when`, `elif`
var branch = newNodeP(nkElifExpr, p)
optInd(p, branch)
addSon(branch, parseExpr(p))
colcom(p, branch)
addSon(branch, parseStmt(p))
skipComment(p, branch)
addSon(result, branch)
if p.tok.tokType != tkElif: break # or not sameOrNoInd(p): break
if p.tok.tokType == tkElse: # and sameOrNoInd(p):
var branch = newNodeP(nkElseExpr, p)
eat(p, tkElse)
colcom(p, branch)
addSon(branch, parseStmt(p))
addSon(result, branch)
else:
var
b: PNode
wasIndented = false
result = newNodeP(kind, p)
getTok(p)
let branch = newNodeP(nkElifExpr, p)
addSon(branch, parseExpr(p)) addSon(branch, parseExpr(p))
colcom(p, branch) colcom(p, branch)
let oldInd = p.currInd
if realInd(p):
p.currInd = p.tok.indent
wasIndented = true
echo result.info, " yes ", p.currInd
addSon(branch, parseExpr(p)) addSon(branch, parseExpr(p))
optInd(p, branch) result.add branch
addSon(result, branch) while sameInd(p) or not wasIndented:
if p.tok.tokType != tkElif: break case p.tok.tokType
var branch = newNodeP(nkElseExpr, p) of tkElif:
eat(p, tkElse) b = newNodeP(nkElifExpr, p)
colcom(p, branch) getTok(p)
addSon(branch, parseExpr(p)) optInd(p, b)
addSon(result, branch) addSon(b, parseExpr(p))
of tkElse:
b = newNodeP(nkElseExpr, p)
getTok(p)
else: break
colcom(p, b)
addSon(b, parseStmt(p))
addSon(result, b)
if b.kind == nkElseExpr: break
if wasIndented:
p.currInd = oldInd
proc parsePragma(p: var TParser): PNode = proc parsePragma(p: var TParser): PNode =
#| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}') #| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
@ -2036,8 +2073,13 @@ proc parseStmt(p: var TParser): PNode =
if a.kind != nkEmpty: if a.kind != nkEmpty:
addSon(result, a) addSon(result, a)
else: else:
parMessage(p, errExprExpected, p.tok) # This is done to make the new 'if' expressions work better.
getTok(p) # XXX Eventually we need to be more strict here.
if p.tok.tokType notin {tkElse, tkElif}:
parMessage(p, errExprExpected, p.tok)
getTok(p)
else:
break
if not p.hasProgress and p.tok.tokType == tkEof: break if not p.hasProgress and p.tok.tokType == tkEof: break
else: else:
# the case statement is only needed for better error messages: # the case statement is only needed for better error messages:

View file

@ -798,7 +798,8 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
if arg.valid: if arg.valid:
let htmlOut = if isObject: let htmlOut = if isObject:
"<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>" "<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>"
else: "<img src=\"$1\"$2 />" else:
"<img src=\"$1\"$2 />"
dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}", dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
[arg, options]) [arg, options])
if len(n) >= 3: renderRstToOut(d, n.sons[2], result) if len(n) >= 3: renderRstToOut(d, n.sons[2], result)

View file

@ -509,7 +509,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
# insert exponent # insert exponent
t[ti] = 'E'; inc(ti) t[ti] = 'E'; inc(ti)
t[ti] = if exp_negative: '-' else: '+'; inc(ti) t[ti] = (if exp_negative: '-' else: '+'); inc(ti)
inc(ti, 3) inc(ti, 3)
# insert adjusted exponent # insert adjusted exponent

View file

@ -32,3 +32,21 @@ let other = x:
echo "no" echo "no"
let outer = y(5): let outer = y(5):
echo "yes" echo "yes"
# bug #6609
type
TextureInternalFormat = enum RED, RGB, RGBA
const channels = 4
let format =
if channels == 1:
TextureInternalFormat.RED
elif channels == 3:
TextureInternalFormat.RGB
elif channels == 4:
TextureInternalFormat.RGBA
else:
echo "Texture Format Unknown, assuming RGB" #This echo causes an error
TextureInternalFormat.RGB