Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler signature re-work #1116

Draft
wants to merge 53 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
d651fb3
Reduce symbols leaks from the compiler
mhermier Oct 21, 2022
4c98594
Remove `parameterList`
mhermier Oct 21, 2022
c14c03a
Add `verror`
mhermier Oct 17, 2022
90ca0b6
Use `verror` in `consume` to make it formattable
mhermier Oct 17, 2022
4a994d8
Add `tokenTypeToString`
mhermier Oct 17, 2022
0f46bee
Add `emitCall`abstraction
mhermier Oct 14, 2022
ddb0688
Rename `maybeSetter` to `maybeSetterParameter̀`
mhermier Oct 21, 2022
710b127
Add `ListConfiguration`
mhermier Oct 26, 2022
5c5dcfc
Add generic `finishList`
mhermier Oct 21, 2022
be6c7b1
Add generic `optionalList`
mhermier Oct 26, 2022
d68bb11
Add `incSignatureArity`
mhermier Oct 26, 2022
641e094
Add `ListConfiguration`s for argument parsing
mhermier Oct 26, 2022
70be295
Add `ListConfiguration`s for parameter parsing
mhermier Oct 26, 2022
45bd169
Use `finishList` in `finishArgumentList`
mhermier Oct 21, 2022
b7b6e48
Use `finishList`in `finishParameterList`
mhermier Oct 21, 2022
a77d446
Add generic `maybeSetter`
mhermier Oct 21, 2022
78286b7
Add `maybeSetterArgument`
mhermier Oct 26, 2022
ba62b7b
Use `maybeSetterArgument` in `namedCall`
mhermier Oct 26, 2022
e40ce4f
Use `maybeSetterArgument` in `subscript`
mhermier Oct 26, 2022
046d40d
Use `maybeSetter` in `maybeSetterParameter`
mhermier Oct 21, 2022
5719cdc
Add `signatureArgumentsCount`
mhermier Oct 14, 2022
ae07cdb
Make `validateNumParameters` takes `Signature*` instead of `int`
mhermier Oct 15, 2022
fb3b1ed
Simplify `signatureToString`
mhermier Oct 21, 2022
99c25f3
Split `Signature::arity` into `bracketArity` and `parenArity`
mhermier Oct 21, 2022
2676d45
Add `Signature::isInitializer`
mhermier Oct 16, 2022
973bea4
Add `Signature::isSetter`
mhermier Oct 16, 2022
bd0e551
Remove now not necessary `SignatureType`
mhermier Oct 21, 2022
2808aa7
test/language/method/setter_operators.wren: add test
mhermier Oct 19, 2022
6ecdbfc
test/language/method/subscript_operators.wren: update test
mhermier Oct 19, 2022
056b111
Make `finishList` handle the empty list
mhermier Oct 25, 2022
af906dc
Simplify function parameter declaration.
mhermier Oct 25, 2022
c374d2d
Simplify `methodCall` with empty argument list
mhermier Oct 25, 2022
4489aef
Simplify `constructorSignature` with empty parameter list
mhermier Oct 21, 2022
1d5ce68
Simplify `namedSignature` with empty parameter list
mhermier Oct 25, 2022
a59ff59
Document functions of any arity
mhermier Oct 21, 2022
cd19105
Document subscripts of any arity
mhermier Oct 21, 2022
c655c6f
Document trailing commas in argument/parameter lists
mhermier Oct 21, 2022
979f759
Make `list` use `finishList` to parse list litterals
mhermier Oct 24, 2022
8b4289a
Make `map` use `finishList` to parse map litterals
mhermier Oct 24, 2022
5d9f738
Allow setters of any arity
mhermier Oct 26, 2022
222b812
Rename `maybeSetter` to `maybeSetterList`
mhermier Oct 24, 2022
2af3441
Rename `maybeSetterArgument` to `maybeSetterArgumentList`
mhermier Oct 24, 2022
90dd58e
Rename `maybeSetterParameter` to `maybeSetterParameterList`
mhermier Oct 24, 2022
93da152
Document setters of any arity
mhermier Oct 19, 2022
d338d1b
Add `type` function to resolve types
mhermier Oct 25, 2022
df6d9a7
Use `type` in `classDefinition` to resolve superclass
mhermier Oct 25, 2022
b1c59b3
Add `->` token type
mhermier Oct 25, 2022
a26bb1c
Add `declareType`
mhermier Oct 25, 2022
fbf6567
Allow optional parameter type definition
mhermier Oct 25, 2022
3867a9b
Add `declareOptionalReturnType`
mhermier Oct 25, 2022
c826de4
Allow optional function return type declaration
mhermier Oct 25, 2022
d4dbab3
Allow optional method return type declaration
mhermier Oct 25, 2022
38b1ec3
Document type hinting
mhermier Oct 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
672 changes: 420 additions & 252 deletions src/vm/wren_compiler.c

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion test/language/function/no_parameters.wren
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
Fn.new {|| null } // expect error
System.print(Fn.new { "" }.call()) // expect:
System.print(Fn.new {|| "||" }.call()) // expect: ||
System.print(Fn.new {| | "| |" }.call()) // expect: | |
48 changes: 48 additions & 0 deletions test/language/function/trailing_comma.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

var f1 = Fn.new {|a,| a }
System.print(f1.call(1,),) // expect: 1

var f2 = Fn.new {|a, b,| a + b }
System.print(f2.call(1, 2,),) // expect: 3

var f3 = Fn.new {|a, b, c,| a + b + c }
System.print(f3.call(1, 2, 3,),) // expect: 6

var f4 = Fn.new {|a, b, c, d,| a + b + c + d }
System.print(f4.call(1, 2, 3, 4,),) // expect: 10

var f5 = Fn.new {|a, b, c, d, e,| a + b + c + d + e }
System.print(f5.call(1, 2, 3, 4, 5,),) // expect: 15

var f6 = Fn.new {|a, b, c, d, e, f,| a + b + c + d + e + f }
System.print(f6.call(1, 2, 3, 4, 5, 6,),) // expect: 21

var f7 = Fn.new {|a, b, c, d, e, f, g,| a + b + c + d + e + f + g }
System.print(f7.call(1, 2, 3, 4, 5, 6, 7,),) // expect: 28

var f8 = Fn.new {|a, b, c, d, e, f, g, h,| a + b + c + d + e + f + g + h }
System.print(f8.call(1, 2, 3, 4, 5, 6, 7, 8,),) // expect: 36

var f9 = Fn.new {|a, b, c, d, e, f, g, h, i,| a + b + c + d + e + f + g + h + i }
System.print(f9.call(1, 2, 3, 4, 5, 6, 7, 8, 9,),) // expect: 45

var f10 = Fn.new {|a, b, c, d, e, f, g, h, i, j,| a + b + c + d + e + f + g + h + i + j }
System.print(f10.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,),) // expect: 55

var f11 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k,| a + b + c + d + e + f + g + h + i + j + k }
System.print(f11.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,),) // expect: 66

var f12 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l,| a + b + c + d + e + f + g + h + i + j + k + l }
System.print(f12.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,),) // expect: 78

var f13 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m,| a + b + c + d + e + f + g + h + i + j + k + l + m }
System.print(f13.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,),) // expect: 91

var f14 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n,| a + b + c + d + e + f + g + h + i + j + k + l + m + n }
System.print(f14.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,),) // expect: 105

var f15 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n, o,| a + b + c + d + e + f + g + h + i + j + k + l + m + n + o }
System.print(f15.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,),) // expect: 120

var f16 = Fn.new {|a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p,| a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p }
System.print(f16.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,),) // expect: 136
6 changes: 6 additions & 0 deletions test/language/function/type_hint.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
System.print(Fn.new { -> String "" }.call()) // expect:
System.print(Fn.new {|| -> String "||" }.call()) // expect: ||
System.print(Fn.new {| | -> String "| |" }.call()) // expect: | |
System.print(Fn.new {|a: String| -> String "|%(a)|" }.call("a")) // expect: |a|
System.print(Fn.new {|a: String, b: String| -> String "|%(a), %(b)|" }.call("a", "b")) // expect: |a, b|
System.print(Fn.new {|a: String, b: String, c: String| -> String "|%(a), %(b), %(c)|" }.call("a", "b", "c")) // expect: |a, b, c|
3 changes: 0 additions & 3 deletions test/language/method/empty_subscript_call.wren

