diff --git a/builtin/core.wren b/builtin/core.wren index c108a744..4186e200 100644 --- a/builtin/core.wren +++ b/builtin/core.wren @@ -103,7 +103,7 @@ class Sequence { } class MapSequence is Sequence { - this new(sequence, fn) { + construct new(sequence, fn) { _sequence = sequence _fn = fn } @@ -113,7 +113,7 @@ class MapSequence is Sequence { } class WhereSequence is Sequence { - this new(sequence, fn) { + construct new(sequence, fn) { _sequence = sequence _fn = fn } @@ -133,7 +133,7 @@ class String is Sequence { } class StringByteSequence is Sequence { - this new(string) { + construct new(string) { _string = string } @@ -180,7 +180,7 @@ class Map { } class MapKeySequence is Sequence { - this new(map) { + construct new(map) { _map = map } @@ -189,7 +189,7 @@ class MapKeySequence is Sequence { } class MapValueSequence is Sequence { - this new(map) { + construct new(map) { _map = map } diff --git a/doc/site/classes.markdown b/doc/site/classes.markdown index 5ec2c82b..317e1416 100644 --- a/doc/site/classes.markdown +++ b/doc/site/classes.markdown @@ -172,18 +172,18 @@ constructor, like so: :::dart class Unicorn { - this new(name, color) { + construct new(name, color) { IO.print("My name is " + name + " and I am " + color + ".") } } -The `this` before the method name makes it a constructor. The `new` isn't +The `construct` before the method name makes it a constructor. The `new` isn't special. Constructors can have any name you like, which lets you clarify how it creates the instance: :::dart class Unicorn { - this brown(name) { + construct brown(name) { IO.print("My name is " + name + " and I am brown.") } } diff --git a/doc/site/syntax.markdown b/doc/site/syntax.markdown index 27f32d4a..00f0b748 100644 --- a/doc/site/syntax.markdown +++ b/doc/site/syntax.markdown @@ -28,8 +28,8 @@ Some people like to see all of the reserved words in a programming language in one lump. If you're one of those folks, here you go: :::dart - break class else false for foreign if import in - is null return static super this true var while + break class construct else false for foreign if import + in is null return static super this true var while ## Identifiers diff --git a/example/syntax.wren b/example/syntax.wren index 976eb18e..affd4462 100644 --- a/example/syntax.wren +++ b/example/syntax.wren @@ -7,7 +7,7 @@ // Class definition with a toplevel name. class SyntaxExample { // Constructor - this new() { + construct new() { // Top-level name `IO` IO.print("I am a constructor!") @@ -26,7 +26,7 @@ class SyntaxExample { } // Constructor with arguments - this constructor(a, b) { + construct constructor(a, b) { print(a, b) field = a } diff --git a/src/vm/wren_compiler.c b/src/vm/wren_compiler.c index 46d021f7..c0cfdf4a 100644 --- a/src/vm/wren_compiler.c +++ b/src/vm/wren_compiler.c @@ -73,6 +73,7 @@ typedef enum TOKEN_BREAK, TOKEN_CLASS, + TOKEN_CONSTRUCT, TOKEN_ELSE, TOKEN_FALSE, TOKEN_FOR, @@ -628,6 +629,7 @@ static void readName(Parser* parser, TokenType type) if (isKeyword(parser, "break")) type = TOKEN_BREAK; else if (isKeyword(parser, "class")) type = TOKEN_CLASS; + else if (isKeyword(parser, "construct")) type = TOKEN_CONSTRUCT; else if (isKeyword(parser, "else")) type = TOKEN_ELSE; else if (isKeyword(parser, "false")) type = TOKEN_FALSE; else if (isKeyword(parser, "for")) type = TOKEN_FOR; @@ -2489,6 +2491,7 @@ GrammarRule rules[] = /* TOKEN_BANGEQ */ INFIX_OPERATOR(PREC_EQUALITY, "!="), /* TOKEN_BREAK */ UNUSED, /* TOKEN_CLASS */ UNUSED, + /* TOKEN_CONSTRUCT */ { NULL, NULL, constructorSignature, PREC_NONE, NULL }, /* TOKEN_ELSE */ UNUSED, /* TOKEN_FALSE */ PREFIX(boolean), /* TOKEN_FOR */ UNUSED, @@ -2501,7 +2504,7 @@ GrammarRule rules[] = /* TOKEN_RETURN */ UNUSED, /* TOKEN_STATIC */ UNUSED, /* TOKEN_SUPER */ PREFIX(super_), - /* TOKEN_THIS */ { this_, NULL, constructorSignature, PREC_NONE, NULL }, + /* TOKEN_THIS */ PREFIX(this_), /* TOKEN_TRUE */ PREFIX(boolean), /* TOKEN_VAR */ UNUSED, /* TOKEN_WHILE */ UNUSED, @@ -3239,17 +3242,20 @@ static void variableDefinition(Compiler* compiler) // like the non-curly body of an if or while. void definition(Compiler* compiler) { - if (match(compiler, TOKEN_CLASS)) { + if (match(compiler, TOKEN_CLASS)) + { classDefinition(compiler); return; } - if (match(compiler, TOKEN_IMPORT)) { + if (match(compiler, TOKEN_IMPORT)) + { import(compiler); return; } - if (match(compiler, TOKEN_VAR)) { + if (match(compiler, TOKEN_VAR)) + { variableDefinition(compiler); return; } diff --git a/src/vm/wren_core.c b/src/vm/wren_core.c index 3c66a810..efbde00e 100644 --- a/src/vm/wren_core.c +++ b/src/vm/wren_core.c @@ -117,7 +117,7 @@ static const char* coreLibSource = "}\n" "\n" "class MapSequence is Sequence {\n" -" this new(sequence, fn) {\n" +" construct new(sequence, fn) {\n" " _sequence = sequence\n" " _fn = fn\n" " }\n" @@ -127,7 +127,7 @@ static const char* coreLibSource = "}\n" "\n" "class WhereSequence is Sequence {\n" -" this new(sequence, fn) {\n" +" construct new(sequence, fn) {\n" " _sequence = sequence\n" " _fn = fn\n" " }\n" @@ -147,7 +147,7 @@ static const char* coreLibSource = "}\n" "\n" "class StringByteSequence is Sequence {\n" -" this new(string) {\n" +" construct new(string) {\n" " _string = string\n" " }\n" "\n" @@ -194,7 +194,7 @@ static const char* coreLibSource = "}\n" "\n" "class MapKeySequence is Sequence {\n" -" this new(map) {\n" +" construct new(map) {\n" " _map = map\n" " }\n" "\n" @@ -203,7 +203,7 @@ static const char* coreLibSource = "}\n" "\n" "class MapValueSequence is Sequence {\n" -" this new(map) {\n" +" construct new(map) {\n" " _map = map\n" " }\n" "\n" diff --git a/test/benchmark/binary_trees.wren b/test/benchmark/binary_trees.wren index cab1df23..3bf44d03 100644 --- a/test/benchmark/binary_trees.wren +++ b/test/benchmark/binary_trees.wren @@ -1,7 +1,7 @@ // Ported from the Python version. class Tree { - this new(item, depth) { + construct new(item, depth) { _item = item if (depth > 0) { var item2 = item + item diff --git a/test/benchmark/delta_blue.wren b/test/benchmark/delta_blue.wren index 9c578f58..4c88d6db 100644 --- a/test/benchmark/delta_blue.wren +++ b/test/benchmark/delta_blue.wren @@ -50,7 +50,7 @@ var ORDERED = null // disrupting current constraints. Strengths cannot be created outside // this class, so == can be used for value comparison. class Strength { - this new(value, name) { + construct new(value, name) { _value = value _name = name } @@ -82,7 +82,7 @@ ORDERED = [ var ThePlanner class Constraint { - this new(strength) { + construct new(strength) { _strength = strength } @@ -131,7 +131,7 @@ class Constraint { // Abstract superclass for constraints having a single possible output variable. class UnaryConstraint is Constraint { - this new(myOutput, strength) { + construct new(myOutput, strength) { super(strength) _satisfied = false _myOutput = myOutput @@ -187,7 +187,7 @@ class UnaryConstraint is Constraint { // change their output during plan execution. This is called "stay // optimization". class StayConstraint is UnaryConstraint { - this new(variable, strength) { + construct new(variable, strength) { super(variable, strength) } @@ -199,7 +199,7 @@ class StayConstraint is UnaryConstraint { // A unary input constraint used to mark a variable that the client // wishes to change. class EditConstraint is UnaryConstraint { - this new(variable, strength) { + construct new(variable, strength) { super(variable, strength) } @@ -219,7 +219,7 @@ var BACKWARD = 0 // Abstract superclass for constraints having two possible output // variables. class BinaryConstraint is Constraint { - this new(v1, v2, strength) { + construct new(v1, v2, strength) { super(strength) _v1 = v1 _v2 = v2 @@ -328,7 +328,7 @@ class BinaryConstraint is Constraint { // this relationship but the scale factor and offset are considered // read-only. class ScaleConstraint is BinaryConstraint { - this new(src, scale, offset, dest, strength) { + construct new(src, scale, offset, dest, strength) { _scale = scale _offset = offset super(src, dest, strength) @@ -376,7 +376,7 @@ class ScaleConstraint is BinaryConstraint { // Constrains two variables to have the same value. class EqualityConstraint is BinaryConstraint { - this new(v1, v2, strength) { + construct new(v1, v2, strength) { super(v1, v2, strength) } @@ -391,7 +391,7 @@ class EqualityConstraint is BinaryConstraint { // various parameters of interest to the DeltaBlue incremental // constraint solver. class Variable { - this new(name, value) { + construct new(name, value) { _constraints = [] _determinedBy = null _mark = 0 @@ -430,7 +430,7 @@ class Variable { // to resatisfy all currently satisfiable constraints in the face of // one or more changing inputs. class Plan { - this new() { + construct new() { _list = [] } @@ -448,7 +448,7 @@ class Plan { } class Planner { - this new() { + construct new() { _currentMark = 0 } diff --git a/test/benchmark/method_call.wren b/test/benchmark/method_call.wren index 799c92b2..71579357 100644 --- a/test/benchmark/method_call.wren +++ b/test/benchmark/method_call.wren @@ -1,5 +1,5 @@ class Toggle { - this new(startState) { + construct new(startState) { _state = startState } @@ -11,7 +11,7 @@ class Toggle { } class NthToggle is Toggle { - this new(startState, maxCounter) { + construct new(startState, maxCounter) { super(startState) _countMax = maxCounter _count = 0 diff --git a/test/core/sequence/map.wren b/test/core/sequence/map.wren index 70b055fd..e977fe68 100644 --- a/test/core/sequence/map.wren +++ b/test/core/sequence/map.wren @@ -1,6 +1,6 @@ // Infinite iterator demonstrating that Sequence.map is not eager class FibIterator { - this new() { + construct new() { _current = 0 _next = 1 } diff --git a/test/core/sequence/where.wren b/test/core/sequence/where.wren index 3721433f..f59b3917 100644 --- a/test/core/sequence/where.wren +++ b/test/core/sequence/where.wren @@ -1,6 +1,6 @@ // Infinite iterator demonstrating that Sequence.where is not eager class FibIterator { - this new() { + construct new() { _current = 0 _next = 1 } diff --git a/test/language/class/new.wren b/test/language/class/new.wren deleted file mode 100644 index 0e0533a9..00000000 --- a/test/language/class/new.wren +++ /dev/null @@ -1,6 +0,0 @@ -class Foo {} - -var foo = Foo.new() -IO.print(foo is Foo) // expect: true - -// TODO: Test precedence and grammar of what follows "new". diff --git a/test/language/constructor/cannot_be_static.wren b/test/language/constructor/cannot_be_static.wren index 7a61efd4..8885708d 100644 --- a/test/language/constructor/cannot_be_static.wren +++ b/test/language/constructor/cannot_be_static.wren @@ -1,4 +1,4 @@ class Foo { - static this new() {} // expect error - this static new() {} // expect error + static construct new() {} // expect error + construct static new() {} // expect error } diff --git a/test/language/constructor/cannot_call_initializer.wren b/test/language/constructor/cannot_call_initializer.wren index d6bb8459..56a2993d 100644 --- a/test/language/constructor/cannot_call_initializer.wren +++ b/test/language/constructor/cannot_call_initializer.wren @@ -1,5 +1,5 @@ class Foo { - this new() { + construct new() { IO.print("ok") } } diff --git a/test/language/constructor/default_calls_new.wren b/test/language/constructor/default_calls_new.wren index 868a0cae..1c00bca0 100644 --- a/test/language/constructor/default_calls_new.wren +++ b/test/language/constructor/default_calls_new.wren @@ -1,5 +1,5 @@ class Foo { - this new() { + construct new() { IO.print("Foo.new()") } } diff --git a/test/language/constructor/infix_class_expression.wren b/test/language/constructor/infix_class_expression.wren deleted file mode 100644 index 23a9d599..00000000 --- a/test/language/constructor/infix_class_expression.wren +++ /dev/null @@ -1,9 +0,0 @@ -class Foo { - +(other) { "Foo " + other } -} - -IO.print(Foo.new() + "value") // expect: Foo value - -// TODO: Other expressions following a constructor, like new Foo.bar("arg"). -// TODO: Delete this test? -// TODO: Other constructor tests, like named constructors, etc. diff --git a/test/language/constructor/named.wren b/test/language/constructor/named.wren index b893775d..b1fc23a1 100644 --- a/test/language/constructor/named.wren +++ b/test/language/constructor/named.wren @@ -1,8 +1,6 @@ -// TODO: Change this. - class Foo { - this named() { _field = "named" } - this other() { _field = "other" } + construct named() { _field = "named" } + construct other() { _field = "other" } toString { _field } } diff --git a/test/language/constructor/no_default.wren b/test/language/constructor/no_default.wren index f35bc783..287f1b83 100644 --- a/test/language/constructor/no_default.wren +++ b/test/language/constructor/no_default.wren @@ -1,5 +1,5 @@ class Foo { - this real() {} + construct real() {} } // Classes do not get an argument-less "new()" if they define a constructor. diff --git a/test/language/constructor/not_inherited.wren b/test/language/constructor/not_inherited.wren index 159f2b35..eacbce17 100644 --- a/test/language/constructor/not_inherited.wren +++ b/test/language/constructor/not_inherited.wren @@ -1,5 +1,5 @@ class Foo { - this base() {} + construct base() {} } class Bar is Foo {} diff --git a/test/language/constructor/object.wren b/test/language/constructor/object.wren index 708b554b..b60f99ac 100644 --- a/test/language/constructor/object.wren +++ b/test/language/constructor/object.wren @@ -2,12 +2,10 @@ // super() call in a subclass, so this does that. class Foo { - this new() { + construct new() { super() // Should not cause a no method error. IO.print("ok") } } Foo.new() // expect: ok - -// TODO: Test that can't invoke initializer on existing instance. diff --git a/test/language/constructor/super_must_have_args.wren b/test/language/constructor/super_must_have_args.wren index 0676b3d6..47778f8b 100644 --- a/test/language/constructor/super_must_have_args.wren +++ b/test/language/constructor/super_must_have_args.wren @@ -1,7 +1,7 @@ class A {} class B is A { - this new() { + construct new() { super // expect error } } diff --git a/test/language/constructor/superclass.wren b/test/language/constructor/superclass.wren index 013d74ae..e292c513 100644 --- a/test/language/constructor/superclass.wren +++ b/test/language/constructor/superclass.wren @@ -1,5 +1,5 @@ class A { - this new(arg) { + construct new(arg) { IO.print("new A ", arg) _field = arg } @@ -8,7 +8,7 @@ class A { } class B is A { - this new(arg1, arg2) { + construct new(arg1, arg2) { super(arg2) IO.print("new B ", arg1) _field = arg1 @@ -18,7 +18,7 @@ class B is A { } class C is B { - this new() { + construct new() { super("one", "two") IO.print("new C") _field = "c" diff --git a/test/language/field/closure.wren b/test/language/field/closure.wren index 4b5a2774..3f0c27ba 100644 --- a/test/language/field/closure.wren +++ b/test/language/field/closure.wren @@ -1,5 +1,5 @@ class Foo { - this new() { _field = "Foo field" } + construct new() { _field = "Foo field" } closeOverGet { return Fn.new { _field } diff --git a/test/language/field/object_reference.wren b/test/language/field/object_reference.wren index c39b530b..5f29fa62 100644 --- a/test/language/field/object_reference.wren +++ b/test/language/field/object_reference.wren @@ -1,6 +1,6 @@ // This test exists mainly to make sure the GC traces instance fields. class Node { - this new(left, value, right) { + construct new(left, value, right) { _left = left _value = value _right = right diff --git a/test/language/for/truth.wren b/test/language/for/truth.wren index e84031ee..ffbfe2b1 100644 --- a/test/language/for/truth.wren +++ b/test/language/for/truth.wren @@ -1,5 +1,5 @@ class Iter { - this new(value) { _value = value } + construct new(value) { _value = value } iterate(iterator) { _value } iteratorValue(iterator) { "value" } } diff --git a/test/language/inheritance/inherited_fields_in_closure.wren b/test/language/inheritance/inherited_fields_in_closure.wren index a43f67e9..c9e8bfb1 100644 --- a/test/language/inheritance/inherited_fields_in_closure.wren +++ b/test/language/inheritance/inherited_fields_in_closure.wren @@ -1,5 +1,5 @@ class Foo { - this new() { _field = "Foo field" } + construct new() { _field = "Foo field" } closeOverFooGet { return Fn.new { Fn.new { _field } } @@ -11,7 +11,7 @@ class Foo { } class Bar is Foo { - this new() { + construct new() { super() _field = "Bar field" } diff --git a/test/language/setter/associativity.wren b/test/language/setter/associativity.wren index ed32a0a8..4693502f 100644 --- a/test/language/setter/associativity.wren +++ b/test/language/setter/associativity.wren @@ -1,5 +1,5 @@ class Foo { - this new(value) { _value = value } + construct new(value) { _value = value } toString { _value } bar=(value) { _value = value diff --git a/test/limit/many_fields.wren b/test/limit/many_fields.wren index a9067663..eed2a9b6 100644 --- a/test/limit/many_fields.wren +++ b/test/limit/many_fields.wren @@ -1,5 +1,5 @@ class Foo { - this new() { + construct new() { _field1 = 1 _field2 = 2 _field3 = 3 diff --git a/test/limit/many_inherited_fields.wren b/test/limit/many_inherited_fields.wren index f5b668fb..c63e99b1 100644 --- a/test/limit/many_inherited_fields.wren +++ b/test/limit/many_inherited_fields.wren @@ -1,5 +1,5 @@ class Foo { - this new() { + construct new() { _field1 = 1 _field2 = 2 _field3 = 3 @@ -137,7 +137,7 @@ class Foo { } class Bar is Foo { - this new() { + construct new() { super() _field129 = 129 _field130 = 130 diff --git a/test/limit/too_many_fields.wren b/test/limit/too_many_fields.wren index 12774ed0..974f4559 100644 --- a/test/limit/too_many_fields.wren +++ b/test/limit/too_many_fields.wren @@ -1,5 +1,5 @@ class Foo { - this new() { + construct new() { _field1 = 1 _field2 = 2 _field3 = 3 diff --git a/test/limit/too_many_inherited_fields.wren b/test/limit/too_many_inherited_fields.wren index 067d8d35..0c90bff1 100644 --- a/test/limit/too_many_inherited_fields.wren +++ b/test/limit/too_many_inherited_fields.wren @@ -1,5 +1,5 @@ class Foo { - this new() { + construct new() { _field1 = 1 _field2 = 2 _field3 = 3 @@ -137,7 +137,7 @@ class Foo { } class Bar is Foo { // expect runtime error: Class 'Bar' may not have more than 255 fields, including inherited ones. - this new() { + construct new() { super() _field129 = 129 _field130 = 130