From 487177b0a6bd874b51f55c719ad4203129ce8d42 Mon Sep 17 00:00:00 2001 From: degory Date: Mon, 15 Apr 2024 19:40:01 +0200 Subject: [PATCH] Type inference improvements Enhancements: - Generic argument type inference for constructors (see #681) - Generic argument type inference for static method calls --- .config/dotnet-tools.json | 2 +- Directory.Build.props | 2 +- .../.vscode/tasks.json | 23 + .../err.expected | 0 .../ghul.json | 3 + .../ghulflags | 0 .../il.expected | 0 .../run.expected | 3 + .../test.ghul | 18 + .../warn.expected | 0 .../ienumerable-boilerplate/ghul.json | 6 +- .../execution/overload-resolution-2/ghul.json | 5 +- .../overload-resolution-2/test.ghulproj | 15 - .../execution/overload-resolution-3/ghul.json | 5 +- .../overload-resolution-3/test.ghulproj | 15 - .../ghul.json | 5 +- .../test.ghulproj | 13 - .../err.expected | 28 +- .../ghul.json | 5 +- .../test.ghul | 90 +- .../ghul.json | 5 +- .../err.expected | 44 +- .../test.ghul | 48 +- .../err.expected | 6 +- .../test.ghul | 81 +- .../.vscode/tasks.json | 23 + .../err.expected | 1 + .../fail.expected | 1 + .../ghul.json | 3 + .../ghulflags | 1 + .../il.expected | 0 .../test.ghul | 15 + .../warn.expected | 0 .../.vscode/tasks.json | 23 + .../err.expected | 1 + .../fail.expected | 1 + .../ghul.json | 3 + .../ghulflags | 1 + .../il.expected | 0 .../test.ghul | 19 + .../warn.expected | 0 .../generic-function-definition-4/ghul.json | 5 +- .../.vscode/ghul.json | 6 + .../.vscode/tasks.json | 23 + .../err.expected | 1 + .../fail.expected | 1 + .../ghul.json | 3 + .../ghulflags | 1 + .../test.ghul | 22 + .../warn.expected | 0 .../semantic/generic-inheritance/err.expected | 4 +- .../semantic/generic-inheritance/test.ghul | 1057 ++++++++--------- .../semantic/generic-overrides/err.expected | 4 +- .../semantic/generic-overrides/ghul.json | 5 +- .../semantic/generic-overrides/test.ghul | 59 +- .../.vscode/tasks.json | 23 + .../err.expected | 1 + .../fail.expected | 1 + .../generic-static-type-inference-1/ghul.json | 3 + .../generic-static-type-inference-1/ghulflags | 1 + .../il.expected | 0 .../generic-static-type-inference-1/test.ghul | 24 + .../warn.expected | 0 .../.vscode/tasks.json | 23 + .../err.expected | 1 + .../fail.expected | 1 + .../generic-static-type-inference-2/ghul.json | 3 + .../generic-static-type-inference-2/ghulflags | 1 + .../il.expected | 0 .../generic-static-type-inference-2/test.ghul | 25 + .../warn.expected | 0 .../semantic/generic-traits/err.expected | 2 +- .../semantic/generic-traits/ghul.json | 5 +- .../semantic/generic-traits/test.ghul | 103 +- .../generic-type-compatibility/err.expected | 4 +- .../generic-type-compatibility/ghul.json | 5 +- .../generic-type-compatibility/test.ghul | 67 +- .../generic-type-constraints/err.expected | 2 +- .../generic-type-constraints/ghul.json | 5 +- .../generic-type-constraints/il.expected | 0 .../generic-type-constraints/test.ghul | 29 +- .../err.expected | 30 +- .../ghul.json | 5 +- integration-tests/semantic/union-1/ghul.json | 5 +- src/lexical/tokenizer.ghul | 2 +- src/semantic/dotnet/type_mapper.ghul | 15 +- src/semantic/overload_resolver.ghul | 182 ++- src/semantic/symbols/classy.ghul | 10 +- src/semantic/symbols/function.ghul | 44 +- .../symbols/function_generic_argument.ghul | 118 -- src/semantic/symbols/generic.ghul | 58 +- src/semantic/symbols/generic_argument.ghul | 123 +- src/semantic/types/error.ghul | 1 + src/semantic/types/generic.ghul | 21 +- ...ic_argument.ghul => generic_argument.ghul} | 29 +- .../types/generic_argument_bind_results.ghul | 35 +- src/semantic/types/infered_return_type.ghul | 1 + src/semantic/types/type.ghul | 10 + src/syntax/process/compile_expressions.ghul | 76 +- src/syntax/trees/expressions/expression.ghul | 3 +- 100 files changed, 1637 insertions(+), 1165 deletions(-) create mode 100644 integration-tests/execution/generic-constructor-type-inference-1/.vscode/tasks.json create mode 100644 integration-tests/execution/generic-constructor-type-inference-1/err.expected create mode 100644 integration-tests/execution/generic-constructor-type-inference-1/ghul.json create mode 100644 integration-tests/execution/generic-constructor-type-inference-1/ghulflags create mode 100644 integration-tests/execution/generic-constructor-type-inference-1/il.expected create mode 100644 integration-tests/execution/generic-constructor-type-inference-1/run.expected create mode 100644 integration-tests/execution/generic-constructor-type-inference-1/test.ghul create mode 100644 integration-tests/execution/generic-constructor-type-inference-1/warn.expected delete mode 100644 integration-tests/execution/overload-resolution-2/test.ghulproj delete mode 100644 integration-tests/execution/overload-resolution-3/test.ghulproj delete mode 100644 integration-tests/semantic/anonymous-function-argument-name-shadow-local/test.ghulproj create mode 100644 integration-tests/semantic/generic-constructor-type-inference-1/.vscode/tasks.json create mode 100644 integration-tests/semantic/generic-constructor-type-inference-1/err.expected create mode 100644 integration-tests/semantic/generic-constructor-type-inference-1/fail.expected create mode 100644 integration-tests/semantic/generic-constructor-type-inference-1/ghul.json create mode 100644 integration-tests/semantic/generic-constructor-type-inference-1/ghulflags create mode 100644 integration-tests/semantic/generic-constructor-type-inference-1/il.expected create mode 100644 integration-tests/semantic/generic-constructor-type-inference-1/test.ghul create mode 100644 integration-tests/semantic/generic-constructor-type-inference-1/warn.expected create mode 100644 integration-tests/semantic/generic-constructor-type-inference-2/.vscode/tasks.json create mode 100644 integration-tests/semantic/generic-constructor-type-inference-2/err.expected create mode 100644 integration-tests/semantic/generic-constructor-type-inference-2/fail.expected create mode 100644 integration-tests/semantic/generic-constructor-type-inference-2/ghul.json create mode 100644 integration-tests/semantic/generic-constructor-type-inference-2/ghulflags create mode 100644 integration-tests/semantic/generic-constructor-type-inference-2/il.expected create mode 100644 integration-tests/semantic/generic-constructor-type-inference-2/test.ghul create mode 100644 integration-tests/semantic/generic-constructor-type-inference-2/warn.expected create mode 100644 integration-tests/semantic/generic-function-type-inference-1/.vscode/ghul.json create mode 100644 integration-tests/semantic/generic-function-type-inference-1/.vscode/tasks.json create mode 100644 integration-tests/semantic/generic-function-type-inference-1/err.expected create mode 100644 integration-tests/semantic/generic-function-type-inference-1/fail.expected create mode 100644 integration-tests/semantic/generic-function-type-inference-1/ghul.json create mode 100644 integration-tests/semantic/generic-function-type-inference-1/ghulflags create mode 100644 integration-tests/semantic/generic-function-type-inference-1/test.ghul create mode 100644 integration-tests/semantic/generic-function-type-inference-1/warn.expected create mode 100644 integration-tests/semantic/generic-static-type-inference-1/.vscode/tasks.json create mode 100644 integration-tests/semantic/generic-static-type-inference-1/err.expected create mode 100644 integration-tests/semantic/generic-static-type-inference-1/fail.expected create mode 100644 integration-tests/semantic/generic-static-type-inference-1/ghul.json create mode 100644 integration-tests/semantic/generic-static-type-inference-1/ghulflags create mode 100644 integration-tests/semantic/generic-static-type-inference-1/il.expected create mode 100644 integration-tests/semantic/generic-static-type-inference-1/test.ghul create mode 100644 integration-tests/semantic/generic-static-type-inference-1/warn.expected create mode 100644 integration-tests/semantic/generic-static-type-inference-2/.vscode/tasks.json create mode 100644 integration-tests/semantic/generic-static-type-inference-2/err.expected create mode 100644 integration-tests/semantic/generic-static-type-inference-2/fail.expected create mode 100644 integration-tests/semantic/generic-static-type-inference-2/ghul.json create mode 100644 integration-tests/semantic/generic-static-type-inference-2/ghulflags create mode 100644 integration-tests/semantic/generic-static-type-inference-2/il.expected create mode 100644 integration-tests/semantic/generic-static-type-inference-2/test.ghul create mode 100644 integration-tests/semantic/generic-static-type-inference-2/warn.expected create mode 100644 integration-tests/semantic/generic-type-constraints/il.expected delete mode 100644 src/semantic/symbols/function_generic_argument.ghul rename src/semantic/types/{function_generic_argument.ghul => generic_argument.ghul} (55%) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index fed6d995e..38a0e2afa 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "ghul.compiler": { - "version": "0.8.40", + "version": "0.8.41", "commands": [ "ghul-compiler" ] diff --git a/Directory.Build.props b/Directory.Build.props index de95fb8f3..ff68a0442 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 0.8.41-alpha.2 + 0.8.42-alpha.124 $(NoWarn);NU1507 diff --git a/integration-tests/execution/generic-constructor-type-inference-1/.vscode/tasks.json b/integration-tests/execution/generic-constructor-type-inference-1/.vscode/tasks.json new file mode 100644 index 000000000..49063613c --- /dev/null +++ b/integration-tests/execution/generic-constructor-type-inference-1/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Run test", + "command": "dotnet ghul-test \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "test", + "isDefault": true + } + }, + { + "label": "Capture test expectation", + "command": "../../../tasks/capture.sh \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/integration-tests/execution/generic-constructor-type-inference-1/err.expected b/integration-tests/execution/generic-constructor-type-inference-1/err.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/execution/generic-constructor-type-inference-1/ghul.json b/integration-tests/execution/generic-constructor-type-inference-1/ghul.json new file mode 100644 index 000000000..ddcfcf2b1 --- /dev/null +++ b/integration-tests/execution/generic-constructor-type-inference-1/ghul.json @@ -0,0 +1,3 @@ +{ + "compiler": "dotnet ../../../publish/ghul.dll" +} diff --git a/integration-tests/execution/generic-constructor-type-inference-1/ghulflags b/integration-tests/execution/generic-constructor-type-inference-1/ghulflags new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/execution/generic-constructor-type-inference-1/il.expected b/integration-tests/execution/generic-constructor-type-inference-1/il.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/execution/generic-constructor-type-inference-1/run.expected b/integration-tests/execution/generic-constructor-type-inference-1/run.expected new file mode 100644 index 000000000..a813fbe34 --- /dev/null +++ b/integration-tests/execution/generic-constructor-type-inference-1/run.expected @@ -0,0 +1,3 @@ +construct generic_constructor_type_inference_1__test.THING[System.Int32,System.Int32] from System.Int32[] and System.Func`2[System.Int32,System.Int32] +construct generic_constructor_type_inference_1__test.THING[System.Int32,System.String] from System.Int32[] and System.Func`2[System.Int32,System.String] +construct generic_constructor_type_inference_1__test.THING[System.Int32[],System.String[]] from System.Int32[][] and System.Func`2[System.Int32[],System.String[]] diff --git a/integration-tests/execution/generic-constructor-type-inference-1/test.ghul b/integration-tests/execution/generic-constructor-type-inference-1/test.ghul new file mode 100644 index 000000000..892d85be8 --- /dev/null +++ b/integration-tests/execution/generic-constructor-type-inference-1/test.ghul @@ -0,0 +1,18 @@ +use Collections; + +use IO.Std.write_line; + +entry() is + let t_int_int: THING[int,int] = THING([1, 2, 3, 4], x => x + 1); + + let t_string_int: THING[int, string] = THING([1, 2, 3, 4], x => "{x}"); + + let t_iint_istring: THING[int[], string[]] = THING([[1], [2], [3], [4]], x => ["a", "b", "c"]); +si + +class THING[T,U] is + init(input: Iterable[T], mapper: T -> U) is + write_line("construct {self} from {input} and {mapper}"); + si +si + diff --git a/integration-tests/execution/generic-constructor-type-inference-1/warn.expected b/integration-tests/execution/generic-constructor-type-inference-1/warn.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/execution/ienumerable-boilerplate/ghul.json b/integration-tests/execution/ienumerable-boilerplate/ghul.json index bf5e5ade2..ddcfcf2b1 100644 --- a/integration-tests/execution/ienumerable-boilerplate/ghul.json +++ b/integration-tests/execution/ienumerable-boilerplate/ghul.json @@ -1,7 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "other_flags": "--v3", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/execution/overload-resolution-2/ghul.json b/integration-tests/execution/overload-resolution-2/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/execution/overload-resolution-2/ghul.json +++ b/integration-tests/execution/overload-resolution-2/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/execution/overload-resolution-2/test.ghulproj b/integration-tests/execution/overload-resolution-2/test.ghulproj deleted file mode 100644 index 86f6a24ab..000000000 --- a/integration-tests/execution/overload-resolution-2/test.ghulproj +++ /dev/null @@ -1,15 +0,0 @@ - - - Exe - net6.0 - - dotnet ghul-compiler - - - - - - - - - diff --git a/integration-tests/execution/overload-resolution-3/ghul.json b/integration-tests/execution/overload-resolution-3/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/execution/overload-resolution-3/ghul.json +++ b/integration-tests/execution/overload-resolution-3/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/execution/overload-resolution-3/test.ghulproj b/integration-tests/execution/overload-resolution-3/test.ghulproj deleted file mode 100644 index 86f6a24ab..000000000 --- a/integration-tests/execution/overload-resolution-3/test.ghulproj +++ /dev/null @@ -1,15 +0,0 @@ - - - Exe - net6.0 - - dotnet ghul-compiler - - - - - - - - - diff --git a/integration-tests/semantic/anonymous-function-argument-name-shadow-local/ghul.json b/integration-tests/semantic/anonymous-function-argument-name-shadow-local/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/anonymous-function-argument-name-shadow-local/ghul.json +++ b/integration-tests/semantic/anonymous-function-argument-name-shadow-local/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/anonymous-function-argument-name-shadow-local/test.ghulproj b/integration-tests/semantic/anonymous-function-argument-name-shadow-local/test.ghulproj deleted file mode 100644 index d30908032..000000000 --- a/integration-tests/semantic/anonymous-function-argument-name-shadow-local/test.ghulproj +++ /dev/null @@ -1,13 +0,0 @@ - - - Exe - net8.0 - true - - dotnet ghul-compiler - - - - - - diff --git a/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/err.expected b/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/err.expected index d68f06e1d..27a486004 100644 --- a/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/err.expected +++ b/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/err.expected @@ -1,14 +1,14 @@ -test.ghul: 37,13..37,18: error: T is not assignable to Ghul.int -test.ghul: 38,13..38,18: error: U is not assignable to Ghul.string -test.ghul: 43,13..43,18: error: Main.X is not assignable to Ghul.int -test.ghul: 44,13..44,18: error: Main.Y is not assignable to Ghul.string -test.ghul: 46,13..46,25: error: Ghul.object is not assignable to T -test.ghul: 47,13..47,25: error: Ghul.object is not assignable to U -test.ghul: 49,13..49,25: error: Ghul.object is not assignable to Main.X -test.ghul: 50,13..50,25: error: Ghul.object is not assignable to Main.Y -test.ghul: 52,13..52,25: error: Ghul.object is not assignable to Ghul.int -test.ghul: 53,13..53,25: error: Ghul.object is not assignable to Ghul.string -test.ghul: 55,13..55,19: error: Ghul.int is not assignable to T -test.ghul: 56,13..56,24: error: Ghul.string is not assignable to Main.Y -test.ghul: 67,17..67,25: error: Ghul.object is not assignable to T -test.ghul: 68,17..68,25: error: Ghul.object is not assignable to U +test.ghul: 17,9..17,14: error: T is not assignable to Ghul.int +test.ghul: 18,9..18,14: error: U is not assignable to Ghul.string +test.ghul: 23,9..23,14: error: X is not assignable to Ghul.int +test.ghul: 24,9..24,14: error: Y is not assignable to Ghul.string +test.ghul: 26,9..26,21: error: Ghul.object is not assignable to T +test.ghul: 27,9..27,21: error: Ghul.object is not assignable to U +test.ghul: 29,9..29,21: error: Ghul.object is not assignable to X +test.ghul: 30,9..30,21: error: Ghul.object is not assignable to Y +test.ghul: 32,9..32,21: error: Ghul.object is not assignable to Ghul.int +test.ghul: 33,9..33,21: error: Ghul.object is not assignable to Ghul.string +test.ghul: 35,9..35,15: error: Ghul.int is not assignable to T +test.ghul: 36,9..36,20: error: Ghul.string is not assignable to Y +test.ghul: 47,13..47,21: error: Ghul.object is not assignable to T +test.ghul: 48,13..48,21: error: Ghul.object is not assignable to U diff --git a/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/ghul.json b/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/ghul.json +++ b/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/test.ghul b/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/test.ghul index cd5c9ec00..87d9e2896 100644 --- a/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/test.ghul +++ b/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-1/test.ghul @@ -1,70 +1,50 @@ -/* +use Std = IO.Std; -https://github.com/degory/ghul/issues/803 +class Main[X,Y] is + entry() static is + let t = function(123, "hello"); -Function generic argument types should only be wildcards when binding - -Function generic argument types should only be wildcards for purposes of -function overload resolution, but they're currently wildcards for all type -comparisons, including for code within the method. - -the following should result in compile time errors, as the assignments of t and u to i and s involve incompatible types: - -function[T,U](t: T, u: U) -> (T,U) is - let i: int = t; - let s: string = u; -si - -*/ - - - use Std = IO.Std; - - class Main[X,Y] is - entry() static is - let t = function(123, "hello"); - - let u = function([123,456], ["aaa", "bbb"]); - si + let u = function([123,456], ["aaa", "bbb"]); + si - function[T,U](t: T, u: U) -> (t: T,u: U) static is - let i: int; - let j: string; + function[T,U](t: T, u: U) -> (t: T,u: U) static is + let i: int; + let j: string; - let x: X; - let y: Y; + let x: X; + let y: Y; - i = t; // expect error T is not an int - j = u; // expect error U is not a string + i = t; // expect error T is not an int + j = u; // expect error U is not a string - t.to_string(); - x.to_string(); + t.to_string(); + x.to_string(); - i = x; // expect error X is not an int - j = y; // expect error Y is not a string + i = x; // expect error X is not an int + j = y; // expect error Y is not a string - t = object(); // expect error object is not a T - u = object(); // expect error object is not a U + t = object(); // expect error object is not a T + u = object(); // expect error object is not a U - x = object(); // expect error object is not a X - y = object(); // expect error object is not a Y + x = object(); // expect error object is not a X + y = object(); // expect error object is not a Y - i = object(); // expect error object is not an int - j = object(); // expect error object is not a string + i = object(); // expect error object is not an int + j = object(); // expect error object is not a string - t = 10; // expect error int is not a T - y = "hello"; // expect error string is not a Y + t = 10; // expect error int is not a T + y = "hello"; // expect error string is not a Y - let o: object; - let p: object; + let o: object; + let p: object; - o = x; // OK X is an object - p = y; // OK Y is an object + o = x; // OK X is an object + p = y; // OK Y is an object - o = t; // OK T is an object - p = u; // OK U is an object - - let w: T = o; // expect error object is not a T - let z: U = p; // expect error object is not a U - si + o = t; // OK T is an object + p = u; // OK U is an object + + let w: T = o; // expect error object is not a T + let z: U = p; // expect error object is not a U si +si diff --git a/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-2/ghul.json b/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-2/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-2/ghul.json +++ b/integration-tests/semantic/function-generic-argument-type-parameters-not-wild-2/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/generic-arguments-type-compatibility-1/err.expected b/integration-tests/semantic/generic-arguments-type-compatibility-1/err.expected index 18dae29a0..d4d004ba9 100644 --- a/integration-tests/semantic/generic-arguments-type-compatibility-1/err.expected +++ b/integration-tests/semantic/generic-arguments-type-compatibility-1/err.expected @@ -1,26 +1,26 @@ test.ghul: 11,12..11,13: error: cannot return value of type U from function of type T -test.ghul: 26,9..26,17: error: null is not assignable to THING.T -test.ghul: 28,9..28,14: error: THING.U is not assignable to THING.T -test.ghul: 31,16..31,17: error: cannot return value of type THING.U from function of type THING.T -test.ghul: 33,16..33,20: error: cannot return value of type null from function of type THING.T -test.ghul: 44,9..44,17: error: null is not assignable to THING.T -test.ghul: 46,9..46,14: error: THING.U is not assignable to THING.T -test.ghul: 49,16..49,17: error: cannot return value of type THING.U from function of type THING.T -test.ghul: 51,16..51,20: error: cannot return value of type null from function of type THING.T -test.ghul: 58,9..58,15: error: THING.T is not assignable to THING.U +test.ghul: 26,9..26,17: error: null is not assignable to T +test.ghul: 28,9..28,14: error: U is not assignable to T +test.ghul: 31,16..31,17: error: cannot return value of type U from function of type T +test.ghul: 33,16..33,20: error: cannot return value of type null from function of type T +test.ghul: 44,9..44,17: error: null is not assignable to T +test.ghul: 46,9..46,14: error: U is not assignable to T +test.ghul: 49,16..49,17: error: cannot return value of type U from function of type T +test.ghul: 51,16..51,20: error: cannot return value of type null from function of type T +test.ghul: 58,9..58,15: error: T is not assignable to U test.ghul: 6,5..6,13: error: null is not assignable to T -test.ghul: 60,9..60,15: error: THING.U is not assignable to THING.T -test.ghul: 64,9..64,18: error: null is not assignable to THING.T -test.ghul: 65,9..65,18: error: null is not assignable to THING.U +test.ghul: 60,9..60,15: error: U is not assignable to T +test.ghul: 64,9..64,18: error: null is not assignable to T +test.ghul: 65,9..65,18: error: null is not assignable to U test.ghul: 70,14..70,24: error: no static overload found for function(null, null), tried function[T,U](t: T, u: U) -> T -test.ghul: 71,24..71,34: error: no static overload found for function(null, null), tried function[Ghul.int,Ghul.int](t: int, u: int) -> Ghul.int -test.ghul: 72,27..72,37: error: no static overload found for function(null, null), tried function[Ghul.int,Ghul.string](t: int, u: string) -> Ghul.int -test.ghul: 73,27..73,40: error: no static overload found for function(Ghul.string, null), tried function[Ghul.string,Ghul.int](t: string, u: int) -> Ghul.string +test.ghul: 71,23..71,33: error: no static overload found for function(null, null), tried function[Ghul.int,Ghul.int](t: int, u: int) -> Ghul.int +test.ghul: 72,26..72,36: error: no static overload found for function(null, null), tried function[Ghul.int,Ghul.string](t: int, u: string) -> Ghul.int +test.ghul: 73,26..73,39: error: no static overload found for function(Ghul.string, null), tried function[Ghul.string,Ghul.int](t: string, u: int) -> Ghul.string test.ghul: 8,5..8,10: error: U is not assignable to T -test.ghul: 85,30..85,40: error: no static overload found for function(null, null), tried THING[Ghul.int,Ghul.int].function(t: int, u: int) -> Ghul.int -test.ghul: 86,33..86,43: error: no static overload found for function(null, null), tried THING[Ghul.int,Ghul.string].function(t: int, u: string) -> Ghul.int -test.ghul: 87,33..87,43: error: no static overload found for function(null, null), tried THING[Ghul.string,Ghul.int].function(t: string, u: int) -> Ghul.string -test.ghul: 89,30..89,43: error: no static overload found for function(Ghul.int, Ghul.string), tried THING[Ghul.int,Ghul.int].function(t: int, u: int) -> Ghul.int -test.ghul: 90,33..90,43: error: no static overload found for function(Ghul.int, Ghul.int), tried THING[Ghul.int,Ghul.string].function(t: int, u: string) -> Ghul.int -test.ghul: 91,33..91,49: error: no static overload found for function(Ghul.string, Ghul.string), tried THING[Ghul.string,Ghul.int].function(t: string, u: int) -> Ghul.string -test.ghul: 92,36..92,49: error: no static overload found for function(Ghul.string, Ghul.int), tried THING[Ghul.string,Ghul.string].function(t: string, u: string) -> Ghul.string +test.ghul: 85,29..85,39: error: no static overload found for function(null, null), tried THING[Ghul.int,Ghul.int].function(t: int, u: int) -> Ghul.int +test.ghul: 86,32..86,42: error: no static overload found for function(null, null), tried THING[Ghul.int,Ghul.string].function(t: int, u: string) -> Ghul.int +test.ghul: 87,32..87,42: error: no static overload found for function(null, null), tried THING[Ghul.string,Ghul.int].function(t: string, u: int) -> Ghul.string +test.ghul: 89,29..89,42: error: no static overload found for function(Ghul.int, Ghul.string), tried THING[Ghul.int,Ghul.int].function(t: int, u: int) -> Ghul.int +test.ghul: 90,32..90,42: error: no static overload found for function(Ghul.int, Ghul.int), tried THING[Ghul.int,Ghul.string].function(t: int, u: string) -> Ghul.int +test.ghul: 91,32..91,48: error: no static overload found for function(Ghul.string, Ghul.string), tried THING[Ghul.string,Ghul.int].function(t: string, u: int) -> Ghul.string +test.ghul: 92,35..92,48: error: no static overload found for function(Ghul.string, Ghul.int), tried THING[Ghul.string,Ghul.string].function(t: string, u: string) -> Ghul.string diff --git a/integration-tests/semantic/generic-arguments-type-compatibility-1/test.ghul b/integration-tests/semantic/generic-arguments-type-compatibility-1/test.ghul index 6a7aa94b9..b07821e30 100644 --- a/integration-tests/semantic/generic-arguments-type-compatibility-1/test.ghul +++ b/integration-tests/semantic/generic-arguments-type-compatibility-1/test.ghul @@ -68,28 +68,28 @@ si entry() is function(null, null); // error, can't infer types - function`[int,int](null, null); // error, int can't be null - function`[int,string](null, null); // error, int can't be null - function`[string,int]("hello", null); // error, int can't be null - - function`[int,string](1234, null); // OK - function`[string,string]("hello", "world"); // OK - function`[string,string](null, "world"); // OK - function`[string,string]("hello", null); // OK - - THING`[int,int].function(1234, 5678); // OK - THING`[int,string].function(1234, "hello"); // OK - THING`[string,int].function("hello", 1234); // OK - THING`[string,string].function("hello", "world"); - - THING`[int,int].function(null, null); // error int can't be null - THING`[int,string].function(null, null); // error int can't be null - THING`[string,int].function(null, null); // error int can't be null - - THING`[int,int].function(1234, "hello"); // error not the same types - THING`[int,string].function(1234, 5678); // error not the same types - THING`[string,int].function("hello", "world"); // error not the same types - THING`[string,string].function("hello", 1234); // error not the same types - THING`[string,string].function(null, "world"); // OK, string can be null - THING`[string,string].function("hello", null); // OK, string can be null + function[int,int](null, null); // error, int can't be null + function[int,string](null, null); // error, int can't be null + function[string,int]("hello", null); // error, int can't be null + + function[int,string](1234, null); // OK + function[string,string]("hello", "world"); // OK + function[string,string](null, "world"); // OK + function[string,string]("hello", null); // OK + + THING[int,int].function(1234, 5678); // OK + THING[int,string].function(1234, "hello"); // OK + THING[string,int].function("hello", 1234); // OK + THING[string,string].function("hello", "world"); + + THING[int,int].function(null, null); // error int can't be null + THING[int,string].function(null, null); // error int can't be null + THING[string,int].function(null, null); // error int can't be null + + THING[int,int].function(1234, "hello"); // error not the same types + THING[int,string].function(1234, 5678); // error not the same types + THING[string,int].function("hello", "world"); // error not the same types + THING[string,string].function("hello", 1234); // error not the same types + THING[string,string].function(null, "world"); // OK, string can be null + THING[string,string].function("hello", null); // OK, string can be null si diff --git a/integration-tests/semantic/generic-class-arguments-are-objects-1/err.expected b/integration-tests/semantic/generic-class-arguments-are-objects-1/err.expected index 04c0071da..88724ab79 100644 --- a/integration-tests/semantic/generic-class-arguments-are-objects-1/err.expected +++ b/integration-tests/semantic/generic-class-arguments-are-objects-1/err.expected @@ -1,3 +1,3 @@ -test.ghul: 27,20..27,25: error: cannot return value of type Test.GenericClassArgumentsAreObjects.THING.T from function of type Test.GenericClassArgumentsAreObjects.BLAH -test.ghul: 32,19..32,23: error: member blah not found in Test.GenericClassArgumentsAreObjects.THING.T -test.ghul: 37,13..37,25: error: Test.GenericClassArgumentsAreObjects.BLAH is not assignable to Test.GenericClassArgumentsAreObjects.THING.T +test.ghul: 26,16..26,21: error: cannot return value of type T from function of type BLAH +test.ghul: 31,15..31,19: error: member blah not found in T +test.ghul: 36,9..36,21: error: BLAH is not assignable to T diff --git a/integration-tests/semantic/generic-class-arguments-are-objects-1/test.ghul b/integration-tests/semantic/generic-class-arguments-are-objects-1/test.ghul index c8391daef..f17bb15dc 100644 --- a/integration-tests/semantic/generic-class-arguments-are-objects-1/test.ghul +++ b/integration-tests/semantic/generic-class-arguments-are-objects-1/test.ghul @@ -1,45 +1,42 @@ -namespace Test.GenericClassArgumentsAreObjects is - use Collections; +use Collections; - class BLAH is - blah(); +class BLAH is + blah(); +si + +class THING[T] is + value: T; + + init(value: T) is + self.value = value; + si + + to_string() -> string is + // expect OK - to_string() is a method on all objects + return value.to_string(); + si + + to_object() -> object is + // expect OK - T should be assignable to object + return value; + si + + to_blah() -> BLAH is + // expect error - T is not assignable to BLAH + return value; + si + + do_blah() is + // expect error - T does not have a method called blah + value.blah(); + si + + set_from_blah(blah: BLAH) is + // expect error - BLAH is not assignable to T + value = blah; si +si - class THING[T] is - value: T; - - init(value: T) is - self.value = value; - si - - to_string() -> string is - // expect OK - to_string() is a method on all objects - return value.to_string(); - si - - to_object() -> object is - // expect OK - T should be assignable to object - return value; - si - - to_blah() -> BLAH is - // expect error - T is not assignable to BLAH - return value; - si - - do_blah() is - // expect error - T does not have a method called blah - value.blah(); - si - - set_from_blah(blah: BLAH) is - // expect error - BLAH is not assignable to T - value = blah; - si - si - - entry() is - - - si -si \ No newline at end of file +entry() is + +si diff --git a/integration-tests/semantic/generic-constructor-type-inference-1/.vscode/tasks.json b/integration-tests/semantic/generic-constructor-type-inference-1/.vscode/tasks.json new file mode 100644 index 000000000..49063613c --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-1/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Run test", + "command": "dotnet ghul-test \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "test", + "isDefault": true + } + }, + { + "label": "Capture test expectation", + "command": "../../../tasks/capture.sh \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/integration-tests/semantic/generic-constructor-type-inference-1/err.expected b/integration-tests/semantic/generic-constructor-type-inference-1/err.expected new file mode 100644 index 000000000..433fa946a --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-1/err.expected @@ -0,0 +1 @@ +test.ghul: 14,9..14,23: error: Ghul.string is not assignable to Ghul.int diff --git a/integration-tests/semantic/generic-constructor-type-inference-1/fail.expected b/integration-tests/semantic/generic-constructor-type-inference-1/fail.expected new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-1/fail.expected @@ -0,0 +1 @@ + diff --git a/integration-tests/semantic/generic-constructor-type-inference-1/ghul.json b/integration-tests/semantic/generic-constructor-type-inference-1/ghul.json new file mode 100644 index 000000000..ddcfcf2b1 --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-1/ghul.json @@ -0,0 +1,3 @@ +{ + "compiler": "dotnet ../../../publish/ghul.dll" +} diff --git a/integration-tests/semantic/generic-constructor-type-inference-1/ghulflags b/integration-tests/semantic/generic-constructor-type-inference-1/ghulflags new file mode 100644 index 000000000..c19c66676 --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-1/ghulflags @@ -0,0 +1 @@ +--type-check \ No newline at end of file diff --git a/integration-tests/semantic/generic-constructor-type-inference-1/il.expected b/integration-tests/semantic/generic-constructor-type-inference-1/il.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-constructor-type-inference-1/test.ghul b/integration-tests/semantic/generic-constructor-type-inference-1/test.ghul new file mode 100644 index 000000000..e5442ba1b --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-1/test.ghul @@ -0,0 +1,15 @@ +use IO.Std.write_line; + +entry() is + let t_int_int: THING[int,int] = THING(123,456); + + let t_string_int: THING[string, int] = THING("hello", 456); +si + +class THING[T,U] is + init(t: T, u: U) is si +si + +err() is + let x: int = "err"; // deliberate error so we know we got this far +si diff --git a/integration-tests/semantic/generic-constructor-type-inference-1/warn.expected b/integration-tests/semantic/generic-constructor-type-inference-1/warn.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-constructor-type-inference-2/.vscode/tasks.json b/integration-tests/semantic/generic-constructor-type-inference-2/.vscode/tasks.json new file mode 100644 index 000000000..49063613c --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-2/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Run test", + "command": "dotnet ghul-test \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "test", + "isDefault": true + } + }, + { + "label": "Capture test expectation", + "command": "../../../tasks/capture.sh \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/integration-tests/semantic/generic-constructor-type-inference-2/err.expected b/integration-tests/semantic/generic-constructor-type-inference-2/err.expected new file mode 100644 index 000000000..2ecee4883 --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-2/err.expected @@ -0,0 +1 @@ +test.ghul: 18,9..18,23: error: Ghul.string is not assignable to Ghul.int diff --git a/integration-tests/semantic/generic-constructor-type-inference-2/fail.expected b/integration-tests/semantic/generic-constructor-type-inference-2/fail.expected new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-2/fail.expected @@ -0,0 +1 @@ + diff --git a/integration-tests/semantic/generic-constructor-type-inference-2/ghul.json b/integration-tests/semantic/generic-constructor-type-inference-2/ghul.json new file mode 100644 index 000000000..ddcfcf2b1 --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-2/ghul.json @@ -0,0 +1,3 @@ +{ + "compiler": "dotnet ../../../publish/ghul.dll" +} diff --git a/integration-tests/semantic/generic-constructor-type-inference-2/ghulflags b/integration-tests/semantic/generic-constructor-type-inference-2/ghulflags new file mode 100644 index 000000000..c19c66676 --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-2/ghulflags @@ -0,0 +1 @@ +--type-check \ No newline at end of file diff --git a/integration-tests/semantic/generic-constructor-type-inference-2/il.expected b/integration-tests/semantic/generic-constructor-type-inference-2/il.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-constructor-type-inference-2/test.ghul b/integration-tests/semantic/generic-constructor-type-inference-2/test.ghul new file mode 100644 index 000000000..765c5bbeb --- /dev/null +++ b/integration-tests/semantic/generic-constructor-type-inference-2/test.ghul @@ -0,0 +1,19 @@ +use Collections; + +use IO.Std.write_line; + +entry() is + let t_int_int: THING[int,int] = THING([1, 2, 3, 4], x => x + 1); + + let t_string_int: THING[int, string] = THING([1, 2, 3, 4], x => "{x}"); + + let t_iint_istring: THING[int[], string[]] = THING([[1], [2], [3], [4]], x => ["a", "b", "c"]); +si + +class THING[T,U] is + init(input: Iterable[T], mapper: T -> U) is si +si + +err() is + let x: int = "err"; // deliberate error so we know we got this far +si diff --git a/integration-tests/semantic/generic-constructor-type-inference-2/warn.expected b/integration-tests/semantic/generic-constructor-type-inference-2/warn.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-function-definition-4/ghul.json b/integration-tests/semantic/generic-function-definition-4/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/generic-function-definition-4/ghul.json +++ b/integration-tests/semantic/generic-function-definition-4/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/generic-function-type-inference-1/.vscode/ghul.json b/integration-tests/semantic/generic-function-type-inference-1/.vscode/ghul.json new file mode 100644 index 000000000..84539d122 --- /dev/null +++ b/integration-tests/semantic/generic-function-type-inference-1/.vscode/ghul.json @@ -0,0 +1,6 @@ +{ + "compiler": "dotnet ../../../publish/ghul.dll", + "source": [ + "." + ] +} diff --git a/integration-tests/semantic/generic-function-type-inference-1/.vscode/tasks.json b/integration-tests/semantic/generic-function-type-inference-1/.vscode/tasks.json new file mode 100644 index 000000000..49063613c --- /dev/null +++ b/integration-tests/semantic/generic-function-type-inference-1/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Run test", + "command": "dotnet ghul-test \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "test", + "isDefault": true + } + }, + { + "label": "Capture test expectation", + "command": "../../../tasks/capture.sh \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/integration-tests/semantic/generic-function-type-inference-1/err.expected b/integration-tests/semantic/generic-function-type-inference-1/err.expected new file mode 100644 index 000000000..28cd99e49 --- /dev/null +++ b/integration-tests/semantic/generic-function-type-inference-1/err.expected @@ -0,0 +1 @@ +test.ghul: 21,9..21,24: error: Ghul.int is not assignable to Ghul.string diff --git a/integration-tests/semantic/generic-function-type-inference-1/fail.expected b/integration-tests/semantic/generic-function-type-inference-1/fail.expected new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/integration-tests/semantic/generic-function-type-inference-1/fail.expected @@ -0,0 +1 @@ + diff --git a/integration-tests/semantic/generic-function-type-inference-1/ghul.json b/integration-tests/semantic/generic-function-type-inference-1/ghul.json new file mode 100644 index 000000000..ddcfcf2b1 --- /dev/null +++ b/integration-tests/semantic/generic-function-type-inference-1/ghul.json @@ -0,0 +1,3 @@ +{ + "compiler": "dotnet ../../../publish/ghul.dll" +} diff --git a/integration-tests/semantic/generic-function-type-inference-1/ghulflags b/integration-tests/semantic/generic-function-type-inference-1/ghulflags new file mode 100644 index 000000000..489577f22 --- /dev/null +++ b/integration-tests/semantic/generic-function-type-inference-1/ghulflags @@ -0,0 +1 @@ +--dotnet \ No newline at end of file diff --git a/integration-tests/semantic/generic-function-type-inference-1/test.ghul b/integration-tests/semantic/generic-function-type-inference-1/test.ghul new file mode 100644 index 000000000..cf2bc2def --- /dev/null +++ b/integration-tests/semantic/generic-function-type-inference-1/test.ghul @@ -0,0 +1,22 @@ +use Collections; + +// #829 - no longer reproducible + +map[T,U] (xs: Iterable[T], f: T -> U) -> Iterable[U] is +si + +test_anon_function_arg_different_name_function_arg(x: int) is + map([1, 2, 3], y => y + 1); +si + +test_anon_function_arg_shadows_function_arg(x: int) is + map([1, 2, 3], x => x + 1); +si + +test_anon_function_arg_shadows_anon_function_arg() is + map([[1, 2, 3], [4, 5, 6]], x => map(x, x => x + 1)); +si + +entry() is + let x: string = 123; // deliberate error to check we make it this far +si diff --git a/integration-tests/semantic/generic-function-type-inference-1/warn.expected b/integration-tests/semantic/generic-function-type-inference-1/warn.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-inheritance/err.expected b/integration-tests/semantic/generic-inheritance/err.expected index 73650c5fd..04f748e35 100644 --- a/integration-tests/semantic/generic-inheritance/err.expected +++ b/integration-tests/semantic/generic-inheritance/err.expected @@ -1,2 +1,2 @@ -test.ghul: 503,23..503,27: error: cannot return value of type null from function of type Test.GenericInheritance.Thing.T -test.ghul: 510,26..510,30: error: cannot return value of type null from function of type Test.GenericInheritance.Thing.T +test.ghul: 503,19..503,23: error: cannot return value of type null from function of type T +test.ghul: 510,22..510,26: error: cannot return value of type null from function of type T diff --git a/integration-tests/semantic/generic-inheritance/test.ghul b/integration-tests/semantic/generic-inheritance/test.ghul index 03b3aac76..9ff7d63f4 100644 --- a/integration-tests/semantic/generic-inheritance/test.ghul +++ b/integration-tests/semantic/generic-inheritance/test.ghul @@ -1,696 +1,695 @@ -namespace Test.GenericInheritance is - use Std = IO.Std; - use Collections; +use Std = IO.Std; - class Other is - main: Main; +use Collections; - test_main() is - let expect_list_thing_int_1 = main.f_list_thing_int(); - let expect_thing_int_1 = expect_list_thing_int_1[5]; - Main.check_thing_int(expect_thing_int_1); +class Other is + main: Main; - let expect_list_thing_int_2 = main.list_thing_int; - let expect_thing_int_2 = expect_list_thing_int_2[5]; - Main.check_thing_int(expect_thing_int_2); - si + test_main() is + let expect_list_thing_int_1 = main.f_list_thing_int(); + let expect_thing_int_1 = expect_list_thing_int_1[5]; + Main.check_thing_int(expect_thing_int_1); + + let expect_list_thing_int_2 = main.list_thing_int; + let expect_thing_int_2 = expect_list_thing_int_2[5]; + Main.check_thing_int(expect_thing_int_2); si +si - class Main is - thing_int: Thing[int]; - thing_char: Thing[char]; +class Main is + thing_int: Thing[int]; + thing_char: Thing[char]; - list_thing_int: List[Thing[int]]; - list_thing_char: List[Thing[char]]; + list_thing_int: List[Thing[int]]; + list_thing_char: List[Thing[char]]; - f_thing_int() -> Thing[int]; - f_list_thing_int() -> List[Thing[int]]; + f_thing_int() -> Thing[int]; + f_list_thing_int() -> List[Thing[int]]; - check_int(i: int) static; - check_char(c: char) static; - check_string(s: string) static; - check_thing_int(ti: Thing[int]) static; - check_thing_char(tc: Thing[char]) static; - check_list_int(li: List[int]) static; - check_list_char(lc: List[char]) static; + check_int(i: int) static; + check_char(c: char) static; + check_string(s: string) static; + check_thing_int(ti: Thing[int]) static; + check_thing_char(tc: Thing[char]) static; + check_list_int(li: List[int]) static; + check_list_char(lc: List[char]) static; - test_thing_long() is - let tl = ThingLong(); + test_thing_long() is + let tl = ThingLong(); - let l = tl.read_t(); - si + let l = tl.read_t(); + si - test_prop_simple_member() is - let it: Main; + test_prop_simple_member() is + let it: Main; - let ti = it.thing_int; - check_thing_int(ti); - let tc = it.thing_char; + let ti = it.thing_int; + check_thing_int(ti); + let tc = it.thing_char; - let expect_int = ti.read_t(); - check_int(expect_int); - let expect_char = tc.read_t(); - check_char(expect_char); + let expect_int = ti.read_t(); + check_int(expect_int); + let expect_char = tc.read_t(); + check_char(expect_char); - let expect_thing_int = ti.read_thing(); - check_thing_int(expect_thing_int); - si + let expect_thing_int = ti.read_thing(); + check_thing_int(expect_thing_int); + si - test_prop_simple() is - let ti = thing_int; - check_thing_int(ti); - let tc = thing_char; + test_prop_simple() is + let ti = thing_int; + check_thing_int(ti); + let tc = thing_char; - let expect_int = ti.read_t(); - check_int(expect_int); - let expect_char = tc.read_t(); - check_char(expect_char); + let expect_int = ti.read_t(); + check_int(expect_int); + let expect_char = tc.read_t(); + check_char(expect_char); - let expect_thing_int = ti.read_thing(); - check_thing_int(expect_thing_int); - si + let expect_thing_int = ti.read_thing(); + check_thing_int(expect_thing_int); + si - test_func_simple() is - let ti = f_thing_int(); - check_thing_int(ti); - let lti = f_list_thing_int(); + test_func_simple() is + let ti = f_thing_int(); + check_thing_int(ti); + let lti = f_list_thing_int(); - let expect_int = ti.read_t(); - check_int(expect_int); - let expect_thing_int = lti[5]; - check_thing_int(expect_thing_int); - si + let expect_int = ti.read_t(); + check_int(expect_int); + let expect_thing_int = lti[5]; + check_thing_int(expect_thing_int); + si - test_prop_generic_direct() is - let expect_thing_int = list_thing_int[5]; - check_thing_int(expect_thing_int); - si + test_prop_generic_direct() is + let expect_thing_int = list_thing_int[5]; + check_thing_int(expect_thing_int); + si - test_prop_generic_indirect() is - let expect_list_thing_int = list_thing_int; + test_prop_generic_indirect() is + let expect_list_thing_int = list_thing_int; - let expect_thing_int = expect_list_thing_int[5]; - check_thing_int(expect_thing_int); + let expect_thing_int = expect_list_thing_int[5]; + check_thing_int(expect_thing_int); - let expect_iterator_thing_int = expect_list_thing_int.iterator; + let expect_iterator_thing_int = expect_list_thing_int.iterator; - let expect_thing_int_2 = expect_iterator_thing_int.current; - check_thing_int(expect_thing_int_2); + let expect_thing_int_2 = expect_iterator_thing_int.current; + check_thing_int(expect_thing_int_2); - let ti = list_thing_int[5]; - check_thing_int(ti); - si + let ti = list_thing_int[5]; + check_thing_int(ti); + si - test_local_generic() is - let list_thing_int: List[Thing[int]]; + test_local_generic() is + let list_thing_int: List[Thing[int]]; - let expect_thing_int_1 = list_thing_int[5]; - check_thing_int(expect_thing_int_1); + let expect_thing_int_1 = list_thing_int[5]; + check_thing_int(expect_thing_int_1); - let expect_iterator_thing_int = list_thing_int.iterator; - - let expect_thing_int_2 = expect_iterator_thing_int.current; - check_thing_int(expect_thing_int_2); + let expect_iterator_thing_int = list_thing_int.iterator; + + let expect_thing_int_2 = expect_iterator_thing_int.current; + check_thing_int(expect_thing_int_2); - let ti = list_thing_int[5]; - check_thing_int(ti); - si + let ti = list_thing_int[5]; + check_thing_int(ti); + si - test_prop_generic_indirect_explicit_type() is - let expect_list_int: List[Thing[int]] = list_thing_int; + test_prop_generic_indirect_explicit_type() is + let expect_list_int: List[Thing[int]] = list_thing_int; - let expect_thing_int = expect_list_int[5]; + let expect_thing_int = expect_list_int[5]; - check_thing_int(expect_thing_int); - si - - test(it: DirectInheritNoParameters) is - let expect_int = it.read_t(); - check_int(expect_int); - it.write_t(expect_int); + check_thing_int(expect_thing_int); + si + + test(it: DirectInheritNoParameters) is + let expect_int = it.read_t(); + check_int(expect_int); + it.write_t(expect_int); + + let expect_thing_int = it.read_thing(); + check_thing_int(expect_thing_int); + it.write_thing(expect_thing_int); + + let expect_list = it.read_list(); + check_list_int(expect_list); + it.write_list(expect_list); + + let prop_int = it.stuff_t; + check_int(prop_int); - let expect_thing_int = it.read_thing(); - check_thing_int(expect_thing_int); - it.write_thing(expect_thing_int); + let prop_thing = it.stuff_thing; + check_thing_int(prop_thing); - let expect_list = it.read_list(); - check_list_int(expect_list); - it.write_list(expect_list); + let prop_list = it.stuff_list; + check_list_int(prop_list); - let prop_int = it.stuff_t; - check_int(prop_int); + let ii = prop_list[5]; + check_int(ii); - let prop_thing = it.stuff_thing; - check_thing_int(prop_thing); + let indexed_iterable_int = it[prop_thing]; + check_int(indexed_iterable_int.iterator.current); + si + + testDirectInheritNoParameters() is + let it = DirectInheritNoParameters(); + + let expect_int = it.read_t(); + check_int(expect_int); + it.write_t(expect_int); + + let expect_thing_int = it.read_thing(); + check_thing_int(expect_thing_int); + it.write_thing(expect_thing_int); + + let expect_list = it.read_list(); + check_list_int(expect_list); + it.write_list(expect_list); + + let prop_int = it.stuff_t; + check_int(prop_int); + let prop_thing = it.stuff_thing; + check_thing_int(prop_thing); + let prop_list = it.stuff_list; + check_list_int(prop_list); + + let ii = prop_list[5]; + check_int(ii); - let prop_list = it.stuff_list; - check_list_int(prop_list); + let indexed_iterable_int = it[prop_thing]; + check_int(indexed_iterable_int.iterator.current); // wrong T + si - let ii = prop_list[5]; - check_int(ii); + testDirectInheritDummyParameter() is + let it = DirectInheritDummyParameter[short](); - let indexed_iterable_int = it[prop_thing]; - check_int(indexed_iterable_int.iterator.current); - si + let expect_int = it.read_t(); + check_int(expect_int); + it.write_t(expect_int); + + let expect_thing_int = it.read_thing(); + check_thing_int(expect_thing_int); + it.write_thing(expect_thing_int); + + let expect_list = it.read_list(); + check_list_int(expect_list); + it.write_list(expect_list); + + let prop_int = it.stuff_t; + check_int(prop_int); + let prop_thing = it.stuff_thing; + check_thing_int(prop_thing); + let prop_list = it.stuff_list; + check_list_int(prop_list); + + let ii = prop_list[5]; + check_int(ii); + + let indexed_iterable_int = it[prop_thing]; + check_int(indexed_iterable_int.iterator.current); + si - testDirectInheritNoParameters() is - let it = DirectInheritNoParameters(); + testIndirectInheritDummyParameter() is + let it = IndirectInheritDummyParameter[long](); - let expect_int = it.read_t(); - check_int(expect_int); - it.write_t(expect_int); - - let expect_thing_int = it.read_thing(); - check_thing_int(expect_thing_int); - it.write_thing(expect_thing_int); - - let expect_list = it.read_list(); - check_list_int(expect_list); - it.write_list(expect_list); - - let prop_int = it.stuff_t; - check_int(prop_int); - let prop_thing = it.stuff_thing; - check_thing_int(prop_thing); - let prop_list = it.stuff_list; - check_list_int(prop_list); - - let ii = prop_list[5]; - check_int(ii); - - let indexed_iterable_int = it[prop_thing]; - check_int(indexed_iterable_int.iterator.current); // wrong T - si - - testDirectInheritDummyParameter() is - let it = DirectInheritDummyParameter[short](); - - let expect_int = it.read_t(); - check_int(expect_int); - it.write_t(expect_int); - - let expect_thing_int = it.read_thing(); - check_thing_int(expect_thing_int); - it.write_thing(expect_thing_int); - - let expect_list = it.read_list(); - check_list_int(expect_list); - it.write_list(expect_list); - - let prop_int = it.stuff_t; - check_int(prop_int); - let prop_thing = it.stuff_thing; - check_thing_int(prop_thing); - let prop_list = it.stuff_list; - check_list_int(prop_list); - - let ii = prop_list[5]; - check_int(ii); - - let indexed_iterable_int = it[prop_thing]; - check_int(indexed_iterable_int.iterator.current); - si - - testIndirectInheritDummyParameter() is - let it = IndirectInheritDummyParameter[long](); - - let expect_int = it.read_t(); - check_int(expect_int); - it.write_t(expect_int); - - let expect_thing_int = it.read_thing(); - check_thing_int(expect_thing_int); - it.write_thing(expect_thing_int); - - let expect_list = it.read_list(); - check_list_int(expect_list); - it.write_list(expect_list); + let expect_int = it.read_t(); + check_int(expect_int); + it.write_t(expect_int); - let prop_int = it.stuff_t; - check_int(prop_int); - let prop_thing = it.stuff_thing; - check_thing_int(prop_thing); - let prop_list = it.stuff_list; - check_list_int(prop_list); + let expect_thing_int = it.read_thing(); + check_thing_int(expect_thing_int); + it.write_thing(expect_thing_int); - let ii = prop_list[5]; - check_int(ii); + let expect_list = it.read_list(); + check_list_int(expect_list); + it.write_list(expect_list); - let indexed_iterable_int = it[prop_thing]; - check_int(indexed_iterable_int.iterator.current); - si + let prop_int = it.stuff_t; + check_int(prop_int); + let prop_thing = it.stuff_thing; + check_thing_int(prop_thing); + let prop_list = it.stuff_list; + check_list_int(prop_list); - testIndirectInheritTwoDummyParameters() is - let it = IndirectInheritTwoDummyParameters[bool](); + let ii = prop_list[5]; + check_int(ii); - let expect_int = it.read_t(); - check_int(expect_int); - it.write_t(expect_int); - - let expect_thing_int = it.read_thing(); - check_thing_int(expect_thing_int); - it.write_thing(expect_thing_int); - - let expect_list = it.read_list(); - check_list_int(expect_list); - it.write_list(expect_list); - - let prop_int = it.stuff_t; - check_int(prop_int); - let prop_thing = it.stuff_thing; - check_thing_int(prop_thing); - let prop_list = it.stuff_list; - check_list_int(prop_list); - - let ii = prop_list[5]; - check_int(ii); + let indexed_iterable_int = it[prop_thing]; + check_int(indexed_iterable_int.iterator.current); + si + + testIndirectInheritTwoDummyParameters() is + let it = IndirectInheritTwoDummyParameters[bool](); + + let expect_int = it.read_t(); + check_int(expect_int); + it.write_t(expect_int); + + let expect_thing_int = it.read_thing(); + check_thing_int(expect_thing_int); + it.write_thing(expect_thing_int); + + let expect_list = it.read_list(); + check_list_int(expect_list); + it.write_list(expect_list); + + let prop_int = it.stuff_t; + check_int(prop_int); + let prop_thing = it.stuff_thing; + check_thing_int(prop_thing); + let prop_list = it.stuff_list; + check_list_int(prop_list); + + let ii = prop_list[5]; + check_int(ii); + + let indexed_iterable_int = it[prop_thing]; + check_int(indexed_iterable_int.iterator.current); + si - let indexed_iterable_int = it[prop_thing]; - check_int(indexed_iterable_int.iterator.current); - si - /* - // suspect this one makes other ones work + // suspect this one makes other ones work - test(it: DirectInheritWithParameter[int]) is - let expect_int = it.read_t(); // correct int - it.write_t(expect_int); // correct int + test(it: DirectInheritWithParameter[int]) is + let expect_int = it.read_t(); // correct int + it.write_t(expect_int); // correct int - let expect_thing_int = it.read_thing(); // correct Thing[int] - it.write_thing(expect_thing_int); // correct Thing[int] + let expect_thing_int = it.read_thing(); // correct Thing[int] + it.write_thing(expect_thing_int); // correct Thing[int] - let expect_list = it.read_list(); // correct List[int] - it.write_list(expect_list); // correct List[int] - si + let expect_list = it.read_list(); // correct List[int] + it.write_list(expect_list); // correct List[int] + si */ - // this one makes the one below work: + // this one makes the one below work: /* - test(it: DirectInheritWithParameter[char]) is - let expect_char = it.read_t(); // correct char - it.write_t(expect_char); // correct char + test(it: DirectInheritWithParameter[char]) is + let expect_char = it.read_t(); // correct char + it.write_t(expect_char); // correct char - let expect_thing_char = it.read_thing(); // correct Thing[char] - it.write_thing(expect_thing_char); // correct Thing[char] + let expect_thing_char = it.read_thing(); // correct Thing[char] + it.write_thing(expect_thing_char); // correct Thing[char] - let expect_list = it.read_list(); // correct List[char] - it.write_list(expect_list); // correct List[char] - si + let expect_list = it.read_list(); // correct List[char] + it.write_list(expect_list); // correct List[char] + si */ - testIndirectInheritWithParameterChar() is - let it = IndirectInheritWithParameter[char](); + testIndirectInheritWithParameterChar() is + let it = IndirectInheritWithParameter[char](); - let expect_char = it.read_t(); - check_char(expect_char); - it.write_t(expect_char); + let expect_char = it.read_t(); + check_char(expect_char); + it.write_t(expect_char); - let expect_thing_char = it.read_thing(); - it.write_thing(expect_thing_char); - check_thing_char(expect_thing_char); + let expect_thing_char = it.read_thing(); + it.write_thing(expect_thing_char); + check_thing_char(expect_thing_char); - let expect_list_char = it.read_list(); - it.write_list(expect_list_char); - check_list_char(expect_list_char); + let expect_list_char = it.read_list(); + it.write_list(expect_list_char); + check_list_char(expect_list_char); - let prop_char = it.stuff_t; - check_char(prop_char); - let prop_thing = it.stuff_thing; - let prop_list = it.stuff_list; + let prop_char = it.stuff_t; + check_char(prop_char); + let prop_thing = it.stuff_thing; + let prop_list = it.stuff_list; - let ic = prop_list[5]; - check_char(ic); - - let indexed_iterable_char = it[prop_thing]; - check_char(indexed_iterable_char.iterator.current); - si + let ic = prop_list[5]; + check_char(ic); + + let indexed_iterable_char = it[prop_thing]; + check_char(indexed_iterable_char.iterator.current); + si - testIndirectInheritWithParameterInt() is - let it = IndirectInheritWithParameter[int](); + testIndirectInheritWithParameterInt() is + let it = IndirectInheritWithParameter[int](); - let expect_int = it.read_t(); - check_int(expect_int); - it.write_t(expect_int); + let expect_int = it.read_t(); + check_int(expect_int); + it.write_t(expect_int); - let expect_thing_int = it.read_thing(); - check_thing_int(expect_thing_int); - it.write_thing(expect_thing_int); + let expect_thing_int = it.read_thing(); + check_thing_int(expect_thing_int); + it.write_thing(expect_thing_int); - let expect_list = it.read_list(); - check_list_int(expect_list); - it.write_list(expect_list); + let expect_list = it.read_list(); + check_list_int(expect_list); + it.write_list(expect_list); - let prop_int = it.stuff_t; - check_int(prop_int); - let prop_thing = it.stuff_thing; - check_thing_int(prop_thing); - let prop_list = it.stuff_list; - check_list_int(prop_list); + let prop_int = it.stuff_t; + check_int(prop_int); + let prop_thing = it.stuff_thing; + check_thing_int(prop_thing); + let prop_list = it.stuff_list; + check_list_int(prop_list); - let ii = prop_list[5]; - check_int(ii); + let ii = prop_list[5]; + check_int(ii); - let indexed_iterable_int = it.stuff_iterable; // it[prop_thing]; - check_int(indexed_iterable_int.iterator.current); // wrong T - si + let indexed_iterable_int = it.stuff_iterable; // it[prop_thing]; + check_int(indexed_iterable_int.iterator.current); // wrong T + si - testIndirectInheritWithParameterInt2() is - let it = IndirectInheritWithParameter[int](); - let ct = IndirectInheritWithParameter[char](); + testIndirectInheritWithParameterInt2() is + let it = IndirectInheritWithParameter[int](); + let ct = IndirectInheritWithParameter[char](); - let expect_int = it.read_t(); - check_int(expect_int); - it.write_t(expect_int); + let expect_int = it.read_t(); + check_int(expect_int); + it.write_t(expect_int); - let expect_thing_int = it.read_thing(); - check_thing_int(expect_thing_int); - it.write_thing(expect_thing_int); + let expect_thing_int = it.read_thing(); + check_thing_int(expect_thing_int); + it.write_thing(expect_thing_int); - let expect_thing_char = ct.read_thing(); - + let expect_thing_char = ct.read_thing(); + - let expect_list = it.read_list(); - check_list_int(expect_list); - it.write_list(expect_list); + let expect_list = it.read_list(); + check_list_int(expect_list); + it.write_list(expect_list); - let prop_int = it.stuff_t; - check_int(prop_int); - let prop_thing = it.stuff_thing; - check_thing_int(prop_thing); - let prop_list = it.stuff_list; - check_list_int(prop_list); + let prop_int = it.stuff_t; + check_int(prop_int); + let prop_thing = it.stuff_thing; + check_thing_int(prop_thing); + let prop_list = it.stuff_list; + check_list_int(prop_list); - let ii = prop_list[5]; - check_int(ii); + let ii = prop_list[5]; + check_int(ii); - let indexed_iterable_int = it.stuff_iterable; // it[prop_thing]; - check_int(indexed_iterable_int.iterator.current); // wrong T - si + let indexed_iterable_int = it.stuff_iterable; // it[prop_thing]; + check_int(indexed_iterable_int.iterator.current); // wrong T + si - testIndirectInheritWithBoundParameter() is - let it = IndirectInheritWithBoundParameter(); + testIndirectInheritWithBoundParameter() is + let it = IndirectInheritWithBoundParameter(); - let expect_char = it.read_t(); - check_char(expect_char); - it.write_t(expect_char); + let expect_char = it.read_t(); + check_char(expect_char); + it.write_t(expect_char); - let expect_thing_char = it.read_thing(); + let expect_thing_char = it.read_thing(); - it.write_thing(expect_thing_char); + it.write_thing(expect_thing_char); - let expect_list_char = it.read_list(); - it.write_list(expect_list_char); + let expect_list_char = it.read_list(); + it.write_list(expect_list_char); - let prop_char = it.stuff_t; - check_char(prop_char); - let prop_thing = it.stuff_thing; - let prop_list = it.stuff_list; + let prop_char = it.stuff_t; + check_char(prop_char); + let prop_thing = it.stuff_thing; + let prop_list = it.stuff_list; - let ic = prop_list[5]; - check_char(ic); + let ic = prop_list[5]; + check_char(ic); - let indexed_iterable_char = it[prop_thing]; - check_char(indexed_iterable_char.iterator.current); - si - - /* - // uncommenting this function makes some functions below work: - testDirectInheritWithParameterExplicitType() is - let it: DirectInheritWithParameter[char]; + let indexed_iterable_char = it[prop_thing]; + check_char(indexed_iterable_char.iterator.current); + si + + /* + // uncommenting this function makes some functions below work: + testDirectInheritWithParameterExplicitType() is + let it: DirectInheritWithParameter[char]; - let expect_char = it.read_t(); - it.write_t(expect_char); + let expect_char = it.read_t(); + it.write_t(expect_char); - let expect_thing_char = it.read_thing(); - it.write_thing(expect_thing_char); + let expect_thing_char = it.read_thing(); + it.write_thing(expect_thing_char); - let expect_list_char = it.read_list(); - it.write_list(expect_list_char); - si - */ + let expect_list_char = it.read_list(); + it.write_list(expect_list_char); + si + */ - testDirectInheritWithParameterInferredType() is - let it = DirectInheritWithParameter[char](); + testDirectInheritWithParameterInferredType() is + let it = DirectInheritWithParameter[char](); - let expect_char = it.read_t(); - it.write_t(expect_char); + let expect_char = it.read_t(); + it.write_t(expect_char); - let expect_thing_char = it.read_thing(); - it.write_thing(expect_thing_char); + let expect_thing_char = it.read_thing(); + it.write_thing(expect_thing_char); - let expect_list_char = it.read_list(); - it.write_list(expect_list_char); + let expect_list_char = it.read_list(); + it.write_list(expect_list_char); - let prop_char = it.stuff_t; - let prop_thing = it.stuff_thing; - let prop_list = it.stuff_list; - si + let prop_char = it.stuff_t; + let prop_thing = it.stuff_thing; + let prop_list = it.stuff_list; + si - testIndirectInheritWithParameterString() is - let it = IndirectInheritWithParameter[string](); + testIndirectInheritWithParameterString() is + let it = IndirectInheritWithParameter[string](); - let expect_string = it.read_t(); - it.write_t(expect_string); + let expect_string = it.read_t(); + it.write_t(expect_string); - let expect_thing_string = it.read_thing(); - it.write_thing(expect_thing_string); + let expect_thing_string = it.read_thing(); + it.write_thing(expect_thing_string); - let expect_list = it.read_list(); - it.write_list(expect_list); - - let prop_string = it.stuff_t; - let prop_thing = it.stuff_thing; - let prop_list = it.stuff_list; - si + let expect_list = it.read_list(); + it.write_list(expect_list); - /* - // uncommenting this function makes some functions above work: - testDirectInheritWithParameterExplicitType() is - let it: DirectInheritWithParameter[char]; + let prop_string = it.stuff_t; + let prop_thing = it.stuff_thing; + let prop_list = it.stuff_list; + si + + /* + // uncommenting this function makes some functions above work: + testDirectInheritWithParameterExplicitType() is + let it: DirectInheritWithParameter[char]; - let expect_char = it.read_t(); - it.write_t(expect_char); + let expect_char = it.read_t(); + it.write_t(expect_char); - let expect_thing_char = it.read_thing(); - it.write_thing(expect_thing_char); + let expect_thing_char = it.read_thing(); + it.write_thing(expect_thing_char); - let expect_list_char = it.read_list(); - it.write_list(expect_list_char); - si - */ + let expect_list_char = it.read_list(); + it.write_list(expect_list_char); + si + */ - testIndirectInheritNoParametersInferredType() is - let it = IndirectInheritNoParameters(); + testIndirectInheritNoParametersInferredType() is + let it = IndirectInheritNoParameters(); - let expect_int = it.read_t(); - it.write_t(expect_int); + let expect_int = it.read_t(); + it.write_t(expect_int); - let expect_thing_int = it.read_thing(); - it.write_thing(expect_thing_int); + let expect_thing_int = it.read_thing(); + it.write_thing(expect_thing_int); - let expect_list_int = it.read_list(); - it.write_list(expect_list_int); + let expect_list_int = it.read_list(); + it.write_list(expect_list_int); - let prop_int = it.stuff_t; - let prop_thing = it.stuff_thing; - let prop_list = it.stuff_list; - si + let prop_int = it.stuff_t; + let prop_thing = it.stuff_thing; + let prop_list = it.stuff_list; si +si - class Thing[T] is - stuff_thing: Thing[T] => null; - stuff_t: T => null; - stuff_list: List[T] => null; - stuff_iterable: Iterable[T] => null; +class Thing[T] is + stuff_thing: Thing[T] => null; + stuff_t: T => null; + stuff_list: List[T] => null; + stuff_iterable: Iterable[T] => null; - [index: Thing[T]]: Iterable[T] => null; + [index: Thing[T]]: Iterable[T] => null; - read_thing() -> Thing[T] => null; - read_t() -> T => null; - read_list() -> List[T] => null; + read_thing() -> Thing[T] => null; + read_t() -> T => null; + read_list() -> List[T] => null; - write_thing(t: Thing[T]); - write_t(t: T); - write_list(l: List[T]); - si + write_thing(t: Thing[T]); + write_t(t: T); + write_list(l: List[T]); +si - class ThingLong: Thing[long] is - init() is si - si +class ThingLong: Thing[long] is + init() is si +si - class DirectInheritNoParameters: Thing[int] is - init() is si +class DirectInheritNoParameters: Thing[int] is + init() is si - test() is - let expect_int = read_t(); - write_t(expect_int); + test() is + let expect_int = read_t(); + write_t(expect_int); - let expect_thing_int = read_thing(); - write_thing(expect_thing_int); + let expect_thing_int = read_thing(); + write_thing(expect_thing_int); - let expect_list = read_list(); - write_list(expect_list); + let expect_list = read_list(); + write_list(expect_list); - let prop_int = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_int = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si +si - class DirectInheritDummyParameter[X]: Thing[int] is - init() is si +class DirectInheritDummyParameter[X]: Thing[int] is + init() is si - test() is - let expect_int = read_t(); - Main.check_int(expect_int); - write_t(expect_int); + test() is + let expect_int = read_t(); + Main.check_int(expect_int); + write_t(expect_int); - let expect_thing_int = read_thing(); - Main.check_thing_int(expect_thing_int); - write_thing(expect_thing_int); + let expect_thing_int = read_thing(); + Main.check_thing_int(expect_thing_int); + write_thing(expect_thing_int); - let expect_list = read_list(); - Main.check_list_int(expect_list); - write_list(expect_list); + let expect_list = read_list(); + Main.check_list_int(expect_list); + write_list(expect_list); - let prop_int = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_int = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si +si - class IndirectInheritNoParameters: DirectInheritNoParameters is - init() is si +class IndirectInheritNoParameters: DirectInheritNoParameters is + init() is si - test() is - let expect_int = read_t(); - write_t(expect_int); + test() is + let expect_int = read_t(); + write_t(expect_int); - let expect_thing_int = read_thing(); - write_thing(expect_thing_int); + let expect_thing_int = read_thing(); + write_thing(expect_thing_int); - let expect_list = read_list(); - write_list(expect_list); + let expect_list = read_list(); + write_list(expect_list); - let prop_int = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_int = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si +si - class DoubleIndirectNoParameters: IndirectInheritNoParameters is - test() is - let expect_int = read_t(); - Main.check_int(expect_int); - write_t(expect_int); +class DoubleIndirectNoParameters: IndirectInheritNoParameters is + test() is + let expect_int = read_t(); + Main.check_int(expect_int); + write_t(expect_int); - let expect_thing_int = read_thing(); - Main.check_thing_int(expect_thing_int); - write_thing(expect_thing_int); + let expect_thing_int = read_thing(); + Main.check_thing_int(expect_thing_int); + write_thing(expect_thing_int); - let expect_list = read_list(); - Main.check_list_int(expect_list); - write_list(expect_list); + let expect_list = read_list(); + Main.check_list_int(expect_list); + write_list(expect_list); - let prop_int = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_int = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si +si - class IndirectInheritTwoDummyParameters[Y]: DirectInheritDummyParameter[Y] is - init() is si +class IndirectInheritTwoDummyParameters[Y]: DirectInheritDummyParameter[Y] is + init() is si - test() is - let expect_int = read_t(); - write_t(expect_int); + test() is + let expect_int = read_t(); + write_t(expect_int); - let expect_thing_int = read_thing(); - write_thing(expect_thing_int); + let expect_thing_int = read_thing(); + write_thing(expect_thing_int); - let expect_list = read_list(); - write_list(expect_list); + let expect_list = read_list(); + write_list(expect_list); - let prop_int = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_int = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si +si - class IndirectInheritDummyParameter[Y]: DirectInheritNoParameters is - init() is si +class IndirectInheritDummyParameter[Y]: DirectInheritNoParameters is + init() is si - test() is - let expect_int = read_t(); - write_t(expect_int); + test() is + let expect_int = read_t(); + write_t(expect_int); - let expect_thing_int = read_thing(); - write_thing(expect_thing_int); + let expect_thing_int = read_thing(); + write_thing(expect_thing_int); - let expect_list = read_list(); - write_list(expect_list); + let expect_list = read_list(); + write_list(expect_list); - let prop_int = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_int = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si +si - class DirectInheritWithParameter[U]: Thing[U] is - init() is si +class DirectInheritWithParameter[U]: Thing[U] is + init() is si - test() is - let expect_u = read_t(); - write_t(expect_u); + test() is + let expect_u = read_t(); + write_t(expect_u); - let expect_thing_u = read_thing(); - write_thing(expect_thing_u); + let expect_thing_u = read_thing(); + write_thing(expect_thing_u); - let expect_list = read_list(); - write_list(expect_list); + let expect_list = read_list(); + write_list(expect_list); - let prop_u = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_u = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si +si - class IndirectInheritWithParameter[V]: DirectInheritWithParameter[V] is - init() is si +class IndirectInheritWithParameter[V]: DirectInheritWithParameter[V] is + init() is si - test() is - let expect_v = read_t(); - write_t(expect_v); + test() is + let expect_v = read_t(); + write_t(expect_v); - let expect_thing_v = read_thing(); - write_thing(expect_thing_v); + let expect_thing_v = read_thing(); + write_thing(expect_thing_v); - let expect_list = read_list(); - write_list(expect_list); + let expect_list = read_list(); + write_list(expect_list); - let prop_v = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_v = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si +si - class IndirectInheritWithBoundParameter: DirectInheritWithParameter[char] is - init() is si +class IndirectInheritWithBoundParameter: DirectInheritWithParameter[char] is + init() is si - test() is - let expect_char = read_t(); - write_t(expect_char); + test() is + let expect_char = read_t(); + write_t(expect_char); - let expect_thing_char = read_thing(); - write_thing(expect_thing_char); + let expect_thing_char = read_thing(); + write_thing(expect_thing_char); - let expect_list = read_list(); - write_list(expect_list); + let expect_list = read_list(); + write_list(expect_list); - let prop_char = stuff_t; - let prop_thing = stuff_thing; - let prop_list = stuff_list; - si + let prop_char = stuff_t; + let prop_thing = stuff_thing; + let prop_list = stuff_list; si -si \ No newline at end of file +si diff --git a/integration-tests/semantic/generic-overrides/err.expected b/integration-tests/semantic/generic-overrides/err.expected index 43f818621..008d6b5b1 100644 --- a/integration-tests/semantic/generic-overrides/err.expected +++ b/integration-tests/semantic/generic-overrides/err.expected @@ -1,2 +1,2 @@ -test.ghul: 15,26..15,30: error: cannot return value of type null from function of type Test.GenericInheritance.Thing.T -test.ghul: 6,23..6,27: error: cannot return value of type null from function of type Test.GenericInheritance.Thing.T +test.ghul: 15,22..15,26: error: cannot return value of type null from function of type T +test.ghul: 6,19..6,23: error: cannot return value of type null from function of type T diff --git a/integration-tests/semantic/generic-overrides/ghul.json b/integration-tests/semantic/generic-overrides/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/generic-overrides/ghul.json +++ b/integration-tests/semantic/generic-overrides/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/generic-overrides/test.ghul b/integration-tests/semantic/generic-overrides/test.ghul index e595857d0..f94c8cacc 100644 --- a/integration-tests/semantic/generic-overrides/test.ghul +++ b/integration-tests/semantic/generic-overrides/test.ghul @@ -1,42 +1,41 @@ -namespace Test.GenericInheritance is - use Collections; - class Thing[T] is - stuff_thing: Thing[T] => null; - stuff_t: T => null; - stuff_list: List[T] => null; - stuff_iterable: Iterable[T] => null; +use Collections; - [index: Thing[T]]: Iterable[T] => null; +class Thing[T] is + stuff_thing: Thing[T] => null; + stuff_t: T => null; + stuff_list: List[T] => null; + stuff_iterable: Iterable[T] => null; - init() is si + [index: Thing[T]]: Iterable[T] => null; - read_thing() -> Thing[T] => null; - read_t() -> T => null; - read_list() -> List[T] => null; + init() is si - write_thing(t: Thing[T]); - write_t(t: T); - write_list(l: List[T]); - si + read_thing() -> Thing[T] => null; + read_t() -> T => null; + read_list() -> List[T] => null; - class WithParamOverrideMethod[U]: Thing[U] is - write_thing(t: Thing[U]) is si - write_thing(i: int) is si + write_thing(t: Thing[T]); + write_t(t: T); + write_list(l: List[T]); +si - write_int(i: int) is si - si +class WithParamOverrideMethod[U]: Thing[U] is + write_thing(t: Thing[U]) is si + write_thing(i: int) is si + + write_int(i: int) is si +si - class WithParamOverrideMethodTest is - test() is - let t: WithParamOverrideMethod[char]; +class WithParamOverrideMethodTest is + test() is + let t: WithParamOverrideMethod[char]; - t.write_thing(1234); - t.write_t(cast char(0)); + t.write_thing(1234); + t.write_t(cast char(0)); - t.write_int(1234); + t.write_int(1234); - t.write_thing(Thing[char]()); - si + t.write_thing(Thing[char]()); si -si \ No newline at end of file +si diff --git a/integration-tests/semantic/generic-static-type-inference-1/.vscode/tasks.json b/integration-tests/semantic/generic-static-type-inference-1/.vscode/tasks.json new file mode 100644 index 000000000..49063613c --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-1/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Run test", + "command": "dotnet ghul-test \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "test", + "isDefault": true + } + }, + { + "label": "Capture test expectation", + "command": "../../../tasks/capture.sh \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/integration-tests/semantic/generic-static-type-inference-1/err.expected b/integration-tests/semantic/generic-static-type-inference-1/err.expected new file mode 100644 index 000000000..e5b6cdcec --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-1/err.expected @@ -0,0 +1 @@ +test.ghul: 23,9..23,23: error: Ghul.string is not assignable to Ghul.int diff --git a/integration-tests/semantic/generic-static-type-inference-1/fail.expected b/integration-tests/semantic/generic-static-type-inference-1/fail.expected new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-1/fail.expected @@ -0,0 +1 @@ + diff --git a/integration-tests/semantic/generic-static-type-inference-1/ghul.json b/integration-tests/semantic/generic-static-type-inference-1/ghul.json new file mode 100644 index 000000000..ddcfcf2b1 --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-1/ghul.json @@ -0,0 +1,3 @@ +{ + "compiler": "dotnet ../../../publish/ghul.dll" +} diff --git a/integration-tests/semantic/generic-static-type-inference-1/ghulflags b/integration-tests/semantic/generic-static-type-inference-1/ghulflags new file mode 100644 index 000000000..c19c66676 --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-1/ghulflags @@ -0,0 +1 @@ +--type-check \ No newline at end of file diff --git a/integration-tests/semantic/generic-static-type-inference-1/il.expected b/integration-tests/semantic/generic-static-type-inference-1/il.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-static-type-inference-1/test.ghul b/integration-tests/semantic/generic-static-type-inference-1/test.ghul new file mode 100644 index 000000000..b4cd0925e --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-1/test.ghul @@ -0,0 +1,24 @@ +use Collections; + +class TEST[T] is + map (xs: Iterable[T], f: (T) -> T) -> Iterable[T] static is si +si + +test_anon_function_arg_different_name_function_arg(x: int) is + TEST.map([1, 2, 3], y => y + 1); +si + +test_anon_function_arg_shadows_function_arg(x: int) is + TEST.map([1, 2, 3], x => x + 1); +si + +test_anon_function_arg_shadows_anon_function_arg() is + TEST.map([[1, 2, 3], [4, 5, 6]], x => TEST.map(x, x => x + 1)); +si + +entry() is +si + +err() is + let x: int = "err"; // deliberate error so we know we got this far +si diff --git a/integration-tests/semantic/generic-static-type-inference-1/warn.expected b/integration-tests/semantic/generic-static-type-inference-1/warn.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-static-type-inference-2/.vscode/tasks.json b/integration-tests/semantic/generic-static-type-inference-2/.vscode/tasks.json new file mode 100644 index 000000000..49063613c --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-2/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Run test", + "command": "dotnet ghul-test \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "test", + "isDefault": true + } + }, + { + "label": "Capture test expectation", + "command": "../../../tasks/capture.sh \"${workspaceFolder}\"", + "type": "shell", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/integration-tests/semantic/generic-static-type-inference-2/err.expected b/integration-tests/semantic/generic-static-type-inference-2/err.expected new file mode 100644 index 000000000..9ca4f5de0 --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-2/err.expected @@ -0,0 +1 @@ +test.ghul: 24,9..24,23: error: Ghul.string is not assignable to Ghul.int diff --git a/integration-tests/semantic/generic-static-type-inference-2/fail.expected b/integration-tests/semantic/generic-static-type-inference-2/fail.expected new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-2/fail.expected @@ -0,0 +1 @@ + diff --git a/integration-tests/semantic/generic-static-type-inference-2/ghul.json b/integration-tests/semantic/generic-static-type-inference-2/ghul.json new file mode 100644 index 000000000..ddcfcf2b1 --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-2/ghul.json @@ -0,0 +1,3 @@ +{ + "compiler": "dotnet ../../../publish/ghul.dll" +} diff --git a/integration-tests/semantic/generic-static-type-inference-2/ghulflags b/integration-tests/semantic/generic-static-type-inference-2/ghulflags new file mode 100644 index 000000000..c19c66676 --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-2/ghulflags @@ -0,0 +1 @@ +--type-check \ No newline at end of file diff --git a/integration-tests/semantic/generic-static-type-inference-2/il.expected b/integration-tests/semantic/generic-static-type-inference-2/il.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-static-type-inference-2/test.ghul b/integration-tests/semantic/generic-static-type-inference-2/test.ghul new file mode 100644 index 000000000..a78018623 --- /dev/null +++ b/integration-tests/semantic/generic-static-type-inference-2/test.ghul @@ -0,0 +1,25 @@ +use Collections; + +class TEST[T,U] is + map (xs: Iterable[T], f: T -> U) -> Iterable[U] static is si +si + +test_anon_function_arg_different_name_function_arg(x: int) is + TEST.map([1, 2, 3], y => y + 1); +si + +test_anon_function_arg_shadows_function_arg(x: int) is + TEST.map([1, 2, 3], x => x + 1); +si + +test_anon_function_arg_shadows_anon_function_arg() is + // FIXME shouldn't need explicit type here + TEST.map([[1, 2, 3], [4, 5, 6]], x => TEST.map(x, y: int => y + 1)); +si + +entry() is +si + +err() is + let x: int = "err"; // deliberate error so we know we got this far +si diff --git a/integration-tests/semantic/generic-static-type-inference-2/warn.expected b/integration-tests/semantic/generic-static-type-inference-2/warn.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-traits/err.expected b/integration-tests/semantic/generic-traits/err.expected index 23e0354c4..526308bdd 100644 --- a/integration-tests/semantic/generic-traits/err.expected +++ b/integration-tests/semantic/generic-traits/err.expected @@ -1 +1 @@ -test.ghul: 55,23..55,27: error: cannot return value of type null from function of type Test.GenericTraits.VECTOR.T +test.ghul: 47,19..47,23: error: cannot return value of type null from function of type T diff --git a/integration-tests/semantic/generic-traits/ghul.json b/integration-tests/semantic/generic-traits/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/generic-traits/ghul.json +++ b/integration-tests/semantic/generic-traits/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/generic-traits/test.ghul b/integration-tests/semantic/generic-traits/test.ghul index 03749f196..1bc36f297 100644 --- a/integration-tests/semantic/generic-traits/test.ghul +++ b/integration-tests/semantic/generic-traits/test.ghul @@ -1,80 +1,71 @@ -namespace Test.GenericTraits is +use Std = IO.Std; +class Main is + init() is + let l = VECTOR[int](); + l[0] = 0; + l[1] = 111; + l[2] = 222; + l[3] = 333; + l[4] = l[0] + l[1] + l[2] + l[3]; + let i = l.elements; + let hme = i.has_more_elements; + let ne = i.next_element(); + let cl = l.copy(); + cl[5] = cl[4]; + si +si - use Std = IO.Std; - - class Main is - init() is - let l = VECTOR[int](); - - l[0] = 0; - l[1] = 111; - l[2] = 222; - l[3] = 333; - l[4] = l[0] + l[1] + l[2] + l[3]; - - let i = l.elements; +trait Iterator[T] is + has_more_elements: bool; + next_element() -> T; +si - let hme = i.has_more_elements; - let ne = i.next_element(); +trait Iterable[T] is + elements: Iterator[T]; +si - let cl = l.copy(); +trait List[T]: Iterable[T] is + copy() -> List[T]; - cl[5] = cl[4]; - si - si + [index: int]: T = value; +si - trait Iterator[T] is - has_more_elements: bool; - next_element() -> T; - si +class VECTOR[T]: object, List[T] is + length: int; - trait Iterable[T] is - elements: Iterator[T]; + init() is si - - trait List[T]: Iterable[T] is - copy() -> List[T]; - [index: int]: T = value; - si - - class VECTOR[T]: object, List[T] is - length: int; - - init() is + [index: int]: T + is return null; si, + = value is si - [index: int]: T - is return null; si, - = value is - si + elements: Iterator[T] is + let self_ = self; - elements: Iterator[T] is - let self_ = self; - - return VECTOR_ITERATOR[T](self); - si - - copy() -> List[T] => VECTOR[T](); + return VECTOR_ITERATOR[T](self); si - class VECTOR_ITERATOR[T]: object, Iterator[T] is - index: int; + copy() -> List[T] => VECTOR[T](); +si - vector: VECTOR[T]; +class VECTOR_ITERATOR[T]: object, Iterator[T] is + index: int; - init(vector: VECTOR[T]) is - self.vector = vector; - si + vector: VECTOR[T]; - has_more_elements: bool => index < vector.length; - next_element() -> T is let result = vector[index]; index = index + 1; return result; si + init(vector: VECTOR[T]) is + self.vector = vector; si -si \ No newline at end of file + + has_more_elements: bool => index < vector.length; + next_element() -> T is let result = vector[index]; index = index + 1; return result; si +si diff --git a/integration-tests/semantic/generic-type-compatibility/err.expected b/integration-tests/semantic/generic-type-compatibility/err.expected index 743ecc30e..04b33e504 100644 --- a/integration-tests/semantic/generic-type-compatibility/err.expected +++ b/integration-tests/semantic/generic-type-compatibility/err.expected @@ -1,2 +1,2 @@ -test.ghul: 13,26..13,30: error: cannot return value of type null from function of type Test.GenericTypeCompatibility.Thing.T -test.ghul: 6,23..6,27: error: cannot return value of type null from function of type Test.GenericTypeCompatibility.Thing.T +test.ghul: 13,22..13,26: error: cannot return value of type null from function of type T +test.ghul: 6,19..6,23: error: cannot return value of type null from function of type T diff --git a/integration-tests/semantic/generic-type-compatibility/ghul.json b/integration-tests/semantic/generic-type-compatibility/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/generic-type-compatibility/ghul.json +++ b/integration-tests/semantic/generic-type-compatibility/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/generic-type-compatibility/test.ghul b/integration-tests/semantic/generic-type-compatibility/test.ghul index d7a7ea03d..7665a7ce4 100644 --- a/integration-tests/semantic/generic-type-compatibility/test.ghul +++ b/integration-tests/semantic/generic-type-compatibility/test.ghul @@ -1,46 +1,45 @@ -namespace Test.GenericTypeCompatibility is - use Collections; - class Thing[T] is - stuff_thing: Thing[T] => null; - stuff_t: T => null; - stuff_list: List[T] => null; - stuff_iterable: Iterable[T] => null; +use Collections; - [index: Thing[T]]: Iterable[T] => null; +class Thing[T] is + stuff_thing: Thing[T] => null; + stuff_t: T => null; + stuff_list: List[T] => null; + stuff_iterable: Iterable[T] => null; - read_thing() -> Thing[T] => null; - read_t() -> T => null; - read_list() -> List[T] => null; + [index: Thing[T]]: Iterable[T] => null; - write_thing(t: Thing[T]); - write_t(t: T); - write_list(l: List[T]); - si + read_thing() -> Thing[T] => null; + read_t() -> T => null; + read_list() -> List[T] => null; + + write_thing(t: Thing[T]); + write_t(t: T); + write_list(l: List[T]); +si - class Test is - do_something(list: List[Thing[int]]) -> Iterable[Thing[int]]; - do_something(list: List[Thing[char]]) -> Iterable[Thing[char]]; +class Test is + do_something(list: List[Thing[int]]) -> Iterable[Thing[int]]; + do_something(list: List[Thing[char]]) -> Iterable[Thing[char]]; - check_int(i: int); - check_char(c: char); + check_int(i: int); + check_char(c: char); - test() is - let vector_thing_int = LIST[Thing[int]](); + test() is + let vector_thing_int = LIST[Thing[int]](); - let iteratable_thing_int = do_something(vector_thing_int); - let iterator_thing_int = iteratable_thing_int.iterator; - let thing_int = iterator_thing_int.current; + let iteratable_thing_int = do_something(vector_thing_int); + let iterator_thing_int = iteratable_thing_int.iterator; + let thing_int = iterator_thing_int.current; - check_int(thing_int.read_t()); + check_int(thing_int.read_t()); - let vector_thing_char = LIST[Thing[char]](); + let vector_thing_char = LIST[Thing[char]](); - let iteratable_thing_char = do_something(vector_thing_char); - let iterator_thing_char = iteratable_thing_char.iterator; - let thing_char = iterator_thing_char.current; - - check_char(thing_char.read_t()); - si + let iteratable_thing_char = do_something(vector_thing_char); + let iterator_thing_char = iteratable_thing_char.iterator; + let thing_char = iterator_thing_char.current; + + check_char(thing_char.read_t()); si -si \ No newline at end of file +si diff --git a/integration-tests/semantic/generic-type-constraints/err.expected b/integration-tests/semantic/generic-type-constraints/err.expected index fec6f13c8..b0f849da3 100644 --- a/integration-tests/semantic/generic-type-constraints/err.expected +++ b/integration-tests/semantic/generic-type-constraints/err.expected @@ -1 +1 @@ -test.ghul: 19,24..19,40: error: member nonTraitFunction not found in Test.GenericTypeConstraints.NeedsSomeTrait.T +test.ghul: 17,20..17,36: error: member nonTraitFunction not found in T diff --git a/integration-tests/semantic/generic-type-constraints/ghul.json b/integration-tests/semantic/generic-type-constraints/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/generic-type-constraints/ghul.json +++ b/integration-tests/semantic/generic-type-constraints/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/generic-type-constraints/il.expected b/integration-tests/semantic/generic-type-constraints/il.expected new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/semantic/generic-type-constraints/test.ghul b/integration-tests/semantic/generic-type-constraints/test.ghul index dbfce5be4..9474821aa 100644 --- a/integration-tests/semantic/generic-type-constraints/test.ghul +++ b/integration-tests/semantic/generic-type-constraints/test.ghul @@ -1,22 +1,19 @@ -namespace Test.GenericTypeConstraints is - use Ghul; - class Main is - init() is - si +class Main is + init() is si +si - trait SomeTrait is - traitFunction(i: int) -> int => i; - si +trait SomeTrait is + traitFunction(i: int) -> int => i; +si - class NeedsSomeTrait[T: SomeTrait] is - callTraitFunction(some_trait: T, some_int: int) is - some_trait.traitFunction(some_int); - si +class NeedsSomeTrait[T: SomeTrait] is + callTraitFunction(some_trait: T, some_int: int) is + some_trait.traitFunction(some_int); + si - callNonTraitFunction(some_trait: T, some_char: char) is - some_trait.nonTraitFunction(some_char); - si + callNonTraitFunction(some_trait: T, some_char: char) is + some_trait.nonTraitFunction(some_char); si -si \ No newline at end of file +si diff --git a/integration-tests/semantic/type-generic-argument-type-parameters-not-wild-1/err.expected b/integration-tests/semantic/type-generic-argument-type-parameters-not-wild-1/err.expected index dd40fe4cc..87d9a114e 100644 --- a/integration-tests/semantic/type-generic-argument-type-parameters-not-wild-1/err.expected +++ b/integration-tests/semantic/type-generic-argument-type-parameters-not-wild-1/err.expected @@ -1,19 +1,19 @@ -test.ghul: 18,10..18,11: error: Main.T is not assignable to Main.X -test.ghul: 18,13..18,14: error: Main.U is not assignable to Main.Y -test.ghul: 21,27..21,31: error: no overload found for function(Main.X, Main.Y), tried Main.function(t: T, u: U) -> (t: T, u: U) -test.ghul: 31,9..31,14: error: Main.T is not assignable to Ghul.int -test.ghul: 32,9..32,14: error: Main.U is not assignable to Ghul.string -test.ghul: 37,9..37,14: error: Main.X is not assignable to Ghul.int -test.ghul: 38,9..38,14: error: Main.Y is not assignable to Ghul.string -test.ghul: 40,9..40,21: error: Ghul.object is not assignable to Main.T -test.ghul: 41,9..41,21: error: Ghul.object is not assignable to Main.U -test.ghul: 43,9..43,21: error: Ghul.object is not assignable to Main.X -test.ghul: 44,9..44,21: error: Ghul.object is not assignable to Main.Y +test.ghul: 18,10..18,11: error: T is not assignable to X +test.ghul: 18,13..18,14: error: U is not assignable to Y +test.ghul: 21,27..21,31: error: no overload found for function(X, Y), tried Main.function(t: T, u: U) -> (t: T, u: U) +test.ghul: 31,9..31,14: error: T is not assignable to Ghul.int +test.ghul: 32,9..32,14: error: U is not assignable to Ghul.string +test.ghul: 37,9..37,14: error: X is not assignable to Ghul.int +test.ghul: 38,9..38,14: error: Y is not assignable to Ghul.string +test.ghul: 40,9..40,21: error: Ghul.object is not assignable to T +test.ghul: 41,9..41,21: error: Ghul.object is not assignable to U +test.ghul: 43,9..43,21: error: Ghul.object is not assignable to X +test.ghul: 44,9..44,21: error: Ghul.object is not assignable to Y test.ghul: 46,9..46,21: error: Ghul.object is not assignable to Ghul.int test.ghul: 47,9..47,21: error: Ghul.object is not assignable to Ghul.string -test.ghul: 49,9..49,15: error: Ghul.int is not assignable to Main.T +test.ghul: 49,9..49,15: error: Ghul.int is not assignable to T test.ghul: 5,31..5,43: error: no overload found for function(Ghul.int, Ghul.string), tried Main.function(t: T, u: U) -> (t: T, u: U) -test.ghul: 50,9..50,20: error: Ghul.string is not assignable to Main.Y +test.ghul: 50,9..50,20: error: Ghul.string is not assignable to Y test.ghul: 6,31..6,56: error: no overload found for function(Ghul.int[], Ghul.string[]), tried Main.function(t: T, u: U) -> (t: T, u: U) -test.ghul: 61,13..61,21: error: Ghul.object is not assignable to Main.T -test.ghul: 62,13..62,21: error: Ghul.object is not assignable to Main.U +test.ghul: 61,13..61,21: error: Ghul.object is not assignable to T +test.ghul: 62,13..62,21: error: Ghul.object is not assignable to U diff --git a/integration-tests/semantic/type-generic-argument-type-parameters-not-wild-1/ghul.json b/integration-tests/semantic/type-generic-argument-type-parameters-not-wild-1/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/type-generic-argument-type-parameters-not-wild-1/ghul.json +++ b/integration-tests/semantic/type-generic-argument-type-parameters-not-wild-1/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/integration-tests/semantic/union-1/ghul.json b/integration-tests/semantic/union-1/ghul.json index 84539d122..ddcfcf2b1 100644 --- a/integration-tests/semantic/union-1/ghul.json +++ b/integration-tests/semantic/union-1/ghul.json @@ -1,6 +1,3 @@ { - "compiler": "dotnet ../../../publish/ghul.dll", - "source": [ - "." - ] + "compiler": "dotnet ../../../publish/ghul.dll" } diff --git a/src/lexical/tokenizer.ghul b/src/lexical/tokenizer.ghul index 89aad5628..bc9b64db5 100644 --- a/src/lexical/tokenizer.ghul +++ b/src/lexical/tokenizer.ghul @@ -114,7 +114,7 @@ namespace Lexical is _symbol_tokens["const"] = TOKEN.CONST; _symbol_tokens["static"] = TOKEN.STATIC; _symbol_tokens["innate"] = TOKEN.INNATE; - _symbol_tokens["rec"] = TOKEN.REC; // if we do add this type inferrence will be difficult + _symbol_tokens["rec"] = TOKEN.REC; _symbol_tokens["if"] = TOKEN.IF; _symbol_tokens["else"] = TOKEN.ELSE; _symbol_tokens["while"] = TOKEN.WHILE; diff --git a/src/semantic/dotnet/type_mapper.ghul b/src/semantic/dotnet/type_mapper.ghul index 799c3f4b3..14a0353d9 100644 --- a/src/semantic/dotnet/type_mapper.ghul +++ b/src/semantic/dotnet/type_mapper.ghul @@ -12,8 +12,6 @@ namespace Semantic.DotNet is use Types.Type; use Types.NAMED; use Types.ERROR; - use FUNCTION_GENERIC_ARGUMENT_SYMBOL = Symbols.FUNCTION_GENERIC_ARGUMENT; - use FUNCTION_GENERIC_ARGUMENT_TYPE = Types.FUNCTION_GENERIC_ARGUMENT; class TypeCreator is _mapper: TYPE_MAPPER; @@ -154,14 +152,14 @@ namespace Semantic.DotNet is fi if type.is_generic_method_parameter then - let symbol = FUNCTION_GENERIC_ARGUMENT_SYMBOL(Source.LOCATION.internal, null, type.name, type.generic_parameter_position); + let symbol = Symbols.FUNCTION_GENERIC_ARGUMENT(Source.LOCATION.internal, null, type.name, type.generic_parameter_position); result = symbol.type; _type_cache.add(type, result); return result; elif type.is_generic_type_parameter then - let symbol = Symbols.GENERIC_ARGUMENT(Source.LOCATION.internal, null, type.name, type.generic_parameter_position); + let symbol = Symbols.CLASSY_GENERIC_ARGUMENT(Source.LOCATION.internal, null, type.name, type.generic_parameter_position); result = symbol.type; _type_cache.add(type, result); @@ -224,6 +222,15 @@ namespace Semantic.DotNet is return result; si + map_type_argument_variance(type: TYPE) -> Types.TYPE_VARIANCE => + if type.generic_parameter_attributes.has_flag(System.Reflection.GenericParameterAttributes.COVARIANT) then + Types.TYPE_VARIANCE.COVARIANT + elif type.generic_parameter_attributes.has_flag(System.Reflection.GenericParameterAttributes.CONTRAVARIANT) then + Types.TYPE_VARIANCE.CONTRAVARIANT + else + Types.TYPE_VARIANCE.INVARIANT + fi; + get_element_type(type: TYPE) -> Type is let element_type = type.get_element_type(); diff --git a/src/semantic/overload_resolver.ghul b/src/semantic/overload_resolver.ghul index 2f846f9ce..1eda18f10 100644 --- a/src/semantic/overload_resolver.ghul +++ b/src/semantic/overload_resolver.ghul @@ -47,13 +47,14 @@ namespace Semantic is group: Symbols.FUNCTION_GROUP, arguments: Collections.List[Type], want_infer: bool, - want_instance: bool + want_instance: bool, + is_constructor_call: bool ) -> OVERLOAD_RESOLVE_RESULT is let mark = _logger.mark(); try - return _resolve(location, group, arguments, want_infer, want_instance); + return _resolve(location, group, arguments, want_infer, want_instance, is_constructor_call); catch e: Exception _logger.release(mark); @@ -90,7 +91,8 @@ namespace Semantic is group: Symbols.FUNCTION_GROUP, arguments: Collections.List[Type], want_infer: bool, - want_instance: bool + want_instance: bool, + is_constructor_call: bool ) -> OVERLOAD_RESOLVE_RESULT is if group == null \/ group.functions == null \/ arguments == null then @@ -98,7 +100,7 @@ namespace Semantic is fi // FIXME: this could just as well be applied to any parameters of generic type, not just anon functions - let needs_second_call = want_infer /\ arguments | .any(a => a? /\ a.is_function_with_any_implicit_argument_types); + let needs_second_call = arguments | .any(a => a? /\ a.is_function_with_any_implicit_argument_types); let is_ambiguous = false; @@ -109,6 +111,11 @@ namespace Semantic is let functions_to_search = group.functions | .filter(f => want_instance \/ !f.is_instance); + // We need to return PARTIAL if any actual argument types are wild. 'PARTIAL' provides + // the caller with the best match we can find, and the caller is expected to use that + // to bind any unknown types in the actual arguments and then try overload resolution + // again + for f in functions_to_search do let actual = f; @@ -117,8 +124,28 @@ namespace Semantic is elif f.arguments.count == 0 /\ arguments.count == 0 then return OVERLOAD_RESOLVE_RESULT(f, Types.MATCH.SAME); elif f.arguments.count == arguments.count then + let want_try_bind_owner_generic_arguments = false; + let want_try_bind_function_generic_arguments = false; + + if is_constructor_call then + want_try_bind_owner_generic_arguments = true; + want_try_bind_function_generic_arguments = false; + elif f.is_instance then + want_try_bind_owner_generic_arguments = false; + want_try_bind_function_generic_arguments = true; + elif f.is_generic then + want_try_bind_owner_generic_arguments = true; + want_try_bind_function_generic_arguments = true; + else + want_try_bind_owner_generic_arguments = true; + want_try_bind_function_generic_arguments = false; + fi + + let try_bind_generic_arguments = false; let score = cast int(Types.MATCH.SAME); + let owner_symbol = cast Symbols.Classy(f.owner); + for i in 0..f.arguments.count do let match: Types.MATCH; @@ -129,32 +156,148 @@ namespace Semantic is match = f_arg.compare(arg); if match == Types.MATCH.DIFFERENT then + // if any argument type compare returns DIFFERENT then + // this overload cannot match the supplied arguments + // even allowing for type argument inference of any + // type arguments in the formal arguments or of + // unknown types in the actual arguments, so + // bail on this overload immediately: score = cast int(Types.MATCH.DIFFERENT); break; - fi - - if match == Types.MATCH.WILD then - match = Types.MATCH.SAME; + elif match == Types.MATCH.WILD then + // either or both of the following has occurred: + // 1. the formal argument type is 'wild', i.e. its type expression + // includes at least one generic type argument that could be free + // to be bound to the type in corresponding position in the actual + // argument type. The type argument could be appear inside the type + // expression at any depth, for example `List[T]` or `int -> T` + // 2. the actual argument type is 'any', i.e. its type expression + // includes at least one unknown type where the actual type can + // potentially be infered based on the formal argument type + + // we need first to figure out which it is. If it's both then type + // inference probably isn't possible, but we will still attempt it + + if f_arg.is_wild then + // this formal argument is wild, we need to figure out if any + // type arguments in it could be free in this context + + // if the overload is an instance method we then can't supply + // actual type parameters to its owning class/struct either explicitly + // or via inference - they're already applied to the instance we're + // calling the method on + + // if the overload is a static method, we can potentially supply + // actual type arguments for its owning class + + // and in either case we can supply actual type arguments for the + // method itself + + // if the function is a global function then we can supply actual + // type arguments for it + + // if the function is a constructor, and we're calling it for a + // constructor expression, it cannot have generic arguments but + // its owning type can, and we do want to supply them if we + // can infer them from this overload + + match = Types.MATCH.SAME; + + + // FIXME: not convinced this is needed - bootstraps and tests pass + // without it. The intention is to block from trying to bind generic + // arguments that are not actually free in the current context + + let generic_arguments = f_arg.get_type_arguments(); + + for ga in generic_arguments do + if ga.is_function_generic_argument /\ !want_try_bind_function_generic_arguments then + score = cast int(Types.MATCH.DIFFERENT); + break; + + elif ga.is_classy_generic_argument /\ !want_try_bind_owner_generic_arguments then + score = cast int(Types.MATCH.DIFFERENT); + break; + + else + match = Types.MATCH.SAME; + fi + od + + if score == cast int(Types.MATCH.DIFFERENT) then + break; + fi + + try_bind_generic_arguments = true; + fi + elif arg.is_any_any then + // The actual argument is any, or is constructed from any. Treat this argument as if it + // matches and see if that results in an unambiguous overload result. If so, the caller + // can use the argument type from that result to try to infer the actual type of this + // argument + + // FIXME not sure it makes sense to be setting score here - should be match + score = cast int(Types.MATCH.PARTIAL); fi else + // something wrong with the argument - treat it as a moderate quality match match = Types.MATCH.ASSIGNABLE; fi score = cast int(score) + cast int(match); od - if f.is_generic /\ score <= best_score /\ score != cast int(Types.MATCH.DIFFERENT) then - let bindings = f.try_bind_generic_arguments(location, arguments); - - if !bindings? then - score = cast int(Types.MATCH.DIFFERENT); - elif bindings.is_bound then - actual = f.specialize_function(bindings.map, null); - elif want_infer then - actual = f.specialize_function(bindings.map, null); - score = cast int(Types.MATCH.PARTIAL); + if try_bind_generic_arguments /\ score <= best_score /\ score < cast int(Types.MATCH.DIFFERENT) then + // if we saw any generic argument types in any of the function formal argument types + // then we need to try to bind them to concrete types from the corresponding actual + // argument types + + let function_generic_argument_bindings = + if want_try_bind_function_generic_arguments then + f.try_bind_generic_arguments(location, arguments); + else + null; + fi; + + let owner_generic_argument_bindings = + if want_try_bind_owner_generic_arguments then + f.try_bind_owner_generic_arguments(location, arguments); + else + null + fi; + + if function_generic_argument_bindings? then + if function_generic_argument_bindings.is_bound then + actual = f.specialize_function(function_generic_argument_bindings.map, null); + elif needs_second_call then + actual = f.specialize_function(function_generic_argument_bindings.map, null); + score = cast int(Types.MATCH.PARTIAL); + else + score = cast int(Types.MATCH.DIFFERENT); + fi + elif owner_generic_argument_bindings? then + if owner_generic_argument_bindings.is_bound then + let specialized_owner = Symbols.GENERIC.try_create_from(location, owner_symbol, owner_generic_argument_bindings.map); + + if specialized_owner? then + actual = specialized_owner.find_specialized_function(f); + else + score = cast int(Types.MATCH.DIFFERENT); + fi + elif needs_second_call then + let specialized_owner = Symbols.GENERIC.try_create_from(location, owner_symbol, owner_generic_argument_bindings.map); + + if specialized_owner? then + actual = specialized_owner.find_specialized_function(f); + score = cast int(Types.MATCH.PARTIAL); + else + score = cast int(Types.MATCH.DIFFERENT); + fi + else + score = cast int(Types.MATCH.DIFFERENT); + fi else - score = cast int(Types.MATCH.DIFFERENT); + score = cast int(Types.MATCH.DIFFERENT); fi fi @@ -168,6 +311,7 @@ namespace Semantic is fi ambiguous_matches.add(actual); + is_ambiguous = true; elif score < best_score then if ambiguous_matches? then diff --git a/src/semantic/symbols/classy.ghul b/src/semantic/symbols/classy.ghul index 9737f3594..9c539c580 100644 --- a/src/semantic/symbols/classy.ghul +++ b/src/semantic/symbols/classy.ghul @@ -452,7 +452,7 @@ namespace Semantic.Symbols is si declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener) -> Symbol is - let result = Symbols.GENERIC_ARGUMENT(location, self, name, index); + let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index); declare(location, result, symbol_definition_listener); @@ -536,7 +536,7 @@ namespace Semantic.Symbols is si declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener) -> Symbol is - let result = Symbols.GENERIC_ARGUMENT(location, self, name, index); + let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index); declare(location, result, symbol_definition_listener); @@ -625,7 +625,7 @@ namespace Semantic.Symbols is // FIXME: most of these can be folded into Classy: declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener) -> Symbol is - let result = Symbols.GENERIC_ARGUMENT(location, self, name, index); + let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index); declare(location, result, symbol_definition_listener); @@ -715,7 +715,7 @@ namespace Semantic.Symbols is // FIXME: most of these can be folded into Classy: declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener) -> Symbol is - let result = Symbols.GENERIC_ARGUMENT(location, self, name, index); + let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index); declare(location, result, symbol_definition_listener); @@ -821,7 +821,7 @@ namespace Semantic.Symbols is // FIXME: most of these can be folded into Classy: declare_type(location: LOCATION, name: string, index: int, symbol_definition_listener: SymbolDefinitionListener) -> Symbol is - let result = Symbols.GENERIC_ARGUMENT(location, self, name, index); + let result = Symbols.CLASSY_GENERIC_ARGUMENT(location, self, name, index); declare(location, result, symbol_definition_listener); diff --git a/src/semantic/symbols/function.ghul b/src/semantic/symbols/function.ghul index 3ff03968a..5c221ed83 100644 --- a/src/semantic/symbols/function.ghul +++ b/src/semantic/symbols/function.ghul @@ -174,12 +174,30 @@ namespace Semantic.Symbols is _declaring_arguments = false; si + /* + given a set of actual function argument types, try to infer actual generic argument types by pattern matching formal + argument types (which may contain formal generic argument types) against correspinding actual arguments. Arguments + could be unknown (!!! or ***), which match anything and do not contradict any type inferences we make. + + map[T,U](from: Iterable[T], mapper: T -> U) -> Iterable[U] + map([1, 2, 3, 4, 5], x => x + 1) + + - the type of [1, 2, ... ] is known to be int[] + - prior type inference should figure out the return type of x => x + 1 must be int (because the only overload + resolution possible for !!! + 1 is int + int -> int) so we'll be called with actual argument types of int[] + and !!! -> int that need to be matched against Iterable[T] and T -> U + + - int[] implements Iterable[int] which pattern matches Iterable[T], allowing us to infer that T should be int + - !!! -> int pattern matches T -> U. !!! doesn't contradict a type of int for T, and int implies a type of int for U + + so we can return a type map of T = int, U = int + */ try_bind_generic_arguments(location: Source.LOCATION, args: Collections.List[Type]) -> Types.GENERIC_ARGUMENT_BIND_RESULTS is - if !is_generic then + if !is_generic /\ !(let owner_classy = cast Classy(owner) in owner_classy? /\ owner_classy.is_generic) then return null; fi - assert args.count == arguments.count; + assert args.count == arguments.count else "expected to bind {arguments.count} arguments in {self} but only {args} supplied"; let results = Types.GENERIC_ARGUMENT_BIND_RESULTS(); @@ -191,10 +209,28 @@ namespace Semantic.Symbols is fi od - if results.check_complete(location, generic_arguments) then - return results; + results.check_complete(location, generic_arguments); + + return results; + si + + try_bind_owner_generic_arguments(location: Source.LOCATION, args: Collections.List[Type]) -> Types.GENERIC_ARGUMENT_BIND_RESULTS is + let owner_classy = cast Classy(owner); + + if !owner_classy? \/ !owner_classy.is_generic then + return null; fi + let results = Types.GENERIC_ARGUMENT_BIND_RESULTS(); + + for i in 0..args.count do + if !arguments[i].bind_type_variables(args[i], results) then + return null; + fi + od + + results.check_complete(location, owner_classy.arguments); + return results; si diff --git a/src/semantic/symbols/function_generic_argument.ghul b/src/semantic/symbols/function_generic_argument.ghul deleted file mode 100644 index 9f109d505..000000000 --- a/src/semantic/symbols/function_generic_argument.ghul +++ /dev/null @@ -1,118 +0,0 @@ -namespace Semantic.Symbols is - use System.Text.StringBuilder; - - use IoC; - use Logging; - use Source; - - use Types.Type; - - // FIXME: should inherit from TYPE - class FUNCTION_GENERIC_ARGUMENT: Scoped, Types.SettableTyped is - type: Type; - set_type(value: Type) is type = value; si - - is_value_type: bool => true; - is_type: bool => true; - is_type_variable: bool => true; - - _ancestor_type: Type; - - index: int; - - ancestors: Collections.List[Type] is - if _ancestor_type == null then - return Collections.LIST[Type](0); - fi - - return [_ancestor_type]; - si - - set_ancestor_type(ancestor: Type) is - _ancestor_type = ancestor; - si - - symbol_kind: SYMBOL_KIND => SYMBOL_KIND.TYPE_PARAMETER; - completion_kind: COMPLETION_KIND => COMPLETION_KIND.TYPE_PARAMETER; - - description: string => "{name} // type variable"; - short_description: string => description; - - _gen_type_override: (Symbol, StringBuilder) -> void; - - init(location: LOCATION, owner: Scope, name: string, index: int) is - init(location, owner, name, Types.FUNCTION_GENERIC_ARGUMENT(self)); - - self.index = index; - si - - init(location: LOCATION, owner: Scope, name: string, type: Type) is - super.init(location, owner, name); - - self.type = type; - si - - freeze() -> Symbol is - let result = cast FUNCTION_GENERIC_ARGUMENT(memberwise_clone()); - - result._gen_type_override = null; - result.type = new Types.NAMED(result); - - return result; - si - - get_ancestor(i: int) -> Type is - return ancestors[i]; - si - - find_member(name: string) -> Symbol is - if _ancestor_type? then - return _ancestor_type.find_member(name); - fi - si - - find_member_matches(prefix: string, matches: Collections.MAP[string, Symbol]) is - if _ancestor_type? then - _ancestor_type.scope.find_member_matches(prefix, matches); - fi - si - - specialize(type_map: Collections.Map[string,Type], owner: GENERIC) -> Symbol is - if type_map.contains_key(name) then - - // FIXME should this be FUNCTION_GENERIC_ARGUMENT? - return GENERIC_ARGUMENT( - location, - self, - name, - type_map[name] - ); - fi - - return self; - si - - gen_type_override(override: (Symbol, StringBuilder) -> void) is - _gen_type_override = override; - si - - gen_type(buffer: StringBuilder) is - if _gen_type_override? then - _gen_type_override(self, buffer); - else - buffer - .append("!!") - .append(index) - .append(' '); - fi - si - - gen_reference(buffer: StringBuilder) is - gen_type(buffer); - si - - gen_class_name(buffer: StringBuilder) is - gen_type(buffer); - si - si -si diff --git a/src/semantic/symbols/generic.ghul b/src/semantic/symbols/generic.ghul index 9592a6d9c..ad3d7127f 100644 --- a/src/semantic/symbols/generic.ghul +++ b/src/semantic/symbols/generic.ghul @@ -18,9 +18,9 @@ namespace Semantic.Symbols is // with all instances of each formal type parameter replaced with the corresponding actual type argument class GENERIC: Symbol, Scope, Types.Typed is _symbol: Classy; - _type_map: Collections.MAP[string,Type]; + _type_map: Collections.Map[string,Type]; - type_map: Collections.MAP[string,Type] => _type_map; + type_map: Collections.Map[string,Type] => _type_map; arguments: Collections.List[Type]; ancestors: Collections.List[Type] => symbol.ancestors; @@ -137,15 +137,33 @@ namespace Semantic.Symbols is fi self.arguments = arguments; - _type_map = Collections.MAP[string,Type](); + let tm = Collections.MAP[string,Type](); for i in 0..length do - type_map[symbol.argument_names[i]] = arguments[i]; + tm[symbol.argument_names[i]] = arguments[i]; od + _type_map = tm; + is_unsafe_constraints = symbol.is_unsafe_constraints; si + try_create_from(location: LOCATION, symbol: Classy, type_map: Collections.Map[string,Type]) -> GENERIC static is + let arguments = Collections.LIST[Type](); + + for name in symbol.argument_names do + if !type_map.contains_key(name) then + return null; + fi + + let t = type_map[name]; + + arguments.add(t); + od + + return GENERIC(location, symbol, arguments); + si + add_member(symbol: Symbol) -> bool is IoC.CONTAINER.instance.logger.warn(location, "cannot inherit {symbol} into specialized generic {self}"); return true; @@ -230,6 +248,38 @@ namespace Semantic.Symbols is null; fi; + find_specialized_function(function: Symbol) -> Function is + let result = find_member(function.name); + + if !result? then + let results = Collections.MAP[string, Symbols.Symbol](); + + symbol.find_member_matches("", results); + + return null; + fi + + let function_result = cast Function(result); + + if function_result? /\ function_result.specialized_from == function then + return function_result; + fi + + let function_group_result = cast FUNCTION_GROUP(result); + + if !function_group_result? then + return null; + fi + + for f in function_group_result.functions do + if f.specialized_from == function then + return f; + fi + od + + return null; + si + get_destructure_member_name(index: int) -> string => symbol.get_destructure_member_name(index); diff --git a/src/semantic/symbols/generic_argument.ghul b/src/semantic/symbols/generic_argument.ghul index 65fc52cb2..25bdde661 100644 --- a/src/semantic/symbols/generic_argument.ghul +++ b/src/semantic/symbols/generic_argument.ghul @@ -9,19 +9,20 @@ namespace Semantic.Symbols is use Types.Type; - class GENERIC_ARGUMENT: Scoped, Types.SettableTyped is + class GenericArgument: Scoped, Types.SettableTyped is type: Type; set_type(value: Type) is type = value; si is_value_type: bool => true; is_type: bool => true; is_type_variable: bool => true; - is_wild: bool => true; _ancestor_type: Type; index: int; + _gen_type_override: (Symbol, StringBuilder) -> void; + // FIXME: should ancestor be a type not a symbol? We could then just use Symbol.ancestors. // We'll need multiple ancestors to support multiple constraints anyway ancestors: Collections.List[Type] is @@ -42,29 +43,12 @@ namespace Semantic.Symbols is description: string => "{name} // type variable"; short_description: string => description; - _gen_type_override: (Symbol, StringBuilder) -> void; - - init(location: LOCATION, owner: Scope, name: string, index: int) is - init(location, owner, name, Types.NAMED(self)); - - self.index = index; - si - init(location: LOCATION, owner: Scope, name: string, type: Type) is super.init(location, owner, name); self.type = type; si - freeze() -> Symbol is - let result = cast GENERIC_ARGUMENT(memberwise_clone()); - - result._gen_type_override = null; - result.type = new Types.NAMED(result); - - return result; - si - get_ancestor(i: int) -> Type => ancestors[i]; @@ -80,41 +64,118 @@ namespace Semantic.Symbols is fi si + gen_type_override(override: (Symbol, StringBuilder) -> void) is + _gen_type_override = override; + si + + gen_reference(buffer: StringBuilder) is + gen_type(buffer); + si + + gen_class_name(buffer: StringBuilder) is + gen_type(buffer); + si + + gen_type(buffer: StringBuilder) is + throw System.InvalidOperationException("shouldn't be generated"); + si + si + + class CLASSY_GENERIC_ARGUMENT: GenericArgument is + init(location: LOCATION, owner: Scope, name: string, index: int) is + super.init(location, owner, name, Types.CLASSY_GENERIC_ARGUMENT(self)); + + self.index = index; + si + + init(location: LOCATION, owner: Scope, name: string, type: Type) is + super.init(location, owner, name, type); + + self.type = type; + si + + freeze() -> Symbol is + let result = cast CLASSY_GENERIC_ARGUMENT(memberwise_clone()); + + result._gen_type_override = null; + result.type = new Types.CLASSY_GENERIC_ARGUMENT(result); + + return result; + si + specialize(type_map: Collections.Map[string,Type], owner: GENERIC) -> Symbol is if type_map.contains_key(name) then - return GENERIC_ARGUMENT( + // FIXME the resulting argument could have the wrong index + return CLASSY_GENERIC_ARGUMENT( location, self, name, type_map[name] - ); + ); fi return self; si - gen_type_override(override: (Symbol, StringBuilder) -> void) is - _gen_type_override = override; - si gen_type(buffer: StringBuilder) is if _gen_type_override? then _gen_type_override(self, buffer); else - buffer .append('!') .append(index) .append(' '); fi - si + si + si + + // FIXME: should inherit from TYPE + class FUNCTION_GENERIC_ARGUMENT: GenericArgument is + init(location: LOCATION, owner: Scope, name: string, index: int) is + super.init(location, owner, name, Types.FUNCTION_GENERIC_ARGUMENT(self)); - gen_reference(buffer: StringBuilder) is - gen_type(buffer); + self.index = index; si - gen_class_name(buffer: StringBuilder) is - gen_type(buffer); + init(location: LOCATION, owner: Scope, name: string, type: Type) is + super.init(location, owner, name, type); + + self.type = type; si + + freeze() -> Symbol is + let result = cast FUNCTION_GENERIC_ARGUMENT(memberwise_clone()); + + result._gen_type_override = null; + result.type = new Types.FUNCTION_GENERIC_ARGUMENT(result); + + return result; + si + + specialize(type_map: Collections.Map[string,Type], owner: GENERIC) -> Symbol is + if type_map.contains_key(name) then + // FIXME the resulting argument could have the wrong index + return new FUNCTION_GENERIC_ARGUMENT( + location, + self, + name, + type_map[name] + ); + fi + + return self; + si + + gen_type(buffer: StringBuilder) is + if _gen_type_override? then + _gen_type_override(self, buffer); + else + buffer + .append("!!") + .append(index) + .append(' '); + fi + si si -si +si diff --git a/src/semantic/types/error.ghul b/src/semantic/types/error.ghul index 7e4056023..c525e2077 100644 --- a/src/semantic/types/error.ghul +++ b/src/semantic/types/error.ghul @@ -6,6 +6,7 @@ namespace Semantic.Types is class ERROR: Type is is_null: bool => true; is_any: bool => true; + is_any_any: bool => true; is_error: bool => true; init() is diff --git a/src/semantic/types/generic.ghul b/src/semantic/types/generic.ghul index 932044d10..ee3647109 100644 --- a/src/semantic/types/generic.ghul +++ b/src/semantic/types/generic.ghul @@ -3,6 +3,8 @@ namespace Semantic.Types is use Source.LOCATION; + use Logging; + enum TYPE_VARIANCE is INVARIANT, COVARIANT, @@ -18,7 +20,7 @@ namespace Semantic.Types is // should be // is_wild: bool => arguments | .any(a => a.is_wild) - // but the following shaves about 10% off compiler build time (nearly 10% at time of change) + // but the following shaves about 10% off compiler build time is_wild: bool is if _is_wild == 0b then let a = symbol.arguments; @@ -42,6 +44,8 @@ namespace Semantic.Types is return _is_wild == 1b; si + is_any_any: bool => arguments | .any(a => a? /\ a.is_any_any); + short_description: string is assert self? else "self is null"; assert symbol? else "symbol is null"; @@ -287,15 +291,16 @@ namespace Semantic.Types is return Types.MATCH.DIFFERENT; si - + + // attempt to bind type variables in this generic against concrete types in + // other by pattern matching bind_type_variables(other: Type, results: GENERIC_ARGUMENT_BIND_RESULTS) -> bool is if other.is_null then return true; fi - if isa GENERIC(other) then - let other_generic = cast GENERIC(other); - + let other_generic = cast GENERIC(other); + if other_generic? then let generic_symbol = cast Symbols.GENERIC(symbol); let generic_other_symbol = cast Symbols.GENERIC(other_generic.symbol); @@ -329,6 +334,12 @@ namespace Semantic.Types is fi si + get_type_arguments_into(results: Collections.LIST[GenericArgument]) is + for a in arguments do + a.get_type_arguments_into(results); + od + si + walk(action: (Type) -> void) is for a in arguments do a.walk(action); diff --git a/src/semantic/types/function_generic_argument.ghul b/src/semantic/types/generic_argument.ghul similarity index 55% rename from src/semantic/types/function_generic_argument.ghul rename to src/semantic/types/generic_argument.ghul index 526f9945c..8566b3b7b 100644 --- a/src/semantic/types/function_generic_argument.ghul +++ b/src/semantic/types/generic_argument.ghul @@ -3,13 +3,19 @@ namespace Semantic.Types is use Source; - class FUNCTION_GENERIC_ARGUMENT: NAMED is + class GenericArgument: NAMED is is_wild: bool => true; + is_function_generic_argument: bool => false; + is_classy_generic_argument: bool => false; init(symbol: Symbols.Symbol) is super.init(symbol); si + get_type_arguments_into(results: Collections.LIST[GenericArgument]) is + results.add(self); + si + freeze() -> Type is let frozen = symbol.freeze(); @@ -17,7 +23,7 @@ namespace Semantic.Types is return null; fi - return new FUNCTION_GENERIC_ARGUMENT(frozen); + return frozen.type; si specialize(type_map: Collections.Map[string,Type]) -> Type is @@ -48,4 +54,23 @@ namespace Semantic.Types is to_string() -> string => symbol.name; si + + // TODO can get is classy vs is function from underlying symbol, + // delete these sub-classes and go back to having just + // one class representing a generic argument type + class CLASSY_GENERIC_ARGUMENT: GenericArgument is + is_classy_generic_argument: bool => true; + + init(symbol: Symbols.Symbol) is + super.init(symbol); + si + si + + class FUNCTION_GENERIC_ARGUMENT: GenericArgument is + is_function_generic_argument: bool => true; + + init(symbol: Symbols.Symbol) is + super.init(symbol); + si + si si \ No newline at end of file diff --git a/src/semantic/types/generic_argument_bind_results.ghul b/src/semantic/types/generic_argument_bind_results.ghul index 4d23de516..89b03b02c 100644 --- a/src/semantic/types/generic_argument_bind_results.ghul +++ b/src/semantic/types/generic_argument_bind_results.ghul @@ -5,17 +5,22 @@ namespace Semantic.Types is use Collections.LIST; use Collections.MAP; + use Logging; + class GENERIC_ARGUMENT_BINDING is - type_argument: FUNCTION_GENERIC_ARGUMENT; + type_argument: GenericArgument; actual_type: Type public; init( - type_argument: FUNCTION_GENERIC_ARGUMENT, + type_argument: GenericArgument, actual_type: Type ) is self.type_argument = type_argument; self.actual_type = actual_type; si + + to_string() -> string => + "{type_argument} bound to {actual_type}"; si class GENERIC_ARGUMENT_BIND_RESULTS is @@ -39,32 +44,43 @@ namespace Semantic.Types is bindings = MAP[string,GENERIC_ARGUMENT_BINDING](); si - bind(type_argument: FUNCTION_GENERIC_ARGUMENT, actual_type: Type) -> bool is + bind(type_argument: GenericArgument, actual_type: Type) -> bool is let existing: GENERIC_ARGUMENT_BINDING; + actual_type = + if actual_type.get_type_arguments().count > 0 then + // FIXME is this actually required? + actual_type.specialize(get_type_map()); + else + actual_type + fi; + if bindings.try_get_value(type_argument.name, existing ref) then if !existing.actual_type.is_none then if actual_type.is_assignable_from(existing.actual_type) then if !actual_type.is_null /\ !actual_type.is_any then existing.actual_type = actual_type; fi - + return true; elif existing.actual_type.is_assignable_from(actual_type) then return true; else existing.actual_type = NONE.instance; + return false; fi + else + // already know can't be bound + return false; fi elif actual_type.is_null \/ actual_type.is_any then return true; else bindings.add(type_argument.name, GENERIC_ARGUMENT_BINDING(type_argument, actual_type)); - return true; fi - return false; + assert false else "should not be reachable"; si check_complete(location: Source.LOCATION, expected_arguments: Collections.List[Type]) -> bool is @@ -79,7 +95,8 @@ namespace Semantic.Types is fi od - if !is_bound then + if !is_bound then + is_bound = false; return false; fi @@ -97,11 +114,15 @@ namespace Semantic.Types is if !argument_is_bound then is_bound = false; + return false; fi od return is_bound; si + + get_type_map() -> Collections.Map[string,Type] => Collections.MAP[string,Type]( + bindings | .map(b => Collections.KeyValuePair`2[string,Type](b.key, b.value.actual_type))); to_string() -> string is let result = System.Text.StringBuilder(); diff --git a/src/semantic/types/infered_return_type.ghul b/src/semantic/types/infered_return_type.ghul index 2d646c1a3..68fa53e04 100644 --- a/src/semantic/types/infered_return_type.ghul +++ b/src/semantic/types/infered_return_type.ghul @@ -6,6 +6,7 @@ namespace Semantic.Types is class INFERED_RETURN_TYPE: Type is is_null: bool => true; is_any: bool => true; + is_any_any: bool => true; is_wild: bool => true; is_inferred: bool => true; diff --git a/src/semantic/types/type.ghul b/src/semantic/types/type.ghul index 0a05b5773..02c453e9d 100644 --- a/src/semantic/types/type.ghul +++ b/src/semantic/types/type.ghul @@ -53,6 +53,7 @@ namespace Semantic.Types is is_null: bool => false; is_consumable: bool => !is_any /\ !is_error /\ !is_wild; is_any: bool => false; + is_any_any: bool => false; is_error: bool => false; is_wild: bool => false; is_inferred: bool => false; @@ -106,6 +107,15 @@ namespace Semantic.Types is bind_type_variables(other: Type, results: GENERIC_ARGUMENT_BIND_RESULTS) -> bool => true; + get_type_arguments_into(results: Collections.LIST[GenericArgument]) is + si + + get_type_arguments() -> Collections.LIST[GenericArgument] is + let result = Collections.LIST[GenericArgument](); + get_type_arguments_into(result); + return result; + si + freeze() -> Type => null; walk(action: (Type) -> void) is diff --git a/src/syntax/process/compile_expressions.ghul b/src/syntax/process/compile_expressions.ghul index 1531be356..8d735753e 100644 --- a/src/syntax/process/compile_expressions.ghul +++ b/src/syntax/process/compile_expressions.ghul @@ -106,8 +106,6 @@ namespace Syntax.Process is fi let move_next = get_zero_argument_function(type, "move_next"); - - let next_element = get_zero_argument_function(type, "nextElement"); if move_next? then let read_current = get_zero_argument_function(type, "$get_current"); @@ -124,11 +122,6 @@ namespace Syntax.Process is `for.move_next = move_next; `for.read_current = read_current; - return true; - elif next_element? then - // FIXME - `for.read_current = next_element; - return true; elif !recursing then let read_iterator = get_zero_argument_function(type, "$get_iterator"); @@ -737,6 +730,8 @@ namespace Syntax.Process is let implied_type: Type; let implied_argument_types: Collections.List[Type]; + // have we been passed expected arguments types? If so we'll use them + // to argument types of any anonymous function literal arguments if _partial_argument_function_type? then implied_argument_types = _partial_argument_function_type.arguments; _partial_argument_function_type = null; @@ -770,6 +765,8 @@ namespace Syntax.Process is if implied_argument_type? /\ !implied_argument_type.is_type_variable then argument_types.add(implied_argument_type); + a.try_set_constraint(implied_argument_type, "{{0}} is not compatible with {{1}}"); + symbol.set_type(implied_argument_type); else _logger.error(a.location, "cannot infer type here"); @@ -1252,7 +1249,7 @@ namespace Syntax.Process is return; fi - let overload_result = _overload_resolver.resolve(`new.location, function_group, argument_types, false, true); + let overload_result = _overload_resolver.resolve(`new.location, function_group, argument_types, false, true, true); if overload_result == null then `new.value = @@ -1289,6 +1286,7 @@ namespace Syntax.Process is ); si + // should be called with logger speculating resolve_constructor(location: LOCATION, right_location: LOCATION, type: Semantic.Types.Type, argument_expressions: Trees.Expressions.LIST) -> (Value, Value) is let result: Value; @@ -1320,19 +1318,57 @@ namespace Syntax.Process is od if !function_group? then - _logger.error(location, "no constructor found init({argument_types|})"); + _logger.error(location, "no constructor found init({argument_types|})"); return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); fi - let overload_result = _overload_resolver.resolve(location, function_group, argument_types, true, true); + let overload_result = _overload_resolver.resolve(location, function_group, argument_types, false, true, true); if overload_result == null then return (cast Value(Load.SYMBOL(null, function_group)), cast Value(DUMMY(type, location))); fi + if overload_result.score == Semantic.Types.MATCH.PARTIAL then + _logger.roll_back(); + _logger.speculate(); + + for (index, a) in argument_expressions | .index() do + // let use debug_despose = debug_enter(); + if !a? then + continue; + elif a.value? /\ isa Trees.Expressions.FUNCTION(a) then + let f = overload_result.function.arguments[index]; + + try + _partial_argument_function_type = f; + + a.walk(self); + finally + _partial_argument_function_type = null; + yrt + + argument_types[index] = a.value.type; + else + // ensure any error messages are committed + a.walk(self); + fi + od + + overload_result = _overload_resolver.resolve(location, function_group, argument_types, false, true, true); + + if !overload_result? then + return (cast Value(Load.SYMBOL(null, function_group)), cast Value(DUMMY(type, location))); + fi + fi + let function = overload_result.function; + if isa Semantic.Symbols.GENERIC(function.owner) then + type_symbol = cast Semantic.Symbols.Symbol(function.owner); + type = function.owner.type; + fi; + let is_directly_owned = false; if isa Semantic.Symbols.GENERIC(type_symbol) /\ isa Semantic.Symbols.Symbol(function.owner) then @@ -1375,7 +1411,9 @@ namespace Syntax.Process is cast Semantic.Symbols.FUNCTION_GROUP(function_group), arguments, false, - unary.right.value.is_consumable); // FIXME: this doesn't seem right + unary.right.value.is_consumable, // FIXME: this doesn't seem right + false + ); if overload_result == null then unary.value = DUMMY(Semantic.Types.ERROR(), unary.location); @@ -1435,7 +1473,8 @@ namespace Syntax.Process is binary_function_group, Collections.LIST[Type]([binary.left.value.type, binary.right.value.type]), false, - _symbol_table.current_instance_context? + _symbol_table.current_instance_context?, + false ); binary_errors = logger_snapshot.backtrack(); @@ -1461,7 +1500,8 @@ namespace Syntax.Process is cast Semantic.Symbols.FUNCTION_GROUP(member_function_group), Collections.LIST[Type]([binary.right.value.type]), false, - binary.left.value.is_consumable + binary.left.value.is_consumable, + false ); member_errors = logger_snapshot.backtrack(); @@ -1641,7 +1681,9 @@ namespace Syntax.Process is cast Semantic.Symbols.FUNCTION_GROUP(symbol), argument_types, false, - true); + true, + false + ); logger_snapshot.backtrack(); @@ -2577,7 +2619,7 @@ namespace Syntax.Process is fi; let function_group = cast Semantic.Symbols.FUNCTION_GROUP(load_symbol); - let overload_result = _overload_resolver.resolve(call.arguments.location, function_group, argument_types, true, want_instance); + let overload_result = _overload_resolver.resolve(call.arguments.location, function_group, argument_types, true, want_instance, false); if overload_result == null then call.value = DUMMY(Semantic.Types.ERROR(), call.location); @@ -2609,7 +2651,7 @@ namespace Syntax.Process is fi od - overload_result = _overload_resolver.resolve(call.arguments.location, function_group, argument_types, false, want_instance); + overload_result = _overload_resolver.resolve(call.arguments.location, function_group, argument_types, false, want_instance, false); if !overload_result? then call.value = DUMMY(Semantic.Types.ERROR(), call.location); @@ -2669,7 +2711,7 @@ namespace Syntax.Process is return; fi else - if load_symbol? /\ load_symbol.is_type then + if load_symbol? /\ load_symbol.is_type then (call.function.value, call.value) = resolve_constructor(call.location, call.right_location, load_symbol.type, call.arguments); else _logger.error(call.function.location, "cannot call value of non-function type {call.function.value.type}"); diff --git a/src/syntax/trees/expressions/expression.ghul b/src/syntax/trees/expressions/expression.ghul index 70d778445..c038ef7d0 100644 --- a/src/syntax/trees/expressions/expression.ghul +++ b/src/syntax/trees/expressions/expression.ghul @@ -36,7 +36,6 @@ namespace Syntax.Trees.Expressions is try_get_string_literal() -> string => null; - try_set_constraint(constraint: Semantic.Types.Type, error_message: string) is - si + try_set_constraint(constraint: Semantic.Types.Type, error_message: string) is si si si