This file was deleted.

3 changes: 0 additions & 3 deletions test/language/method/empty_subscript_definition.wren

This file was deleted.

55 changes: 55 additions & 0 deletions test/language/method/setter_operators.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class Foo {
static foo = () { "static 0-setter foo = ()" }
static foo = (a) { "static 1-setter foo = (%(a))" }
static foo = (a, b) { "static 2-setter foo = (%(a), %(b))" }
static foo = (a, b, c) { "static 3-setter foo = (%(a), %(b), %(c))" }
static [subscript] = () { "static 0-subscript setter [%(subscript)] = ()" }
static [subscript] = (a) { "static 1-subscript setter [%(subscript)] = (%(a))" }
static [subscript] = (a, b) { "static 2-subscript setter [%(subscript)] = (%(a), %(b))" }
static [subscript] = (a, b, c) { "static 3-subscript setter [%(subscript)] = (%(a), %(b), %(c))" }

construct new() {}
foo = () { "0-setter foo = ()" }
foo = (a) { "1-setter foo = (%(a))" }
foo = (a, b) { "2-setter foo = (%(a), %(b))" }
foo = (a, b, c) { "3-setter foo = (%(a), %(b), %(c))" }
[subscript] = () { "0-subscript setter [%(subscript)] = ()" }
[subscript] = (a) { "1-subscript setter [%(subscript)] = (%(a))" }
[subscript] = (a, b) { "2-subscript setter [%(subscript)] = (%(a), %(b))" }
[subscript] = (a, b, c) { "3-subscript setter [%(subscript)] = (%(a), %(b), %(c))" }
}

class Bar {
static bar = a { "static 1-setter bar = (%(a))" }

construct new() {}
bar = a { "1-setter bar = (%(a))" }
}

System.print(Foo.foo = ()) // expect: static 0-setter foo = ()
System.print(Foo.foo = "a") // expect: static 1-setter foo = (a)
System.print(Foo.foo = ("a")) // expect: static 1-setter foo = (a)
System.print(Foo.foo = ("a", "b")) // expect: static 2-setter foo = (a, b)
System.print(Foo.foo = ("a", "b", "c")) // expect: static 3-setter foo = (a, b, c)
System.print(Foo["subscript"] = ()) // expect: static 0-subscript setter [subscript] = ()
System.print(Foo["subscript"] = "a") // expect: static 1-subscript setter [subscript] = (a)
System.print(Foo["subscript"] = ("a")) // expect: static 1-subscript setter [subscript] = (a)
System.print(Foo["subscript"] = ("a", "b")) // expect: static 2-subscript setter [subscript] = (a, b)
System.print(Foo["subscript"] = ("a", "b", "c")) // expect: static 3-subscript setter [subscript] = (a, b, c)

System.print(Bar.bar = "a") // expect: static 1-setter bar = (a)

var foo = Foo.new()
System.print(foo.foo = ()) // expect: 0-setter foo = ()
System.print(foo.foo = "a") // expect: 1-setter foo = (a)
System.print(foo.foo = ("a")) // expect: 1-setter foo = (a)
System.print(foo.foo = ("a", "b")) // expect: 2-setter foo = (a, b)
System.print(foo.foo = ("a", "b", "c")) // expect: 3-setter foo = (a, b, c)
System.print(foo["subscript"] = ()) // expect: 0-subscript setter [subscript] = ()
System.print(foo["subscript"] = "a") // expect: 1-subscript setter [subscript] = (a)
System.print(foo["subscript"] = ("a")) // expect: 1-subscript setter [subscript] = (a)
System.print(foo["subscript"] = ("a", "b")) // expect: 2-subscript setter [subscript] = (a, b)
System.print(foo["subscript"] = ("a", "b", "c")) // expect: 3-subscript setter [subscript] = (a, b, c)

var bar = Bar.new()
System.print(bar.bar = "a") // expect: 1-setter bar = (a)
14 changes: 0 additions & 14 deletions test/language/method/static_operators.wren
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ class Foo {
static ! { "prefix !%(this)" }
static ~ { "prefix ~%(this)" }
static - { "prefix -%(this)" }

static [a] { "%(this) 1-subscript %(a)" }
static [a, b] { "%(this) 2-subscript %(a) %(b)" }
static [a, b, c] { "%(this) 3-subscript %(a) %(b) %(c)" }
static [a]=(value) { "%(this) 1-subscript setter %(a) = %(value)" }
static [a, b]=(value) { "%(this) 2-subscript setter %(a) %(b) = %(value)" }
static [a, b, c]=(value) { "%(this) 3-subscript setter %(a) %(b) %(c) = %(value)" }
}

System.print(Foo + "a") // expect: infix Foo + a
Expand All @@ -43,10 +36,3 @@ System.print(!Foo) // expect: prefix !Foo
System.print(~Foo) // expect: prefix ~Foo
System.print(-Foo) // expect: prefix -Foo
System.print(Foo is "a") // expect: infix Foo is a

System.print(Foo["a"]) // expect: Foo 1-subscript a
System.print(Foo["a", "b"]) // expect: Foo 2-subscript a b
System.print(Foo["a", "b", "c"]) // expect: Foo 3-subscript a b c
System.print(Foo["a"] = "value") // expect: Foo 1-subscript setter a = value
System.print(Foo["a", "b"] = "value") // expect: Foo 2-subscript setter a b = value
System.print(Foo["a", "b", "c"] = "value") // expect: Foo 3-subscript setter a b c = value
46 changes: 34 additions & 12 deletions test/language/method/subscript_operators.wren
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
class Foo {
static [] { "static 0-subscript []" }
static [a] { "static 1-subscript [%(a)]" }
static [a, b] { "static 2-subscript [%(a), %(b)]" }
static [a, b, c] { "static 3-subscript [%(a), %(b), %(c)]" }
static []=(value) { "static 0-subscript setter [] = %(value)" }
static [a]=(value) { "static 1-subscript setter [%(a)] = %(value)" }
static [a, b]=(value) { "static 2-subscript setter [%(a), %(b)] = %(value)" }
static [a, b, c]=(value) { "static 3-subscript setter [%(a), %(b), %(c)] = %(value)" }

construct new() {}
[a] { "1-subscript %(a)" }
[a, b] { "2-subscript %(a) %(b)" }
[a, b, c] { "3-subscript %(a) %(b) %(c)" }
[a]=(value) { "1-subscript setter %(a) = %(value)" }
[a, b]=(value) { "2-subscript setter %(a) %(b) = %(value)" }
[a, b, c]=(value) { "3-subscript setter %(a) %(b) %(c) = %(value)" }
[] { "0-subscript []" }
[a] { "1-subscript [%(a)]" }
[a, b] { "2-subscript [%(a), %(b)]" }
[a, b, c] { "3-subscript [%(a), %(b), %(c)]" }
[]=(value) { "0-subscript setter [] = %(value)" }
[a]=(value) { "1-subscript setter [%(a)] = %(value)" }
[a, b]=(value) { "2-subscript setter [%(a), %(b)] = %(value)" }
[a, b, c]=(value) { "3-subscript setter [%(a), %(b), %(c)] = %(value)" }
}

System.print(Foo[]) // expect: static 0-subscript []
System.print(Foo["a"]) // expect: static 1-subscript [a]
System.print(Foo["a", "b"]) // expect: static 2-subscript [a, b]
System.print(Foo["a", "b", "c"]) // expect: static 3-subscript [a, b, c]
System.print(Foo[] = "value") // expect: static 0-subscript setter [] = value
System.print(Foo["a"] = "value") // expect: static 1-subscript setter [a] = value
System.print(Foo["a", "b"] = "value") // expect: static 2-subscript setter [a, b] = value
System.print(Foo["a", "b", "c"] = "value") // expect: static 3-subscript setter [a, b, c] = value

