" Test MNV9 generic function import './util/mnv9.mnv' as v9 " Test for definint a generic function def Test_generic_func_definition() var lines =<< trim END mnv9script def Fn(x: A, y: B): A return x enddef defcompile END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1552: Type variable name must start with an uppercase letter: t>()', 2) lines =<< trim END mnv9script def Fn<>() enddef defcompile END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 2) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1008: Missing after >()', 2) lines =<< trim END mnv9script def Fn<,>() enddef defcompile END v9.CheckSourceFailure(lines, 'E1008: Missing after <,>(', 2) lines =<< trim END mnv9script def Fn after ()', 2) # Use a multi-character generic type name lines =<< trim END mnv9script def Fn(a: MyType1, b: My_Type2): My_Type2 var x: MyType1 var y: My_Type2 return b enddef assert_equal([1, 2], Fn>('a', [1, 2])) END v9.CheckSourceSuccess(lines) # Use a generic type name starting with a lower case letter lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1552: Type variable name must start with an uppercase letter: mytype>()', 2) # Use a non-alphanumeric character in the generic type name lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1553: Missing comma after type in generic function: My-type>()', 2) # Use an existing type name as the generic type name lines =<< trim END mnv9script type FooBar = number def Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "FooBar"', 3) # Use a very long type name lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceSuccess(lines) # Use a function name as the generic type name lines =<< trim END mnv9script def MyFunc() enddef def Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "MyFunc"', 4) enddef " Test for white space error when defining a generic function def Test_generic_func_definition_whitespace_error() var lines =<< trim END mnv9script def Fn () enddef defcompile END v9.CheckSourceFailure(lines, "E1068: No white space allowed before '<': ()", 2) lines =<< trim END mnv9script def Fn () enddef defcompile END v9.CheckSourceFailure(lines, "E1068: No white space allowed before '(': (", 2) lines =<< trim END mnv9script def Fn< A>() enddef defcompile END v9.CheckSourceFailure(lines, "E1202: No white space allowed after '<': < A>()", 2) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1202: No white space allowed after 'A': A >()", 2) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1069: White space required after ',': ,>()", 2) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1008: Missing after >()", 2) lines =<< trim END mnv9script def Fn<, A>() enddef defcompile END v9.CheckSourceFailure(lines, "E1008: Missing after <, A>()", 2) lines =<< trim END mnv9script def Fn<,A>() enddef defcompile END v9.CheckSourceFailure(lines, "E1008: Missing after <,A>()", 2) lines =<< trim END mnv9script def Fn< , A>() enddef defcompile END v9.CheckSourceFailure(lines, "E1202: No white space allowed after '<': < , A>()", 2) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1069: White space required after ',': ,B>(", 2) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1202: No white space allowed after 'A': A , B>()", 2) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1202: No white space allowed after 'B': B >()", 2) lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1202: No white space allowed after 'MyType': MyType , FooBar>()", 2) enddef " Test for invoking a generic function def Test_generic_func_invoke() var lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 4) lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 4) lines =<< trim END mnv9script def Fn() enddef Fn<>() END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function '<>()'", 4) lines =<< trim END mnv9script def Fn() enddef Fn<> END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function '<>'", 4) lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 4) lines =<< trim END mnv9script def Fn() enddef Fn< END v9.CheckSourceFailure(lines, "E1554: Missing '>' in generic function: <", 4) lines =<< trim END mnv9script def Fn() enddef Fn<() END v9.CheckSourceFailure(lines, "E1008: Missing after <", 4) lines =<< trim END mnv9script def Fn() enddef Fn END v9.CheckSourceFailure(lines, 'E492: Not an editor command: Fn', 4) lines =<< trim END mnv9script def Fn() enddef Fn( END v9.CheckSourceFailure(lines, 'E116: Invalid arguments for function Fn(', 4) lines =<< trim END mnv9script def Fn() enddef Fn () END v9.CheckSourceFailure(lines, 'E492: Not an editor command: Fn ()', 4) lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, 'E1008: Missing after ()', 4) lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, 'E1010: Type not recognized: abc', 4) lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, "E1202: No white space allowed after 'number': () xxx enddef Fn() END v9.CheckSourceFailure(lines, 'E476: Invalid command: xxx', 1) enddef " Test for whitespace error when invoking a generic function def Test_generic_func_invoke_whitespace_error() var lines =<< trim END mnv9script def Fn() enddef Fn< number>() END v9.CheckSourceFailure(lines, "E1202: No white space allowed after '<': < number>()", 4) lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, "E1202: No white space allowed after 'number': () enddef Fn() END v9.CheckSourceFailure(lines, "E1069: White space required after ',': ()", 4) lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, "E1008: Missing after ()", 4) lines =<< trim END mnv9script def Fn() enddef Fn() END v9.CheckSourceFailure(lines, "E1069: White space required after ',': ()", 4) lines =<< trim END mnv9script def Fn() enddef Fn () END v9.CheckSourceFailure(lines, "E1202: No white space allowed after '>': ()", 4) enddef def Test_generic_func_typename() var lines =<< trim END mnv9script def Foo(a: list, b: dict): list return [] enddef def Fn(x: T, s: string) assert_equal(s, typename(x)) enddef Fn(true, 'bool') Fn(10, 'number') Fn(3.4, 'float') Fn('abc', 'string') Fn(0z1020, 'blob') Fn>>([[0z10, 0z20], [0z30]], 'list>') Fn>((1, 'abc'), 'tuple') Fn>({a: 'a', b: 'b'}, 'dict') if has('job') Fn(test_null_job(), 'job') endif if has('channel') Fn(test_null_channel(), 'channel') endif Fn(function('Foo'), 'func(list, dict): list') END v9.CheckSourceSuccess(lines) enddef def Test_generic_func_single_arg() var lines =<< trim END mnv9script def Fn(x: A): number return len(x) enddef assert_equal(3, Fn>([1, 2, 3])) assert_equal(2, Fn>({a: 1, b: 2})) assert_equal(1, Fn(0z10)) END v9.CheckSourceSuccess(lines) enddef " Test for using a generic type as the type of a function argument def Test_generic_func_arg_type() var lines =<< trim END mnv9script def F1(x: list): list return x enddef def F2(y: dict): dict return y enddef assert_equal(['a', 'b'], F1(['a', 'b'])) assert_equal({a: 0z10, b: 0z20}, F2({a: 0z10, b: 0z20})) END v9.CheckSourceSuccess(lines) enddef " Test for using a tuple type for a generic function argument def Test_generic_func_tuple_arg_type() var lines =<< trim END mnv9script def Fn(x: tuple): tuple return x enddef assert_equal((1, 2), Fn((1, 2))) assert_equal(('a', 'b'), Fn(('a', 'b'))) END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script def Fn(x: tuple>): tuple> return x enddef assert_equal(('a', 1, 2), Fn(('a', 1, 2))) assert_equal((3, 'a', 'b'), Fn((3, 'a', 'b'))) END v9.CheckSourceSuccess(lines) enddef def Test_generic_func_ret_type() var lines =<< trim END mnv9script def Fn(x: A): A return x enddef assert_equal([1], Fn>([1])) assert_equal({a: 1}, Fn>({a: 1})) assert_equal((1,), Fn>((1,))) assert_equal(0z10, Fn(0z10)) END v9.CheckSourceSuccess(lines) # Using the generic type as the member of the List return value lines =<< trim END mnv9script def Fn(x: A): list return [x] enddef assert_equal([1], Fn(1)) assert_equal(['abc'], Fn('abc')) END v9.CheckSourceSuccess(lines) # Using the generic type as the member of the Dict return value lines =<< trim END mnv9script def Fn(x: A): dict return {v: x} enddef assert_equal({v: 1}, Fn(1)) assert_equal({v: 'abc'}, Fn('abc')) END v9.CheckSourceSuccess(lines) enddef " Test for using a generic type as the type of the vararg variable def Test_generic_func_varargs() var lines =<< trim END mnv9script def Fn(...x: list>): list> return x enddef assert_equal([[1], [2], [3]], Fn([1], [2], [3])) assert_equal([['a'], ['b'], ['c']], Fn(['a'], ['b'], ['c'])) END v9.CheckSourceSuccess(lines) enddef " Test for using func type as a generic function argument type def Test_generic_func_type_as_argument() var lines =<< trim END mnv9script def Fn(Foo: func(A, B): C): string return typename(Foo) enddef def F1(a: number, b: string): blob return 0z10 enddef def F2(a: float, b: blob): string return 'abc' enddef assert_equal('func(number, string): blob', Fn(F1)) assert_equal('func(float, blob): string', Fn(F2)) END v9.CheckSourceSuccess(lines) enddef def Test_generic_nested_call() var lines =<< trim END mnv9script def Fn(n: number, x: A): A if n return x endif assert_equal('abc', Fn(1, 'abc')) return x enddef assert_equal(10, Fn(0, 10)) END v9.CheckSourceSuccess(lines) enddef def Test_generic_failure_in_def_function() var lines =<< trim END mnv9script def Fn() enddef def Foo() Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1010: Type not recognized: abc', 1) lines =<< trim END mnv9script def Foo() Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1010: Type not recognized: abc', 1) lines =<< trim END mnv9script def Fn() enddef def Foo() Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 1) lines =<< trim END mnv9script def Fn() enddef def Foo() Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 1) lines =<< trim END mnv9script def Fn() enddef def Foo() Fn<>() enddef defcompile END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function '<>()'", 1) lines =<< trim END mnv9script def Fn(x: A, y: B) enddef def Foo() Fn(10, 'abc') enddef defcompile END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 1) lines =<< trim END mnv9script def Fn(x: number) enddef def Foo() Fn(10) enddef defcompile END v9.CheckSourceFailure(lines, 'E1560: Not a generic function', 1) lines =<< trim END mnv9script def Fn(x: A, y: B) enddef def Foo() Fn(10) enddef defcompile END v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function', 1) lines =<< trim END mnv9script def Fn() enddef def Foo() Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1008: Missing after ()', 1) lines =<< trim END mnv9script def Fn() enddef def Foo() Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1010: Type not recognized: abc', 1) lines =<< trim END mnv9script def Fn() enddef def Foo() Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1202: No white space allowed after 'number'", 1) enddef " Test for using function() to get a generic funcref def Test_get_generic_funcref_using_function() var lines =<< trim END mnv9script def Fn(x: A): A return x enddef var Fx = function(Fn>) assert_equal([1], Fx([1])) END v9.CheckSourceSuccess(lines) # Get a generic funcref without specifying any type arguments lines =<< trim END mnv9script def Fn() enddef var Fx = function(Fn) Fx() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 5) # Get a generic funcref specifying additional type arguments lines =<< trim END mnv9script def Fn() enddef var Fx = function(Fn) END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 4) # Get a generic funcref specifying less type arguments lines =<< trim END mnv9script def Fn() enddef var Fx = function(Fn) END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 4) # Get a generic funcref specifying non-existing type lines =<< trim END mnv9script def Fn() enddef var Fx = function(Fn) END v9.CheckSourceFailure(lines, 'E1010: Type not recognized: foobar', 4) # Get a generic funcref specifying an empty type argument list lines =<< trim END mnv9script def Fn() enddef var Fx = function(Fn<>) END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function '<>)'", 4) # Get a generic funcref specifying only the opening bracket after name lines =<< trim END mnv9script def Fn() enddef var Fx = function(Fn<) END v9.CheckSourceFailure(lines, 'E1008: Missing after <', 4) # Get a generic funcref specifying only the opening bracket and type lines =<< trim END mnv9script def Fn() enddef var Fx = function(Fn() enddef var Fx = function(Fn) END v9.CheckSourceFailure(lines, 'E1560: Not a generic function: Fn', 4) # Call a generic funcref using a different argument type lines =<< trim END mnv9script def Fn(t: T) enddef var Fx = function(Fn) Fx(10) END v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 5) # Assign a generic funcref return value to a variable of different type lines =<< trim END mnv9script def Fn(t: T): T return t enddef var Fx = function(Fn) var x: number = Fx('abc') END v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string', 6) # Call a generic funcref specifying types lines =<< trim END mnv9script def Fn() enddef var Fx = function(Fn) Fx() END v9.CheckSourceFailure(lines, 'E15: Invalid expression: "Fx()"', 5) enddef def Test_generic_funcref_string() var lines =<< trim END mnv9script def Fn(x: A): A return x enddef var Fx = function('Fn>') assert_equal([1], Fx([1])) END v9.CheckSourceSuccess(lines) # Get a generic funcref without specifying any type arguments lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') Fx() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 5) # Get a generic funcref specifying additional type arguments lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 4) # Get a generic funcref specifying less type arguments lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 4) # Get a generic funcref specifying non-existing type lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') END v9.CheckSourceFailure(lines, 'E1010: Type not recognized: foobar', 4) # Get a generic funcref specifying an empty type argument list lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn<>') END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 4) # Get a generic funcref specifying only the opening bracket after name lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn<') END v9.CheckSourceFailure(lines, "E1554: Missing '>' in generic function: <", 4) # Get a generic funcref specifying only the opening bracket and type lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn' in generic function: () enddef var Fx = function('Fn' in generic function: ') Fx() END v9.CheckSourceFailure(lines, 'E1560: Not a generic function:', 5) lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') Fx() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 5) lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') Fx<>() END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function '<>()'", 5) lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') Fx() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 5) lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') Fx() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 5) lines =<< trim END mnv9script def Fn() enddef var Fx = function('Fn') Fx() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 5) enddef " Test for calling a generic funcref from another function def Test_generic_funcref_string_from_another_function() var lines =<< trim END mnv9script def Fn(x: A): A return x enddef def Foo() var Fx = function('Fn>') assert_equal([1], Fx([1])) enddef Foo() END v9.CheckSourceSuccess(lines) # Get a generic funcref without specifying any type arguments lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn') Fx() enddef Foo() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 2) # Get a generic funcref specifying additional type arguments lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn') Fx() enddef Foo() END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 2) # Get a generic funcref specifying less type arguments lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn') Fx() enddef Foo() END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 2) # Get a generic funcref specifying an empty type argument list lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn<>') enddef Foo() END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 1) # Get a generic funcref specifying only the opening bracket after name lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn<') enddef Foo() END v9.CheckSourceFailure(lines, "E1554: Missing '>' in generic function: <", 1) # Get a generic funcref specifying only the opening bracket and type lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn' in generic function: () enddef def Foo() var Fx = function('Fn' in generic function: ') Fx() enddef Foo() END v9.CheckSourceFailure(lines, 'E1560: Not a generic function:', 2) lines =<< trim END mnv9script def Fn(x: A): A return x enddef def Foo() var Fx = function('Fn') Fx() enddef Foo() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 2) lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn') Fx<>() enddef Foo() END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 2) lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn') Fx() enddef Foo() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 2) lines =<< trim END mnv9script def Fn() enddef def Foo() var Fx = function('Fn') Fx() enddef Foo() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 2) enddef def Test_generic_obj_method() var lines =<< trim END mnv9script class A def Fn(t: X): X var n: X = t return n enddef endclass var a = A.new() assert_equal(['a', 'b'], a.Fn>(['a', 'b'])) END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script class A def Fn<>() enddef endclass defcompile END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function 'Fn'", 4) lines =<< trim END mnv9script class A def Fn<,>() enddef endclass defcompile END v9.CheckSourceFailure(lines, "E1008: Missing after <,>()", 4) lines =<< trim END mnv9script class A def Fn() enddef endclass var a = A.new() a.Fn<>() END v9.CheckSourceFailureList(lines, ["E1555: Empty type list specified for generic function '<>()'"]) lines =<< trim END mnv9script class A def Fn() enddef endclass var a = A.new() a.Fn() END v9.CheckSourceFailure(lines, "E1556: Too many types specified for generic function 'Fn'", 8) lines =<< trim END mnv9script class A def Fn() enddef endclass var a = A.new() a.Fn() END v9.CheckSourceFailure(lines, "E1557: Not enough types specified for generic function 'Fn'", 8) lines =<< trim END mnv9script class A def Fn() enddef endclass var a = A.new() a.Fn() END v9.CheckSourceFailure(lines, "E1559: Type arguments missing for generic function", 8) lines =<< trim END mnv9script class A def Fn() enddef endclass var a = A.new() a.Fn() END v9.CheckSourceFailure(lines, 'E1560: Not a generic function: Fn', 8) enddef def Test_generic_obj_method_call_from_another_method() var lines =<< trim END mnv9script class A def Fn(t: X): X var n: X = t return n enddef endclass def Foo() var a = A.new() assert_equal(['a', 'b'], a.Fn>(['a', 'b'])) enddef Foo() END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script class A def Fn() enddef endclass def Foo() var a = A.new() a.Fn<>() enddef defcompile END v9.CheckSourceFailureList(lines, ["E1555: Empty type list specified for generic function '<>()'"]) lines =<< trim END mnv9script class A def Fn() enddef endclass def Foo() var a = A.new() a.Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1556: Too many types specified for generic function 'Fn'", 2) lines =<< trim END mnv9script class A def Fn() enddef endclass def Foo() var a = A.new() a.Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1557: Not enough types specified for generic function 'Fn'", 2) lines =<< trim END mnv9script class A def Fn() enddef endclass def Foo() var a = A.new() a.Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1559: Type arguments missing for generic function", 2) lines =<< trim END mnv9script class A def Fn() enddef endclass def Foo() var a = A.new() a.Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1560: Not a generic function: Fn', 2) # Try calling a non-existing generic object method lines =<< trim END mnv9script class A endclass def Foo() var a = A.new() a.Bar() enddef defcompile END v9.CheckSourceFailure(lines, 'E1325: Method "Bar" not found in class "A"', 2) # Error in compiling generic object method arguments lines =<< trim END mnv9script class A def Fn(x: number, y: number) enddef endclass def Foo() var a = A.new() a.Fn(10,) enddef defcompile END v9.CheckSourceFailure(lines, "E1069: White space required after ',': ,)", 2) # Try calling a super abstract method from a child class lines =<< trim END mnv9script abstract class A abstract def F1() endclass class B extends A def F1() enddef def Foo() super.F1() enddef endclass defcompile END v9.CheckSourceFailure(lines, 'E1431: Abstract method "F1" in class "A" cannot be accessed directly', 1) # Try calling a protected method in a class lines =<< trim END mnv9script class A def _Foo() enddef endclass def Bar() var a = A.new() a._Foo() enddef defcompile END v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Foo()', 2) enddef def Test_generic_class_method() var lines =<< trim END mnv9script class A static def Fn(t: X): X var n: X = t return n enddef endclass assert_equal(['a', 'b'], A.Fn>(['a', 'b'])) END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script class A static def Fn<>() enddef endclass defcompile END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function 'Fn'", 4) lines =<< trim END mnv9script class A static def Fn<,>() enddef endclass defcompile END v9.CheckSourceFailure(lines, "E1008: Missing after <,>()", 4) lines =<< trim END mnv9script class A static def Fn() enddef endclass A.Fn<>() END v9.CheckSourceFailureList(lines, ["E1555: Empty type list specified for generic function '<>()'"]) lines =<< trim END mnv9script class A static def Fn() enddef endclass A.Fn() END v9.CheckSourceFailure(lines, "E1556: Too many types specified for generic function 'Fn'", 7) lines =<< trim END mnv9script class A static def Fn() enddef endclass A.Fn() END v9.CheckSourceFailure(lines, "E1557: Not enough types specified for generic function 'Fn'", 7) lines =<< trim END mnv9script class A static def Fn() enddef endclass A.Fn() END v9.CheckSourceFailure(lines, "E1559: Type arguments missing for generic function 'Fn'", 7) lines =<< trim END mnv9script class A static def Fn() enddef endclass A.Fn() END v9.CheckSourceFailure(lines, 'E1560: Not a generic function: Fn', 7) enddef def Test_generic_class_method_call_from_another_method() var lines =<< trim END mnv9script class A static def Fn(t: X): X var n: X = t return n enddef endclass def Foo() assert_equal(['a', 'b'], A.Fn>(['a', 'b'])) enddef Foo() END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script class A static def Fn() enddef endclass def Foo() A.Fn<>() enddef defcompile END v9.CheckSourceFailureList(lines, ["E1555: Empty type list specified for generic function '<>()'"]) lines =<< trim END mnv9script class A static def Fn() enddef endclass def Foo() A.Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1556: Too many types specified for generic function 'Fn'", 1) lines =<< trim END mnv9script class A static def Fn() enddef endclass def Foo() A.Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1557: Not enough types specified for generic function 'Fn'", 1) lines =<< trim END mnv9script class A static def Fn() enddef endclass def Foo() A.Fn() enddef defcompile END v9.CheckSourceFailure(lines, "E1559: Type arguments missing for generic function 'Fn'", 1) lines =<< trim END mnv9script class A static def Fn() enddef endclass def Foo() A.Fn() enddef defcompile END v9.CheckSourceFailure(lines, 'E1560: Not a generic function: Fn', 1) enddef " Test for using a generic funcref from another method def Test_generic_funcref_use_from_def_method() var lines =<< trim END mnv9script def Foo(t: T): T return t enddef def Fx() var Fn = Foo> var x: list = Fn(['abc', 'b']) assert_equal(['abc', 'b'], x) enddef Fx() END v9.CheckSourceSuccess(lines) # Assigning a generic function without specifying any type arguments lines =<< trim END mnv9script def Foo() enddef def Fx() var Fn = Foo enddef defcompile END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 1) # Assigning a generic function specifying additional type arguments lines =<< trim END mnv9script def Foo() enddef def Fx() var Fn = Foo enddef defcompile END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 1) # Assigning a generic function specifying less type arguments lines =<< trim END mnv9script def Foo() enddef def Fx() var Fn = Foo enddef defcompile END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 1) # Assigning a generic function specifying an empty type argument list lines =<< trim END mnv9script def Foo() enddef def Fx() var Fn = Foo<> enddef defcompile END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 1) # Assigning a generic function specifying only the opening bracket lines =<< trim END mnv9script def Foo() enddef def Fx() var Fn = Foo< enddef defcompile END v9.CheckSourceFailure(lines, "E1554: Missing '>' in generic function: <", 1) # Assigning a generic function without specifying the closing bracket lines =<< trim END mnv9script def Foo() enddef def Fx() var Fn = Foo' in generic function: () enddef def Fx() var Fn = Foo' in generic function: enddef defcompile END v9.CheckSourceFailure(lines, 'E1560: Not a generic function', 1) # Call a generic funcref using a different argument type lines =<< trim END mnv9script def Foo(t: T) enddef def Fx() var Fn = Foo Fn(10) enddef defcompile END v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 2) # Assign a generic funcref return value to a variable of different type lines =<< trim END mnv9script def Foo(t: T): T return t enddef def Fx() var Fn = Foo var x: number = Fn('abc') enddef defcompile END v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got string', 2) enddef def Test_generic_mnv9_lambda() var lines =<< trim END mnv9script def Fn() var Lambda = (x: A, y: B): C => x + y assert_equal(30, Lambda(10, 20)) enddef Fn() END v9.CheckSourceSuccess(lines) enddef " Test for using a generic type in a nested def function def Test_generic_nested_def() var lines =<< trim END mnv9script def F1() def F2(x: A, y: B): C return x + y enddef assert_equal(30, F2(10, 20)) enddef F1() END v9.CheckSourceSuccess(lines) # Lambda function in a nested def function lines =<< trim END mnv9script def F1() def F2(): func var Lambda = (x: A, y: B): C => x + y return Lambda enddef var Fx = F2() assert_equal(60, Fx(20, 40)) enddef F1() END v9.CheckSourceSuccess(lines) enddef " Test for type substitution in a generic function call. Only the generic types " should be substituted. Other "any" types should be ignored. def Test_generic_type_substitution() var lines =<< trim END mnv9script def Fn(a: any, b: T): any return a enddef assert_equal('abc', Fn('abc', 20)) END v9.CheckSourceSuccess(lines) enddef " Test for a global generic function g:MyFunc def Test_generic_global_function() var lines =<< trim END mnv9script def g:Fn1(a: T): T return a enddef assert_equal('abc', g:Fn1('abc')) def Foo() assert_equal(['a', 'b'], g:Fn1>(['a', 'b'])) enddef Foo() END v9.CheckSourceSuccess(lines) enddef " Test for calling a nested generic function def Test_generic_function_call_nested() var lines =<< trim END mnv9script def Id_(o: T): T return o enddef class Test def Id(o: U): U return Id_(o) enddef endclass assert_equal(".", Id_(".")) assert_equal(0, Id_(0)) assert_equal(false, Id_(false)) assert_equal(false, Id_(false)) assert_equal(0, Id_(0)) assert_equal(".", Id_(".")) assert_equal([], Test.new().Id([])) assert_equal(".", Test.new().Id(".")) assert_equal(0, Test.new().Id(0)) assert_equal(false, Test.new().Id(false)) END v9.CheckSourceSuccess(lines) enddef " Test for an imported generic function foo#MyFunc def Test_generic_import() var lines =<< trim END mnv9script export def Fn(a: A, b: B): B return b enddef export def Foobar() enddef END writefile(lines, 'Ximport_generic.mnv', 'D') lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo assert_equal(20, Foo.Fn('abc', 20)) def MyFunc() assert_equal('xyz', Foo.Fn(30, 'xyz')) enddef MyFunc() END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo Foo.Fn('abc', 20) END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 4) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo def MyFunc() Foo.Fn('abc', 20) enddef MyFunc() END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 1) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo Foo.Fn(10, 20) END v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 4) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo def MyFunc() Foo.Fn(10, 20) enddef MyFunc() END v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number', 1) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo Foo.Fn(10, 20) END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 4) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo def MyFunc() Foo.Fn(10, 20) enddef MyFunc() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 1) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo Foo.Fn after after () END v9.CheckSourceFailure(lines, "E1560: Not a generic function", 4) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo def MyFunc() Foo.Foobar() enddef MyFunc() END v9.CheckSourceFailure(lines, "E1560: Not a generic function: Foo", 1) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo Foo.Fx('abc', 20) END v9.CheckSourceFailure(lines, 'E1048: Item not found in script: Fx', 4) lines =<< trim END mnv9script import "./Ximport_generic.mnv" as Foo def MyFunc() Foo.Fx('abc', 20) enddef MyFunc() END v9.CheckSourceFailure(lines, 'E1048: Item not found in script: Fx', 1) # Source the script twice lines =<< trim END mnv9script export def Fn(a: list) enddef END writefile(lines, 'Ximport_generic_2.mnv', 'D') lines =<< trim END mnv9script import "./Ximport_generic_2.mnv" as Foo Foo.Fn>>([[{}]]) END :new setline(1, lines) :source :source :bw! enddef " Test for disassembling a generic function def Test_generic_function_disassemble() var lines =<< trim END mnv9script def Fn(): A var x: A var y: B [x, y] = g:values return x enddef g:instr = execute('disassemble Fn, dict>') END v9.CheckScriptSuccess(lines) assert_match('\d\+_Fn, dict>\_s*' .. 'var x: A\_s*' .. '0 NEWLIST size 0\_s*' .. '1 SETTYPE list\_s*' .. '2 STORE $0\_s*' .. 'var y: B\_s*' .. '3 NEWDICT size 0\_s*' .. '4 SETTYPE dict\_s*' .. '5 STORE $1\_s*' .. '\[x, y\] = g:values\_s*' .. '6 LOADG g:values\_s*\_s*' .. '7 CHECKTYPE list|tuple stack\[-1\]\_s*' .. '8 CHECKLEN 2\_s*' .. '9 ITEM 0\_s*' .. '10 CHECKTYPE list stack\[-1\] var 1\_s*' .. '11 SETTYPE list\_s*' .. '12 STORE $0\_s*' .. '13 ITEM 1\_s*' .. '14 CHECKTYPE dict stack\[-1\] var 2\_s*' .. '15 SETTYPE dict\_s*' .. '16 STORE $1\_s*' .. '17 DROP\_s*' .. 'return x\_s*' .. '18 LOAD $0\_s*' .. '19 RETURN', g:instr) unlet g:instr lines =<< trim END mnv9script disassemble Fn END v9.CheckScriptFailure(lines, "E1554: Missing '>' in generic function: ", 2) lines =<< trim END mnv9script disassemble Fn> END v9.CheckScriptFailure(lines, 'E1061: Cannot find function Fn>', 2) lines =<< trim END mnv9script disassemble Fn' in generic function: ' in generic function: <", 2) lines =<< trim END mnv9script def Fn() enddef disassemble Fn END v9.CheckScriptFailure(lines, 'E1560: Not a generic function:', 4) lines =<< trim END mnv9script def Fn() enddef disassemble Fn END v9.CheckScriptFailure(lines, 'E1556: Too many types specified for generic function', 4) lines =<< trim END mnv9script def Fn() enddef disassemble Fn END v9.CheckScriptFailure(lines, 'E1559: Type arguments missing for generic function', 4) lines =<< trim END mnv9script def Fn() enddef disassemble Fn END v9.CheckScriptFailure(lines, 'E1557: Not enough types specified for generic function', 4) lines =<< trim END mnv9script def Fn() enddef disassemble Fn<> END v9.CheckScriptFailure(lines, "E1555: Empty type list specified for generic function '<>'", 4) enddef " Test for disassembling a generic function calling another generic function def Test_nested_generic_func_call_disassemble() var lines =<< trim END mnv9script def Fn1(o: T): T return o enddef def Fn2(o: U): U return Fn1(o) enddef g:instr1 = execute('disassemble Fn2') g:instr2 = execute('disassemble Fn2') END v9.CheckScriptSuccess(lines) assert_match('\d\+_Fn2\_s*' .. 'return Fn1(o)\_s*' .. '0 LOAD arg\[-1\]\_s*' .. '1 DCALL \d\+_Fn1(argc 1)\_s*' .. '2 RETURN\_s*', g:instr1) assert_match('\d\+_Fn2\_s*' .. 'return Fn1(o)\_s*' .. '0 LOAD arg\[-1\]\_s*' .. '1 DCALL \d\+_Fn1(argc 1)\_s*' .. '2 RETURN\_s*', g:instr2) unlet g:instr1 unlet g:instr2 enddef " Test for disassembling a generic object method def Test_generic_disassemble_generic_obj_method() var lines =<< trim END mnv9script class Foo def Fn() var x: A var y: B [x, y] = g:values enddef endclass g:instr = execute('disassemble Foo.Fn, dict>') END v9.CheckScriptSuccess(lines) assert_match('Fn, dict>\_s*' .. 'var x: A\_s*' .. '0 NEWLIST size 0\_s*' .. '1 SETTYPE list\_s*' .. '2 STORE $1\_s*' .. 'var y: B\_s*' .. '3 NEWDICT size 0\_s*' .. '4 SETTYPE dict\_s*' .. '5 STORE $2\_s*' .. '\[x, y\] = g:values\_s*' .. '6 LOADG g:values\_s*' .. '7 CHECKTYPE list|tuple stack\[-1\]\_s*' .. '8 CHECKLEN 2\_s*' .. '9 ITEM 0\_s*' .. '10 CHECKTYPE list stack\[-1\] var 1\_s*' .. '11 SETTYPE list\_s*' .. '12 STORE $1\_s*' .. '13 ITEM 1\_s*' .. '14 CHECKTYPE dict stack\[-1\] var 2\_s*' .. '15 SETTYPE dict\_s*' .. '16 STORE $2\_s*' .. '17 DROP\_s*' .. '18 RETURN void', g:instr) unlet g:instr lines =<< trim END mnv9script class Foo def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, "E1554: Missing '>' in generic function: Fn", 6) lines =<< trim END mnv9script class Foo endclass disassemble Foo.Fn> END v9.CheckScriptFailure(lines, 'E1337: Class variable "Fn" not found in class "Foo"', 4) lines =<< trim END mnv9script class Foo def Fn() enddef endclass disassemble Foo.Fn' in generic function: Fn() enddef endclass disassemble Foo.Fn< END v9.CheckScriptFailure(lines, "E1554: Missing '>' in generic function: Fn<", 6) lines =<< trim END mnv9script class Foo def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, 'E1560: Not a generic function:', 6) lines =<< trim END mnv9script class Foo def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, 'E1556: Too many types specified for generic function', 6) lines =<< trim END mnv9script class Foo def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, 'E1559: Type arguments missing for generic function', 6) lines =<< trim END mnv9script class Foo def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, 'E1557: Not enough types specified for generic function', 6) lines =<< trim END mnv9script class Foo def Fn() enddef endclass disassemble Foo.Fn<> END v9.CheckScriptFailure(lines, "E1555: Empty type list specified for generic function 'Fn'", 6) enddef " Test for disassembling a generic class method def Test_generic_disassemble_generic_class_method() var lines =<< trim END mnv9script class Foo static def Fn() var x: A var y: B [x, y] = g:values enddef endclass g:instr = execute('disassemble Foo.Fn, dict>') END v9.CheckScriptSuccess(lines) assert_match('Fn, dict>\_s*' .. 'var x: A\_s*' .. '0 NEWLIST size 0\_s*' .. '1 SETTYPE list\_s*' .. '2 STORE $0\_s*' .. 'var y: B\_s*' .. '3 NEWDICT size 0\_s*' .. '4 SETTYPE dict\_s*' .. '5 STORE $1\_s*' .. '\[x, y\] = g:values\_s*' .. '6 LOADG g:values\_s*' .. '7 CHECKTYPE list|tuple stack\[-1\]\_s*' .. '8 CHECKLEN 2\_s*' .. '9 ITEM 0\_s*' .. '10 CHECKTYPE list stack\[-1\] var 1\_s*' .. '11 SETTYPE list\_s*' .. '12 STORE $0\_s*' .. '13 ITEM 1\_s*' .. '14 CHECKTYPE dict stack\[-1\] var 2\_s*' .. '15 SETTYPE dict\_s*' .. '16 STORE $1\_s*' .. '17 DROP\_s*' .. '18 RETURN void', g:instr) unlet g:instr lines =<< trim END mnv9script class Foo static def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, "E1554: Missing '>' in generic function: Fn", 6) lines =<< trim END mnv9script class Foo static def Fn() enddef endclass disassemble Foo.Fn' in generic function: Fn() enddef endclass disassemble Foo.Fn< END v9.CheckScriptFailure(lines, "E1554: Missing '>' in generic function: Fn<", 6) lines =<< trim END mnv9script class Foo static def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, 'E1560: Not a generic function:', 6) lines =<< trim END mnv9script class Foo static def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, 'E1556: Too many types specified for generic function', 6) lines =<< trim END mnv9script class Foo static def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, 'E1559: Type arguments missing for generic function', 6) lines =<< trim END mnv9script class Foo static def Fn() enddef endclass disassemble Foo.Fn END v9.CheckScriptFailure(lines, 'E1557: Not enough types specified for generic function', 6) lines =<< trim END mnv9script class Foo static def Fn() enddef endclass disassemble Foo.Fn<> END v9.CheckScriptFailure(lines, "E1555: Empty type list specified for generic function 'Fn'", 6) enddef " Test for disassembling a generic function using a Funcref variable def Test_generic_disassemble_variable() var lines =<< trim END mnv9script def Foo() echomsg "Foo" enddef var Fn = Foo disassemble Fn g:instr = execute('disassemble Fn') END v9.CheckScriptSuccess(lines) assert_match('\d\+_Foo\_s*' .. 'echomsg "Foo"\_s*' .. '0 PUSHS "Foo"\_s*' .. '1 ECHOMSG 1\_s*' .. '2 RETURN void\_s*', g:instr) unlet g:instr enddef def Test_generic_duplicate_names() var lines =<< trim END mnv9script def Fn() enddef defcompile END v9.CheckScriptFailure(lines, 'E1561: Duplicate type variable name: A', 2) lines =<< trim END mnv9script class A endclass def Fn() enddef defcompile END v9.CheckScriptFailure(lines, 'E1041: Redefining script item: "A"', 4) lines =<< trim END mnv9script type A = number def Fn() enddef defcompile END v9.CheckScriptFailure(lines, 'E1041: Redefining script item: "A"', 3) lines =<< trim END mnv9script var B = 'abc' def Fn() enddef defcompile END v9.CheckScriptFailure(lines, 'E1041: Redefining script item: "B"', 3) lines =<< trim END mnv9script def Fn1() enddef def Fn2() enddef defcompile END v9.CheckScriptSuccess(lines) lines =<< trim END mnv9script def I(x: A): A return x enddef def Id(x: I): I return x enddef END v9.CheckScriptFailure(lines, 'E1041: Redefining script item: "I"', 7) enddef " Test for nested generic functions def Test_generic_nested_functions() var lines =<< trim END mnv9script def Fn(t: T): T def Fx(a: A): A return a enddef return Fx(t) enddef assert_equal(100, Fn(100)) END v9.CheckScriptSuccess(lines) # Use the generic type from the outer generic function lines =<< trim END mnv9script def Fn(b: B): B def Fx(t: T): T return t enddef return Fx(b) enddef assert_equal(100, Fn(100)) assert_equal('abc', Fn('abc')) END v9.CheckScriptSuccess(lines) # duplicate definition lines =<< trim END mnv9script def Fn() def Fn() enddef enddef defcompile END v9.CheckScriptFailure(lines, 'E1073: Name already defined: Fn', 1) # overlaps with a script-local function lines =<< trim END mnv9script def Fx() enddef def Fn() def Fx() enddef enddef defcompile END v9.CheckScriptFailure(lines, 'E1073: Name already defined: Fx', 1) # overlaps with another nested function lines =<< trim END mnv9script def Fn() def Fx() enddef def Fx() enddef enddef defcompile END v9.CheckScriptFailure(lines, 'E1073: Name already defined: Fx', 3) # Empty list of types lines =<< trim END mnv9script def Fn() def Fx<>() enddef enddef defcompile END v9.CheckScriptFailure(lines, 'E1555: Empty type list specified for generic function', 3) lines =<< trim END mnv9script def Fn() def Fx<,>() enddef enddef defcompile END v9.CheckScriptFailure(lines, 'E1008: Missing after <', 3) # missing closing bracket in the inner generic function lines =<< trim END mnv9script def Fn() def Fx() def Fx() enddef enddef defcompile END v9.CheckScriptFailure(lines, 'E1552: Type variable name must start with an uppercase letter: a>()', 1) # duplicate generic type lines =<< trim END mnv9script def Fn() def Fx() enddef enddef defcompile END v9.CheckScriptFailure(lines, 'E1561: Duplicate type variable name: T', 1) enddef " Test for using a generic function in call() as a string def Test_generic_function_use_in_call_function_as_string() var lines =<< trim END mnv9script def Fn(a: A): A return a enddef assert_equal(['a', 'b'], call("Fn>", [['a', 'b']])) END v9.CheckSourceSuccess(lines) # Test for passing more types lines =<< trim END mnv9script def Fn() enddef call("Fn", []) END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 4) # Test for passing less types lines =<< trim END mnv9script def Fn() enddef call("Fn", []) END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 4) # Test for passing empty types lines =<< trim END mnv9script def Fn() enddef call("Fn<>", []) END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 4) # Test for passing no types lines =<< trim END mnv9script def Fn() enddef call("Fn", []) END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 4) # Test for missing types and closing bracket lines =<< trim END mnv9script def Fn() enddef call("Fn<", []) END v9.CheckSourceFailure(lines, "E1554: Missing '>' in generic function: <", 4) # Test for missing types lines =<< trim END mnv9script def Fn() enddef call("Fn' in generic function: () enddef call("Fn' in generic function: () enddef call("Fn", []) END v9.CheckSourceFailure(lines, "E1069: White space required after ','", 4) # Test for missing types lines =<< trim END mnv9script def Fn() enddef call("Fn", []) END v9.CheckSourceFailure(lines, 'E1008: Missing after ', 4) # Test for calling a non-existing generic function lines =<< trim END mnv9script call("FooBar", []) END v9.CheckSourceFailure(lines, 'E1558: Unknown generic function', 2) # Test for calling a regular function as a generic function lines =<< trim END mnv9script def Fn() enddef call("Fn", []) END v9.CheckSourceFailure(lines, 'E1560: Not a generic function', 4) enddef " Test for using a generic function in call() as a string in a method def Test_generic_use_in_call_func_as_string_in_method() var lines =<< trim END mnv9script def Fn(a: A): A return a enddef def Foo() assert_equal(['a', 'b'], call("Fn>", [['a', 'b']])) enddef Foo() END v9.CheckSourceSuccess(lines) # Test for passing more types lines =<< trim END mnv9script def Fn() enddef def Foo() call("Fn", []) enddef Foo() END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 1) # Test for passing less types lines =<< trim END mnv9script def Fn() enddef def Foo() call("Fn", []) enddef Foo() END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 1) # Test for passing empty types lines =<< trim END mnv9script def Fn() enddef def Foo() call("Fn<>", []) enddef Foo() END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 1) # Test for passing no types lines =<< trim END mnv9script def Fn() enddef def Foo() call("Fn", []) enddef Foo() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 1) # Test for missing types and closing bracket lines =<< trim END mnv9script def Fn() enddef def Foo() call("Fn<", []) enddef Foo() END v9.CheckSourceFailure(lines, "E1554: Missing '>' in generic function: <", 1) # Test for missing types lines =<< trim END mnv9script def Fn() enddef def Foo() call("Fn' in generic function: () enddef def Foo() call("Fn' in generic function: () enddef def Foo() call("Fn", []) enddef Foo() END v9.CheckSourceFailure(lines, "E1069: White space required after ','", 1) # Test for missing types lines =<< trim END mnv9script def Fn() enddef def Foo() call("Fn", []) enddef Foo() END v9.CheckSourceFailure(lines, 'E1008: Missing after ', 1) # Test for calling a non-existing generic function lines =<< trim END mnv9script def Foo() call("FooBar", []) enddef Foo() END v9.CheckSourceFailure(lines, 'E1558: Unknown generic function', 1) # Test for calling a regular function as a generic function lines =<< trim END mnv9script def Fn() enddef def Foo() call("Fn", []) enddef Foo() END v9.CheckSourceFailure(lines, 'E1560: Not a generic function', 1) enddef " Test for using a generic function in call() as a funcref def Test_generic_function_use_in_call_function_as_funcref() var lines =<< trim END mnv9script def Fn(a: A): A return a enddef assert_equal({a: 'xyz'}, call(Fn>, [{a: 'xyz'}])) END v9.CheckSourceSuccess(lines) # Test for passing more types lines =<< trim END mnv9script def Fn() enddef call(Fn, []) END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 4) # Test for passing less types lines =<< trim END mnv9script def Fn() enddef call(Fn, []) END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 4) # Test for passing empty types lines =<< trim END mnv9script def Fn() enddef call(Fn<>, []) END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 4) # Test for passing no types lines =<< trim END mnv9script def Fn() enddef call(Fn, []) END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 4) # Test for missing types and closing bracket lines =<< trim END mnv9script def Fn() enddef call(Fn<, []) END v9.CheckSourceFailure(lines, "E1008: Missing after <", 4) # Test for missing types lines =<< trim END mnv9script def Fn() enddef call(Fn after () enddef call(Fn() enddef call(Fn, []) END v9.CheckSourceFailure(lines, "E1069: White space required after ','", 4) # Test for missing types lines =<< trim END mnv9script def Fn() enddef call(Fn, []) END v9.CheckSourceFailure(lines, 'E1008: Missing after ', 4) # Test for calling a non-existing generic function lines =<< trim END mnv9script call(FooBar, []) END v9.CheckSourceFailure(lines, 'E121: Undefined variable: FooBar', 2) # Test for calling a regular function as a generic function lines =<< trim END mnv9script def Fn() enddef call(Fn, []) END v9.CheckSourceFailure(lines, 'E1560: Not a generic function', 4) enddef " Test for using a generic function with the :call command def Test_generic_function_use_call_cmd() var lines =<< trim END mnv9script var funcArgs = {} def Fn(a: A) funcArgs = a enddef call Fn>({a: 'xyz'}) assert_equal({a: 'xyz'}, funcArgs) END v9.CheckSourceSuccess(lines) # Test for passing extra types lines =<< trim END mnv9script def Fn() enddef call Fn() END v9.CheckSourceFailure(lines, 'E1556: Too many types specified for generic function', 4) # Test for passing less types lines =<< trim END mnv9script def Fn() enddef call Fn() END v9.CheckSourceFailure(lines, 'E1557: Not enough types specified for generic function', 4) # Test for passing empty types lines =<< trim END mnv9script def Fn() enddef call Fn<>() END v9.CheckSourceFailure(lines, 'E1555: Empty type list specified for generic function', 4) # Test for passing no types lines =<< trim END mnv9script def Fn() enddef call Fn() END v9.CheckSourceFailure(lines, 'E1559: Type arguments missing for generic function', 4) # Test for missing types and closing bracket lines =<< trim END mnv9script def Fn() enddef call Fn<() END v9.CheckSourceFailure(lines, "E1008: Missing after <", 4) # Test for missing types lines =<< trim END mnv9script def Fn() enddef call Fn after () enddef call Fn() enddef call Fn() END v9.CheckSourceFailure(lines, "E1069: White space required after ','", 4) # Test for missing types lines =<< trim END mnv9script def Fn() enddef call Fn() END v9.CheckSourceFailure(lines, 'E1008: Missing after ', 4) # Test for calling a non-existing generic function lines =<< trim END mnv9script call FooBar() END v9.CheckSourceFailure(lines, 'E1558: Unknown generic function', 2) # Test for calling a regular function as a generic function lines =<< trim END mnv9script def Fn() enddef call Fn() END v9.CheckSourceFailure(lines, 'E1560: Not a generic function', 4) enddef def Test_generic_function_with_sort() var lines =<< trim END mnv9script def g:CompareByLength(a: T, b: T): number return string(a)->strlen() - string(b)->strlen() enddef var l = ['aaaa', 'aaa', 'a', 'aa'] ->sort((a, b) => g:CompareByLength(a, b)) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) l = ['aaaa', 'aaa', 'a', 'aa'] ->sort(g:CompareByLength) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) l = ['aaaa', 'aaa', 'a', 'aa'] ->sort(function(g:CompareByLength)) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) l = ['aaaa', 'aaa', 'a', 'aa'] ->sort(funcref('g:CompareByLength')) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) l = ['aaaa', 'aaa', 'a', 'aa'] ->sort(function('g:CompareByLength')) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script def Foo() var l = ['aaaa', 'aaa', 'a', 'aa'] ->sort((a, b) => g:CompareByLength(a, b)) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) l = ['aaaa', 'aaa', 'a', 'aa'] ->sort(g:CompareByLength) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) l = ['aaaa', 'aaa', 'a', 'aa'] ->sort(function(g:CompareByLength)) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) l = ['aaaa', 'aaa', 'a', 'aa'] ->sort(funcref('g:CompareByLength')) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) l = ['aaaa', 'aaa', 'a', 'aa'] ->sort(function('g:CompareByLength')) assert_equal(['a', 'aa', 'aaa', 'aaaa'], l) enddef Foo() END v9.CheckSourceSuccess(lines) enddef " Test for using a generic type in the return value of a function. def Test_generic_function_func_ret_val() var lines =<< trim END mnv9script def Id(): func(U): U return (X: U) => X enddef assert_equal(123, Id()(123)) assert_equal(321, Id()(Id())(321)) const F: func(number): number = Id() var G: func(number): number G = Id()(F) assert_equal(true, typename(F) == typename(G)) assert_equal(456, G(456)) G = Id()(F) assert_equal(456, G(456)) END v9.CheckSourceSuccess(lines) lines =<< trim END mnv9script def Id(): func(U): U return (X: U) => X enddef def Foo() assert_equal(123, Id()(123)) assert_equal(321, Id()(Id())(321)) const F: func(number): number = Id() var G: func(number): number G = Id()(F) assert_equal(true, typename(F) == typename(G)) assert_equal(456, G(456)) G = Id()(F) assert_equal(456, G(456)) enddef Foo() END v9.CheckSourceSuccess(lines) enddef " Test for recursively calling a generic function def Test_generic_function_recursive_call() var lines =<< trim END mnv9script def Y0_(): func(func(U): U): U return (F: func(U): U) => F(Y0_()(F)) enddef const Partial_: func(func(any): any): any = Y0_() Partial_((x: any) => x) END v9.CheckSourceFailure(lines, "E132: Function call depth is higher than 'maxfuncdepth'", 1) lines =<< trim END mnv9script def Y0_(): func(func(U): U): U return (F: func(U): U) => F(Y0_()(F)) enddef def Foo() const Partial_: func(func(any): any): any = Y0_() Partial_((x: any) => x) enddef Foo() END v9.CheckSourceFailure(lines, "E132: Function call depth is higher than 'maxfuncdepth'", 1) enddef " Test for overriding a generic object method def Test_generic_object_method_override() var lines =<< trim END mnv9script class A def Fn(t: T): T return t enddef endclass class B extends A def Fn(t: T): T return t enddef endclass var a = A.new() var b = B.new() assert_equal(10, a.Fn(10)) assert_equal('abc', b.Fn('abc')) assert_equal(['a', 'b'], a.Fn>(['a', 'b'])) assert_equal({a: 10, b: 20}, b.Fn>({a: 10, b: 20})) END v9.CheckSourceSuccess(lines) enddef " Test for failures in overriding a generic object method def Test_generic_object_method_override_fails() var lines =<< trim END mnv9script class A def Fn(t: T): T return t enddef endclass class B extends A def Fn(t: number): number return t enddef endclass END v9.CheckSourceFailure(lines, 'E1432: Overriding generic method "Fn" in class "A" with a concrete method', 13) lines =<< trim END mnv9script class A def Fn(t: number): number return t enddef endclass class B extends A def Fn(t: T): T return t enddef endclass END v9.CheckSourceFailure(lines, 'E1433: Overriding concrete method "Fn" in class "A" with a generic method', 13) lines =<< trim END mnv9script class A def Fn(t: T): T return t enddef endclass class B extends A def Fn(t: X): X return t enddef endclass END v9.CheckSourceFailure(lines, 'E1434: Mismatched number of type variables for generic method "Fn" in class "A"', 13) lines =<< trim END mnv9script class A def Fn(t: X): X return t enddef endclass class B extends A def Fn(t: T): T return t enddef endclass END v9.CheckSourceFailure(lines, 'E1434: Mismatched number of type variables for generic method "Fn" in class "A"', 13) enddef " Test for overriding a generic abstract object method def Test_generic_abstract_object_method_override() var lines =<< trim END mnv9script abstract class A abstract def Fn(t: T): T endclass class B extends A def Fn(t: T): T return t enddef endclass var b = B.new() assert_equal('abc', b.Fn('abc')) assert_equal({a: 10, b: 20}, b.Fn>({a: 10, b: 20})) END v9.CheckSourceSuccess(lines) enddef " Test for failures in overriding a generic abstract method def Test_generic_abstract_method_override_fails() var lines =<< trim END mnv9script abstract class A abstract def Fn(t: T): T endclass class B extends A def Fn(t: number): number return t enddef endclass END v9.CheckSourceFailure(lines, 'E1432: Overriding generic method "Fn" in class "A" with a concrete method', 11) lines =<< trim END mnv9script abstract class A abstract def Fn(t: number): number endclass class B extends A def Fn(t: T): T return t enddef endclass END v9.CheckSourceFailure(lines, 'E1433: Overriding concrete method "Fn" in class "A" with a generic method', 11) lines =<< trim END mnv9script abstract class A abstract def Fn(t: T): T endclass class B extends A def Fn(t: X): X return t enddef endclass END v9.CheckSourceFailure(lines, 'E1434: Mismatched number of type variables for generic method "Fn" in class "A"', 11) lines =<< trim END mnv9script abstract class A abstract def Fn(t: X): X endclass class B extends A def Fn(t: T): T return t enddef endclass END v9.CheckSourceFailure(lines, 'E1434: Mismatched number of type variables for generic method "Fn" in class "A"', 11) enddef " Test for using a generic method to initialize an object member variable def Test_generic_method_in_object_member_init_expr() var lines =<< trim END mnv9script def Id(o: T): T return o enddef class Test def Id(o: T): T return o enddef # call the script-local "Id" function const name: string = Id('Test') # call the object "Id" method const hello: string = this.Id('hello') endclass var t = Test.new() assert_equal('Test', t.name) assert_equal('hello', t.hello) END v9.CheckSourceSuccess(lines) enddef " Test for using generic type variables in the enum constructor def Test_generic_enum_constructor() var lines =<< trim END mnv9script enum CommonPair HelloWorld('hello', 'world'), Booleans(true, false) const _fst: any const _snd: any def new(fst: T, snd: U) this._fst = fst this._snd = snd enddef def string(): string return printf("(%s, %s)", this._fst, this._snd) enddef endenum assert_equal('(hello, world)', string(CommonPair.HelloWorld)) assert_equal('(true, false)', string(CommonPair.Booleans)) END v9.CheckSourceSuccess(lines) enddef " Test for errors in using generic type variables in the enum constructor def Test_generic_enum_constructor_error() var lines =<< trim END mnv9script enum Foo HelloWorld('hello') def new(a: string) enddef endenum END v9.CheckSourceFailure(lines, 'E1560: Not a generic function: new', 6) lines =<< trim END mnv9script enum Foo HelloWorld('hello') endenum END v9.CheckSourceFailure(lines, 'E1560: Not a generic function: new', 4) lines =<< trim END mnv9script enum Foo HelloWorld('hello') def new(a: T) enddef endenum END v9.CheckSourceFailure(lines, "E1559: Type arguments missing for generic function 'new'", 6) lines =<< trim END mnv9script enum Foo HelloWorld('hello') def new(a: T) enddef endenum END v9.CheckSourceFailure(lines, "E1556: Too many types specified for generic function 'new'", 6) lines =<< trim END mnv9script enum Foo HelloWorld('hello') def new(a: A) enddef endenum END v9.CheckSourceFailure(lines, "E1557: Not enough types specified for generic function 'new'", 6) lines =<< trim END mnv9script enum Foo One(), HelloWorld<>() def new() enddef endenum END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function '<>()'", 4) lines =<< trim END mnv9script enum Foo HelloWorld() def new<>() enddef endenum END v9.CheckSourceFailure(lines, "E1555: Empty type list specified for generic function 'new'", 4) lines =<< trim END mnv9script enum Foo One(), Two() def new() enddef endenum END v9.CheckSourceFailure(lines, "E1010: Type not recognized: A", 4) enddef " Test for using more than 10 type arguments def Test_generic_max_type_args() var lines =<< trim END mnv9script def Fn(a1: A1): A1 var x: A1 = a1 return x enddef assert_equal(10, Fn(10)) assert_equal('abc', Fn('abc')) END v9.CheckSourceSuccess(lines) enddef " mnv: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker