mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-21 06:45:27 +00:00
folding const expressions with branching logic (#24689)
motivating example:
```nim
iterator p(a: openArray[char]): int =
if a.len != 0:
if a[0] != '/':
discard
for t in p(""): discard
```
The compiler wants to evaluate `a[0]` at compile time even though it is
protected by the if statement above it. Similarly expressions like
`a.len != 0 and a[0] == '/'` have problems. It seems like the logic in
semfold needs to be more aware of branches to positively identify when
it is okay to fail compilation in these scenarios. It's a bit tough
though because it may be the case that non-constant expressions in
branching logic can properly protect some constant expressions.
This commit is contained in:
@@ -471,19 +471,20 @@ proc foldArrayAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNo
|
||||
if result.kind == nkExprColonExpr: result = result[1]
|
||||
else:
|
||||
result = nil
|
||||
localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
||||
#localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
||||
of nkBracket:
|
||||
idx -= toInt64(firstOrd(g.config, x.typ))
|
||||
if idx >= 0 and idx < x.len: result = x[int(idx)]
|
||||
else:
|
||||
result = nil
|
||||
localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
||||
#localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
result = newNodeIT(nkCharLit, x.info, n.typ)
|
||||
if idx >= 0 and idx < x.strVal.len:
|
||||
result.intVal = ord(x.strVal[int(idx)])
|
||||
else:
|
||||
localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n)
|
||||
result = nil
|
||||
#localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n)
|
||||
else: result = nil
|
||||
|
||||
proc foldFieldAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||
|
||||
@@ -114,3 +114,10 @@ block named: # works
|
||||
if true:
|
||||
break named
|
||||
doAssert false, "not reached"
|
||||
|
||||
block:
|
||||
iterator p(a: openArray[char]): int =
|
||||
if a.len != 0:
|
||||
if a[0] != '/':
|
||||
discard
|
||||
for t in p(""): discard
|
||||
|
||||
Reference in New Issue
Block a user