var foo = Foo.new()
System.print(foo["a"]) // expect: 1-subscript a
System.print(foo["a", "b"]) // expect: 2-subscript a b
System.print(foo["a", "b", "c"]) // expect: 3-subscript a b c
System.print(foo["a"] = "value") // expect: 1-subscript setter a = value
System.print(foo["a", "b"] = "value") // expect: 2-subscript setter a b = value
System.print(foo["a", "b", "c"] = "value") // expect: 3-subscript setter a b c = value
System.print(foo[]) // expect: 0-subscript []
System.print(foo["a"]) // expect: 1-subscript [a]
System.print(foo["a", "b"]) // expect: 2-subscript [a, b]
System.print(foo["a", "b", "c"]) // expect: 3-subscript [a, b, c]
System.print(foo[] = "value") // expect: 0-subscript setter [] = value
System.print(foo["a"] = "value") // expect: 1-subscript setter [a] = value
System.print(foo["a", "b"] = "value") // expect: 2-subscript setter [a, b] = value
System.print(foo["a", "b", "c"] = "value") // expect: 3-subscript setter [a, b, c] = value
37 changes: 37 additions & 0 deletions test/language/method/trailing_comma.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

class Foo {
static [a,] { "static 1-subscript [%(a)]"}
static [a, b,] { "static 2-subscript [%(a), %(b)]"}
static [a, b, c,] { "static 3-subscript [%(a), %(b), %(c)]"}
static foo(a,) { "static foo(%(a))" }
static foo(a, b,) { "static foo(%(a), %(b))" }
static foo(a, b, c,) { "static foo(%(a), %(b), %(c))" }

construct new(a,) { System.print("construct new(%(a))",) }
construct new(a, b,) { System.print("construct new(%(a), %(b))",) }
construct new(a, b, c,) { System.print("construct new(%(a), %(b), %(c))",) }
[a,] { "1-subscript [%(a)]"}
[a, b,] { "2-subscript [%(a), %(b)]"}
[a, b, c,] { "3-subscript [%(a), %(b), %(c)]"}
foo(a,) { "foo(%(a))" }
foo(a, b,) { "foo(%(a), %(b))" }
foo(a, b, c,) { "foo(%(a), %(b), %(c))" }
}

System.print(Foo["a",],) // expect: static 1-subscript [a]
System.print(Foo["a", "b",],) // expect: static 2-subscript [a, b]
System.print(Foo["a", "b", "c",],) // expect: static 3-subscript [a, b, c]
System.print(Foo.foo("a",),) // expect: static foo(a)
System.print(Foo.foo("a", "b",),) // expect: static foo(a, b)
System.print(Foo.foo("a", "b", "c",),) // expect: static foo(a, b, c)

