# # Test of expression checker (negative tests). # See also testexec/mainapp/expressions.slul for positive tests. # # Copyright © 2022-2024 Samuel Lidén Borell # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # data bool exprchk_bool = true # ERROR .31: error: Left side of . is not of struct type data bool exprchk_badstruct = exprchk_bool.field # ERROR .10: error: Missing operand data [not]byte exprchk_badlengthexpr = [1,2,3] # ERROR .7: error: Incomplete expression data [if]byte exprchk_badlengthexpr = [1,2,3] type ExprChkTypeA = int type ExprChkTypeB = int data ExprChkTypeB exprchk_cyclic1 = exprchk_cyclic2 # ERROR .19: error: Cyclic reference in declaration data ExprChkTypeB exprchk_cyclic2 = exprchk_cyclic1 data ExprChkTypeB exprchk_deep_cyclic1 = exprchk_deep_cyclic2 data ExprChkTypeB exprchk_deep_cyclic9 = exprchk_deep_cyclic1 data ExprChkTypeB exprchk_deep_cyclic3 = exprchk_deep_cyclic4 data ExprChkTypeB exprchk_deep_cyclic4 = exprchk_deep_cyclic5 data ExprChkTypeB exprchk_deep_cyclic5 = exprchk_deep_cyclic6 data ExprChkTypeB exprchk_deep_cyclic6 = exprchk_deep_cyclic7 data ExprChkTypeB exprchk_deep_cyclic7 = exprchk_deep_cyclic8 # ERROR .19: error: Cyclic reference in declaration data ExprChkTypeB exprchk_deep_cyclic8 = exprchk_deep_cyclic9 data ExprChkTypeB exprchk_deep_cyclic2 = exprchk_deep_cyclic3 func exprchk_badtype_eval() -> int { # ERROR .5: error: Type 'ExprChkNonExistent01' does not exist ExprChkNonExistent01 j = 234 return j } func exprchk_return_test() { # FIXME It would be nicer it the errors were reported at the = sign # ERROR .21: error: Incompatible types bool b1 = f_void() # ERROR .18: error: Incompatible types if f_int_void(123) { } # ERROR .20: error: Incompatible types int i1 = f_bool() } func exprchk_param_test() { int i = 123 # ERROR .5: error: Too many arguments to function f_void(123) # ERROR .8: error: Too few arguments to function if f_int_bool() { } # ERROR .17: error: Incompatible types f_bool_void(i) # ERROR +2.5: error: Too few arguments to function # ERROR .20: error: Missing operand f_intbool_void(, 123) # TODO the "incompatible types" error should be suppressed if possible # ERROR +3.5: error: Too few arguments to function # ERROR +2.20: error: Missing operand # ERROR .22: error: Incompatible types f_intbool_void(, false) # ERROR +2.5: error: Too few arguments to function # ERROR .20: error: Missing operand f_intbool_void(,) # ERROR +2.5: error: Too few arguments to function # ERROR .24: error: Trailing comma not allowed in parameter list f_intbool_void(123,) # ERROR .24: error: Missing operand f_intbool_void(123,,false) # ERROR +2.20: error: Incompatible types # ERROR .26: error: Missing operand f_intbool_void(false,,false) # ERROR +3.5: error: Too few arguments to function # ERROR +2.24: error: Missing operand # ERROR .25: error: Trailing comma not allowed in parameter list f_intbool_void(123,,) } func exprchk_not_callable() { { # ERROR .9: error: Left expression is not callable (missing operator?) 1() } { # ERROR .9: error: Left expression is not callable (missing operator?) 1(true) } { # ERROR .9: error: Left expression is not callable (missing operator?) true() } { # ERROR .9: error: Left expression is not callable (missing operator?) true(true) } { # ERROR .9: error: Left expression is not callable (missing operator?) ""() } { # ERROR .9: error: Left expression is not callable (missing operator?) ""(true) } { # ERROR .9: error: Left expression is not callable (missing operator?) "x" "y"(true) } { # ERROR .10: error: Left expression is not callable (missing operator?) ([])() } { # ERROR .10: error: Left expression is not callable (missing operator?) ([123,456])() } } func exprchk_misc_test() -> bool { # ERROR .22: error: Incompatible types f_intbool_bool = 1 { # TODO reduce number of errors # ERROR +4.32: warning: Unreachable statement # ERROR +3.31: error: Unbalanced parenthesis (not closed) # ERROR +2.32: error: Error in statement (end of statement detected, but line continues) # ERROR .32: error: Syntax error, or missing line break, before this symbol return f_intbool_bool(}, 123) { # ERROR .31: error: Unexpected symbol in expression return f_intbool_bool(else, 123) } # ERROR +4.5: warning: Unreachable statement # ERROR +3.11: error: Identifier 'x' does not exist # ERROR +2.16: error: Identifier 'a' does not exist # ERROR .17: error: Expected { before statement block while x != a } func exprchk_bad_line_start() { # ERROR .5: error: Invalid start of line in function ] # ERROR .5: error: Invalid start of line in function , } func exprchk_none_test() { # ERROR .14: error: Target type is not an type that can take a "none" value byte b = none # ERROR .16: error: Target type is not an type that can take a "none" value string s = none # ERROR .24: error: Target type is not an type that can take a "none" value ref StructType r = none # These are OK ?ref StructType ro = none ?string so = none # "none" does not have a known type by itself. # It needs a target type to derive the type from. # ERROR .16: error: Type of expression is not clear bool b1 = (none == none) } func exprchk_arrayindex_test() { [4]int intarr = [11,22,33,44] [2,3]int nestedarr = [[1,2,3],[6,7,8]] [3,1,2]int deeparr = [ [[111,112]], [[211,212]], [[311,312]], ] # ERROR .14: error: Incompatible types bool b = intarr[0] # ERROR .14: error: Incompatible types int i1 = nestedarr[0] # ERROR .14: error: Incompatible types int i2 = deeparr[0,0] # ERROR .15: error: Incompatible types bool b2 = deeparr[0,0,0] # These are OK int ok1 = intarr[0] int ok2 = nestedarr[1,2] int ok3 = nestedarr[1][2] int ok4 = deeparr[2,0,1] [1,2]int ok5 = deeparr[2] [2]int ok6 = deeparr[2,0] int64 ok7 = intarr[0] int64 ok8 = deeparr[2,0,1] # ERROR .29: error: Trailing comma not allowed in array index int badcomma = intarr[0,] } func exprchk_array_nonconst_length() { # ERROR .14: <-- definition: i var uint i = 3 # ERROR .10: error: Identifier value is not known at compile-time var [i]int arr1 # ERROR .10: <-- definition: j uint j # ERROR +2.10: error: Identifier value is not known at compile-time # ERROR .10: error: Variable is (or might be) unassigned at this point var [j]int arr2 # FIXME this should only be allowed if the array is behind a reference #int k = i #var [k]int arr3 # These are OK uint c = 3 var [c]int arr_ok1 int x = [1,2,3][1] int y = [[11,22,33],[44,55,66]][1,2] } func exprchk_array_literal() { # ERROR .13: error: Target type is not an array int i = [1,2,3] # ERROR +3.18: error: Target type is not an array # ERROR +2.26: error: Target type is not an array # ERROR .34: error: Target type is not an array [3]int a1 = [[1,2,3],[4,5,6],[7,8,9]] # Wrong lengths # ERROR .17: error: Incompatible types. Array lengths differ [2]int a2 = [11,22,33] # ERROR .17: error: Incompatible types. Array lengths differ [3]int a3 = [11,22] # TODO array types with "== constrained" length should be allowed also # TODO others should not be allowed # Wrong element types # ERROR +2.19: error: Incompatible types # ERROR .21: error: Incompatible types [2]bool e1 = [1,2] # ERROR +2.18: error: Incompatible types # ERROR .23: error: Incompatible types [2]int e2 = [true,false] # ERROR +2.20: error: Incompatible types. Array lengths differ # ERROR .28: error: Incompatible types. Array lengths differ [2,3]int e3 = [[11,22],[44,55]] # This is OK [2,3]int ok_e1 = [[11,22,33],[44,55,66]] } func exprchk_field_test() { var StructType s1 = (.x=123, .b=false) # ERROR .8: error: Field "nonexistingfield" does not exist s1.nonexistingfield[1,0,2] += 1 } func exprchk_typescope_check() -> int { # ERROR .14: error: Target type has no .typescope int i = .make() return 123 } func exprchk_typeident_bad() { # ERROR .25: error: Space after "." in .typeident ExprChkEnum1 e1 = . a } func exprchk_typeident_ambiguouos() { # ERROR .28: error: Type identifier 'ambiguous_constructor' in 'ClosedTypeInLib' is defined in more than one module ClosedTypeInLib obj = .ambiguous_constructor() # ERROR .9: error: Type identifier 'ambiguous_method' in 'ClosedTypeInLib' is defined in more than one module obj.ambiguous_method() } func exprchk_struct_init_bad() { # ERROR .23: error: ".x" does not exist in the target type StructType s1 = (.x) # ERROR .25: error: Missing operand StructType s2 = (.x=) # ERROR .21: error: Too few values in struct initializer StructType s3 = (.x=1) # ERROR .38: error: Too many values in struct initializer StructType s4 = (.x=1, .b=true, .b=true) # ERROR .23: error: Struct fields come in the wrong order StructType s5 = (.b=true, .x=1) # ERROR .23: error: Field "a" does not exist StructType s6 = (.a=1) # ERROR .29: error: Field "c" does not exist StructType s7 = (.x=1, .c=false) # ERROR .29: error: Field "s1" does not exist StructType s8 = (.x=1, .s1=true) # ERROR .22: error: Identifier 'b' does not exist StructType s9 = (b=1) var bool b # ERROR .30: error: Expected a ".field=initial_value" expression StructType s10 = (.x=1, b=true) # TODO the code below should give a better error message #StructType s11 = (b=true) # ERROR .44: error: Trailing comma is not needed in struct value TinyStructType t1 = (.a_byte_value=123,) # ERROR .13: error: .typeident= makes no sense here assert .x = 123 } func exprchk_struct_init_truncated1() { # ERROR .22: error: Unbalanced parenthesis (not closed) StructType s1 = ( } func exprchk_struct_init_truncated2() { # ERROR .23: error: Dot which is not followed by identifier StructType s1 = (. } func exprchk_struct_init_truncated3() { # ERROR .24: error: Unbalanced parenthesis (not closed) StructType s1 = (.x } func exprchk_struct_init_truncated4() { # ERROR .23: error: Unbalanced parenthesis (not closed) StructType s1 = (x } func exprchk_struct_init_truncated5() { # ERROR .25: error: Unbalanced parenthesis (not closed) StructType s1 = (.x= } func exprchk_struct_init_truncated6() { # ERROR .26: error: Unbalanced parenthesis (not closed) StructType s1 = (.x=1 } func exprchk_struct_init_truncated7() { # ERROR .27: error: Unbalanced parenthesis (not closed) StructType s1 = (.x=1, } # from "var1 = 0": # ERROR +5.21: <-- target type: ExprChkEnum1 # from "var1 = true" # ERROR +3.21: <-- target type: ExprChkEnum1 # from "var1 = .z" # ERROR .21: <-- definition: ExprChkEnum1 type ExprChkEnum1 = enum { a b c } # from "ExprChkEnum2 local2b = 1" # ERROR .21: <-- target type: ExprChkEnum2 type ExprChkEnum2 = enum { a b c } # from "ExprChkEnum3 local3 = .a" # ERROR .21: <-- definition: ExprChkEnum3 type ExprChkEnum3 = enum { x y } func exprchk_mismatching_enums(ExprChkEnum1 prm1, ExprChkEnum2 prm2) -> ExprChkEnum1 { # OK ExprChkEnum1 local1_ok = .a ExprChkEnum2 local2_ok = .b # ERROR .27: error: Mismatch of named types ExprChkEnum1 local1 = prm2 # ERROR .27: error: Mismatch of named types ExprChkEnum2 local2 = local1_ok # ERROR .28: error: Incompatible types ExprChkEnum2 local2b = 1 # ERROR .29: error: Mismatch of named types var ExprChkEnum1 var1 = prm2 # ERROR .22: error: Target type has no .typescope bool boolvar1 = .a # ERROR .28: error: ".a" does not exist in the target type ExprChkEnum3 local3 = .a # ERROR .12: error: Mismatch of named types var1 = prm2 # ERROR .12: error: Incompatible types var1 = 0 # ERROR .12: error: Incompatible types var1 = true # OK var1 = .a # ERROR .13: error: ".z" does not exist in the target type var1 = .z # ERROR .26: error: Mismatch of named types if prm1 == .b return prm2 # ERROR .12: error: Mismatch of named types return local2_ok } func exprchk_not_numeric() { # ERROR .16: error: Numeric target type is required bool b1 = 1-1 # ERROR .15: error: Numeric target type is required bool b2 = -1 # ERROR .15: error: Incompatible types bool b3 = 1 # ERROR .16: error: Numeric target type is required bool b4 = 1*0 # ERROR .16: error: Numeric target type is required bool b5 = 1/1 # ERROR .9: error: Numeric target type is required if 1+1 { } # ERROR .15: error: Incompatible types int i = 1+b1 # ERROR .15: error: Incompatible types (not b1 = 123) } func exprchk_unclear_exprs() { # TODO get rid of the first error # ERROR +2.17: error: Unknown target type. Numeric target type is required # ERROR .17: error: Type of expression is not clear bool b6 = (1+2) == 4 # ERROR +2.16: error: Unknown target type. Numeric target type is required # ERROR .16: error: Type of expression is not clear bool b7 = i+1 == 4 } func exprchk_nonexisting_var() -> int { # ERROR .5: error: Identifier 'nonexisting1' does not exist nonexisting1 = 123 # ERROR .5: error: Identifier 'nonex2' does not exist nonex2 = 1+2 # ERROR .8: error: Identifier 'nonex3' does not exist if nonex3 { # ERROR +2.9: error: Identifier 'nonex4' does not exist # ERROR .16: error: Identifier 'nonex5' does not exist nonex4(nonex5) # ERROR .17: error: Identifier 'nonex6' does not exist int i = nonex6 # ERROR .16: error: Identifier 'nonex7' does not exist return nonex7 } # ERROR +3.5: error: Identifier 'nonex8' does not exist # ERROR +2.12: error: Identifier 'nonex9' does not exist # ERROR .22: error: Identifier 'nonex10' does not exist nonex8[nonex9] = nonex10 # ERROR +2.5: error: Identifier 'nonex11' does not exist # ERROR .38: error: Identifier 'nonex12' does not exist nonex11.do_stuff(.field, .constr(nonex12)[.field()]) # ERROR +2.5: error: Identifier 'nonex13' does not exist # ERROR .19: error: Identifier 'nonex14' does not exist nonex13.field[nonex14.other.field] = 1 # ERROR .18: error: Identifier 'nonex_last' does not exist return 123 + nonex_last } func exprchk_nonexisting_type() { var string e1 = "abc" var int e2 = 123 var bool e3 = true # ERROR .9: error: Type 'ExprChkNonExisting1' does not exist var ExprChkNonExisting1 n1 = "test" # ERROR .9: error: Type 'ExprChkNonExisting2' does not exist var ExprChkNonExisting2 n2 = "test" # ERROR .9: error: Type 'ExprChkNonExisting3' does not exist var ExprChkNonExisting3 n3 = "test" e1 = n1 e2 = n2 e2 = 1 + n2 e3 = n3 e3 = not n3 if n3 { } if (not n3) or e2 == 0 { } n1 = e1 n2 = e2 n3 = e3 n1.somefield = e1 n2[0].somefield = e2 n2[0].somefield = n3.arr[1].nested[2] n2[0].somefield.inner[0].stuff[1] = n3.arr[1] } func exprchk_confusing_booleans() { bool a = true bool b = false bool c = false # ERROR .23: error: Ambiguous mix of different operators. Use parentheses bool l1 = a and b or c # ERROR .22: error: Ambiguous mix of different operators. Use parentheses bool l2 = a or b and c # ERROR .21: error: Ambiguous mix of different operators. Use parentheses bool l3 = not a and b # ERROR .21: error: Ambiguous mix of different operators. Use parentheses bool l4 = not a or c # ERROR .27: error: Ambiguous mix of different operators. Use parentheses bool l5 = a and not b and c # ERROR .22: error: Ambiguous mix of different operators. Use parentheses bool e1 = a == b == c # ERROR .22: error: Ambiguous mix of different operators. Use parentheses bool e2 = a != b != c # ERROR .22: error: Ambiguous mix of different operators. Use parentheses bool e3 = a != b == c # ERROR .21: error: Ambiguous mix of different operators. Use parentheses bool e4 = 2 < 3 == c # TODO forbid this: var bool vb if vb=true {} } func exprchk_bad_funcref() { var funcref() fr1 = exprchk_bad_funcref var ?funcref() opt_fr1 = exprchk_bad_funcref var funcref() fr2 = fr1 var int i = 123 # ERROR .11: error: Reference not expected fr1 = refto i # ERROR .11: error: Reference not expected fr1 = refto fr2 # FIXME fix typo (an -> a) # ERROR .11: error: Target type is not an type that can take a "none" value fr1 = none opt_fr1 = none # FIXME should give errors # XXX is there a better name for the ref_is/ref_is_not operators? # - same / not_same ? # - is_same / is_not_same ? # - same_as / not_same_as # - is / isnt (or "is_not" or "is not") #bool b = fr1 ref_is fr2 #if fr1 ref_is fr2 { } #if opt_fr1 ref_is opt_fr1 { } } func exprchk_bad_rparen() { # FIXME fix these error messages # ERROR +2.16: error: Incomplete expression # ERROR .16: error: Syntax error, or missing line break, before this symbol int i = (1)) } # from "StructType a = (.x)" # ERROR .19: <-- definition: StructType type StructType = struct { int x bool b } type TinyStructType = struct { byte a_byte_value }