diff --git a/compiler/ast/report_enums.nim b/compiler/ast/report_enums.nim index 9131448c9c3..654778f8b70 100644 --- a/compiler/ast/report_enums.nim +++ b/compiler/ast/report_enums.nim @@ -355,6 +355,7 @@ type rsemTIsNotAConcreteType rsemProcIsNotAConcreteType rsemRangeIsEmpty + rsemStringRangeNotAllowed rsemCannotInstantiate rsemCannotInstantiateWithParameter diff --git a/compiler/front/cli_reporter.nim b/compiler/front/cli_reporter.nim index 8a02802a39c..0959948dbcc 100644 --- a/compiler/front/cli_reporter.nim +++ b/compiler/front/cli_reporter.nim @@ -1136,6 +1136,9 @@ proc reportBody*(conf: ConfigRef, r: SemReport): string = of rsemRangeIsEmpty: result = "range is empty" + of rsemStringRangeNotAllowed: + result = "cannot create a range of strings" + of rsemExpectedOrdinalOrFloat: result = "ordinal or float type expected" diff --git a/compiler/sem/semtypes.nim b/compiler/sem/semtypes.nim index 383093882b0..337f99e362a 100644 --- a/compiler/sem/semtypes.nim +++ b/compiler/sem/semtypes.nim @@ -765,6 +765,9 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var Int128): PNode = result.add(bt) if emptyRange(ac, bc): localReport(c.config, b, reportSem rsemRangeIsEmpty) + elif t[0].typ.skipTypes(abstractInst).kind == tyString: + # XXX: ``nkError`` needs to be used here + localReport(c.config, b, reportSem rsemStringRangeNotAllowed) else: covered = covered + getOrdValue(bc) + 1 - getOrdValue(ac) proc semCaseBranchRange(c: PContext, t, b: PNode, diff --git a/tests/errmsgs/tstring_range.nim b/tests/errmsgs/tstring_range.nim new file mode 100644 index 00000000000..454b677b10d --- /dev/null +++ b/tests/errmsgs/tstring_range.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "cannot create a range of strings" + line: 8 +""" + +var x = "a" +case x +of "a".."def": + discard diff --git a/tests/lang_stmts/casestmt/tcasestmt.nim b/tests/lang_stmts/casestmt/tcasestmt.nim index 53cccdb6418..8725661f6c3 100644 --- a/tests/lang_stmts/casestmt/tcasestmt.nim +++ b/tests/lang_stmts/casestmt/tcasestmt.nim @@ -1,4 +1,8 @@ discard """ +targets: "c js vm" +knownIssue.js: ''' + The code generator rejects 'of' branch ranges > 2^16 +''' output: ''' Not found! @@ -14,7 +18,9 @@ an identifier OK OK OK -ayyydd +a +yyy +dd ''' """ @@ -133,12 +139,12 @@ block tcasestm: i: int case y - of eA: write(stdout, "a") - of eB, eC: write(stdout, "b or c") + of eA: echo "a" + of eB, eC: echo "b or c" case x - of "Andreas", "Rumpf": write(stdout, "Hallo Meister!") - of "aa", "bb": write(stdout, "Du bist nicht mein Meister") + of "Andreas", "Rumpf": echo "Hallo Meister!" + of "aa", "bb": echo "Du bist nicht mein Meister" of "cc", "hash", "when": discard of "will", "it", "finally", "be", "generated": discard @@ -148,7 +154,7 @@ block tcasestm: elif x == "Ha": "cc" elif x == "yyy": - write(stdout, x) + echo x "dd" else: "zz" @@ -178,8 +184,8 @@ block tcasestm: doAssert(a == true) doAssert(b == false) - static: - #bug #7407 + block: + # bug https://github.com/nim-lang/nim/issues/7407 let bstatic = "N".toBool() doAssert(bstatic == false) @@ -272,18 +278,34 @@ func foo2(b, input: string): int = else: continue else: return - -static: - doAssert(foo("3") == 3) - doAssert(foo("a") == 0) - doAssert(foo2("Y", "a2") == 0) - doAssert(foo2("Y", "2a") == 2) - doAssert(foo2("N", "a3") == 3) - doAssert(foo2("z", "2") == 0) - doAssert(foo("3") == 3) doAssert(foo("a") == 0) doAssert(foo2("Y", "a2") == 0) doAssert(foo2("Y", "2a") == 2) doAssert(foo2("N", "a3") == 3) doAssert(foo2("z", "2") == 0) + +block float_slice_list: + ## Tests for slice lists of float values + proc p(f: float): int = + case f + of 5.0, -2.0 .. 1.2, 6.0: 0 # slice-list with gaps + of 1.5: 1 + of 20.0 .. 32.0: 2 + else: 3 + + # direct matches + doAssert p(5.0) == 0 + doAssert p(-2.0) == 0 + doAssert p(1.2) == 0 + doAssert p(6.0) == 0 + doAssert p(1.5) == 1 + doAssert p(20.0) == 2 + doAssert p(32.0) == 2 + + # in ranges + doAssert p(0.1) == 0 + doAssert p(-1.0) == 0 + doAssert p(1.1) == 0 + doAssert p(1.6) == 3 + doAssert p(25.0) == 2 \ No newline at end of file diff --git a/tests/vm/tcasestmt.nim b/tests/vm/tcasestmt.nim deleted file mode 100644 index 2a2c55a58ee..00000000000 --- a/tests/vm/tcasestmt.nim +++ /dev/null @@ -1,51 +0,0 @@ -discard """ - description: "Tests for case statement with selector of non-ordinal type" - action: compile -""" - -## XXX: merge into `casestmt/tcasestmt.nim` once testament has a VM target - -# case stmt with string slice-lists -static: - proc p(str: string): int = - case str - of "a": 1 - of "b".."e", "l".."o", "p": 2 # slice-list with gap - of "f".."k": 3 - of "q".."z": 4 - #of "9".."1": 5 # empty range; rejected by sem - else: 6 - - doAssert p("a") == 1 - doAssert p("d") == 2 - doAssert p("h") == 3 - doAssert p("p") == 2 - doAssert p("z") == 4 - doAssert p("z1") == 6 - doAssert p("2") == 6 - doAssert p("other") == 6 - -# case stmt with float slice-lists -static: - proc p(f: float): int = - case f - of 5.0, -2.0 .. 1.2, 6.0: 0 # slice-list with gaps - of 1.5: 1 - of 20.0 .. 32.0: 2 - else: 3 - - # direct matches - doAssert p(5.0) == 0 - doAssert p(-2.0) == 0 - doAssert p(1.2) == 0 - doAssert p(6.0) == 0 - doAssert p(1.5) == 1 - doAssert p(20.0) == 2 - doAssert p(32.0) == 2 - - # in ranges - doAssert p(0.1) == 0 - doAssert p(-1.0) == 0 - doAssert p(1.1) == 0 - doAssert p(1.6) == 3 - doAssert p(25.0) == 2 \ No newline at end of file