var foo
foo = Foo.new("a",) // expect: construct new(a)
foo = Foo.new("a", "b",) // expect: construct new(a, b)
foo = Foo.new("a", "b", "c",) // expect: construct new(a, b, c)
System.print(foo["a",],) // expect: 1-subscript [a]
System.print(foo["a", "b",],) // expect: 2-subscript [a, b]
System.print(foo["a", "b", "c",],) // expect: 3-subscript [a, b, c]
System.print(foo.foo("a",),) // expect: foo(a)
System.print(foo.foo("a", "b",),) // expect: foo(a, b)
System.print(foo.foo("a", "b", "c",),) // expect: foo(a, b, c)
76 changes: 76 additions & 0 deletions test/language/method/type_hint.wren
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
class Foo {
static [] -> String { "static 0-subscript []" }
static [a: String] -> String { "static 1-subscript [%(a)]" }
static [a: String, b: String] -> String { "static 2-subscript [%(a), %(b)]" }
static [a: String, b: String, c: String] -> String { "static 3-subscript [%(a), %(b), %(c)]" }
static []=(value: String) -> String { "static 0-subscript setter [] = %(value)" }
static [a: String]=(value: String) -> String { "static 1-subscript setter [%(a)] = %(value)" }
static [a: String, b: String]=(value: String) -> String { "static 2-subscript setter [%(a), %(b)] = %(value)" }
static [a: String, b: String, c: String]=(value: String) -> String { "static 3-subscript setter [%(a), %(b), %(c)] = %(value)" }

static method -> String { "static method" }
static method() -> String { "static method()" }
static method(a: String) -> String { "static method(%(a))" }
static method(a: String, b: String) -> String { "static method(%(a), %(b))" }
static method(a: String, b: String, c: String) -> String { "static method(%(a), %(b), %(c))" }

construct new() -> Foo {}

[] -> String { "0-subscript []" }
[a: String] -> String { "1-subscript [%(a)]" }
[a: String, b: String] -> String { "2-subscript [%(a), %(b)]" }
[a: String, b: String, c: String] -> String { "3-subscript [%(a), %(b), %(c)]" }
[]=(value: String) -> String { "0-subscript setter [] = %(value)" }
[a: String]=(value: String) -> String { "1-subscript setter [%(a)] = %(value)" }
[a: String, b: String]=(value: String) -> String { "2-subscript setter [%(a), %(b)] = %(value)" }
[a: String, b: String, c: String]=(value: String) -> String { "3-subscript setter [%(a), %(b), %(c)] = %(value)" }

method -> String { "method" }
method() -> String { "method()" }
method(a: String) -> String { "method(%(a))" }
method(a: String, b: String) -> String { "method(%(a), %(b))" }
method(a: String, b: String, c: String) -> String { "method(%(a), %(b), %(c))" }
}

class Bar {
static bar = a: String -> String { "static 1-setter bar = (%(a))" }

construct new() {}
bar = a: String -> String { "1-setter bar = (%(a))" }
}

System.print(Foo[]) // expect: static 0-subscript []
System.print(Foo["a"]) // expect: static 1-subscript [a]
System.print(Foo["a", "b"]) // expect: static 2-subscript [a, b]
System.print(Foo["a", "b", "c"]) // expect: static 3-subscript [a, b, c]
System.print(Foo[] = "value") // expect: static 0-subscript setter [] = value
System.print(Foo["a"] = "value") // expect: static 1-subscript setter [a] = value
System.print(Foo["a", "b"] = "value") // expect: static 2-subscript setter [a, b] = value
System.print(Foo["a", "b", "c"] = "value") // expect: static 3-subscript setter [a, b, c] = value

System.print(Foo.method) // expect: static method
System.print(Foo.method()) // expect: static method()
System.print(Foo.method("a")) // expect: static method(a)
System.print(Foo.method("a", "b")) // expect: static method(a, b)
System.print(Foo.method("a", "b", "c")) // expect: static method(a, b, c)

System.print(Bar.bar = "a") // expect: static 1-setter bar = (a)

var foo = Foo.new()
System.print(foo[]) // expect: 0-subscript []
System.print(foo["a"]) // expect: 1-subscript [a]
System.print(foo["a", "b"]) // expect: 2-subscript [a, b]
System.print(foo["a", "b", "c"]) // expect: 3-subscript [a, b, c]
System.print(foo[] = "value") // expect: 0-subscript setter [] = value
System.print(foo["a"] = "value") // expect: 1-subscript setter [a] = value
System.print(foo["a", "b"] = "value") // expect: 2-subscript setter [a, b] = value
System.print(foo["a", "b", "c"] = "value") // expect: 3-subscript setter [a, b, c] = value

System.print(foo.method) // expect: method
System.print(foo.method()) // expect: method()
System.print(foo.method("a")) // expect: method(a)
System.print(foo.method("a", "b")) // expect: method(a, b)
System.print(foo.method("a", "b", "c")) // expect: method(a, b, c)

var bar = Bar.new()
System.print(bar.bar = "a") // expect: 1-setter bar = (a)