diff options
Diffstat (limited to 'tests/casestmt')
-rw-r--r-- | tests/casestmt/t18964.nim | 12 | ||||
-rw-r--r-- | tests/casestmt/t7699.nim | 15 | ||||
-rw-r--r-- | tests/casestmt/tcase_issues.nim | 7 | ||||
-rw-r--r-- | tests/casestmt/tcaseexpr1.nim | 39 | ||||
-rw-r--r-- | tests/casestmt/tcaseoverlaprange.nim | 15 | ||||
-rw-r--r-- | tests/casestmt/tcaseoverlaprange2.nim | 18 | ||||
-rw-r--r-- | tests/casestmt/tcasestmt.nim | 319 | ||||
-rw-r--r-- | tests/casestmt/tcomputedgoto.nim | 59 | ||||
-rw-r--r-- | tests/casestmt/tcstring.nim | 52 | ||||
-rw-r--r-- | tests/casestmt/tincompletecaseobject.nim | 115 | ||||
-rw-r--r-- | tests/casestmt/tincompletecaseobject2.nim | 26 | ||||
-rw-r--r-- | tests/casestmt/tlinearscanend.nim | 26 | ||||
-rw-r--r-- | tests/casestmt/trangeexhaustiveness.nim | 7 |
13 files changed, 710 insertions, 0 deletions
diff --git a/tests/casestmt/t18964.nim b/tests/casestmt/t18964.nim new file mode 100644 index 000000000..1d2de2bbc --- /dev/null +++ b/tests/casestmt/t18964.nim @@ -0,0 +1,12 @@ +discard """ +errormsg: "invalid order of case branches" +""" + +import macros + +macro genCase(val: string): untyped = + result = nnkCaseStmt.newTree(val, + nnkElse.newTree(quote do: echo "else"), + nnkOfBranch.newTree(newLit("miauz"), quote do: echo "first branch")) + +genCase("miauz") diff --git a/tests/casestmt/t7699.nim b/tests/casestmt/t7699.nim new file mode 100644 index 000000000..1354551c1 --- /dev/null +++ b/tests/casestmt/t7699.nim @@ -0,0 +1,15 @@ +discard """ + errormsg: "case statement cannot work on enums with holes for computed goto" + line: 13 +""" + +type + X = enum + A = 0, B = 100 + +var z = A +while true: + {.computedGoto.} + case z + of A: discard + of B: discard diff --git a/tests/casestmt/tcase_issues.nim b/tests/casestmt/tcase_issues.nim new file mode 100644 index 000000000..20a79df2c --- /dev/null +++ b/tests/casestmt/tcase_issues.nim @@ -0,0 +1,7 @@ +discard """ + targets: "c js" +""" + +block: # bug #24031 + case 0 + else: discard \ No newline at end of file diff --git a/tests/casestmt/tcaseexpr1.nim b/tests/casestmt/tcaseexpr1.nim new file mode 100644 index 000000000..4f5bbf100 --- /dev/null +++ b/tests/casestmt/tcaseexpr1.nim @@ -0,0 +1,39 @@ +discard """ + cmd: "nim check $options $file" + action: "reject" + nimout: ''' +tcaseexpr1.nim(33, 10) Error: not all cases are covered; missing: {C} +tcaseexpr1.nim(39, 12) Error: type mismatch: got <string> but expected 'int literal(10)' +''' +""" + + + + + + + + + + + +# line 20 +type + E = enum A, B, C + +proc foo(x: int): auto = + return case x + of 1..9: "digit" + else: "number" + +var r = foo(10) + +var x = C + +var t1 = case x: + of A: "a" + of B: "b" + +var t2 = case x: + of A: 10 + of B, C: "23" diff --git a/tests/casestmt/tcaseoverlaprange.nim b/tests/casestmt/tcaseoverlaprange.nim new file mode 100644 index 000000000..e9651c69f --- /dev/null +++ b/tests/casestmt/tcaseoverlaprange.nim @@ -0,0 +1,15 @@ +discard """ + errormsg: "duplicate case label" + line: 13 +""" + +type + TE = enum A, B, C, D + +var + e: TE + +case e +of A..D, B..C: + echo "redundant" +else: nil diff --git a/tests/casestmt/tcaseoverlaprange2.nim b/tests/casestmt/tcaseoverlaprange2.nim new file mode 100644 index 000000000..4a1cb3ea6 --- /dev/null +++ b/tests/casestmt/tcaseoverlaprange2.nim @@ -0,0 +1,18 @@ +discard """ + errormsg: "duplicate case label" + line: 13 +""" + + + + +proc checkDuplicates(myval: int32): bool = + case myval + of 0x7B: + echo "this should not compile" + of 0x78 .. 0x7D: + result = true + else: + nil + +echo checkDuplicates(0x7B) diff --git a/tests/casestmt/tcasestmt.nim b/tests/casestmt/tcasestmt.nim new file mode 100644 index 000000000..66de4183d --- /dev/null +++ b/tests/casestmt/tcasestmt.nim @@ -0,0 +1,319 @@ +discard """ +output: +''' +Not found! +Found! +1 +compiles for 1 +i am always two +default for 3 +set is 4 not 5 +array is 6 not 7 +default for 8 +an identifier +OK +OK +OK +ayyydd +''' +""" + + +block arrayconstr: + const md_extension = [".md", ".markdown"] + + proc test(ext: string) = + case ext + of ".txt", md_extension: + echo "Found!" + else: + echo "Not found!" + + test(".something") + # ensure it's not evaluated at compile-time: + var foo = ".markdown" + test(foo) + + +converter toInt(x: char): int = + x.int +block t8333: + case 0 + of 'a': echo 0 + else: echo 1 +block: # issue #11422 + var c: int = 5 + case c + of 'a' .. 'c': discard + else: discard + + +block emptyset_when: + proc whenCase(a: int) = + case a + of (when compiles(whenCase(1)): 1 else: {}): echo "compiles for 1" + of {}: echo "me not fail" + of 2: echo "i am always two" + of []: echo "me neither" + of {4,5}: echo "set is 4 not 5" + of [6,7]: echo "array is 6 not 7" + of (when compiles(neverCompilesIBet()): 3 else: {}): echo "compiles for 3" + #of {},[]: echo "me neither" + else: echo "default for ", a + + whenCase(1) + whenCase(2) + whenCase(3) + whenCase(4) + whenCase(6) + whenCase(8) + + +block setconstr: + 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") + + + +block tduplicates: + type Kind = enum A, B + var k = A + + template reject(b) = + static: doAssert(not compiles(b)) + + reject: + var i = 2 + case i + of [1, 1]: discard + else: discard + + reject: + var i = 2 + case i + of 1, { 1..2 }: discard + else: discard + + reject: + var i = 2 + case i + of { 1, 1 }: discard + of { 1, 1 }: discard + else: discard + + reject: + case k + of [A, A]: discard + + var i = 2 + case i + of { 1, 1 }: discard + of { 2, 2 }: echo "OK" + else: discard + + case i + of { 10..30, 15..25, 5..15, 25..35 }: discard + else: echo "OK" + + case k + of {A, A..A}: echo "OK" + of B: discard + + +block tcasestm: + type + Tenum = enum eA, eB, eC + + var + x: string = "yyy" + y: Tenum = eA + i: int + + case y + of eA: write(stdout, "a") + of eB, eC: write(stdout, "b or c") + + case x + of "Andreas", "Rumpf": write(stdout, "Hallo Meister!") + of "aa", "bb": write(stdout, "Du bist nicht mein Meister") + of "cc", "hash", "when": discard + of "will", "it", "finally", "be", "generated": discard + + var z = case i + of 1..5, 8, 9: "aa" + of 6, 7: "bb" + elif x == "Ha": + "cc" + elif x == "yyy": + write(stdout, x) + "dd" + else: + "zz" + + echo z + #OUT ayyy + + let str1 = "Y" + let str2 = "NN" + let a = case str1: + of "Y": true + of "N": false + else: + echo "no good" + quit("quitting") + + proc toBool(s: string): bool = + case s: + of "": raise newException(ValueError, "Invalid boolean") + elif s[0] == 'Y': true + elif s[0] == 'N': false + else: "error".quit(2) + + + let b = "NN".toBool() + + doAssert(a == true) + doAssert(b == false) + + static: + #bug #7407 + let bstatic = "N".toBool() + doAssert(bstatic == false) + + var bb: bool + doAssert(not compiles( + bb = case str2: + of "": raise newException(ValueError, "Invalid boolean") + elif str.startsWith("Y"): true + elif str.startsWith("N"): false + )) + + doAssert(not compiles( + bb = case str2: + of "Y": true + of "N": false + )) + + doAssert(not compiles( + bb = case str2: + of "Y": true + of "N": raise newException(ValueError, "N not allowed") + )) + + doAssert(not compiles( + bb = case str2: + of "Y": raise newException(ValueError, "Invalid Y") + else: raise newException(ValueError, "Invalid N") + )) + + + doAssert(not compiles( + bb = case str2: + of "Y": + raise newException(ValueError, "Invalid Y") + true + else: raise newException(ValueError, "Invalid") + )) + + + doAssert(not compiles( + bb = case str2: + of "Y": + "invalid Y".quit(3) + true + else: raise newException(ValueError, "Invalid") + )) + +#issue #11552 + +proc positiveOrNegative(num: int): string = + result = case num + of (low(int)+2) .. -1: + "negative" + of 0: + "zero" + else: + "impossible" + +#issue #11551 + +proc negativeOrNot(num: int): string = + result = case num + of low(int) .. -1: + "negative" + else: + "zero or positive" + +doAssert negativeOrNot(-1) == "negative" +doAssert negativeOrNot(10000000) == "zero or positive" +doAssert negativeOrNot(0) == "zero or positive" + +######################################################## +# issue #13490 +import strutils +func foo(input: string): int = + try: + parseInt(input) + except: + return + +func foo2(b, input: string): int = + case b: + of "Y": + for c in input: + result = if c in '0'..'9': parseInt($c) + else: break + of "N": + for c in input: + result = if c in '0'..'9': parseInt($c) + 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) + + +# bug #20031 +proc main(a: uint64) = + case a + else: + discard + +static: + main(10) +main(10) + +block: + # Just needs to compile + proc bar(): int {.discardable.} = discard + + proc foo() {.noreturn.} = discard + + case "*" + of "*": + bar() + else: + # Make sure this noreturn doesn't + # cause the discardable to not discard + foo() diff --git a/tests/casestmt/tcomputedgoto.nim b/tests/casestmt/tcomputedgoto.nim new file mode 100644 index 000000000..f7603dac3 --- /dev/null +++ b/tests/casestmt/tcomputedgoto.nim @@ -0,0 +1,59 @@ +discard """ + output: ''' +yeah A enumB +uneven +yeah A enumB +yeah CD enumD +uneven +yeah CD enumE +yeah A enumB +uneven +yeah CD enumE +yeah CD enumD +uneven +yeah A enumB +yeah B enumC +uneven +yeah A enumB +yeah A enumB +uneven +yeah A enumB +''' +""" + +type + MyEnum = enum + enumA, enumB, enumC, enumD, enumE, enumLast + +proc vm() = + var instructions: array[0..100, MyEnum] + instructions[2] = enumC + instructions[3] = enumD + instructions[4] = enumA + instructions[5] = enumD + instructions[6] = enumC + instructions[7] = enumA + instructions[8] = enumB + + instructions[12] = enumE + var pc = 0 + while true: + {.computedGoto.} + let instr = instructions[pc] + let ra = instr.succ # instr.regA + case instr + of enumA: + echo "yeah A ", ra + of enumC, enumD: + echo "yeah CD ", ra + of enumB: + echo "yeah B ", ra + of enumE: + break + of enumLast: discard + inc(pc) + + if pc mod 2 == 1: + echo "uneven" + +vm() diff --git a/tests/casestmt/tcstring.nim b/tests/casestmt/tcstring.nim new file mode 100644 index 000000000..288373402 --- /dev/null +++ b/tests/casestmt/tcstring.nim @@ -0,0 +1,52 @@ +discard """ + targets: "c cpp js" +""" + +type Result = enum none, a, b, c, d, e, f + +proc foo1(x: cstring): Result = + const y = cstring"hash" + const arr = [cstring"it", cstring"finally"] + result = none + case x + of "Andreas", "Rumpf": result = a + of cstring"aa", "bb": result = b + of "cc", y, "when": result = c + of "will", arr, "be", "generated": result = d + of nil: result = f + +var results = [ + foo1("Rumpf"), foo1("Andreas"), + foo1("aa"), foo1(cstring"bb"), + foo1("cc"), foo1("hash"), + foo1("finally"), foo1("generated"), + foo1("no"), foo1("another no"), + foo1(nil)] +doAssert results == [a, a, b, b, c, c, d, d, none, none, f], $results + +proc foo2(x: cstring): Result = + const y = cstring"hash" + const arr = [cstring"it", cstring"finally"] + doAssert not (compiles do: + result = case x + of "Andreas", "Rumpf": a + of cstring"aa", "bb": b + of "cc", y, "when": c + of "will", arr, "be", "generated": d) + case x + of "Andreas", "Rumpf": a + of cstring"aa", "bb": b + of "cc", y, "when": c + of "will", arr, "be", "generated": d + of nil: f + else: e + +results = [ + foo2("Rumpf"), foo2("Andreas"), + foo2("aa"), foo2(cstring"bb"), + foo2("cc"), foo2("hash"), + foo2("finally"), foo2("generated"), + foo2("no"), foo2("another no"), + foo2(nil)] + +doAssert results == [a, a, b, b, c, c, d, d, e, e, f], $results diff --git a/tests/casestmt/tincompletecaseobject.nim b/tests/casestmt/tincompletecaseobject.nim new file mode 100644 index 000000000..aa5deda7a --- /dev/null +++ b/tests/casestmt/tincompletecaseobject.nim @@ -0,0 +1,115 @@ +discard """ +errormsg: ''' +not all cases are covered; missing: {nnkComesFrom, nnkDotCall, nnkHiddenCallConv, nnkVarTuple, nnkCurlyExpr, nnkRange, nnkCheckedFieldExpr, nnkDerefExpr, nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkBind, nnkClosedSymChoice, nnkHiddenSubConv, nnkConv, nnkStaticExpr, nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange, nnkStringToCString, nnkCStringToString, nnkFastAsgn, nnkGenericParams, nnkFormalParams, nnkOfInherit, nnkImportAs, nnkConverterDef, nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch, nnkElifBranch, nnkExceptBranch, nnkElse, nnkAsmStmt, nnkTypeDef, nnkFinally, nnkContinueStmt, nnkImportStmt, nnkImportExceptStmt, nnkExportStmt, nnkExportExceptStmt, nnkFromStmt, nnkIncludeStmt, nnkUsingStmt, nnkBlockExpr, nnkStmtListType, nnkBlockType, nnkWith, nnkWithout, nnkTypeOfExpr, nnkObjectTy, nnkTupleTy, nnkTupleClassTy, nnkTypeClassTy, nnkStaticTy, nnkRecList, nnkRecCase, nnkRecWhen, nnkVarTy, nnkConstTy, nnkMutableTy, nnkDistinctTy, nnkProcTy, nnkIteratorTy, nnkSharedTy, nnkEnumTy, nnkEnumFieldDef, nnkArgList, nnkPattern, nnkReturnToken, nnkClosure, nnkGotoState, nnkState, nnkBreakState, nnkFuncDef, nnkTupleConstr} +''' +""" + +# this isn't imported from macros.nim to make it robust against possible changes in the ast. + +type + NimNodeKind* = enum + nnkNone, nnkEmpty, nnkIdent, nnkSym, + nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit, + nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkUIntLit, nnkUInt8Lit, + nnkUInt16Lit, nnkUInt32Lit, nnkUInt64Lit, nnkFloatLit, + nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit, + nnkTripleStrLit, nnkNilLit, nnkComesFrom, nnkDotCall, + nnkCommand, nnkCall, nnkCallStrLit, nnkInfix, + nnkPrefix, nnkPostfix, nnkHiddenCallConv, + nnkExprEqExpr, + nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, + nnkPar, nnkObjConstr, nnkCurly, nnkCurlyExpr, + nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange, + nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, + nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted, + nnkTableConstr, nnkBind, + nnkClosedSymChoice, + nnkOpenSymChoice, + nnkHiddenStdConv, + nnkHiddenSubConv, nnkConv, nnkCast, nnkStaticExpr, + nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, + nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange, + nnkStringToCString, nnkCStringToString, nnkAsgn, + nnkFastAsgn, nnkGenericParams, nnkFormalParams, nnkOfInherit, + nnkImportAs, nnkProcDef, nnkMethodDef, nnkConverterDef, + nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch, + nnkElifBranch, nnkExceptBranch, nnkElse, + nnkAsmStmt, nnkPragma, nnkPragmaBlock, nnkIfStmt, nnkWhenStmt, + nnkForStmt, nnkParForStmt, nnkWhileStmt, nnkCaseStmt, + nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection, + nnkConstDef, nnkTypeDef, + nnkYieldStmt, nnkDefer, nnkTryStmt, nnkFinally, nnkRaiseStmt, + nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt, + nnkDiscardStmt, nnkStmtList, + nnkImportStmt = 1337, # make a hole just for fun + nnkImportExceptStmt, + nnkExportStmt, + nnkExportExceptStmt, + nnkFromStmt, + nnkIncludeStmt, + nnkBindStmt, nnkMixinStmt, nnkUsingStmt, + nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, + nnkStmtListType, nnkBlockType, + nnkWith, nnkWithout, + nnkTypeOfExpr, nnkObjectTy, + nnkTupleTy, nnkTupleClassTy, nnkTypeClassTy, nnkStaticTy, + nnkRecList, nnkRecCase, nnkRecWhen, + nnkRefTy, nnkPtrTy, nnkVarTy, + nnkConstTy, nnkMutableTy, + nnkDistinctTy, + nnkProcTy, + nnkIteratorTy, # iterator type + nnkSharedTy, # 'shared T' + nnkEnumTy, + nnkEnumFieldDef, + nnkArgList, nnkPattern + nnkReturnToken, + nnkClosure, + nnkGotoState, + nnkState, + nnkBreakState, + nnkFuncDef, + nnkTupleConstr + +const + nnkLiterals* = {nnkCharLit..nnkNilLit} + + nnkSomething* = {nnkStmtList, nnkStmtListExpr, nnkDiscardStmt, nnkVarSection, nnkLetSection, + nnkConstSection, nnkPar, nnkAccQuoted, nnkAsgn, nnkDefer, nnkCurly, nnkBracket, + nnkStaticStmt, nnkTableConstr, nnkExprColonExpr, nnkInfix, nnkPrefix, + nnkRaiseStmt, nnkYieldStmt, nnkBracketExpr, nnkDotExpr, nnkCast, nnkBlockStmt, + nnkExprEqExpr} + +type + MyFictionalType = object + a: int + case n: NimNodeKind + of nnkLiterals, nnkCommentStmt, nnkNone, nnkEmpty, nnkIdent, nnkSym, + nnkType, nnkBindStmt, nnkMixinStmt, nnkTypeSection, nnkPragmaBlock, + nnkPragmaExpr, nnkPragma, nnkBreakStmt, nnkCallStrLit, nnkPostfix, + nnkOpenSymChoice: + b: int + of nnkCall, nnkCommand: + c: int + of nnkReturnStmt: + d: int + of nnkForStmt, nnkParForStmt, nnkWhileStmt, nnkProcDef, nnkMethodDef: + e: int + of nnkSomething, nnkRefTy, nnkPtrTy, nnkHiddenStdConv: + f: int + of nnkObjConstr: + g: int + of nnkIfStmt, nnkIfExpr, nnkWhenStmt: + # if when and case statements are branching statements. So a + # single function call is allowed to be in all of the braches and + # the entire expression can still be considered as a forwarding + # template. + h: int + of nnkCaseStmt: + i: int + of nnkTryStmt: + j: int + of nnkIdentDefs: + k: int + of nnkConstDef: + l: int diff --git a/tests/casestmt/tincompletecaseobject2.nim b/tests/casestmt/tincompletecaseobject2.nim new file mode 100644 index 000000000..bbeae1909 --- /dev/null +++ b/tests/casestmt/tincompletecaseobject2.nim @@ -0,0 +1,26 @@ +discard """ +cmd: "nim check $file" +""" +type + ABCD = enum A, B, C, D + AliasABCD = ABCD + RangeABC = range[A .. C] + AliasRangeABC = RangeABC + PrintableChars = range[' ' .. '~'] + +case PrintableChars 'x': #[tt.Error +^ not all cases are covered; missing: {' ', '!', '\"', '#', '$$', '%', '&', '\'', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'}]# +of '0'..'9', 'A'..'Z', 'a'..'z': discard +of '(', ')': discard + +case AliasABCD A: #[tt.Error +^ not all cases are covered; missing: {B, C, D}]# +of A: discard + +case RangeABC A: #[tt.Error +^ not all cases are covered; missing: {A, C}]# +of B: discard + +case AliasRangeABC A: #[tt.Error +^ not all cases are covered; missing: {A, B}]# +of C: discard diff --git a/tests/casestmt/tlinearscanend.nim b/tests/casestmt/tlinearscanend.nim new file mode 100644 index 000000000..96e3727d5 --- /dev/null +++ b/tests/casestmt/tlinearscanend.nim @@ -0,0 +1,26 @@ +discard """ +action: compile +""" + +import strutils + +var x = 343 + +case stdin.readline.parseInt +of 0: + echo "most common case" +of 1: + {.linearScanEnd.} + echo "second most common case" +of 2: echo "unlikely: use branch table" +else: + echo "unlikely too: use branch table" + + +case x +of 23: echo "23" +of 343: echo "343" +of 21: echo "21" +else: + {.linearScanEnd.} + echo "default" diff --git a/tests/casestmt/trangeexhaustiveness.nim b/tests/casestmt/trangeexhaustiveness.nim new file mode 100644 index 000000000..2b7f3558e --- /dev/null +++ b/tests/casestmt/trangeexhaustiveness.nim @@ -0,0 +1,7 @@ +block: # issue #22661 + template foo(a: typed) = + a + + foo: + case false + of false..true: discard |