case branches support constant sets for convenience
This commit is contained in:
parent
54021471e4
commit
8b6f9ef5e8
5 changed files with 92 additions and 17 deletions
|
|
@ -278,24 +278,62 @@ proc checkForOverlap(c: PContext, t, ex: PNode, branchIndex: int) =
|
||||||
proc semBranchExpr(c: PContext, t, e: PNode): PNode =
|
proc semBranchExpr(c: PContext, t, e: PNode): PNode =
|
||||||
result = semConstExpr(c, e)
|
result = semConstExpr(c, e)
|
||||||
checkMinSonsLen(t, 1)
|
checkMinSonsLen(t, 1)
|
||||||
if cmpTypes(t.sons[0].typ, result.typ) <= isConvertible:
|
result = fitNode(c, t.sons[0].typ, result)
|
||||||
typeMismatch(result, t.sons[0].typ, result.typ)
|
#if cmpTypes(t.sons[0].typ, result.typ) <= isConvertible:
|
||||||
|
# typeMismatch(result, t.sons[0].typ, result.typ)
|
||||||
|
|
||||||
proc SemCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
proc SemCaseBranchRange(c: PContext, t, b: PNode,
|
||||||
|
covered: var biggestInt): PNode =
|
||||||
|
checkSonsLen(b, 3)
|
||||||
|
result = newNodeI(nkRange, b.info)
|
||||||
|
result.add(semBranchExpr(c, t, b.sons[1]))
|
||||||
|
result.add(semBranchExpr(c, t, b.sons[2]))
|
||||||
|
if emptyRange(result[0], result[1]): GlobalError(b.info, errRangeIsEmpty)
|
||||||
|
covered = covered + getOrdValue(result[1]) - getOrdValue(result[0]) + 1
|
||||||
|
|
||||||
|
proc semCaseBranchSetElem(c: PContext, t, b: PNode,
|
||||||
|
covered: var biggestInt): PNode =
|
||||||
|
if isRange(b):
|
||||||
|
checkSonsLen(b, 3)
|
||||||
|
result = newNodeI(nkRange, b.info)
|
||||||
|
result.add(semBranchExpr(c, t, b.sons[1]))
|
||||||
|
result.add(semBranchExpr(c, t, b.sons[2]))
|
||||||
|
if emptyRange(result[0], result[1]): GlobalError(b.info, errRangeIsEmpty)
|
||||||
|
covered = covered + getOrdValue(result[1]) - getOrdValue(result[0]) + 1
|
||||||
|
elif b.kind == nkRange:
|
||||||
|
checkSonsLen(b, 2)
|
||||||
|
result = newNodeI(nkRange, b.info)
|
||||||
|
result.add(semBranchExpr(c, t, b.sons[0]))
|
||||||
|
result.add(semBranchExpr(c, t, b.sons[1]))
|
||||||
|
if emptyRange(result[0], result[1]): GlobalError(b.info, errRangeIsEmpty)
|
||||||
|
covered = covered + getOrdValue(result[1]) - getOrdValue(result[0]) + 1
|
||||||
|
else:
|
||||||
|
result = fitNode(c, t.sons[0].typ, b)
|
||||||
|
inc(covered)
|
||||||
|
|
||||||
|
proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||||
covered: var biggestInt) =
|
covered: var biggestInt) =
|
||||||
for i in countup(0, sonsLen(branch) - 2):
|
for i in countup(0, sonsLen(branch) - 2):
|
||||||
var b = branch.sons[i]
|
var b = branch.sons[i]
|
||||||
if isRange(b):
|
if isRange(b):
|
||||||
checkSonsLen(b, 3)
|
branch.sons[i] = semCaseBranchRange(c, t, b, covered)
|
||||||
var r = newNodeI(nkRange, b.info)
|
|
||||||
r.add(semBranchExpr(c, t, b.sons[1]))
|
|
||||||
r.add(semBranchExpr(c, t, b.sons[2]))
|
|
||||||
if emptyRange(r[0], r[1]): GlobalError(b.info, errRangeIsEmpty)
|
|
||||||
covered = covered + getOrdValue(r[1]) - getOrdValue(r[0]) + 1
|
|
||||||
branch.sons[i] = r
|
|
||||||
else:
|
else:
|
||||||
branch.sons[i] = semBranchExpr(c, t, b)
|
var r = semConstExpr(c, b)
|
||||||
inc(covered)
|
# for ``{}`` we want to trigger the type mismatch in ``fitNode``:
|
||||||
|
if r.kind != nkCurly or len(r) == 0:
|
||||||
|
checkMinSonsLen(t, 1)
|
||||||
|
branch.sons[i] = fitNode(c, t.sons[0].typ, r)
|
||||||
|
inc(covered)
|
||||||
|
else:
|
||||||
|
# constant sets have special rules
|
||||||
|
# first element is special and will overwrite: branch.sons[i]:
|
||||||
|
branch.sons[i] = semCaseBranchSetElem(c, t, r[0], covered)
|
||||||
|
# other elements have to be added to ``branch``
|
||||||
|
for j in 1 .. <r.len:
|
||||||
|
branch.add(semCaseBranchSetElem(c, t, r[j], covered))
|
||||||
|
# caution! last son of branch must be the actions to execute:
|
||||||
|
var L = branch.len
|
||||||
|
swap(branch.sons[L-2], branch.sons[L-1])
|
||||||
checkForOverlap(c, t, branch.sons[i], branchIndex)
|
checkForOverlap(c, t, branch.sons[i], branchIndex)
|
||||||
|
|
||||||
proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||||
|
|
|
||||||
|
|
@ -1527,6 +1527,27 @@ given, control passes after the ``case`` statement.
|
||||||
To suppress the static error in the ordinal case an ``else`` part with a ``nil``
|
To suppress the static error in the ordinal case an ``else`` part with a ``nil``
|
||||||
statement can be used.
|
statement can be used.
|
||||||
|
|
||||||
|
As a special semantic extension, an expression in an ``of`` branch of a case
|
||||||
|
statement may evaluate to a set constructor; the set is then expanded into
|
||||||
|
a list of its elements:
|
||||||
|
|
||||||
|
.. code-block:: nimrod
|
||||||
|
const
|
||||||
|
SymChars: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
|
||||||
|
|
||||||
|
proc classify(s: string) =
|
||||||
|
case s[0]
|
||||||
|
of SymChars, '_': echo "an identifier"
|
||||||
|
of '0'..'9': echo "a number"
|
||||||
|
else: echo "other"
|
||||||
|
|
||||||
|
# is equivalent to:
|
||||||
|
proc classify(s: string) =
|
||||||
|
case s[0]
|
||||||
|
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': echo "an identifier"
|
||||||
|
of '0'..'9': echo "a number"
|
||||||
|
else: echo "other"
|
||||||
|
|
||||||
|
|
||||||
When statement
|
When statement
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
|
||||||
15
tests/accept/run/tcase_setconstr.nim
Normal file
15
tests/accept/run/tcase_setconstr.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
discard """
|
||||||
|
output: "an identifier"
|
||||||
|
"""
|
||||||
|
|
||||||
|
const
|
||||||
|
SymChars: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
|
||||||
|
|
||||||
|
proc classify(s: string) =
|
||||||
|
case s[0]
|
||||||
|
of SymChars, '_': echo "an identifier"
|
||||||
|
of {'0'..'9'}: echo "a number"
|
||||||
|
else: echo "other"
|
||||||
|
|
||||||
|
classify("Hurra")
|
||||||
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -46,8 +46,7 @@ version 0.9.XX
|
||||||
- generalized case statement (requires better transf)
|
- generalized case statement (requires better transf)
|
||||||
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
- tlastmod returns wrong results on BSD (Linux, MacOS X: works)
|
||||||
- nested tuple unpacking
|
- nested tuple unpacking
|
||||||
- case statement branches should support constant sets
|
- 'nimrod def': does not always work?
|
||||||
- 'nimrod def': does not always work
|
|
||||||
- test branch coverage
|
- test branch coverage
|
||||||
- checked exceptions
|
- checked exceptions
|
||||||
- fix implicit generic routines
|
- fix implicit generic routines
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ Additions
|
||||||
- Added ``system.raiseHook``.
|
- Added ``system.raiseHook``.
|
||||||
- Added ``system.writeFile ``.
|
- Added ``system.writeFile ``.
|
||||||
- ``system.echo`` is guaranteed to be thread-safe.
|
- ``system.echo`` is guaranteed to be thread-safe.
|
||||||
|
- Case statement branches support constant sets for programming convenience.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2010-10-20 Version 0.8.10 released
|
2010-10-20 Version 0.8.10 released
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue