diff --git a/builtin/core.wren b/builtin/core.wren index 52ae9ac3..c108a744 100644 --- a/builtin/core.wren +++ b/builtin/core.wren @@ -52,11 +52,11 @@ class Sequence { } } - isEmpty { iterate(null) ? false : true } - - map(transformation) { new MapSequence(this, transformation) } + isEmpty { iterate(null) ? false : true } - where(predicate) { new WhereSequence(this, predicate) } + map(transformation) { MapSequence.new(this, transformation) } + + where(predicate) { WhereSequence.new(this, predicate) } reduce(acc, f) { for (element in this) { @@ -94,7 +94,7 @@ class Sequence { } toList { - var result = new List + var result = List.new() for (element in this) { result.add(element) } @@ -103,7 +103,7 @@ class Sequence { } class MapSequence is Sequence { - new(sequence, fn) { + this new(sequence, fn) { _sequence = sequence _fn = fn } @@ -113,7 +113,7 @@ class MapSequence is Sequence { } class WhereSequence is Sequence { - new(sequence, fn) { + this new(sequence, fn) { _sequence = sequence _fn = fn } @@ -129,11 +129,11 @@ class WhereSequence is Sequence { } class String is Sequence { - bytes { new StringByteSequence(this) } + bytes { StringByteSequence.new(this) } } class StringByteSequence is Sequence { - new(string) { + this new(string) { _string = string } @@ -162,8 +162,8 @@ class List is Sequence { } class Map { - keys { new MapKeySequence(this) } - values { new MapValueSequence(this) } + keys { MapKeySequence.new(this) } + values { MapValueSequence.new(this) } toString { var first = true @@ -180,7 +180,7 @@ class Map { } class MapKeySequence is Sequence { - new(map) { + this new(map) { _map = map } @@ -189,7 +189,7 @@ class MapKeySequence is Sequence { } class MapValueSequence is Sequence { - new(map) { + this new(map) { _map = map } diff --git a/doc/site/classes.markdown b/doc/site/classes.markdown index c3713a32..5ec2c82b 100644 --- a/doc/site/classes.markdown +++ b/doc/site/classes.markdown @@ -64,7 +64,7 @@ class is fine: And you can call each of the methods like so: :::dart - var unicorn = new Unicorn + var unicorn = Unicorn.new() unicorn.prance unicorn.prance("Antwerp") unicorn.prance("Brussels", "high noon") @@ -86,7 +86,7 @@ method that takes an *empty* argument list (`()`) and no argument list at all: method() { "empty argument list" } } - var confusing = new Confusing + var confusing = Confusing.new() confusing.method // "no argument list". confusing.method() // "empty argument list". @@ -159,39 +159,50 @@ overloading by arity, it's no problem for a class to define both. ## Constructors -To create a new instance of a class, you use the `new` keyword. We can make a -unicorn like so: +To create a new instance of a class, call a *constructor method* on its class. +By default, if you don't define any constructors yourself, you get a free one +named `new()`: :::dart - new Unicorn + Unicorn.new() -You almost always want to define some state or do some other initialization on -a new object. For that, you'll want to define a constructor, like so: +However, you almost always want to define some state or do some other +initialization on a new object. For that, you'll want to define your own +constructor, like so: :::dart class Unicorn { - new { - IO.print("I am a constructor!") - } - } - -When you create an instance with `new`, its constructor will be invoked. It's -just a method with a special name. Like methods, you can pass arguments to the -constructor by adding a parenthesized parameter list after `new`: - - :::dart - class Unicorn { - new(name, color) { + this new(name, color) { IO.print("My name is " + name + " and I am " + color + ".") } } -Values are passed to the constructor like so: +The `this` 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 - new Unicorn("Flicker", "purple") + class Unicorn { + this brown(name) { + IO.print("My name is " + name + " and I am brown.") + } + } -Like other methods, you can overload constructors by [arity](#signature). +Constructors can obviously have arguments, and can be overloaded by +[arity](#signature). A constructor *must* be a named method with a (possibly +empty) argument list. Operators, getters, and setters cannot be constructors. + +A constructor is actually a pair of methods. You get a method on the class: + + :::dart + Unicorn.brown("Fred") + +That creates the new instance, then it invokes the *initializer* on that +instance. This is where the constructor body you defined gets run. + +This distinction is important because it means inside the body of the +constructor, you can access `this`, assign [fields](#fields), call superclass +constructors, etc. ## Fields @@ -292,8 +303,8 @@ And also instance methods. When you do so, there is still only one static field shared among all instances of the class: :::dart - var foo1 = new Foo - var foo2 = new Foo + var foo1 = Foo.new() + var foo2 = Foo.new() foo1.setFromInstance("updated") IO.print(foo2.baz) // updated. @@ -330,17 +341,36 @@ are not inherited. Pegasus.canFly // ERROR: Static methods are not inherited. -Constructors, however, initialize the instance *after* it has been created. -They are defined as instance methods on the class and not on the metaclass. -That means that constructors *are* inherited. +This also means constructors are not inherited: :::dart class Unicorn { - new(name) { + this new(name) { IO.print("My name is " + name + ".") } } class Pegasus is Unicorn {} - new Pegasus("Fred") // Prints "My name is Fred.". + Pegasus.new("Fred") // Error! + +Each class gets to control how it may be constructed independently of its base +classes. However, constructor *initializers* are inherited since those are +instance methods on the new object. + +This means you can do `super` calls inside a constructor: + + :::dart + class Unicorn { + this new(name) { + IO.print("My name is " + name + ".") + } + } + + class Pegasus is Unicorn { + this new(name) { + super(name) + } + } + + Pegasus.new("Fred") // Prints "My name is Fred.". diff --git a/doc/site/core/fiber.markdown b/doc/site/core/fiber.markdown index 0e10bd71..9e66e960 100644 --- a/doc/site/core/fiber.markdown +++ b/doc/site/core/fiber.markdown @@ -3,13 +3,13 @@ A lightweight coroutine. [Here](../fibers.html) is a gentle introduction. -### new **Fiber**(function) +### Fiber.**new**(function) Creates a new fiber that executes `function` in a separate coroutine when the fiber is run. Does not immediately start running the fiber. :::dart - var fiber = new Fiber { + var fiber = Fiber.new { IO.print("I won't get printed") } @@ -25,7 +25,7 @@ Pauses the current fiber and transfers control to the parent fiber. "Parent" here means the last fiber that was started using `call` and not `run`. :::dart - var fiber = new Fiber { + var fiber = Fiber.new { IO.print("Before yield") Fiber.yield() IO.print("After yield") @@ -41,7 +41,7 @@ If a yielded fiber is resumed by calling `call()` or `run()` with an argument, `yield()` returns that value. :::dart - var fiber = new Fiber { + var fiber = Fiber.new { IO.print(Fiber.yield()) // "value" } @@ -65,7 +65,7 @@ Similar to `Fiber.yield` but provides a value to return to the parent fiber's `call`. :::dart - var fiber = new Fiber { + var fiber = Fiber.new { Fiber.yield("value") } @@ -78,7 +78,7 @@ Similar to `Fiber.yield` but provides a value to return to the parent fiber's Starts or resumes the fiber if it is in a paused state. :::dart - var fiber = new Fiber { + var fiber = Fiber.new { IO.print("Fiber called") Fiber.yield() IO.print("Fiber called again") @@ -94,7 +94,7 @@ If the called fiber is resuming from a yield, the `yield()` method returns `null` in the called fiber. :::dart - var fiber = new Fiber { + var fiber = Fiber.new { IO.print(Fiber.yield()) } @@ -107,7 +107,7 @@ Invokes the fiber or resumes the fiber if it is in a paused state and sets `value` as the returned value of the fiber's call to `yield`. :::dart - var fiber = new Fiber { + var fiber = Fiber.new { IO.print(Fiber.yield()) } diff --git a/doc/site/core/fn.markdown b/doc/site/core/fn.markdown index a1522b94..df62d26c 100644 --- a/doc/site/core/fn.markdown +++ b/doc/site/core/fn.markdown @@ -4,7 +4,7 @@ A first class function—an object that wraps an executable chunk of code. [Here](../functions.html) is a friendly introduction. -### new **Fn**(function) +### Fn.**new**(function) Creates a new function from... `function`. Of course, `function` is already a function, so this really just returns the argument. It exists mainly to let you @@ -12,7 +12,7 @@ create a "bare" function when you don't want to immediately pass it as a [block argument](../functions.html#block-arguments) to some other method. :::dart - var fn = new Fn { + var fn = Fn.new { IO.print("The body") } @@ -25,15 +25,15 @@ It is a runtime error if `function` is not a function. The number of arguments the function requires. :::dart - IO.print(new Fn {}.arity) // 0. - IO.print(new Fn {|a, b, c| a }.arity) // 3. + IO.print(Fn.new {}.arity) // 0. + IO.print(Fn.new {|a, b, c| a }.arity) // 3. ### **call**(args...) Invokes the function with the given arguments. :::dart - var fn = new Fn { |arg| + var fn = Fn.new { |arg| IO.print(arg) } diff --git a/doc/site/core/sequence.markdown b/doc/site/core/sequence.markdown index 4a12df95..c80061b9 100644 --- a/doc/site/core/sequence.markdown +++ b/doc/site/core/sequence.markdown @@ -109,11 +109,11 @@ To force eager evaluation, just call `.toList` on the result. ### **reduce**(function) -Reduces the sequence down to a single value. `function` is a function that takes -two arguments, the accumulator and sequence item and returns the new accumulator -value. The accumulator is initialized from the first item in the sequence. Then, -the function is invoked on each remaining item in the sequence, iteratively -updating the accumulator. +Reduces the sequence down to a single value. `function` is a function that +takes two arguments, the accumulator and sequence item and returns the new +accumulator value. The accumulator is initialized from the first item in the +sequence. Then, the function is invoked on each remaining item in the sequence, +iteratively updating the accumulator. It is a runtime error to call this on an empty sequence. diff --git a/doc/site/error-handling.markdown b/doc/site/error-handling.markdown index e81568b6..e0271e8a 100644 --- a/doc/site/error-handling.markdown +++ b/doc/site/error-handling.markdown @@ -52,7 +52,7 @@ superclasses) don't define that method, there's nothing Wren can do: :::dart class Foo {} - var foo = new Foo + var foo = Foo.new() foo.someRandomMethod If you run this, Wren will print: @@ -103,7 +103,7 @@ error message as a string. For example, if you run this program: :::dart - var fiber = new Fiber { + var fiber = Fiber.new { 123.badMethod } diff --git a/doc/site/expressions.markdown b/doc/site/expressions.markdown index e0340a04..a7a84abb 100644 --- a/doc/site/expressions.markdown +++ b/doc/site/expressions.markdown @@ -113,13 +113,13 @@ base class constructor: :::dart class Base { - new(arg) { + this new(arg) { IO.print("base constructor got ", arg) } } class Derived is Base { - new { + this new() { super("value") // Prints "base constructor got value". } } diff --git a/doc/site/fibers.markdown b/doc/site/fibers.markdown index ba543e5a..5cd71542 100644 --- a/doc/site/fibers.markdown +++ b/doc/site/fibers.markdown @@ -27,7 +27,7 @@ script, a main fiber is created for you automatically. You can spawn new fibers using the `Fiber` class's constructor: :::dart - var fiber = new Fiber { + var fiber = Fiber.new { IO.print("This runs in a separate fiber.") } @@ -48,7 +48,7 @@ until it passes control to another fiber. If it reaches the end of its body, it's considered *done*: :::dart - var fiber = new Fiber { IO.print("Hi") } + var fiber = Fiber.new { IO.print("Hi") } fiber.isDone // false fiber.call() fiber.isDone // true @@ -70,7 +70,7 @@ fiber is called, it picks up right where it left off and keeps going. You can make a fiber yield by calling the static `yield()` method on `Fiber`: :::dart - var fiber = new Fiber { + var fiber = Fiber.new { IO.print("fiber 1") Fiber.yield() IO.print("fiber 2") @@ -103,7 +103,7 @@ fiber has yielded and is waiting to resume, the value becomes the return value of the `yield()` call: :::dart - var fiber = new Fiber { + var fiber = Fiber.new { var result = Fiber.yield() IO.print(result) } @@ -120,7 +120,7 @@ Fibers can also pass values *back* when they yield. If you pass an argument to invoke the fiber: :::dart - var fiber = new Fiber { + var fiber = Fiber.new { Fiber.yield("sent") } @@ -140,7 +140,7 @@ Wren's fibers can do that, but they can do much more. Like Lua, they are full example: :::dart - var fiber = new Fiber { + var fiber = Fiber.new { (1..10).map {|i| Fiber.yield(i) } diff --git a/doc/site/functions.markdown b/doc/site/functions.markdown index 0744f80e..6d753fb1 100644 --- a/doc/site/functions.markdown +++ b/doc/site/functions.markdown @@ -61,7 +61,7 @@ but *don't* need to pass it to a method. For that, you can call the `Fn` class's constructor: :::dart - var someFn = new Fn { + var someFn = Fn.new { IO.print("Hi!") } @@ -91,7 +91,7 @@ method is dynamically-dispatched like any other, so you can define your own } } - blondie.callMe(new FakeFn) + blondie.callMe(FakeFn.new()) ## Function parameters @@ -130,9 +130,9 @@ value using a `return` statement. In other words, these two functions do the same thing: :::dart - new Fn { "return value" } + Fn.new { "return value" } - new Fn { + Fn.new { return "return value" } @@ -146,7 +146,7 @@ leaving the scope where the function is defined: class Counter { static create { var i = 0 - return new Fn { i = i + 1 } + return Fn.new { i = i + 1 } } } diff --git a/doc/site/index.markdown b/doc/site/index.markdown index 5cecebc5..75a40a1b 100644 --- a/doc/site/index.markdown +++ b/doc/site/index.markdown @@ -14,7 +14,7 @@ a familiar, modern [syntax][]. } } - var adjectives = new Fiber { + var adjectives = Fiber.new { ["small", "clean", "fast"].each {|word| Fiber.yield(word) } } diff --git a/doc/site/qa.markdown b/doc/site/qa.markdown index c1dd6f24..a8617a84 100644 --- a/doc/site/qa.markdown +++ b/doc/site/qa.markdown @@ -56,12 +56,12 @@ Here's the same example in Wren: :::dart class Account { - new(balance) { _balance = balance } + this new(balance) { _balance = balance } withdraw(amount) { _balance = _balance - amount } } // create and use an Account - var acc = new Account(1000) + var acc = Account.new(1000) acc.withdraw(100) Classes have a reputation for complexity because most of the widely used diff --git a/doc/site/syntax.markdown b/doc/site/syntax.markdown index b6ab3633..27f32d4a 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 - new null return static super this true var while + break class else false for foreign if import in + is null return static super this true var while ## Identifiers @@ -102,12 +102,12 @@ compact notation: :::dart { "single expression" } -If there is no newline after the `{` (or after the parameter list in a of +If there is no newline after the `{` (or after the parameter list in a [function](functions.html)), then the block may only contain a single expression, and it automatically returns the result of it. It's exactly the same as doing: :::dart { - return "single expression" + return "single expression" } diff --git a/example/import-module/lovecraft.wren b/example/import-module/lovecraft.wren index 11f27d98..7eebb15e 100644 --- a/example/import-module/lovecraft.wren +++ b/example/import-module/lovecraft.wren @@ -1,7 +1,7 @@ import "cthulu" for Cthulu class Lovecraft { - say { (new Cthulu).message } + say() { Cthulu.new().message } } -IO.print((new Lovecraft).say) +IO.print(Lovecraft.new().say()) diff --git a/example/syntax.wren b/example/syntax.wren index 3255dbf2..976eb18e 100644 --- a/example/syntax.wren +++ b/example/syntax.wren @@ -7,7 +7,7 @@ // Class definition with a toplevel name. class SyntaxExample { // Constructor - new { + this new() { // Top-level name `IO` IO.print("I am a constructor!") @@ -26,7 +26,7 @@ class SyntaxExample { } // Constructor with arguments - new(a, b) { + this constructor(a, b) { print(a, b) field = a } @@ -82,14 +82,11 @@ class SyntaxExample { // `class`, `is` class ReservedWords is SyntaxExample { - // `new` - new { + reserved { // `super`, `true`, `false` super(true, false) // `this` this.foo - // `new` - new SyntaxExample } foo { diff --git a/script/test.py b/script/test.py index 639f62f4..025567ae 100755 --- a/script/test.py +++ b/script/test.py @@ -148,14 +148,15 @@ class Test: def validate_runtime_error(self, error_lines): - if not error_lines: + if len(error_lines) < 2: self.fail('Expected runtime error "{0} and got none.', - runtime_error_message) + self.runtime_error_message) return # Make sure we got the right error. if error_lines[0] != self.runtime_error_message: - self.fail('Expected runtime error "{0}" and got:', runtime_error_message) + self.fail('Expected runtime error "{0}" and got:', + self.runtime_error_message) self.fail(error_lines[0]) # Make sure the stack trace has the right line. diff --git a/src/vm/wren_common.h b/src/vm/wren_common.h index 380a5893..4303332c 100644 --- a/src/vm/wren_common.h +++ b/src/vm/wren_common.h @@ -95,14 +95,15 @@ // The maximum length of a method signature. Signatures look like: // -// foo // Getter. -// foo() // No-argument method. -// foo(_) // One-argument method. -// foo(_,_) // Two-argument method. +// foo // Getter. +// foo() // No-argument method. +// foo(_) // One-argument method. +// foo(_,_) // Two-argument method. +// this foo() // Constructor initializer. // // The maximum signature length takes into account the longest method name, the -// maximum number of parameters with separators between them, and "()". -#define MAX_METHOD_SIGNATURE (MAX_METHOD_NAME + (MAX_PARAMETERS * 2) + 1) +// maximum number of parameters with separators between them, "this ", and "()". +#define MAX_METHOD_SIGNATURE (MAX_METHOD_NAME + (MAX_PARAMETERS * 2) + 6) // The maximum length of an identifier. The only real reason for this limitation // is so that error messages mentioning variables can be stack allocated. diff --git a/src/vm/wren_compiler.c b/src/vm/wren_compiler.c index 67d118d8..a3426733 100644 --- a/src/vm/wren_compiler.c +++ b/src/vm/wren_compiler.c @@ -81,7 +81,6 @@ typedef enum TOKEN_IMPORT, TOKEN_IN, TOKEN_IS, - TOKEN_NEW, TOKEN_NULL, TOKEN_RETURN, TOKEN_STATIC, @@ -213,6 +212,39 @@ typedef struct sLoop struct sLoop* enclosing; } Loop; +// The different signature syntaxes for different kinds of methods. +typedef enum +{ + // A name followed by a (possibly empty) parenthesized parameter list. Also + // used for binary operators. + SIG_METHOD, + + // Just a name. Also used for unary operators. + SIG_GETTER, + + // A name followed by "=". + SIG_SETTER, + + // A square bracketed parameter list. + SIG_SUBSCRIPT, + + // A square bracketed parameter list followed by "=". + SIG_SUBSCRIPT_SETTER, + + // A constructor initializer function. This has a distinct signature to + // prevent it from being invoked directly outside of the constructor on the + // metaclass. + SIG_INITIALIZER +} SignatureType; + +typedef struct +{ + const char* name; + int length; + SignatureType type; + int arity; +} Signature; + // Bookkeeping information for compiling a class definition. typedef struct { @@ -220,14 +252,10 @@ typedef struct SymbolTable* fields; // True if the current method being compiled is static. - bool isStaticMethod; + bool inStatic; - // The name of the method being compiled. Note that this is just the bare - // method name, and not its full signature. - const char* methodName; - - // The length of the method name being compiled. - int methodLength; + // The signature of the method being compiled. + Signature* signature; } ClassCompiler; struct sCompiler @@ -608,7 +636,6 @@ static void readName(Parser* parser, TokenType type) else if (isKeyword(parser, "import")) type = TOKEN_IMPORT; else if (isKeyword(parser, "in")) type = TOKEN_IN; else if (isKeyword(parser, "is")) type = TOKEN_IS; - else if (isKeyword(parser, "new")) type = TOKEN_NEW; else if (isKeyword(parser, "null")) type = TOKEN_NULL; else if (isKeyword(parser, "return")) type = TOKEN_RETURN; else if (isKeyword(parser, "static")) type = TOKEN_STATIC; @@ -1386,34 +1413,6 @@ typedef enum typedef void (*GrammarFn)(Compiler*, bool allowAssignment); -// The different signature syntaxes for different kinds of methods. -typedef enum -{ - // A name followed by a (possibly empty) parenthesized parameter list. Also - // used for binary operators. - SIG_METHOD, - - // Just a name. Also used for unary operators. - SIG_GETTER, - - // A name followed by "=". - SIG_SETTER, - - // A square bracketed parameter list. - SIG_SUBSCRIPT, - - // A square bracketed parameter list followed by "=". - SIG_SUBSCRIPT_SETTER -} SignatureType; - -typedef struct -{ - const char* name; - int length; - SignatureType type; - int arity; -} Signature; - typedef void (*SignatureFn)(Compiler* compiler, Signature* signature); typedef struct @@ -1484,13 +1483,16 @@ static bool finishBlock(Compiler* compiler) } // Parses a method or function body, after the initial "{" has been consumed. -static void finishBody(Compiler* compiler, bool isConstructor) +// +// It [isInitializer] is `true`, this is the body of a constructor initializer. +// In that case, this adds the code to ensure it returns `this`. +static void finishBody(Compiler* compiler, bool isInitializer) { bool isExpressionBody = finishBlock(compiler); - if (isConstructor) + if (isInitializer) { - // If the constructor body evaluates to a value, discard it. + // If the initializer body evaluates to a value, discard it. if (isExpressionBody) emit(compiler, CODE_POP); // The receiver is always stored in the first local slot. @@ -1559,9 +1561,11 @@ static void signatureParameterList(char name[MAX_METHOD_SIGNATURE], int* length, static void signatureToString(Signature* signature, char name[MAX_METHOD_SIGNATURE], int* length) { + *length = 0; + // Build the full name from the signature. - *length = signature->length; - memcpy(name, signature->name, *length); + memcpy(name + *length, signature->name, signature->length); + *length += signature->length; switch (signature->type) { @@ -1587,6 +1591,13 @@ static void signatureToString(Signature* signature, name[(*length)++] = '='; signatureParameterList(name, length, 1, '(', ')'); break; + + case SIG_INITIALIZER: + memcpy(name, "this ", 5); + memcpy(name + 5, signature->name, signature->length); + *length = 5 + signature->length; + signatureParameterList(name, length, signature->arity, '(', ')'); + break; } name[*length] = '\0'; @@ -1608,7 +1619,6 @@ static void signatureFromToken(Compiler* compiler, Signature* signature) { // Get the token for the method name. Token* token = &compiler->parser->previous; - signature->type = SIG_GETTER; signature->arity = 0; signature->name = token->start; signature->length = token->length; @@ -1667,15 +1677,18 @@ static void callMethod(Compiler* compiler, int numArgs, const char* name, emitShortArg(compiler, (Code)(CODE_CALL_0 + numArgs), symbol); } -// Compiles an (optional) argument list and then calls it. +// Compiles an (optional) argument list for a method call with [methodSignature] +// and then calls it. static void methodCall(Compiler* compiler, Code instruction, - const char* name, int length) + Signature* methodSignature) { + // Make a new signature that contains the updated arity and type based on + // the arguments we find. Signature signature; signature.type = SIG_GETTER; signature.arity = 0; - signature.name = name; - signature.length = length; + signature.name = methodSignature->name; + signature.length = methodSignature->length; // Parse the argument list, if any. if (match(compiler, TOKEN_LEFT_PAREN)) @@ -1726,6 +1739,18 @@ static void methodCall(Compiler* compiler, Code instruction, // TODO: Allow Grace-style mixfix methods? + // If this is a super() call for an initializer, make sure we got an actual + // argument list. + if (methodSignature->type == SIG_INITIALIZER) + { + if (signature.type != SIG_METHOD) + { + error(compiler, "A superclass constructor must have an argument list."); + } + + signature.type = SIG_INITIALIZER; + } + callSignature(compiler, instruction, &signature); } @@ -1754,7 +1779,7 @@ static void namedCall(Compiler* compiler, bool allowAssignment, } else { - methodCall(compiler, instruction, signature.name, signature.length); + methodCall(compiler, instruction, &signature); } } @@ -1791,7 +1816,7 @@ static void list(Compiler* compiler, bool allowAssignment) emitShortArg(compiler, CODE_LOAD_MODULE_VAR, listClassSymbol); // Instantiate a new list. - callMethod(compiler, 0, "", 13); + callMethod(compiler, 0, "new()", 5); // Compile the list elements. Each one compiles to a ".add()" call. if (peek(compiler) != TOKEN_RIGHT_BRACKET) @@ -1827,7 +1852,7 @@ static void map(Compiler* compiler, bool allowAssignment) emitShortArg(compiler, CODE_LOAD_MODULE_VAR, mapClassSymbol); // Instantiate a new map. - callMethod(compiler, 0, "", 13); + callMethod(compiler, 0, "new()", 5); // Compile the map elements. Each one is compiled to just invoke the // subscript setter on the map. @@ -1912,7 +1937,7 @@ static void field(Compiler* compiler, bool allowAssignment) { error(compiler, "Cannot reference a field outside of a class definition."); } - else if (enclosingClass->isStaticMethod) + else if (enclosingClass->inStatic) { error(compiler, "Cannot use an instance field in a static method."); } @@ -2138,14 +2163,17 @@ static void super_(Compiler* compiler, bool allowAssignment) { error(compiler, "Cannot use 'super' outside of a method."); } - else if (enclosingClass->isStaticMethod) + else if (enclosingClass->inStatic) { + // TODO: Why not? error(compiler, "Cannot use 'super' in a static method."); } loadThis(compiler); // TODO: Super operator calls. + // TODO: There's no syntax for invoking a superclass constructor with a + // different name from the enclosing one. Figure that out. // See if it's a named super call, or an unnamed one. if (match(compiler, TOKEN_DOT)) @@ -2159,8 +2187,7 @@ static void super_(Compiler* compiler, bool allowAssignment) // No explicit name, so use the name of the enclosing method. Make sure we // check that enclosingClass isn't NULL first. We've already reported the // error, but we don't want to crash here. - methodCall(compiler, CODE_SUPER_0, enclosingClass->methodName, - enclosingClass->methodLength); + methodCall(compiler, CODE_SUPER_0, enclosingClass->signature); } } @@ -2209,23 +2236,6 @@ static void call(Compiler* compiler, bool allowAssignment) namedCall(compiler, allowAssignment, CODE_CALL_0); } -static void new_(Compiler* compiler, bool allowAssignment) -{ - // Allow a dotted name after 'new'. - consume(compiler, TOKEN_NAME, "Expect name after 'new'."); - name(compiler, false); - while (match(compiler, TOKEN_DOT)) - { - call(compiler, false); - } - - // The angle brackets in the name are to ensure users can't call it directly. - callMethod(compiler, 0, "", 13); - - // Invoke the constructor on the new instance. - methodCall(compiler, CODE_CALL_0, "new", 3); -} - static void and_(Compiler* compiler, bool allowAssignment) { ignoreNewlines(compiler); @@ -2309,7 +2319,6 @@ void infixSignature(Compiler* compiler, Signature* signature) void unarySignature(Compiler* compiler, Signature* signature) { // Do nothing. The name is already complete. - signature->type = SIG_GETTER; } // Compiles a method signature for an operator that can either be unary or @@ -2381,9 +2390,9 @@ static void parameterList(Compiler* compiler, Signature* signature) { // The parameter list is optional. if (!match(compiler, TOKEN_LEFT_PAREN)) return; - + signature->type = SIG_METHOD; - + // Allow an empty parameter list. if (match(compiler, TOKEN_RIGHT_PAREN)) return; @@ -2395,7 +2404,7 @@ static void parameterList(Compiler* compiler, Signature* signature) void namedSignature(Compiler* compiler, Signature* signature) { signature->type = SIG_GETTER; - + // If it's a setter, it can't also have a parameter list. if (maybeSetter(compiler, signature)) return; @@ -2406,10 +2415,29 @@ void namedSignature(Compiler* compiler, Signature* signature) // Compiles a method signature for a constructor. void constructorSignature(Compiler* compiler, Signature* signature) { - signature->type = SIG_GETTER; + signature->type = SIG_INITIALIZER; + + consume(compiler, TOKEN_NAME, "Expect constructor name after 'this'."); + + // Capture the name. + signatureFromToken(compiler, signature); + + if (match(compiler, TOKEN_EQ)) + { + error(compiler, "A constructor cannot be a setter."); + } - // Add the parameters, if there are any. - parameterList(compiler, signature); + if (!match(compiler, TOKEN_LEFT_PAREN)) + { + error(compiler, "A constructor cannot be a getter."); + return; + } + + // Allow an empty parameter list. + if (match(compiler, TOKEN_RIGHT_PAREN)) return; + + finishParameterList(compiler, signature); + consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after parameters."); } // This table defines all of the parsing rules for the prefix and infix @@ -2468,12 +2496,11 @@ GrammarRule rules[] = /* TOKEN_IMPORT */ UNUSED, /* TOKEN_IN */ UNUSED, /* TOKEN_IS */ INFIX_OPERATOR(PREC_IS, "is"), - /* TOKEN_NEW */ { new_, NULL, constructorSignature, PREC_NONE, NULL }, /* TOKEN_NULL */ PREFIX(null), /* TOKEN_RETURN */ UNUSED, /* TOKEN_STATIC */ UNUSED, /* TOKEN_SUPER */ PREFIX(super_), - /* TOKEN_THIS */ PREFIX(this_), + /* TOKEN_THIS */ { this_, NULL, constructorSignature, PREC_NONE, NULL }, /* TOKEN_TRUE */ PREFIX(boolean), /* TOKEN_VAR */ UNUSED, /* TOKEN_WHILE */ UNUSED, @@ -2570,6 +2597,7 @@ static int getNumArguments(const uint8_t* bytecode, const Value* constants, case CODE_LOAD_LOCAL_6: case CODE_LOAD_LOCAL_7: case CODE_LOAD_LOCAL_8: + case CODE_CONSTRUCT: return 0; case CODE_LOAD_LOCAL: @@ -2904,24 +2932,103 @@ void statement(Compiler* compiler) emit(compiler, CODE_POP); } -// Compiles a method definition inside a class body. Returns the symbol in the -// method table for the new method. -static int method(Compiler* compiler, ClassCompiler* classCompiler, - bool isConstructor, bool isForeign, SignatureFn signatureFn) +// Creates a matching constructor method for an initializer with [signature] +// and [initializerSymbol]. +// +// Construction is a two-stage process in Wren that involves two separate +// methods. There is a static method that allocates a new instance of the class. +// It then invokes an initializer method on the new instance, forwarding all of +// the constructor arguments to it. +// +// The allocator method always has a fixed implementation: +// +// CODE_CONSTRUCT - Replace the class in slot 0 with a new instance of it. +// CODE_CALL - Invoke the initializer on the new instance. +// +// This creates that method and calls the initializer with [initializerSymbol]. +static void createConstructor(Compiler* compiler, Signature* signature, + int initializerSymbol) { - // Build the method signature. - Signature signature; - signatureFromToken(compiler, &signature); + Compiler methodCompiler; + initCompiler(&methodCompiler, compiler->parser, compiler, false); + + // Allocate the instance. + emit(&methodCompiler, CODE_CONSTRUCT); + + // Run its initializer. + emitShortArg(&methodCompiler, CODE_CALL_0 + signature->arity, + initializerSymbol); + + // Return the instance. + emit(&methodCompiler, CODE_RETURN); + + endCompiler(&methodCompiler, "", 0); +} - classCompiler->methodName = signature.name; - classCompiler->methodLength = signature.length; +// Loads the enclosing class onto the stack and then binds the function already +// on the stack as a method on that class. +static void defineMethod(Compiler* compiler, int classSlot, bool isStatic, + int methodSymbol) +{ + // Load the class. We have to do this for each method because we can't + // keep the class on top of the stack. If there are static fields, they + // will be locals above the initial variable slot for the class on the + // stack. To skip past those, we just load the class each time right before + // defining a method. + if (compiler->scopeDepth == 0) + { + // The class is at the top level (scope depth is 0, not -1 to account for + // the static variable scope surrounding the class itself), so load it from + // there. + emitShortArg(compiler, CODE_LOAD_MODULE_VAR, classSlot); + } + else + { + loadLocal(compiler, classSlot); + } + + // Define the method. + Code instruction = isStatic ? CODE_METHOD_STATIC : CODE_METHOD_INSTANCE; + emitShortArg(compiler, instruction, methodSymbol); +} + +// Compiles a method definition inside a class body. +// +// Returns `true` if it compiled successfully, or `false` if the method couldn't +// be parsed. +static bool method(Compiler* compiler, ClassCompiler* classCompiler, + int classSlot, bool* hasConstructor) +{ + Signature signature; + classCompiler->signature = &signature; + + // TODO: What about foreign constructors? + bool isForeign = match(compiler, TOKEN_FOREIGN); + classCompiler->inStatic = match(compiler, TOKEN_STATIC); + + SignatureFn signatureFn = rules[compiler->parser->current.type].method; + nextToken(compiler->parser); + + if (signatureFn == NULL) + { + error(compiler, "Expect method definition."); + return false; + } + + // Build the method signature. + signatureFromToken(compiler, &signature); Compiler methodCompiler; initCompiler(&methodCompiler, compiler->parser, compiler, false); // Compile the method signature. signatureFn(&methodCompiler, &signature); - + + if (classCompiler->inStatic && signature.type == SIG_INITIALIZER) + { + error(compiler, "A constructor cannot be static."); + } + // Include the full signature in debug messages in stack traces. char fullSignature[MAX_METHOD_SIGNATURE]; int length; @@ -2941,12 +3048,52 @@ static int method(Compiler* compiler, ClassCompiler* classCompiler, else { consume(compiler, TOKEN_LEFT_BRACE, "Expect '{' to begin method body."); - finishBody(&methodCompiler, isConstructor); + finishBody(&methodCompiler, signature.type == SIG_INITIALIZER); endCompiler(&methodCompiler, fullSignature, length); } + + // Define the method. For a constructor, this defines the instance + // initializer method. + int methodSymbol = signatureSymbol(compiler, &signature); + defineMethod(compiler, classSlot, classCompiler->inStatic, methodSymbol); - return signatureSymbol(compiler, &signature); + if (signature.type == SIG_INITIALIZER) + { + // Also define a matching constructor method on the metaclass. + signature.type = SIG_METHOD; + int constructorSymbol = signatureSymbol(compiler, &signature); + + createConstructor(compiler, &signature, methodSymbol); + defineMethod(compiler, classSlot, true, constructorSymbol); + + // We don't need a default constructor anymore. + *hasConstructor = true; + } + + return true; +} + +// Defines a default "new()" constructor on the current class. +// +// It just invokes "this new()" on the instance. If a base class defines that, +// it will get invoked. Otherwise, it falls to the default one in Object which +// does nothing. +static void createDefaultConstructor(Compiler* compiler, int classSlot) +{ + Signature signature; + signature.name = "new"; + signature.length = 3; + signature.type = SIG_INITIALIZER; + signature.arity = 0; + + int initializerSymbol = signatureSymbol(compiler, &signature); + + signature.type = SIG_METHOD; + int constructorSymbol = signatureSymbol(compiler, &signature); + + createConstructor(compiler, &signature, initializerSymbol); + defineMethod(compiler, classSlot, true, constructorSymbol); } // Compiles a class definition. Assumes the "class" token has already been @@ -2955,7 +3102,6 @@ static void classDefinition(Compiler* compiler) { // Create a variable to store the class in. int slot = declareNamedVariable(compiler); - bool isModule = compiler->scopeDepth == -1; // Make a string constant for the name. int nameConstant = addConstant(compiler, wrenNewString(compiler->parser->vm, @@ -3004,60 +3150,23 @@ static void classDefinition(Compiler* compiler) consume(compiler, TOKEN_LEFT_BRACE, "Expect '{' after class declaration."); matchLine(compiler); + bool hasConstructor = false; + while (!match(compiler, TOKEN_RIGHT_BRACE)) { - Code instruction = CODE_METHOD_INSTANCE; - bool isConstructor = false; - // TODO: What about foreign constructors? - bool isForeign = match(compiler, TOKEN_FOREIGN); - - classCompiler.isStaticMethod = false; - - if (match(compiler, TOKEN_STATIC)) - { - instruction = CODE_METHOD_STATIC; - classCompiler.isStaticMethod = true; - } - else if (peek(compiler) == TOKEN_NEW) - { - // If the method name is "new", it's a constructor. - isConstructor = true; - } - - SignatureFn signature = rules[compiler->parser->current.type].method; - nextToken(compiler->parser); - - if (signature == NULL) - { - error(compiler, "Expect method definition."); - break; - } - - int methodSymbol = method(compiler, &classCompiler, isConstructor, - isForeign, signature); - - // Load the class. We have to do this for each method because we can't - // keep the class on top of the stack. If there are static fields, they - // will be locals above the initial variable slot for the class on the - // stack. To skip past those, we just load the class each time right before - // defining a method. - if (isModule) - { - emitShortArg(compiler, CODE_LOAD_MODULE_VAR, slot); - } - else - { - loadLocal(compiler, slot); - } - - // Define the method. - emitShortArg(compiler, instruction, methodSymbol); - + if (!method(compiler, &classCompiler, slot, &hasConstructor)) break; + // Don't require a newline after the last definition. if (match(compiler, TOKEN_RIGHT_BRACE)) break; consumeLine(compiler, "Expect newline after definition in class."); } + + // If no constructor was defined, create a default new() one. + if (!hasConstructor) + { + createDefaultConstructor(compiler, slot); + } // Update the class with the number of fields. compiler->bytecode.data[numFieldsInstruction] = (uint8_t)fields.count; diff --git a/src/vm/wren_core.c b/src/vm/wren_core.c index c16b514b..3c66a810 100644 --- a/src/vm/wren_core.c +++ b/src/vm/wren_core.c @@ -68,9 +68,9 @@ static const char* coreLibSource = "\n" " isEmpty { iterate(null) ? false : true }\n" "\n" -" map(transformation) { new MapSequence(this, transformation) }\n" +" map(transformation) { MapSequence.new(this, transformation) }\n" "\n" -" where(predicate) { new WhereSequence(this, predicate) }\n" +" where(predicate) { WhereSequence.new(this, predicate) }\n" "\n" " reduce(acc, f) {\n" " for (element in this) {\n" @@ -108,7 +108,7 @@ static const char* coreLibSource = " }\n" "\n" " toList {\n" -" var result = new List\n" +" var result = List.new()\n" " for (element in this) {\n" " result.add(element)\n" " }\n" @@ -117,7 +117,7 @@ static const char* coreLibSource = "}\n" "\n" "class MapSequence is Sequence {\n" -" new(sequence, fn) {\n" +" this 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" -" new(sequence, fn) {\n" +" this new(sequence, fn) {\n" " _sequence = sequence\n" " _fn = fn\n" " }\n" @@ -143,11 +143,11 @@ static const char* coreLibSource = "}\n" "\n" "class String is Sequence {\n" -" bytes { new StringByteSequence(this) }\n" +" bytes { StringByteSequence.new(this) }\n" "}\n" "\n" "class StringByteSequence is Sequence {\n" -" new(string) {\n" +" this new(string) {\n" " _string = string\n" " }\n" "\n" @@ -176,8 +176,8 @@ static const char* coreLibSource = "}\n" "\n" "class Map {\n" -" keys { new MapKeySequence(this) }\n" -" values { new MapValueSequence(this) }\n" +" keys { MapKeySequence.new(this) }\n" +" values { MapValueSequence.new(this) }\n" "\n" " toString {\n" " var first = true\n" @@ -194,7 +194,7 @@ static const char* coreLibSource = "}\n" "\n" "class MapKeySequence is Sequence {\n" -" new(map) {\n" +" this new(map) {\n" " _map = map\n" " }\n" "\n" @@ -203,7 +203,7 @@ static const char* coreLibSource = "}\n" "\n" "class MapValueSequence is Sequence {\n" -" new(map) {\n" +" this new(map) {\n" " _map = map\n" " }\n" "\n" @@ -215,13 +215,9 @@ static const char* coreLibSource = // A simple primitive that just returns "this". Used in a few different places: // -// * The default constructor on Object needs no initialization so just uses -// this. +// * The default new() initializer on Object needs no initialization so just +// uses this. // * String's toString method obviously can use this. -// * Fiber's instantiate method just returns the Fiber class. The new() method -// is responsible for creating the new fiber. -// * Fn's "constructor" is given the actual function as an argument, so the -// instantiate method just returns the Fn class. DEF_PRIMITIVE(return_this) { RETURN_VAL(args[0]); @@ -244,11 +240,6 @@ DEF_PRIMITIVE(bool_toString) } } -DEF_PRIMITIVE(class_instantiate) -{ - RETURN_VAL(wrenNewInstance(vm, AS_CLASS(args[0]))); -} - DEF_PRIMITIVE(class_name) { RETURN_OBJ(AS_CLASS(args[0])->name); @@ -532,7 +523,7 @@ DEF_PRIMITIVE(fn_toString) RETURN_VAL(CONST_STRING(vm, "")); } -DEF_PRIMITIVE(list_instantiate) +DEF_PRIMITIVE(list_new) { RETURN_OBJ(wrenNewList(vm, 0)); } @@ -649,7 +640,7 @@ DEF_PRIMITIVE(list_subscriptSetter) RETURN_VAL(args[2]); } -DEF_PRIMITIVE(map_instantiate) +DEF_PRIMITIVE(map_new) { RETURN_OBJ(wrenNewMap(vm)); } @@ -998,11 +989,6 @@ DEF_PRIMITIVE(object_type) RETURN_OBJ(wrenGetClass(vm, args[0])); } -DEF_PRIMITIVE(object_instantiate) -{ - RETURN_ERROR("Must provide a class to 'new' to construct."); -} - DEF_PRIMITIVE(range_from) { RETURN_NUM(AS_RANGE(args[0])->from); @@ -1303,16 +1289,14 @@ void wrenInitializeCore(WrenVM* vm) PRIMITIVE(vm->objectClass, "!", object_not); PRIMITIVE(vm->objectClass, "==(_)", object_eqeq); PRIMITIVE(vm->objectClass, "!=(_)", object_bangeq); - PRIMITIVE(vm->objectClass, "new", return_this); + PRIMITIVE(vm->objectClass, "this new()", return_this); PRIMITIVE(vm->objectClass, "is(_)", object_is); PRIMITIVE(vm->objectClass, "toString", object_toString); PRIMITIVE(vm->objectClass, "type", object_type); - PRIMITIVE(vm->objectClass, "", object_instantiate); // Now we can define Class, which is a subclass of Object. vm->classClass = defineClass(vm, "Class"); wrenBindSuperclass(vm, vm->classClass, vm->objectClass); - PRIMITIVE(vm->classClass, "", class_instantiate); PRIMITIVE(vm->classClass, "name", class_name); PRIMITIVE(vm->classClass, "supertype", class_supertype); PRIMITIVE(vm->classClass, "toString", class_toString); @@ -1361,7 +1345,6 @@ void wrenInitializeCore(WrenVM* vm) PRIMITIVE(vm->boolClass, "!", bool_not); vm->fiberClass = AS_CLASS(wrenFindVariable(vm, "Fiber")); - PRIMITIVE(vm->fiberClass->obj.classObj, "", return_this); PRIMITIVE(vm->fiberClass->obj.classObj, "new(_)", fiber_new); PRIMITIVE(vm->fiberClass->obj.classObj, "abort(_)", fiber_abort); PRIMITIVE(vm->fiberClass->obj.classObj, "current", fiber_current); @@ -1376,7 +1359,6 @@ void wrenInitializeCore(WrenVM* vm) PRIMITIVE(vm->fiberClass, "try()", fiber_try); vm->fnClass = AS_CLASS(wrenFindVariable(vm, "Fn")); - PRIMITIVE(vm->fnClass->obj.classObj, "", return_this); PRIMITIVE(vm->fnClass->obj.classObj, "new(_)", fn_new); PRIMITIVE(vm->fnClass, "arity", fn_arity); @@ -1463,7 +1445,7 @@ void wrenInitializeCore(WrenVM* vm) PRIMITIVE(vm->stringClass, "toString", return_this); vm->listClass = AS_CLASS(wrenFindVariable(vm, "List")); - PRIMITIVE(vm->listClass->obj.classObj, "", list_instantiate); + PRIMITIVE(vm->listClass->obj.classObj, "new()", list_new); PRIMITIVE(vm->listClass, "[_]", list_subscript); PRIMITIVE(vm->listClass, "[_]=(_)", list_subscriptSetter); PRIMITIVE(vm->listClass, "add(_)", list_add); @@ -1475,7 +1457,7 @@ void wrenInitializeCore(WrenVM* vm) PRIMITIVE(vm->listClass, "removeAt(_)", list_removeAt); vm->mapClass = AS_CLASS(wrenFindVariable(vm, "Map")); - PRIMITIVE(vm->mapClass->obj.classObj, "", map_instantiate); + PRIMITIVE(vm->mapClass->obj.classObj, "new()", map_new); PRIMITIVE(vm->mapClass, "[_]", map_subscript); PRIMITIVE(vm->mapClass, "[_]=(_)", map_subscriptSetter); PRIMITIVE(vm->mapClass, "clear()", map_clear); diff --git a/src/vm/wren_debug.c b/src/vm/wren_debug.c index 9967a90e..a631b5e9 100644 --- a/src/vm/wren_debug.c +++ b/src/vm/wren_debug.c @@ -277,6 +277,8 @@ static int dumpInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine) break; } + case CODE_CONSTRUCT: printf("CODE_CONSTRUCT\n"); break; + case CODE_CLASS: { int numFields = READ_BYTE(); diff --git a/src/vm/wren_opcodes.h b/src/vm/wren_opcodes.h index 5b894159..6a48ce45 100644 --- a/src/vm/wren_opcodes.h +++ b/src/vm/wren_opcodes.h @@ -150,6 +150,13 @@ OPCODE(RETURN) // Pushes the created closure. OPCODE(CLOSURE) +// Creates a new instance of a class. +// +// Assumes the class object is in slot zero, and replaces it with the new +// uninitialized instance of that class. This opcode is only emitted by the +// compiler-generated constructor metaclass methods. +OPCODE(CONSTRUCT) + // Creates a class. Top of stack is the superclass, or `null` if the class // inherits Object. Below that is a string for the name of the class. Byte // [arg] is the number of fields in the class. diff --git a/src/vm/wren_vm.c b/src/vm/wren_vm.c index f8477712..1d67f46d 100644 --- a/src/vm/wren_vm.c +++ b/src/vm/wren_vm.c @@ -1023,6 +1023,11 @@ static WrenInterpretResult runInterpreter(WrenVM* vm, register ObjFiber* fiber) DISPATCH(); } + CASE_CODE(CONSTRUCT): + ASSERT(IS_CLASS(stackStart[0]), "'this' should be a class."); + stackStart[0] = wrenNewInstance(vm, AS_CLASS(stackStart[0])); + DISPATCH(); + CASE_CODE(CLOSURE): { ObjFn* prototype = AS_FN(fn->constants[READ_SHORT()]); diff --git a/test/benchmark/binary_trees.wren b/test/benchmark/binary_trees.wren index 4923f1fe..cab1df23 100644 --- a/test/benchmark/binary_trees.wren +++ b/test/benchmark/binary_trees.wren @@ -1,13 +1,13 @@ // Ported from the Python version. class Tree { - new(item, depth) { + this new(item, depth) { _item = item if (depth > 0) { var item2 = item + item depth = depth - 1 - _left = new Tree(item2 - 1, depth) - _right = new Tree(item2, depth) + _left = Tree.new(item2 - 1, depth) + _right = Tree.new(item2, depth) } } @@ -27,9 +27,9 @@ var stretchDepth = maxDepth + 1 var start = IO.clock IO.print("stretch tree of depth ", stretchDepth, " check: ", - new Tree(0, stretchDepth).check) + Tree.new(0, stretchDepth).check) -var longLivedTree = new Tree(0, maxDepth) +var longLivedTree = Tree.new(0, maxDepth) // iterations = 2 ** maxDepth var iterations = 1 @@ -41,7 +41,7 @@ var depth = minDepth while (depth < stretchDepth) { var check = 0 for (i in 1..iterations) { - check = check + new Tree(i, depth).check + new Tree(-i, depth).check + check = check + Tree.new(i, depth).check + Tree.new(-i, depth).check } IO.print((iterations * 2), " trees of depth ", depth, " check: ", check) diff --git a/test/benchmark/delta_blue.wren b/test/benchmark/delta_blue.wren index ec26ff79..9c578f58 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 { - new(value, name) { + this new(value, name) { _value = value _name = name } @@ -67,13 +67,13 @@ class Strength { } // Compile time computed constants. -REQUIRED = new Strength(0, "required") -STRONG_REFERRED = new Strength(1, "strongPreferred") -PREFERRED = new Strength(2, "preferred") -STRONG_DEFAULT = new Strength(3, "strongDefault") -NORMAL = new Strength(4, "normal") -WEAK_DEFAULT = new Strength(5, "weakDefault") -WEAKEST = new Strength(6, "weakest") +REQUIRED = Strength.new(0, "required") +STRONG_REFERRED = Strength.new(1, "strongPreferred") +PREFERRED = Strength.new(2, "preferred") +STRONG_DEFAULT = Strength.new(3, "strongDefault") +NORMAL = Strength.new(4, "normal") +WEAK_DEFAULT = Strength.new(5, "weakDefault") +WEAKEST = Strength.new(6, "weakest") ORDERED = [ WEAKEST, WEAK_DEFAULT, NORMAL, STRONG_DEFAULT, PREFERRED, STRONG_REFERRED @@ -82,7 +82,7 @@ ORDERED = [ var ThePlanner class Constraint { - new(strength) { + this new(strength) { _strength = strength } @@ -131,7 +131,7 @@ class Constraint { // Abstract superclass for constraints having a single possible output variable. class UnaryConstraint is Constraint { - new(myOutput, strength) { + this 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 { - new(variable, strength) { + this 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 { - EditConstraint(variable, strength) { + this 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 { - new(v1, v2, strength) { + this 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 { - new(src, scale, offset, dest, strength) { + this 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 { - new(v1, v2, strength) { + this 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 { - new(name, value) { + this 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 { - new { + this new() { _list = [] } @@ -448,7 +448,7 @@ class Plan { } class Planner { - new { + this new() { _currentMark = 0 } @@ -521,7 +521,7 @@ class Planner { // Assume: [sources] are all satisfied. makePlan(sources) { var mark = newMark - var plan = new Plan + var plan = Plan.new() var todo = sources while (todo.count > 0) { var constraint = todo.removeAt(-1) @@ -622,23 +622,23 @@ var total = 0 // constraint so it cannot be accomodated. The cost in this case is, // of course, very low. Typical situations lie somewhere between these // two extremes. -var chainTest = new Fn {|n| - ThePlanner = new Planner +var chainTest = Fn.new {|n| + ThePlanner = Planner.new() var prev = null var first = null var last = null // Build chain of n equality constraints. for (i in 0..n) { - var v = new Variable("v", 0) - if (prev != null) new EqualityConstraint(prev, v, REQUIRED) + var v = Variable.new("v", 0) + if (prev != null) EqualityConstraint.new(prev, v, REQUIRED) if (i == 0) first = v if (i == n) last = v prev = v } - new StayConstraint(last, STRONG_DEFAULT) - var edit = new EditConstraint(first, PREFERRED) + StayConstraint.new(last, STRONG_DEFAULT) + var edit = EditConstraint.new(first, PREFERRED) var plan = ThePlanner.extractPlanFromConstraints([edit]) for (i in 0...100) { first.value = i @@ -647,8 +647,8 @@ var chainTest = new Fn {|n| } } -var change = new Fn {|v, newValue| - var edit = new EditConstraint(v, PREFERRED) +var change = Fn.new {|v, newValue| + var edit = EditConstraint.new(v, PREFERRED) var plan = ThePlanner.extractPlanFromConstraints([edit]) for (i in 0...10) { v.value = newValue @@ -662,20 +662,20 @@ var change = new Fn {|v, newValue| // other by a simple linear transformation (scale and offset). The // time is measured to change a variable on either side of the // mapping and to change the scale and offset factors. -var projectionTest = new Fn {|n| - ThePlanner = new Planner - var scale = new Variable("scale", 10) - var offset = new Variable("offset", 1000) +var projectionTest = Fn.new {|n| + ThePlanner = Planner.new() + var scale = Variable.new("scale", 10) + var offset = Variable.new("offset", 1000) var src = null var dst = null var dests = [] for (i in 0...n) { - src = new Variable("src", i) - dst = new Variable("dst", i) + src = Variable.new("src", i) + dst = Variable.new("dst", i) dests.add(dst) - new StayConstraint(src, NORMAL) - new ScaleConstraint(src, scale, offset, dst, REQUIRED) + StayConstraint.new(src, NORMAL) + ScaleConstraint.new(src, scale, offset, dst, REQUIRED) } change.call(src, 17) diff --git a/test/benchmark/fibers.wren b/test/benchmark/fibers.wren index 0094e601..83ff0f79 100644 --- a/test/benchmark/fibers.wren +++ b/test/benchmark/fibers.wren @@ -5,7 +5,7 @@ var sum = 0 var start = IO.clock for (i in 0...100000) { - fibers.add(new Fiber { + fibers.add(Fiber.new { sum = sum + i if (i < 99999) fibers[i + 1].call() }) diff --git a/test/benchmark/method_call.wren b/test/benchmark/method_call.wren index 984e844f..799c92b2 100644 --- a/test/benchmark/method_call.wren +++ b/test/benchmark/method_call.wren @@ -1,5 +1,5 @@ class Toggle { - new(startState) { + this new(startState) { _state = startState } @@ -11,7 +11,7 @@ class Toggle { } class NthToggle is Toggle { - new(startState, maxCounter) { + this new(startState, maxCounter) { super(startState) _countMax = maxCounter _count = 0 @@ -31,7 +31,7 @@ class NthToggle is Toggle { var start = IO.clock var n = 100000 var val = true -var toggle = new Toggle(val) +var toggle = Toggle.new(val) for (i in 0...n) { val = toggle.activate.value @@ -49,7 +49,7 @@ for (i in 0...n) { IO.print(toggle.value) val = true -var ntoggle = new NthToggle(val, 3) +var ntoggle = NthToggle.new(val, 3) for (i in 0...n) { val = ntoggle.activate.value diff --git a/test/core/fiber/abort.wren b/test/core/fiber/abort.wren index df6aefa6..2823ede3 100644 --- a/test/core/fiber/abort.wren +++ b/test/core/fiber/abort.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { Fiber.abort("Error message.") } diff --git a/test/core/fiber/call.wren b/test/core/fiber/call.wren index 0e6bb252..7ad0b832 100644 --- a/test/core/fiber/call.wren +++ b/test/core/fiber/call.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber") } diff --git a/test/core/fiber/call_direct_reenter.wren b/test/core/fiber/call_direct_reenter.wren index a8d3cbe4..6ff95e0e 100644 --- a/test/core/fiber/call_direct_reenter.wren +++ b/test/core/fiber/call_direct_reenter.wren @@ -1,6 +1,6 @@ var fiber -fiber = new Fiber { +fiber = Fiber.new { fiber.call() // expect runtime error: Fiber has already been called. } diff --git a/test/core/fiber/call_indirect_reenter.wren b/test/core/fiber/call_indirect_reenter.wren index b523b1d0..4726b3da 100644 --- a/test/core/fiber/call_indirect_reenter.wren +++ b/test/core/fiber/call_indirect_reenter.wren @@ -1,11 +1,11 @@ var a var b -a = new Fiber { +a = Fiber.new { b.call() // expect runtime error: Fiber has already been called. } -b = new Fiber { +b = Fiber.new { a.call() } diff --git a/test/core/fiber/call_return_implicit_null.wren b/test/core/fiber/call_return_implicit_null.wren index 7cb9116e..cde91b15 100644 --- a/test/core/fiber/call_return_implicit_null.wren +++ b/test/core/fiber/call_return_implicit_null.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber") } diff --git a/test/core/fiber/call_return_value.wren b/test/core/fiber/call_return_value.wren index d28335e4..6203f845 100644 --- a/test/core/fiber/call_return_value.wren +++ b/test/core/fiber/call_return_value.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber") return "result" } diff --git a/test/core/fiber/call_when_done.wren b/test/core/fiber/call_when_done.wren index 5546064a..894a803f 100644 --- a/test/core/fiber/call_when_done.wren +++ b/test/core/fiber/call_when_done.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("call") } diff --git a/test/core/fiber/call_with_value.wren b/test/core/fiber/call_with_value.wren index 16d78fe0..10c905f8 100644 --- a/test/core/fiber/call_with_value.wren +++ b/test/core/fiber/call_with_value.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber") } diff --git a/test/core/fiber/call_with_value_direct_reenter.wren b/test/core/fiber/call_with_value_direct_reenter.wren index 05804b08..0b1d1384 100644 --- a/test/core/fiber/call_with_value_direct_reenter.wren +++ b/test/core/fiber/call_with_value_direct_reenter.wren @@ -1,6 +1,6 @@ var fiber -fiber = new Fiber { +fiber = Fiber.new { fiber.call(2) // expect runtime error: Fiber has already been called. } diff --git a/test/core/fiber/call_with_value_indirect_reenter.wren b/test/core/fiber/call_with_value_indirect_reenter.wren index d31c5a61..6547fce8 100644 --- a/test/core/fiber/call_with_value_indirect_reenter.wren +++ b/test/core/fiber/call_with_value_indirect_reenter.wren @@ -1,11 +1,11 @@ var a var b -a = new Fiber { +a = Fiber.new { b.call(3) // expect runtime error: Fiber has already been called. } -b = new Fiber { +b = Fiber.new { a.call(2) } diff --git a/test/core/fiber/call_with_value_when_done.wren b/test/core/fiber/call_with_value_when_done.wren index c3fc2f7d..491a7f6e 100644 --- a/test/core/fiber/call_with_value_when_done.wren +++ b/test/core/fiber/call_with_value_when_done.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("call") } diff --git a/test/core/fiber/error.wren b/test/core/fiber/error.wren index 09b2cd9d..f6087d98 100644 --- a/test/core/fiber/error.wren +++ b/test/core/fiber/error.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { "s".unknown } diff --git a/test/core/fiber/is_done.wren b/test/core/fiber/is_done.wren index a73a748a..f4d500b8 100644 --- a/test/core/fiber/is_done.wren +++ b/test/core/fiber/is_done.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("1") Fiber.yield() IO.print("2") diff --git a/test/core/fiber/is_done_after_error.wren b/test/core/fiber/is_done_after_error.wren index c3e685c0..479b8d3c 100644 --- a/test/core/fiber/is_done_after_error.wren +++ b/test/core/fiber/is_done_after_error.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { "s".unknown } diff --git a/test/core/fiber/new_wrong_arg_type.wren b/test/core/fiber/new_wrong_arg_type.wren index 8d2ed726..6c57744d 100644 --- a/test/core/fiber/new_wrong_arg_type.wren +++ b/test/core/fiber/new_wrong_arg_type.wren @@ -1 +1 @@ -var fiber = new Fiber("not fn") // expect runtime error: Argument must be a function. +var fiber = Fiber.new("not fn") // expect runtime error: Argument must be a function. diff --git a/test/core/fiber/resume_caller.wren b/test/core/fiber/resume_caller.wren index fa6282c8..64a726db 100644 --- a/test/core/fiber/resume_caller.wren +++ b/test/core/fiber/resume_caller.wren @@ -1,8 +1,8 @@ -var b = new Fiber { +var b = Fiber.new { IO.print("fiber b") } -var a = new Fiber { +var a = Fiber.new { IO.print("begin fiber a") b.call() IO.print("end fiber a") diff --git a/test/core/fiber/run.wren b/test/core/fiber/run.wren index 700875e2..a1add056 100644 --- a/test/core/fiber/run.wren +++ b/test/core/fiber/run.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber") } diff --git a/test/core/fiber/run_direct_reenter.wren b/test/core/fiber/run_direct_reenter.wren index c91a4505..84fbe024 100644 --- a/test/core/fiber/run_direct_reenter.wren +++ b/test/core/fiber/run_direct_reenter.wren @@ -1,6 +1,6 @@ var fiber -fiber = new Fiber { +fiber = Fiber.new { IO.print(1) // expect: 1 fiber.run() IO.print(2) // expect: 2 diff --git a/test/core/fiber/run_indirect_reenter.wren b/test/core/fiber/run_indirect_reenter.wren index 1cae328f..01eaf6db 100644 --- a/test/core/fiber/run_indirect_reenter.wren +++ b/test/core/fiber/run_indirect_reenter.wren @@ -1,13 +1,13 @@ var a var b -a = new Fiber { +a = Fiber.new { IO.print(2) b.run() IO.print("nope") } -b = new Fiber { +b = Fiber.new { IO.print(1) a.run() IO.print(3) diff --git a/test/core/fiber/run_when_done.wren b/test/core/fiber/run_when_done.wren index 13cc5675..1e9c1db0 100644 --- a/test/core/fiber/run_when_done.wren +++ b/test/core/fiber/run_when_done.wren @@ -1,10 +1,10 @@ -var a = new Fiber { +var a = Fiber.new { IO.print("run") } // Run a through an intermediate fiber since it will get discarded and we need // to return to the main one after a completes. -var b = new Fiber { +var b = Fiber.new { a.run() IO.print("nope") } diff --git a/test/core/fiber/run_with_value.wren b/test/core/fiber/run_with_value.wren index e3cef529..638b9fd1 100644 --- a/test/core/fiber/run_with_value.wren +++ b/test/core/fiber/run_with_value.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber") } diff --git a/test/core/fiber/run_with_value_direct_reenter.wren b/test/core/fiber/run_with_value_direct_reenter.wren index 641785bb..03ee62e1 100644 --- a/test/core/fiber/run_with_value_direct_reenter.wren +++ b/test/core/fiber/run_with_value_direct_reenter.wren @@ -1,6 +1,6 @@ var fiber -fiber = new Fiber { +fiber = Fiber.new { IO.print(1) // expect: 1 fiber.run("ignored") IO.print(2) // expect: 2 diff --git a/test/core/fiber/run_with_value_indirect_reenter.wren b/test/core/fiber/run_with_value_indirect_reenter.wren index cd3e3c4f..d5aa24fb 100644 --- a/test/core/fiber/run_with_value_indirect_reenter.wren +++ b/test/core/fiber/run_with_value_indirect_reenter.wren @@ -1,13 +1,13 @@ var a var b -a = new Fiber { +a = Fiber.new { IO.print(2) b.run("ignored") IO.print("nope") } -b = new Fiber { +b = Fiber.new { IO.print(1) a.run("ignored") IO.print(3) diff --git a/test/core/fiber/try.wren b/test/core/fiber/try.wren index b491064b..dbb5582e 100644 --- a/test/core/fiber/try.wren +++ b/test/core/fiber/try.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("before") true.unknownMethod IO.print("after") diff --git a/test/core/fiber/try_direct_reenter.wren b/test/core/fiber/try_direct_reenter.wren index cc7cfdc5..80df90ac 100644 --- a/test/core/fiber/try_direct_reenter.wren +++ b/test/core/fiber/try_direct_reenter.wren @@ -1,6 +1,6 @@ var fiber -fiber = new Fiber { +fiber = Fiber.new { fiber.try() // expect runtime error: Fiber has already been called. } diff --git a/test/core/fiber/try_indirect_reenter.wren b/test/core/fiber/try_indirect_reenter.wren index 8fc7bc6c..78ec14ac 100644 --- a/test/core/fiber/try_indirect_reenter.wren +++ b/test/core/fiber/try_indirect_reenter.wren @@ -1,11 +1,11 @@ var a var b -a = new Fiber { +a = Fiber.new { b.try() // expect runtime error: Fiber has already been called. } -b = new Fiber { +b = Fiber.new { a.call() } diff --git a/test/core/fiber/try_when_done.wren b/test/core/fiber/try_when_done.wren index 9e4a552a..180d9d95 100644 --- a/test/core/fiber/try_when_done.wren +++ b/test/core/fiber/try_when_done.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("try") } diff --git a/test/core/fiber/try_without_error.wren b/test/core/fiber/try_without_error.wren index 177f708e..c9314303 100644 --- a/test/core/fiber/try_without_error.wren +++ b/test/core/fiber/try_without_error.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber") } diff --git a/test/core/fiber/type.wren b/test/core/fiber/type.wren index 1c69deff..49da2437 100644 --- a/test/core/fiber/type.wren +++ b/test/core/fiber/type.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber {} +var fiber = Fiber.new {} IO.print(fiber is Fiber) // expect: true IO.print(fiber is Object) // expect: true IO.print(fiber is Bool) // expect: false diff --git a/test/core/fiber/yield.wren b/test/core/fiber/yield.wren index 81c2842d..412bb6f5 100644 --- a/test/core/fiber/yield.wren +++ b/test/core/fiber/yield.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber 1") Fiber.yield() IO.print("fiber 2") diff --git a/test/core/fiber/yield_return_call_value.wren b/test/core/fiber/yield_return_call_value.wren index 261dce11..c728a654 100644 --- a/test/core/fiber/yield_return_call_value.wren +++ b/test/core/fiber/yield_return_call_value.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber 1") var result = Fiber.yield() IO.print(result) diff --git a/test/core/fiber/yield_return_run_value.wren b/test/core/fiber/yield_return_run_value.wren index 63482c6b..b43317e3 100644 --- a/test/core/fiber/yield_return_run_value.wren +++ b/test/core/fiber/yield_return_run_value.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber") var result = Fiber.yield() IO.print(result) diff --git a/test/core/fiber/yield_with_no_caller.wren b/test/core/fiber/yield_with_no_caller.wren index d0b66886..7f6b606d 100644 --- a/test/core/fiber/yield_with_no_caller.wren +++ b/test/core/fiber/yield_with_no_caller.wren @@ -1,11 +1,11 @@ -var a = new Fiber { +var a = Fiber.new { IO.print("before") // expect: before Fiber.yield() } // Run a chain of fibers. Since none of them are called, they all get discarded // and there is no remaining caller. -var b = new Fiber { a.run() } -var c = new Fiber { b.run() } +var b = Fiber.new { a.run() } +var c = Fiber.new { b.run() } c.run() IO.print("not reached") \ No newline at end of file diff --git a/test/core/fiber/yield_with_value.wren b/test/core/fiber/yield_with_value.wren index a97b944d..4d909de7 100644 --- a/test/core/fiber/yield_with_value.wren +++ b/test/core/fiber/yield_with_value.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber { +var fiber = Fiber.new { IO.print("fiber 1") Fiber.yield("yield 1") IO.print("fiber 2") diff --git a/test/core/fiber/yield_with_value_with_no_caller.wren b/test/core/fiber/yield_with_value_with_no_caller.wren index 8035cd94..960c70aa 100644 --- a/test/core/fiber/yield_with_value_with_no_caller.wren +++ b/test/core/fiber/yield_with_value_with_no_caller.wren @@ -1,11 +1,11 @@ -var a = new Fiber { +var a = Fiber.new { IO.print("before") // expect: before Fiber.yield(1) } // Run a chain of fibers. Since none of them are called, they all get discarded // and there is no remaining caller. -var b = new Fiber { a.run() } -var c = new Fiber { b.run() } +var b = Fiber.new { a.run() } +var c = Fiber.new { b.run() } c.run() IO.print("not reached") diff --git a/test/core/function/arity.wren b/test/core/function/arity.wren index 9e6047e4..ab40eff9 100644 --- a/test/core/function/arity.wren +++ b/test/core/function/arity.wren @@ -1,5 +1,5 @@ -IO.print(new Fn {}.arity) // expect: 0 -IO.print(new Fn {|a| a}.arity) // expect: 1 -IO.print(new Fn {|a, b| a}.arity) // expect: 2 -IO.print(new Fn {|a, b, c| a}.arity) // expect: 3 -IO.print(new Fn {|a, b, c, d| a}.arity) // expect: 4 +IO.print(Fn.new {}.arity) // expect: 0 +IO.print(Fn.new {|a| a}.arity) // expect: 1 +IO.print(Fn.new {|a, b| a}.arity) // expect: 2 +IO.print(Fn.new {|a, b, c| a}.arity) // expect: 3 +IO.print(Fn.new {|a, b, c, d| a}.arity) // expect: 4 diff --git a/test/core/function/call_extra_arguments.wren b/test/core/function/call_extra_arguments.wren index 45f37886..f183576f 100644 --- a/test/core/function/call_extra_arguments.wren +++ b/test/core/function/call_extra_arguments.wren @@ -1,7 +1,7 @@ -var f0 = new Fn { IO.print("zero") } -var f1 = new Fn {|a| IO.print("one ", a) } -var f2 = new Fn {|a, b| IO.print("two ", a, " ", b) } -var f3 = new Fn {|a, b, c| IO.print("three ", a, " ", b, " ", c) } +var f0 = Fn.new { IO.print("zero") } +var f1 = Fn.new {|a| IO.print("one ", a) } +var f2 = Fn.new {|a, b| IO.print("two ", a, " ", b) } +var f3 = Fn.new {|a, b, c| IO.print("three ", a, " ", b, " ", c) } f0.call("a") // expect: zero f0.call("a", "b") // expect: zero diff --git a/test/core/function/call_missing_arguments.wren b/test/core/function/call_missing_arguments.wren index 7e9c159c..162623c9 100644 --- a/test/core/function/call_missing_arguments.wren +++ b/test/core/function/call_missing_arguments.wren @@ -1,2 +1,2 @@ -var f2 = new Fn {|a, b| IO.print(a, b) } +var f2 = Fn.new {|a, b| IO.print(a, b) } f2.call("a") // expect runtime error: Function expects more arguments. diff --git a/test/core/function/equality.wren b/test/core/function/equality.wren index ee1730d7..29239518 100644 --- a/test/core/function/equality.wren +++ b/test/core/function/equality.wren @@ -1,16 +1,16 @@ // Not structurally equal. -IO.print(new Fn { 123 } == new Fn { 123 }) // expect: false -IO.print(new Fn { 123 } != new Fn { 123 }) // expect: true +IO.print(Fn.new { 123 } == Fn.new { 123 }) // expect: false +IO.print(Fn.new { 123 } != Fn.new { 123 }) // expect: true // Not equal to other types. -IO.print(new Fn { 123 } == 1) // expect: false -IO.print(new Fn { 123 } == false) // expect: false -IO.print(new Fn { 123 } == "fn 123") // expect: false -IO.print(new Fn { 123 } != 1) // expect: true -IO.print(new Fn { 123 } != false) // expect: true -IO.print(new Fn { 123 } != "fn 123") // expect: true +IO.print(Fn.new { 123 } == 1) // expect: false +IO.print(Fn.new { 123 } == false) // expect: false +IO.print(Fn.new { 123 } == "fn 123") // expect: false +IO.print(Fn.new { 123 } != 1) // expect: true +IO.print(Fn.new { 123 } != false) // expect: true +IO.print(Fn.new { 123 } != "fn 123") // expect: true // Equal by identity. -var f = new Fn { 123 } +var f = Fn.new { 123 } IO.print(f == f) // expect: true IO.print(f != f) // expect: false diff --git a/test/core/function/new_wrong_arg_type.wren b/test/core/function/new_wrong_arg_type.wren index e0f2a2ea..0c27fb15 100644 --- a/test/core/function/new_wrong_arg_type.wren +++ b/test/core/function/new_wrong_arg_type.wren @@ -1 +1 @@ -new Fn(3) // expect runtime error: Argument must be a function. +Fn.new(3) // expect runtime error: Argument must be a function. diff --git a/test/core/function/to_string.wren b/test/core/function/to_string.wren index 70924d7d..8a72cbe3 100644 --- a/test/core/function/to_string.wren +++ b/test/core/function/to_string.wren @@ -1 +1 @@ -IO.print(new Fn {}) // expect: +IO.print(Fn.new {}) // expect: diff --git a/test/core/function/type.wren b/test/core/function/type.wren index 6090a9d0..429d9e37 100644 --- a/test/core/function/type.wren +++ b/test/core/function/type.wren @@ -1,4 +1,4 @@ -IO.print(new Fn { 0 } is Fn) // expect: true -IO.print(new Fn { 0 } is Object) // expect: true -IO.print(new Fn { 0 } is String) // expect: false -IO.print(new Fn { 0 }.type == Fn) // expect: true +IO.print(Fn.new { 0 } is Fn) // expect: true +IO.print(Fn.new { 0 } is Object) // expect: true +IO.print(Fn.new { 0 } is String) // expect: false +IO.print(Fn.new { 0 }.type == Fn) // expect: true diff --git a/test/core/list/join.wren b/test/core/list/join.wren index 12a39307..02bbe9d4 100644 --- a/test/core/list/join.wren +++ b/test/core/list/join.wren @@ -18,6 +18,6 @@ class Foo { toString { "Foo.toString" } } -IO.print([1, new Foo, 2].join(", ")) // expect: 1, Foo.toString, 2 +IO.print([1, Foo.new(), 2].join(", ")) // expect: 1, Foo.toString, 2 // TODO: Handle lists that contain themselves. diff --git a/test/core/list/new.wren b/test/core/list/new.wren index 0db068c7..2e3af0e6 100644 --- a/test/core/list/new.wren +++ b/test/core/list/new.wren @@ -1,4 +1,4 @@ -var list = new List +var list = List.new() IO.print(list.count) // expect: 0 IO.print(list) // expect: [] diff --git a/test/core/list/reduce.wren b/test/core/list/reduce.wren index 6dc799d7..87fb87ee 100644 --- a/test/core/list/reduce.wren +++ b/test/core/list/reduce.wren @@ -1,7 +1,7 @@ var a = [1, 4, 2, 1, 5] var b = ["W", "o", "r", "l", "d"] -var max = new Fn {|a, b| a > b ? a : b } -var sum = new Fn {|a, b| a + b } +var max = Fn.new {|a, b| a > b ? a : b } +var sum = Fn.new {|a, b| a + b } IO.print(a.reduce(max)) // expect: 5 IO.print(a.reduce(10, max)) // expect: 10 diff --git a/test/core/list/to_string.wren b/test/core/list/to_string.wren index f20d720b..9de95977 100644 --- a/test/core/list/to_string.wren +++ b/test/core/list/to_string.wren @@ -12,6 +12,6 @@ class Foo { toString { "Foo.toString" } } -IO.print([1, new Foo, 2]) // expect: [1, Foo.toString, 2] +IO.print([1, Foo.new(), 2]) // expect: [1, Foo.toString, 2] // TODO: Handle lists that contain themselves. diff --git a/test/core/map/key_types.wren b/test/core/map/key_types.wren index 78895b9b..57ec3519 100644 --- a/test/core/map/key_types.wren +++ b/test/core/map/key_types.wren @@ -1,4 +1,4 @@ -var fiber = new Fiber {} +var fiber = Fiber.new {} var map = { null: "null value", diff --git a/test/core/map/new.wren b/test/core/map/new.wren index 88f36298..557ee40c 100644 --- a/test/core/map/new.wren +++ b/test/core/map/new.wren @@ -1,4 +1,4 @@ -var map = new Map +var map = Map.new() IO.print(map.count) // expect: 0 IO.print(map) // expect: {} diff --git a/test/core/map/to_string.wren b/test/core/map/to_string.wren index 46b6b5b9..8b51c6a7 100644 --- a/test/core/map/to_string.wren +++ b/test/core/map/to_string.wren @@ -12,7 +12,7 @@ class Foo { toString { "Foo.toString" } } -IO.print({1: new Foo}) // expect: {1: Foo.toString} +IO.print({1: Foo.new()}) // expect: {1: Foo.toString} // Since iteration order is unspecified, we don't know what order the results // will be. diff --git a/test/core/object/not.wren b/test/core/object/not.wren index d2a04a59..14da7283 100644 --- a/test/core/object/not.wren +++ b/test/core/object/not.wren @@ -1,2 +1,2 @@ class Foo {} -IO.print(!(new Foo)) // expect: false +IO.print(!Foo.new()) // expect: false diff --git a/test/core/object/same.wren b/test/core/object/same.wren index ec604d86..95274db4 100644 --- a/test/core/object/same.wren +++ b/test/core/object/same.wren @@ -26,15 +26,15 @@ IO.print(Object.same(Bool, Bool)) // expect: true // Other types compare by identity. class Foo {} -var foo = new Foo +var foo = Foo.new() IO.print(Object.same(foo, foo)) // expect: true -IO.print(Object.same(foo, new Foo)) // expect: false +IO.print(Object.same(foo, Foo.new())) // expect: false // Ignores == operators. class Bar { ==(other) { true } } -var bar = new Bar +var bar = Bar.new() IO.print(Object.same(bar, bar)) // expect: true -IO.print(Object.same(bar, new Bar)) // expect: false +IO.print(Object.same(bar, Bar.new())) // expect: false diff --git a/test/core/object/to_string.wren b/test/core/object/to_string.wren index 41aa9824..b64a8f82 100644 --- a/test/core/object/to_string.wren +++ b/test/core/object/to_string.wren @@ -1,2 +1,2 @@ class Foo {} -IO.print((new Foo).toString == "instance of Foo") // expect: true +IO.print(Foo.new().toString == "instance of Foo") // expect: true diff --git a/test/core/sequence/count.wren b/test/core/sequence/count.wren index e939bd2a..4d753cc1 100644 --- a/test/core/sequence/count.wren +++ b/test/core/sequence/count.wren @@ -8,4 +8,4 @@ class TestSequence is Sequence { iteratorValue(iterator) { iterator } } -IO.print((new TestSequence).count) // expect: 10 +IO.print(TestSequence.new().count) // expect: 10 diff --git a/test/core/sequence/is_empty.wren b/test/core/sequence/is_empty.wren index 30d2492d..9bf15213 100644 --- a/test/core/sequence/is_empty.wren +++ b/test/core/sequence/is_empty.wren @@ -7,4 +7,4 @@ class InfiniteSequence is Sequence { } // Should not try to iterate the whole sequence. -IO.print((new InfiniteSequence).isEmpty) // expect: false +IO.print(InfiniteSequence.new().isEmpty) // expect: false diff --git a/test/core/sequence/map.wren b/test/core/sequence/map.wren index 45beba20..70b055fd 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 { - new { + this new() { _current = 0 _next = 1 } @@ -16,7 +16,7 @@ class FibIterator { class Fib is Sequence { iterate(iterator) { - if (iterator == null) return new FibIterator + if (iterator == null) return FibIterator.new() iterator.iterate return iterator } @@ -24,7 +24,7 @@ class Fib is Sequence { iteratorValue(iterator) { iterator.value } } -var squareFib = (new Fib).map {|fib| fib * fib } +var squareFib = Fib.new().map {|fib| fib * fib } var iterator = null IO.print(squareFib is Sequence) // expect: true diff --git a/test/core/sequence/to_list.wren b/test/core/sequence/to_list.wren index 42b466d0..7594d8dd 100644 --- a/test/core/sequence/to_list.wren +++ b/test/core/sequence/to_list.wren @@ -8,4 +8,4 @@ class TestSequence is Sequence { iteratorValue(iterator) { iterator } } -IO.print((new TestSequence).toList) // expect: [1, 2, 3] +IO.print(TestSequence.new().toList) // expect: [1, 2, 3] diff --git a/test/core/sequence/where.wren b/test/core/sequence/where.wren index e641ab22..3721433f 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 { - new { + this new() { _current = 0 _next = 1 } @@ -16,7 +16,7 @@ class FibIterator { class Fib is Sequence { iterate(iterator) { - if (iterator == null) return new FibIterator + if (iterator == null) return FibIterator.new() iterator.iterate return iterator } @@ -24,7 +24,7 @@ class Fib is Sequence { iteratorValue(iterator) { iterator.value } } -var largeFibs = (new Fib).where {|fib| fib > 100 } +var largeFibs = Fib.new().where {|fib| fib > 100 } var iterator = null IO.print(largeFibs is Sequence) // expect: true diff --git a/test/io/print.wren b/test/io/print.wren index 7a15fc8a..d402ac12 100644 --- a/test/io/print.wren +++ b/test/io/print.wren @@ -3,7 +3,7 @@ class Foo { } // Calls toString on argument. -IO.print(new Foo) // expect: Foo.toString +IO.print(Foo.new()) // expect: Foo.toString // With one argument, returns the argument. IO.print(IO.print(1) == 1) // expect: 1 diff --git a/test/io/print_bad_to_string.wren b/test/io/print_bad_to_string.wren index e8bd5ae9..9dbd99af 100644 --- a/test/io/print_bad_to_string.wren +++ b/test/io/print_bad_to_string.wren @@ -2,4 +2,4 @@ class BadToString { toString { 3 } } -IO.print(new BadToString) // expect: [invalid toString] +IO.print(BadToString.new()) // expect: [invalid toString] diff --git a/test/io/write_bad_to_string.wren b/test/io/write_bad_to_string.wren index da946062..c8015573 100644 --- a/test/io/write_bad_to_string.wren +++ b/test/io/write_bad_to_string.wren @@ -2,5 +2,5 @@ class BadToString { toString { 3 } } -IO.write(new BadToString) // expect: [invalid toString] +IO.write(BadToString.new()) // expect: [invalid toString] IO.print \ No newline at end of file diff --git a/test/language/assignment/local.wren b/test/language/assignment/local.wren index fc6eecbe..3805a7bd 100644 --- a/test/language/assignment/local.wren +++ b/test/language/assignment/local.wren @@ -1,4 +1,4 @@ -new Fn { +Fn.new { var a = "before" IO.print(a) // expect: before diff --git a/test/language/break/closure_in_for.wren b/test/language/break/closure_in_for.wren index c1c8d7b3..2c204f50 100644 --- a/test/language/break/closure_in_for.wren +++ b/test/language/break/closure_in_for.wren @@ -1,7 +1,7 @@ var f for (i in [1, 2, 3]) { var j = 4 - f = new Fn { IO.print(i + j) } + f = Fn.new { IO.print(i + j) } break } diff --git a/test/language/break/closure_in_while.wren b/test/language/break/closure_in_while.wren index 7d9f8b01..084b6c46 100644 --- a/test/language/break/closure_in_while.wren +++ b/test/language/break/closure_in_while.wren @@ -1,7 +1,7 @@ var f while (true) { var i = "i" - f = new Fn { IO.print(i) } + f = Fn.new { IO.print(i) } break } diff --git a/test/language/break/in_function_in_loop.wren b/test/language/break/in_function_in_loop.wren index 035e4c90..8f69fc11 100644 --- a/test/language/break/in_function_in_loop.wren +++ b/test/language/break/in_function_in_loop.wren @@ -1,6 +1,6 @@ var done = false while (!done) { - new Fn { + Fn.new { break // expect error } done = true diff --git a/test/language/class/lowercase_name_inside_body.wren b/test/language/class/lowercase_name_inside_body.wren index 9ec3aa5c..015e9eae 100644 --- a/test/language/class/lowercase_name_inside_body.wren +++ b/test/language/class/lowercase_name_inside_body.wren @@ -12,4 +12,4 @@ class foo { } foo.callFoo // expect: static foo method -(new foo).callFoo // expect: instance foo method +foo.new().callFoo // expect: instance foo method diff --git a/test/language/class/name_inside_body.wren b/test/language/class/name_inside_body.wren index c98ad565..871a004d 100644 --- a/test/language/class/name_inside_body.wren +++ b/test/language/class/name_inside_body.wren @@ -11,4 +11,4 @@ class Foo { } Foo.sayName // expect: Foo! -(new Foo).sayName // expect: Foo! +Foo.new().sayName // expect: Foo! diff --git a/test/language/class/new.wren b/test/language/class/new.wren index c99e5e07..0e0533a9 100644 --- a/test/language/class/new.wren +++ b/test/language/class/new.wren @@ -1,6 +1,6 @@ class Foo {} -var foo = new 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/closure/assign_to_closure.wren b/test/language/closure/assign_to_closure.wren index 58732540..37a76fce 100644 --- a/test/language/closure/assign_to_closure.wren +++ b/test/language/closure/assign_to_closure.wren @@ -3,13 +3,13 @@ var g = null { var local = "local" - f = new Fn { + f = Fn.new { IO.print(local) local = "after f" IO.print(local) } - g = new Fn { + g = Fn.new { IO.print(local) local = "after g" IO.print(local) diff --git a/test/language/closure/close_over_function_parameter.wren b/test/language/closure/close_over_function_parameter.wren index 86fea8b3..9a786ff3 100644 --- a/test/language/closure/close_over_function_parameter.wren +++ b/test/language/closure/close_over_function_parameter.wren @@ -1,7 +1,7 @@ var f = null -new Fn {|param| - f = new Fn { +Fn.new {|param| + f = Fn.new { IO.print(param) } }.call("param") diff --git a/test/language/closure/close_over_later_variable.wren b/test/language/closure/close_over_later_variable.wren index ef466380..719b9d75 100644 --- a/test/language/closure/close_over_later_variable.wren +++ b/test/language/closure/close_over_later_variable.wren @@ -3,10 +3,10 @@ // would crash because it walked to the end of the upvalue list (correct), but // then didn't handle not finding the variable. -new Fn { +Fn.new { var a = "a" var b = "b" - new Fn { + Fn.new { IO.print(b) // expect: b IO.print(a) // expect: a }.call() diff --git a/test/language/closure/close_over_method_parameter.wren b/test/language/closure/close_over_method_parameter.wren index 6cba2a40..93831906 100644 --- a/test/language/closure/close_over_method_parameter.wren +++ b/test/language/closure/close_over_method_parameter.wren @@ -2,11 +2,11 @@ var F = null class Foo { method(param) { - F = new Fn { + F = Fn.new { IO.print(param) } } } -(new Foo).method("param") +Foo.new().method("param") F.call() // expect: param diff --git a/test/language/closure/closed_closure_in_function.wren b/test/language/closure/closed_closure_in_function.wren index 0248df5f..d3e8d6c5 100644 --- a/test/language/closure/closed_closure_in_function.wren +++ b/test/language/closure/closed_closure_in_function.wren @@ -2,7 +2,7 @@ var f = null { var local = "local" - f = new Fn { + f = Fn.new { IO.print(local) } } diff --git a/test/language/closure/closed_closure_in_method.wren b/test/language/closure/closed_closure_in_method.wren index 3025841e..78300fa8 100644 --- a/test/language/closure/closed_closure_in_method.wren +++ b/test/language/closure/closed_closure_in_method.wren @@ -1,3 +1,4 @@ +// TODO: Is this right? Shouldn't it resolve to this.local? var foo = null { @@ -8,7 +9,7 @@ var foo = null } } - foo = new Foo + foo = Foo.new() } foo.method // expect: local diff --git a/test/language/closure/nested_closure.wren b/test/language/closure/nested_closure.wren index 4ea237e3..b4e239d5 100644 --- a/test/language/closure/nested_closure.wren +++ b/test/language/closure/nested_closure.wren @@ -1,12 +1,12 @@ var f = null -new Fn { +Fn.new { var a = "a" - new Fn { + Fn.new { var b = "b" - new Fn { + Fn.new { var c = "c" - f = new Fn { + f = Fn.new { IO.print(a) IO.print(b) IO.print(c) diff --git a/test/language/closure/open_closure_in_function.wren b/test/language/closure/open_closure_in_function.wren index fc2e2e29..a49585e2 100644 --- a/test/language/closure/open_closure_in_function.wren +++ b/test/language/closure/open_closure_in_function.wren @@ -1,6 +1,6 @@ { var local = "local" - new Fn { + Fn.new { IO.print(local) // expect: local }.call() } diff --git a/test/language/closure/open_closure_in_method.wren b/test/language/closure/open_closure_in_method.wren index bd1d1e52..f4c577b3 100644 --- a/test/language/closure/open_closure_in_method.wren +++ b/test/language/closure/open_closure_in_method.wren @@ -1,3 +1,4 @@ +// TODO: Is this right? Shouldn't it resolve to this.local? { var local = "local" class Foo { @@ -6,5 +7,5 @@ } } - (new Foo).method // expect: local + Foo.new().method // expect: local } diff --git a/test/language/closure/reference_closure_multiple_times.wren b/test/language/closure/reference_closure_multiple_times.wren index 57a0b08e..0d9f79cd 100644 --- a/test/language/closure/reference_closure_multiple_times.wren +++ b/test/language/closure/reference_closure_multiple_times.wren @@ -2,7 +2,7 @@ var f = null { var a = "a" - f = new Fn { + f = Fn.new { IO.print(a) IO.print(a) } diff --git a/test/language/closure/reuse_closure_slot.wren b/test/language/closure/reuse_closure_slot.wren index 1feda092..f9de1a4f 100644 --- a/test/language/closure/reuse_closure_slot.wren +++ b/test/language/closure/reuse_closure_slot.wren @@ -3,7 +3,7 @@ { var a = "a" - f = new Fn { IO.print(a) } + f = Fn.new { IO.print(a) } } { diff --git a/test/language/closure/shadow_closure_with_local.wren b/test/language/closure/shadow_closure_with_local.wren index 9953819f..34f29986 100644 --- a/test/language/closure/shadow_closure_with_local.wren +++ b/test/language/closure/shadow_closure_with_local.wren @@ -1,6 +1,6 @@ { var foo = "closure" - new Fn { + Fn.new { { IO.print(foo) // expect: closure var foo = "shadow" diff --git a/test/language/conditional/precedence.wren b/test/language/conditional/precedence.wren index be4889c1..41cd8c45 100644 --- a/test/language/conditional/precedence.wren +++ b/test/language/conditional/precedence.wren @@ -15,7 +15,7 @@ IO.print(true || false ? 1 : 2) // expect: 1 IO.print(!false ? 1 : 2) // expect: 1 IO.print(~0 ? 1 : 2) // expect: 1 IO.print(3 is Num ? 1 : 2) // expect: 1 -IO.print(new Foo ? 1 : 2) // expect: 1 +IO.print(Foo.new() ? 1 : 2) // expect: 1 var a = 0 IO.print(a = 3 ? 1 : 2) // expect: 1 @@ -32,7 +32,7 @@ IO.print(true ? 1 || false : 2) // expect: 1 IO.print(true ? !true : 2) // expect: false IO.print(true ? ~0 : 2) // expect: 4294967295 IO.print(true ? 3 is Bool : 2) // expect: false -IO.print(true ? new Foo : 2) // expect: instance of Foo +IO.print(true ? Foo.new() : 2) // expect: instance of Foo IO.print(true ? a = 5 : 2) // expect: 5 IO.print(a) // expect: 5 @@ -48,7 +48,7 @@ IO.print(false ? 1 : 2 || false) // expect: 2 IO.print(false ? 1 : !false) // expect: true IO.print(false ? 1 : ~0) // expect: 4294967295 IO.print(false ? 1 : 3 is Num) // expect: true -IO.print(false ? 1 : new Foo) // expect: instance of Foo +IO.print(false ? 1 : Foo.new()) // expect: instance of Foo // Associativity. IO.print(true ? 2 : true ? 4 : 5) // expect: 2 diff --git a/test/language/constructor/cannot_be_infix.wren b/test/language/constructor/cannot_be_infix.wren new file mode 100644 index 00000000..d5950e67 --- /dev/null +++ b/test/language/constructor/cannot_be_infix.wren @@ -0,0 +1,5 @@ +class Foo { + this +(value) { // expect error + IO.print("ok") + } +} diff --git a/test/language/constructor/cannot_be_minus.wren b/test/language/constructor/cannot_be_minus.wren new file mode 100644 index 00000000..75fbe5e9 --- /dev/null +++ b/test/language/constructor/cannot_be_minus.wren @@ -0,0 +1,5 @@ +class Foo { + this -(value) { // expect error + IO.print("ok") + } +} diff --git a/test/language/constructor/cannot_be_setter.wren b/test/language/constructor/cannot_be_setter.wren new file mode 100644 index 00000000..773e34ff --- /dev/null +++ b/test/language/constructor/cannot_be_setter.wren @@ -0,0 +1,5 @@ +class Foo { + this name=(value) { // expect error + IO.print("ok") + } +} diff --git a/test/language/constructor/cannot_be_static.wren b/test/language/constructor/cannot_be_static.wren new file mode 100644 index 00000000..7a61efd4 --- /dev/null +++ b/test/language/constructor/cannot_be_static.wren @@ -0,0 +1,4 @@ +class Foo { + static this new() {} // expect error + this static new() {} // expect error +} diff --git a/test/language/constructor/cannot_be_subscript.wren b/test/language/constructor/cannot_be_subscript.wren new file mode 100644 index 00000000..db798d1d --- /dev/null +++ b/test/language/constructor/cannot_be_subscript.wren @@ -0,0 +1,5 @@ +class Foo { + this [value] { // expect error + IO.print("ok") + } +} diff --git a/test/language/constructor/cannot_be_unary.wren b/test/language/constructor/cannot_be_unary.wren new file mode 100644 index 00000000..ae15e9e3 --- /dev/null +++ b/test/language/constructor/cannot_be_unary.wren @@ -0,0 +1,5 @@ +class Foo { + this ! { // expect error + IO.print("ok") + } +} diff --git a/test/language/constructor/cannot_call_initializer.wren b/test/language/constructor/cannot_call_initializer.wren new file mode 100644 index 00000000..d6bb8459 --- /dev/null +++ b/test/language/constructor/cannot_call_initializer.wren @@ -0,0 +1,8 @@ +class Foo { + this new() { + IO.print("ok") + } +} + +var foo = Foo.new() // expect: ok +foo.new() // expect runtime error: Foo does not implement 'new()'. diff --git a/test/language/constructor/default.wren b/test/language/constructor/default.wren index 6a6b3c60..77585262 100644 --- a/test/language/constructor/default.wren +++ b/test/language/constructor/default.wren @@ -2,7 +2,7 @@ class Foo { toString { "Foo" } } -// Classes inherit the argument-less "new" one by default. -var foo = new Foo +// Classes get an argument-less "new()" by default. +var foo = Foo.new() IO.print(foo is Foo) // expect: true IO.print(foo.toString) // expect: Foo diff --git a/test/language/constructor/default_calls_new.wren b/test/language/constructor/default_calls_new.wren new file mode 100644 index 00000000..868a0cae --- /dev/null +++ b/test/language/constructor/default_calls_new.wren @@ -0,0 +1,9 @@ +class Foo { + this new() { + IO.print("Foo.new()") + } +} + +class Bar is Foo {} + +Bar.new() // expect: Foo.new() diff --git a/test/language/constructor/infix_class_expression.wren b/test/language/constructor/infix_class_expression.wren index fc93e135..23a9d599 100644 --- a/test/language/constructor/infix_class_expression.wren +++ b/test/language/constructor/infix_class_expression.wren @@ -2,6 +2,8 @@ class Foo { +(other) { "Foo " + other } } -IO.print(new Foo + "value") // expect: Foo value +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 new file mode 100644 index 00000000..b893775d --- /dev/null +++ b/test/language/constructor/named.wren @@ -0,0 +1,16 @@ +// TODO: Change this. + +class Foo { + this named() { _field = "named" } + this other() { _field = "other" } + + toString { _field } +} + +IO.print(Foo.named()) // expect: named +IO.print(Foo.other()) // expect: other + +// Returns the new instance. +var foo = Foo.named() +IO.print(foo is Foo) // expect: true +IO.print(foo.toString) // expect: named diff --git a/test/language/constructor/new.wren b/test/language/constructor/new.wren deleted file mode 100644 index f58f490b..00000000 --- a/test/language/constructor/new.wren +++ /dev/null @@ -1,19 +0,0 @@ -class Foo { - new { IO.print("none") } - new() { IO.print("zero") } - new(a) { IO.print(a) } - new(a, b) { IO.print(a + b) } - - toString { "Foo" } -} - -// Can overload by arity. -new Foo // expect: none -new Foo() // expect: zero -new Foo("one") // expect: one -new Foo("one", "two") // expect: onetwo - -// Returns the new instance. -var foo = new Foo // expect: none -IO.print(foo is Foo) // expect: true -IO.print(foo.toString) // expect: Foo diff --git a/test/language/constructor/no_default.wren b/test/language/constructor/no_default.wren new file mode 100644 index 00000000..f35bc783 --- /dev/null +++ b/test/language/constructor/no_default.wren @@ -0,0 +1,6 @@ +class Foo { + this real() {} +} + +// Classes do not get an argument-less "new()" if they define a constructor. +var foo = Foo.new() // expect runtime error: Foo metaclass does not implement 'new()'. diff --git a/test/language/constructor/no_parameter_list.wren b/test/language/constructor/no_parameter_list.wren new file mode 100644 index 00000000..6de9df1b --- /dev/null +++ b/test/language/constructor/no_parameter_list.wren @@ -0,0 +1,5 @@ +class Foo { + this new { // expect error + IO.print("ok") + } +} diff --git a/test/language/constructor/not_inherited.wren b/test/language/constructor/not_inherited.wren new file mode 100644 index 00000000..159f2b35 --- /dev/null +++ b/test/language/constructor/not_inherited.wren @@ -0,0 +1,7 @@ +class Foo { + this base() {} +} + +class Bar is Foo {} + +Bar.base() // expect runtime error: Bar metaclass does not implement 'base()'. diff --git a/test/language/constructor/object.wren b/test/language/constructor/object.wren new file mode 100644 index 00000000..708b554b --- /dev/null +++ b/test/language/constructor/object.wren @@ -0,0 +1,13 @@ +// Tests that Object implements new(). The only way to call that is through a +// super() call in a subclass, so this does that. + +class Foo { + this 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 new file mode 100644 index 00000000..0676b3d6 --- /dev/null +++ b/test/language/constructor/super_must_have_args.wren @@ -0,0 +1,7 @@ +class A {} + +class B is A { + this new() { + super // expect error + } +} diff --git a/test/language/constructor/superclass.wren b/test/language/constructor/superclass.wren index fede3a72..013d74ae 100644 --- a/test/language/constructor/superclass.wren +++ b/test/language/constructor/superclass.wren @@ -1,5 +1,5 @@ class A { - new(arg) { + this new(arg) { IO.print("new A ", arg) _field = arg } @@ -8,7 +8,7 @@ class A { } class B is A { - new(arg1, arg2) { + this new(arg1, arg2) { super(arg2) IO.print("new B ", arg1) _field = arg1 @@ -18,7 +18,7 @@ class B is A { } class C is B { - new { + this new() { super("one", "two") IO.print("new C") _field = "c" @@ -27,7 +27,7 @@ class C is B { cField { _field } } -var c = new C +var c = C.new() // expect: new A two // expect: new B one // expect: new C diff --git a/test/language/fiber/closure.wren b/test/language/fiber/closure.wren index 9d2025f9..8a720dd7 100644 --- a/test/language/fiber/closure.wren +++ b/test/language/fiber/closure.wren @@ -3,7 +3,7 @@ var closure { var a = "before" - fiber = new Fiber { + fiber = Fiber.new { IO.print(a) Fiber.yield() a = "after" @@ -12,7 +12,7 @@ var closure a = "final" } - closure = new Fn { + closure = Fn.new { IO.print(a) } } diff --git a/test/language/field/closure.wren b/test/language/field/closure.wren index a1d585f9..4b5a2774 100644 --- a/test/language/field/closure.wren +++ b/test/language/field/closure.wren @@ -1,16 +1,16 @@ class Foo { - new { _field = "Foo field" } + this new() { _field = "Foo field" } closeOverGet { - return new Fn { _field } + return Fn.new { _field } } closeOverSet { - return new Fn { _field = "new value" } + return Fn.new { _field = "new value" } } } -var foo = new Foo +var foo = Foo.new() IO.print(foo.closeOverGet.call()) // expect: Foo field foo.closeOverSet.call() IO.print(foo.closeOverGet.call()) // expect: new value diff --git a/test/language/field/default_to_null.wren b/test/language/field/default_to_null.wren index aeba18d1..7b9e2fc4 100644 --- a/test/language/field/default_to_null.wren +++ b/test/language/field/default_to_null.wren @@ -2,4 +2,4 @@ class Foo { write { IO.print(_field) } } -(new Foo).write // expect: null +Foo.new().write // expect: null diff --git a/test/language/field/in_fn_in_static_method.wren b/test/language/field/in_fn_in_static_method.wren index d0a76014..ccb483b3 100644 --- a/test/language/field/in_fn_in_static_method.wren +++ b/test/language/field/in_fn_in_static_method.wren @@ -1,5 +1,5 @@ class Foo { static bar { - new Fn { _field = "wat" } // expect error + Fn.new { _field = "wat" } // expect error } } diff --git a/test/language/field/multiple.wren b/test/language/field/multiple.wren index 879993d9..dcf7536d 100644 --- a/test/language/field/multiple.wren +++ b/test/language/field/multiple.wren @@ -16,7 +16,7 @@ class Foo { } } -var foo = new Foo +var foo = Foo.new() foo.set(1, 2, 3, 4, 5) foo.write // expect: 1 diff --git a/test/language/field/nested_class.wren b/test/language/field/nested_class.wren index 85153bdf..d9f53d6e 100644 --- a/test/language/field/nested_class.wren +++ b/test/language/field/nested_class.wren @@ -10,9 +10,9 @@ class Outer { } } - (new Inner).method + Inner.new().method IO.print(_field) // expect: outer } } -(new Outer).method +Outer.new().method diff --git a/test/language/field/object_reference.wren b/test/language/field/object_reference.wren index 2a201dad..c39b530b 100644 --- a/test/language/field/object_reference.wren +++ b/test/language/field/object_reference.wren @@ -1,36 +1,32 @@ // This test exists mainly to make sure the GC traces instance fields. class Node { - set(left, value, right) { + this new(left, value, right) { _left = left _value = value _right = right } - write { + write() { if (_left is Node) { - _left.write + _left.write() } IO.print(_value) if (_right is Node) { - _right.write + _right.write() } } } -var a = new Node -a.set(null, "a", null) -var b = new Node -b.set(null, "b", null) -var c = new Node -c.set(a, "c", b) +var a = Node.new(null, "a", null) +var b = Node.new(null, "b", null) +var c = Node.new(a, "c", b) a = null b = null -var d = new Node -d.set(c, "d", null) +var d = Node.new(c, "d", null) c = null -d.write +d.write() // expect: a // expect: c // expect: b diff --git a/test/language/field/use_before_set.wren b/test/language/field/use_before_set.wren index 6674547c..62e5d83d 100644 --- a/test/language/field/use_before_set.wren +++ b/test/language/field/use_before_set.wren @@ -3,7 +3,7 @@ class Foo { init { _field = "value" } // ...before an assignment to it. } -var foo = new Foo +var foo = Foo.new() // But invoke them in the right order. foo.init foo.write // expect: value diff --git a/test/language/for/close_over_loop_variable.wren b/test/language/for/close_over_loop_variable.wren index 6c5e2aac..21e50d14 100644 --- a/test/language/for/close_over_loop_variable.wren +++ b/test/language/for/close_over_loop_variable.wren @@ -1,7 +1,7 @@ var list = [] for (i in [1, 2, 3]) { - list.add(new Fn { IO.print(i) }) + list.add(Fn.new { IO.print(i) }) } for (f in list) f.call() diff --git a/test/language/for/closure_in_body.wren b/test/language/for/closure_in_body.wren index 7be38667..1dcd20e2 100644 --- a/test/language/for/closure_in_body.wren +++ b/test/language/for/closure_in_body.wren @@ -2,7 +2,7 @@ var list = [] for (i in [1, 2, 3]) { var j = i + 1 - list.add(new Fn { IO.print(j) }) + list.add(Fn.new { IO.print(j) }) } for (f in list) f.call() diff --git a/test/language/for/only_evaluate_sequence_once.wren b/test/language/for/only_evaluate_sequence_once.wren index 0c953960..9053a4a5 100644 --- a/test/language/for/only_evaluate_sequence_once.wren +++ b/test/language/for/only_evaluate_sequence_once.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { IO.print("evaluate sequence") return [1, 2, 3] } diff --git a/test/language/for/return_closure.wren b/test/language/for/return_closure.wren index 02c11d57..8643ef3f 100644 --- a/test/language/for/return_closure.wren +++ b/test/language/for/return_closure.wren @@ -1,6 +1,6 @@ -var f = new Fn { +var f = Fn.new { for (i in [1, 2, 3]) { - return new Fn { IO.print(i) } + return Fn.new { IO.print(i) } } } diff --git a/test/language/for/return_inside.wren b/test/language/for/return_inside.wren index d2302a14..6e92f0b9 100644 --- a/test/language/for/return_inside.wren +++ b/test/language/for/return_inside.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { for (i in [1, 2, 3]) { return i } diff --git a/test/language/for/truth.wren b/test/language/for/truth.wren index cfb0bdfc..e84031ee 100644 --- a/test/language/for/truth.wren +++ b/test/language/for/truth.wren @@ -1,32 +1,32 @@ class Iter { - new(value) { _value = value } + this new(value) { _value = value } iterate(iterator) { _value } iteratorValue(iterator) { "value" } } // False and null are false. -for (n in new Iter(false)) { +for (n in Iter.new(false)) { IO.print("bad") break } -for (n in new Iter(null)) { +for (n in Iter.new(null)) { IO.print("bad") break } // Everything else is true. -for (n in new Iter(true)) { +for (n in Iter.new(true)) { IO.print("true") // expect: true break } -for (n in new Iter(0)) { +for (n in Iter.new(0)) { IO.print(0) // expect: 0 break } -for (n in new Iter("")) { +for (n in Iter.new("")) { IO.print("string") // expect: string break } diff --git a/test/language/function/empty_body.wren b/test/language/function/empty_body.wren index bb62333d..773dcfed 100644 --- a/test/language/function/empty_body.wren +++ b/test/language/function/empty_body.wren @@ -1,2 +1,2 @@ -var f = new Fn {} +var f = Fn.new {} IO.print(f.call()) // expect: null diff --git a/test/language/function/newline_body.wren b/test/language/function/newline_body.wren index a99fce6c..9151ea2d 100644 --- a/test/language/function/newline_body.wren +++ b/test/language/function/newline_body.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { // Hi. } IO.print(f.call()) // expect: null diff --git a/test/language/function/no_newline_before_close.wren b/test/language/function/no_newline_before_close.wren index 98c14962..060db9a8 100644 --- a/test/language/function/no_newline_before_close.wren +++ b/test/language/function/no_newline_before_close.wren @@ -1,2 +1,2 @@ -new Fn { +Fn.new { IO.print("ok") } // expect error \ No newline at end of file diff --git a/test/language/function/no_parameters.wren b/test/language/function/no_parameters.wren index c37db655..3363748b 100644 --- a/test/language/function/no_parameters.wren +++ b/test/language/function/no_parameters.wren @@ -1 +1 @@ -new Fn {|| null } // expect error +Fn.new {|| null } // expect error diff --git a/test/language/function/parameters.wren b/test/language/function/parameters.wren index 3b553227..98c79f88 100644 --- a/test/language/function/parameters.wren +++ b/test/language/function/parameters.wren @@ -1,50 +1,50 @@ -var f0 = new Fn { 0 } +var f0 = Fn.new { 0 } IO.print(f0.call()) // expect: 0 -var f1 = new Fn {|a| a } +var f1 = Fn.new {|a| a } IO.print(f1.call(1)) // expect: 1 -var f2 = new Fn {|a, b| a + b } +var f2 = Fn.new {|a, b| a + b } IO.print(f2.call(1, 2)) // expect: 3 -var f3 = new Fn {|a, b, c| a + b + c } +var f3 = Fn.new {|a, b, c| a + b + c } IO.print(f3.call(1, 2, 3)) // expect: 6 -var f4 = new Fn {|a, b, c, d| a + b + c + d } +var f4 = Fn.new {|a, b, c, d| a + b + c + d } IO.print(f4.call(1, 2, 3, 4)) // expect: 10 -var f5 = new Fn {|a, b, c, d, e| a + b + c + d + e } +var f5 = Fn.new {|a, b, c, d, e| a + b + c + d + e } IO.print(f5.call(1, 2, 3, 4, 5)) // expect: 15 -var f6 = new Fn {|a, b, c, d, e, f| a + b + c + d + e + f } +var f6 = Fn.new {|a, b, c, d, e, f| a + b + c + d + e + f } IO.print(f6.call(1, 2, 3, 4, 5, 6)) // expect: 21 -var f7 = new Fn {|a, b, c, d, e, f, g| a + b + c + d + e + f + g } +var f7 = Fn.new {|a, b, c, d, e, f, g| a + b + c + d + e + f + g } IO.print(f7.call(1, 2, 3, 4, 5, 6, 7)) // expect: 28 -var f8 = new Fn {|a, b, c, d, e, f, g, h| a + b + c + d + e + f + g + h } +var f8 = Fn.new {|a, b, c, d, e, f, g, h| a + b + c + d + e + f + g + h } IO.print(f8.call(1, 2, 3, 4, 5, 6, 7, 8)) // expect: 36 -var f9 = new Fn {|a, b, c, d, e, f, g, h, i| a + b + c + d + e + f + g + h + i } +var f9 = Fn.new {|a, b, c, d, e, f, g, h, i| a + b + c + d + e + f + g + h + i } IO.print(f9.call(1, 2, 3, 4, 5, 6, 7, 8, 9)) // expect: 45 -var f10 = new Fn {|a, b, c, d, e, f, g, h, i, j| a + b + c + d + e + f + g + h + i + j } +var f10 = Fn.new {|a, b, c, d, e, f, g, h, i, j| a + b + c + d + e + f + g + h + i + j } IO.print(f10.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // expect: 55 -var f11 = new Fn {|a, b, c, d, e, f, g, h, i, j, k| a + b + c + d + e + f + g + h + i + j + k } +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 } IO.print(f11.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)) // expect: 66 -var f12 = new Fn {|a, b, c, d, e, f, g, h, i, j, k, l| a + b + c + d + e + f + g + h + i + j + k + l } +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 } IO.print(f12.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) // expect: 78 -var f13 = new Fn {|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 } +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 } IO.print(f13.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)) // expect: 91 -var f14 = new Fn {|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 } +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 } IO.print(f14.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)) // expect: 105 -var f15 = new Fn {|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 } +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 } IO.print(f15.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)) // expect: 120 -var f16 = new Fn {|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 } +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 } IO.print(f16.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)) // expect: 136 diff --git a/test/language/function/syntax.wren b/test/language/function/syntax.wren index c9086c70..2672d6be 100644 --- a/test/language/function/syntax.wren +++ b/test/language/function/syntax.wren @@ -1,19 +1,19 @@ // Single expression body. -new Fn { IO.print("ok") }.call() // expect: ok +Fn.new { IO.print("ok") }.call() // expect: ok // Curly body. -new Fn { +Fn.new { IO.print("ok") // expect: ok }.call() // Multiple statements. -new Fn { +Fn.new { IO.print("1") // expect: 1 IO.print("2") // expect: 2 }.call() // Extra newlines. -new Fn { +Fn.new { IO.print("1") // expect: 1 diff --git a/test/language/implicit_receiver/inherited_methods.wren b/test/language/implicit_receiver/inherited_methods.wren index 331cec20..89dae1e6 100644 --- a/test/language/implicit_receiver/inherited_methods.wren +++ b/test/language/implicit_receiver/inherited_methods.wren @@ -20,4 +20,4 @@ class Bar is Foo { } } -(new Bar).test +Bar.new().test diff --git a/test/language/implicit_receiver/instance_methods.wren b/test/language/implicit_receiver/instance_methods.wren index 3d32ba30..a3db0f42 100644 --- a/test/language/implicit_receiver/instance_methods.wren +++ b/test/language/implicit_receiver/instance_methods.wren @@ -18,6 +18,6 @@ class Foo { } } -(new Foo).test +Foo.new().test // TODO: Need to decide how these interact with globals. diff --git a/test/language/implicit_receiver/locals_shadow_getter.wren b/test/language/implicit_receiver/locals_shadow_getter.wren index 353451db..90ef6a58 100644 --- a/test/language/implicit_receiver/locals_shadow_getter.wren +++ b/test/language/implicit_receiver/locals_shadow_getter.wren @@ -14,4 +14,4 @@ class Foo { } } -(new Foo).test +Foo.new().test diff --git a/test/language/implicit_receiver/locals_shadow_setter.wren b/test/language/implicit_receiver/locals_shadow_setter.wren index c5312240..09de076c 100644 --- a/test/language/implicit_receiver/locals_shadow_setter.wren +++ b/test/language/implicit_receiver/locals_shadow_setter.wren @@ -17,4 +17,4 @@ class Foo { } } -(new Foo).test +Foo.new().test diff --git a/test/language/implicit_receiver/nested_class.wren b/test/language/implicit_receiver/nested_class.wren index fc2cc209..5e9fc18c 100644 --- a/test/language/implicit_receiver/nested_class.wren +++ b/test/language/implicit_receiver/nested_class.wren @@ -36,7 +36,7 @@ class Outer { } } - (new Inner).test + Inner.new().test getter // expect: outer getter setter = "value" // expect: outer setter @@ -44,4 +44,4 @@ class Outer { } } -(new Outer).test +Outer.new().test diff --git a/test/language/inheritance/inherit_fields.wren b/test/language/inheritance/inherit_fields.wren index 90d713fa..d9532870 100644 --- a/test/language/inheritance/inherit_fields.wren +++ b/test/language/inheritance/inherit_fields.wren @@ -22,7 +22,7 @@ class Bar is Foo { } } -var bar = new Bar +var bar = Bar.new() bar.foo("foo 1", "foo 2") bar.bar("bar 1", "bar 2") diff --git a/test/language/inheritance/inherit_from_closure.wren b/test/language/inheritance/inherit_from_closure.wren index ab3ea6be..85d79f74 100644 --- a/test/language/inheritance/inherit_from_closure.wren +++ b/test/language/inheritance/inherit_from_closure.wren @@ -2,7 +2,7 @@ var ClosureType { var a = "a" - ClosureType = new Fn { IO.print(a) }.type + ClosureType = Fn.new { IO.print(a) }.type } class Subclass is ClosureType {} // expect runtime error: Subclass cannot inherit from Fn. diff --git a/test/language/inheritance/inherit_methods.wren b/test/language/inheritance/inherit_methods.wren index 2308d37b..1361b581 100644 --- a/test/language/inheritance/inherit_methods.wren +++ b/test/language/inheritance/inherit_methods.wren @@ -12,7 +12,7 @@ class Bar is Foo { override { IO.print("bar") } } -var bar = new Bar +var bar = Bar.new() bar.methodOnFoo // expect: foo bar.methodOnBar // expect: bar diff --git a/test/language/inheritance/inherited_fields_in_closure.wren b/test/language/inheritance/inherited_fields_in_closure.wren index 4d097d59..a43f67e9 100644 --- a/test/language/inheritance/inherited_fields_in_closure.wren +++ b/test/language/inheritance/inherited_fields_in_closure.wren @@ -1,31 +1,31 @@ class Foo { - new { _field = "Foo field" } + this new() { _field = "Foo field" } closeOverFooGet { - return new Fn { new Fn { _field } } + return Fn.new { Fn.new { _field } } } closeOverFooSet { - return new Fn { new Fn { _field = "new foo value" } } + return Fn.new { Fn.new { _field = "new foo value" } } } } class Bar is Foo { - new { - super + this new() { + super() _field = "Bar field" } closeOverBarGet { - return new Fn { new Fn { _field } } + return Fn.new { Fn.new { _field } } } closeOverBarSet { - return new Fn { new Fn { _field = "new bar value" } } + return Fn.new { Fn.new { _field = "new bar value" } } } } -var bar = new Bar +var bar = Bar.new() IO.print(bar.closeOverFooGet.call().call()) // expect: Foo field IO.print(bar.closeOverBarGet.call().call()) // expect: Bar field bar.closeOverFooSet.call().call() diff --git a/test/language/inheritance/is.wren b/test/language/inheritance/is.wren index 5c865e00..893e21a1 100644 --- a/test/language/inheritance/is.wren +++ b/test/language/inheritance/is.wren @@ -1,9 +1,9 @@ class A {} class B is A {} class C is B {} -var a = new A -var b = new B -var c = new C +var a = A.new() +var b = B.new() +var c = C.new() IO.print(a is A) // expect: true IO.print(a is B) // expect: false diff --git a/test/language/is/is.wren b/test/language/is/is.wren index 717bf1b6..fe4c41ff 100644 --- a/test/language/is/is.wren +++ b/test/language/is/is.wren @@ -1,6 +1,6 @@ IO.print(Num is Class) // expect: true IO.print(true is Bool) // expect: true -IO.print(new Fn { 1 } is Fn) // expect: true +IO.print(Fn.new { 1 } is Fn) // expect: true IO.print(123 is Num) // expect: true IO.print(null is Null) // expect: true IO.print("s" is String) // expect: true @@ -8,7 +8,7 @@ IO.print("s" is String) // expect: true IO.print(Num is Bool) // expect: false IO.print(null is Class) // expect: false IO.print(true is Fn) // expect: false -IO.print(new Fn { 1 } is Num) // expect: false +IO.print(Fn.new { 1 } is Num) // expect: false IO.print("s" is Null) // expect: false IO.print(123 is String) // expect: false @@ -16,7 +16,7 @@ IO.print(123 is String) // expect: false IO.print(Num is Object) // expect: true IO.print(null is Object) // expect: true IO.print(true is Object) // expect: true -IO.print(new Fn { 1 } is Object) // expect: true +IO.print(Fn.new { 1 } is Object) // expect: true IO.print("s" is Object) // expect: true IO.print(123 is Object) // expect: true @@ -24,7 +24,7 @@ IO.print(123 is Object) // expect: true IO.print(Num is Class) // expect: true IO.print(null is Class) // expect: false IO.print(true is Class) // expect: false -IO.print(new Fn { 1 } is Class) // expect: false +IO.print(Fn.new { 1 } is Class) // expect: false IO.print("s" is Class) // expect: false IO.print(123 is Class) // expect: false diff --git a/test/language/method/arity.wren b/test/language/method/arity.wren index 5e8ea4c4..91efd35d 100644 --- a/test/language/method/arity.wren +++ b/test/language/method/arity.wren @@ -19,7 +19,7 @@ class Foo { method(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} } -var foo = new Foo +var foo = Foo.new() IO.print(foo.method) // expect: getter IO.print(foo.method()) // expect: no args IO.print(foo.method(1)) // expect: 1 diff --git a/test/language/method/empty_block.wren b/test/language/method/empty_block.wren index 4ee5aa7b..fcd0a2d8 100644 --- a/test/language/method/empty_block.wren +++ b/test/language/method/empty_block.wren @@ -2,4 +2,4 @@ class Foo { bar {} } -IO.print((new Foo).bar) // expect: null +IO.print(Foo.new().bar) // expect: null diff --git a/test/language/method/long_name.wren b/test/language/method/long_name.wren index c95363b9..871f7221 100644 --- a/test/language/method/long_name.wren +++ b/test/language/method/long_name.wren @@ -4,4 +4,4 @@ class Foo { } } -IO.print((new Foo).thisHasAMethodNameThatIsExactly64CharactersLongWhichIsTheMaximum) // expect: result +IO.print(Foo.new().thisHasAMethodNameThatIsExactly64CharactersLongWhichIsTheMaximum) // expect: result diff --git a/test/language/method/many_methods.wren b/test/language/method/many_methods.wren index f3e29cfe..d24d34b4 100644 --- a/test/language/method/many_methods.wren +++ b/test/language/method/many_methods.wren @@ -1010,7 +1010,7 @@ class Foo { method999 { 1 } } -var foo = new Foo +var foo = Foo.new() var result = 0 result = result + foo.method000 result = result + foo.method001 diff --git a/test/language/method/newlines.wren b/test/language/method/newlines.wren index ec29cb90..87cf45e6 100644 --- a/test/language/method/newlines.wren +++ b/test/language/method/newlines.wren @@ -3,7 +3,7 @@ class Foo { [a, b] { "subscript " + a + " " + b } } -var foo = new Foo +var foo = Foo.new() // Allow newlines after commas and before ")". IO.print(foo.method("a", diff --git a/test/language/method/not_found.wren b/test/language/method/not_found.wren index 49f4347a..68e0dbc9 100644 --- a/test/language/method/not_found.wren +++ b/test/language/method/not_found.wren @@ -1,3 +1,3 @@ class Foo {} -(new Foo).someUnknownMethod // expect runtime error: Foo does not implement 'someUnknownMethod'. +Foo.new().someUnknownMethod // expect runtime error: Foo does not implement 'someUnknownMethod'. diff --git a/test/language/method/not_found_eleven_arguments.wren b/test/language/method/not_found_eleven_arguments.wren index b76f613e..fd946fe8 100644 --- a/test/language/method/not_found_eleven_arguments.wren +++ b/test/language/method/not_found_eleven_arguments.wren @@ -1,3 +1,3 @@ class Foo {} -(new Foo).someUnknownMethod(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) // expect runtime error: Foo does not implement 'someUnknownMethod(_,_,_,_,_,_,_,_,_,_,_)'. \ No newline at end of file +Foo.new().someUnknownMethod(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) // expect runtime error: Foo does not implement 'someUnknownMethod(_,_,_,_,_,_,_,_,_,_,_)'. \ No newline at end of file diff --git a/test/language/method/not_found_multiple_arguments.wren b/test/language/method/not_found_multiple_arguments.wren index 891e2875..75436201 100644 --- a/test/language/method/not_found_multiple_arguments.wren +++ b/test/language/method/not_found_multiple_arguments.wren @@ -1,3 +1,3 @@ class Foo {} -(new Foo).someUnknownMethod(1, 2) // expect runtime error: Foo does not implement 'someUnknownMethod(_,_)'. \ No newline at end of file +Foo.new().someUnknownMethod(1, 2) // expect runtime error: Foo does not implement 'someUnknownMethod(_,_)'. \ No newline at end of file diff --git a/test/language/method/not_found_one_argument.wren b/test/language/method/not_found_one_argument.wren index e77d3ce7..d86a083d 100644 --- a/test/language/method/not_found_one_argument.wren +++ b/test/language/method/not_found_one_argument.wren @@ -1,3 +1,3 @@ class Foo {} -(new Foo).someUnknownMethod(1) // expect runtime error: Foo does not implement 'someUnknownMethod(_)'. \ No newline at end of file +Foo.new().someUnknownMethod(1) // expect runtime error: Foo does not implement 'someUnknownMethod(_)'. \ No newline at end of file diff --git a/test/language/method/operators.wren b/test/language/method/operators.wren index b3aff324..c181c788 100644 --- a/test/language/method/operators.wren +++ b/test/language/method/operators.wren @@ -18,7 +18,7 @@ class Foo { - { "prefix -" } } -var foo = new Foo +var foo = Foo.new() IO.print(foo + "a") // expect: infix + a IO.print(foo - "a") // expect: infix - a IO.print(foo * "a") // expect: infix * a diff --git a/test/language/method/static.wren b/test/language/method/static.wren index 948b197f..bbab05ef 100644 --- a/test/language/method/static.wren +++ b/test/language/method/static.wren @@ -6,7 +6,7 @@ class Foo { static bar(arg) { "on metaclass " + arg } } -IO.print((new Foo).bar) // expect: on instance +IO.print(Foo.new().bar) // expect: on instance IO.print(Foo.bar) // expect: on metaclass -IO.print((new Foo).bar("arg")) // expect: on instance arg +IO.print(Foo.new().bar("arg")) // expect: on instance arg IO.print(Foo.bar("arg")) // expect: on metaclass arg diff --git a/test/language/method/subscript_operators.wren b/test/language/method/subscript_operators.wren index b46588be..4daca244 100644 --- a/test/language/method/subscript_operators.wren +++ b/test/language/method/subscript_operators.wren @@ -7,7 +7,7 @@ class Foo { [a, b, c]=(value) { "3-subscript setter " + a + " " + b + " " + c + " = " + value } } -var foo = new Foo +var foo = Foo.new() IO.print(foo["a"]) // expect: 1-subscript a IO.print(foo["a", "b"]) // expect: 2-subscript a b IO.print(foo["a", "b", "c"]) // expect: 3-subscript a b c diff --git a/test/language/new/new_on_nonclass.wren b/test/language/new/new_on_nonclass.wren deleted file mode 100644 index 94a46af5..00000000 --- a/test/language/new/new_on_nonclass.wren +++ /dev/null @@ -1,2 +0,0 @@ -var a = 123 -new a // expect runtime error: Must provide a class to 'new' to construct. diff --git a/test/language/new/newline_after_new.wren b/test/language/new/newline_after_new.wren deleted file mode 100644 index d6562edb..00000000 --- a/test/language/new/newline_after_new.wren +++ /dev/null @@ -1,2 +0,0 @@ -new // expect error -Fn {} \ No newline at end of file diff --git a/test/language/nonlocal/assignment.wren b/test/language/nonlocal/assignment.wren index d26ba628..90fd6223 100644 --- a/test/language/nonlocal/assignment.wren +++ b/test/language/nonlocal/assignment.wren @@ -12,7 +12,7 @@ class Foo { Foo.method IO.print(Nonlocal) // expect: method -new Fn { +Fn.new { Nonlocal = "fn" }.call() IO.print(Nonlocal) // expect: fn diff --git a/test/language/nonlocal/mutual_recursion.wren b/test/language/nonlocal/mutual_recursion.wren index 6114b9d0..f88169f9 100644 --- a/test/language/nonlocal/mutual_recursion.wren +++ b/test/language/nonlocal/mutual_recursion.wren @@ -1,9 +1,9 @@ class Foo { - static bar { new Bar } + static bar { Bar.new() } } class Bar { - static foo { new Foo } + static foo { Foo.new() } } IO.print(Foo.bar) // expect: instance of Bar diff --git a/test/language/nonlocal/undefined.wren b/test/language/nonlocal/undefined.wren index b78b2c83..7fab4f29 100644 --- a/test/language/nonlocal/undefined.wren +++ b/test/language/nonlocal/undefined.wren @@ -1,7 +1,6 @@ -var fn = new Fn { +var fn = Fn.new { IO.print(Foo) IO.print(Bar) } -// expect error line 7 -// expect error line 7 \ No newline at end of file +// expect error line 6 \ No newline at end of file diff --git a/test/language/nonlocal/use_in_function.wren b/test/language/nonlocal/use_in_function.wren index 024a9f70..657eeef2 100644 --- a/test/language/nonlocal/use_in_function.wren +++ b/test/language/nonlocal/use_in_function.wren @@ -1,5 +1,5 @@ var Global = "global" -new Fn { +Fn.new { IO.print(Global) // expect: global }.call() diff --git a/test/language/nonlocal/use_in_function_before_definition.wren b/test/language/nonlocal/use_in_function_before_definition.wren index f2103e9b..1a797cc2 100644 --- a/test/language/nonlocal/use_in_function_before_definition.wren +++ b/test/language/nonlocal/use_in_function_before_definition.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { IO.print(Global) } diff --git a/test/language/nonlocal/use_in_method.wren b/test/language/nonlocal/use_in_method.wren index a22d6e81..bef96b5f 100644 --- a/test/language/nonlocal/use_in_method.wren +++ b/test/language/nonlocal/use_in_method.wren @@ -10,5 +10,5 @@ class Foo { } } -(new Foo).method // expect: global +Foo.new().method // expect: global Foo.classMethod // expect: global diff --git a/test/language/nonlocal/use_in_method_before_definition.wren b/test/language/nonlocal/use_in_method_before_definition.wren index 1e7d283d..8c2974c7 100644 --- a/test/language/nonlocal/use_in_method_before_definition.wren +++ b/test/language/nonlocal/use_in_method_before_definition.wren @@ -10,5 +10,5 @@ class Foo { var Global = "global" -(new Foo).method // expect: global +Foo.new().method // expect: global Foo.classMethod // expect: global diff --git a/test/language/return/after_else.wren b/test/language/return/after_else.wren index e1cb0ccb..58ca87fe 100644 --- a/test/language/return/after_else.wren +++ b/test/language/return/after_else.wren @@ -1,3 +1,3 @@ -IO.print(new Fn { +IO.print(Fn.new { if (false) "no" else return "ok" }.call()) // expect: ok diff --git a/test/language/return/after_if.wren b/test/language/return/after_if.wren index 15a37ebd..cd57363b 100644 --- a/test/language/return/after_if.wren +++ b/test/language/return/after_if.wren @@ -1,3 +1,3 @@ -IO.print(new Fn { +IO.print(Fn.new { if (true) return "ok" }.call()) // expect: ok diff --git a/test/language/return/after_while.wren b/test/language/return/after_while.wren index 9dd620dc..4f09fb3b 100644 --- a/test/language/return/after_while.wren +++ b/test/language/return/after_while.wren @@ -1,3 +1,3 @@ -IO.print(new Fn { +IO.print(Fn.new { while (true) return "ok" }.call()) // expect: ok diff --git a/test/language/return/in_function.wren b/test/language/return/in_function.wren index a7e8201a..9b031b7e 100644 --- a/test/language/return/in_function.wren +++ b/test/language/return/in_function.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { return "ok" IO.print("bad") } diff --git a/test/language/return/in_method.wren b/test/language/return/in_method.wren index 6e68dde4..7f0cbbc2 100644 --- a/test/language/return/in_method.wren +++ b/test/language/return/in_method.wren @@ -5,4 +5,4 @@ class Foo { } } -IO.print((new Foo).method) // expect: ok +IO.print(Foo.new().method) // expect: ok diff --git a/test/language/return/return_null_if_newline.wren b/test/language/return/return_null_if_newline.wren index 3d467330..d206dbe1 100644 --- a/test/language/return/return_null_if_newline.wren +++ b/test/language/return/return_null_if_newline.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { return IO.print("bad") } diff --git a/test/language/setter/associativity.wren b/test/language/setter/associativity.wren index 2c0e526f..ed32a0a8 100644 --- a/test/language/setter/associativity.wren +++ b/test/language/setter/associativity.wren @@ -1,5 +1,5 @@ class Foo { - new(value) { _value = value } + this new(value) { _value = value } toString { _value } bar=(value) { _value = value @@ -7,9 +7,9 @@ class Foo { } } -var a = new Foo("a") -var b = new Foo("b") -var c = new Foo("c") +var a = Foo.new("a") +var b = Foo.new("b") +var c = Foo.new("c") // Assignment is right-associative. a.bar = b.bar = c.bar = "d" diff --git a/test/language/setter/grouping.wren b/test/language/setter/grouping.wren index 47fd97b8..4d7a9bcd 100644 --- a/test/language/setter/grouping.wren +++ b/test/language/setter/grouping.wren @@ -2,5 +2,5 @@ class Foo { bar=(value) { value } } -var foo = new Foo +var foo = Foo.new() (foo.bar) = "value" // expect error diff --git a/test/language/setter/infix_operator.wren b/test/language/setter/infix_operator.wren index e694c545..0b2c9c60 100644 --- a/test/language/setter/infix_operator.wren +++ b/test/language/setter/infix_operator.wren @@ -2,5 +2,5 @@ class Foo { bar=(value) { value } } -var foo = new Foo +var foo = Foo.new() "a" + foo.bar = "value" // expect error diff --git a/test/language/setter/instance.wren b/test/language/setter/instance.wren index e2941fab..b9f5c1a8 100644 --- a/test/language/setter/instance.wren +++ b/test/language/setter/instance.wren @@ -4,5 +4,5 @@ class Foo { } } -var foo = new Foo +var foo = Foo.new() foo.bar = "value" // expect: value diff --git a/test/language/setter/is.wren b/test/language/setter/is.wren index 1797bccb..1f414d78 100644 --- a/test/language/setter/is.wren +++ b/test/language/setter/is.wren @@ -2,5 +2,5 @@ class Foo { bar=(value) { value } } -var foo = new Foo +var foo = Foo.new() a is foo.bar = "value" // expect error diff --git a/test/language/setter/prefix_operator.wren b/test/language/setter/prefix_operator.wren index 20b80542..2fa02a20 100644 --- a/test/language/setter/prefix_operator.wren +++ b/test/language/setter/prefix_operator.wren @@ -2,5 +2,5 @@ class Foo { bar=(value) { value } } -var foo = new Foo +var foo = Foo.new() !foo.bar = "value" // expect error diff --git a/test/language/setter/result.wren b/test/language/setter/result.wren index ca153aa7..55d78346 100644 --- a/test/language/setter/result.wren +++ b/test/language/setter/result.wren @@ -2,5 +2,5 @@ class Foo { bar=(value) { "result" } } -var foo = new Foo +var foo = Foo.new() IO.print(foo.bar = "value") // expect: result diff --git a/test/language/setter/same_name_as_method.wren b/test/language/setter/same_name_as_method.wren index c409328a..4e05c388 100644 --- a/test/language/setter/same_name_as_method.wren +++ b/test/language/setter/same_name_as_method.wren @@ -3,6 +3,6 @@ class Foo { bar { IO.print("get") } } -var foo = new Foo +var foo = Foo.new() foo.bar = "value" // expect: set foo.bar // expect: get diff --git a/test/language/static_field/closure.wren b/test/language/static_field/closure.wren index 422667a1..46e7d5b5 100644 --- a/test/language/static_field/closure.wren +++ b/test/language/static_field/closure.wren @@ -2,11 +2,11 @@ class Foo { static initialize { __field = "Foo field" } static closeOverGet { - return new Fn { __field } + return Fn.new { __field } } static closeOverSet { - return new Fn { __field = "new value" } + return Fn.new { __field = "new value" } } } diff --git a/test/language/static_field/in_instance_method.wren b/test/language/static_field/in_instance_method.wren index 85af790b..0e0f8060 100644 --- a/test/language/static_field/in_instance_method.wren +++ b/test/language/static_field/in_instance_method.wren @@ -7,7 +7,7 @@ class Foo { __e = e } - write { + write() { IO.print(__a) IO.print(__b) IO.print(__c) @@ -16,8 +16,8 @@ class Foo { } } -(new Foo).set(1, 2, 3, 4, 5) -(new Foo).write +Foo.new().set(1, 2, 3, 4, 5) +Foo.new().write() // expect: 1 // expect: 2 // expect: 3 diff --git a/test/language/static_field/nested_class.wren b/test/language/static_field/nested_class.wren index 18f20f56..3517da77 100644 --- a/test/language/static_field/nested_class.wren +++ b/test/language/static_field/nested_class.wren @@ -25,10 +25,10 @@ class Outer { } } - (new Inner).instanceMethod + Inner.new().instanceMethod IO.print(__field) // expect: outer } } Outer.staticMethod -(new Outer).instanceMethod +Outer.new().instanceMethod diff --git a/test/language/super/call_different_arity.wren b/test/language/super/call_different_arity.wren index 5798a932..0666149a 100644 --- a/test/language/super/call_different_arity.wren +++ b/test/language/super/call_different_arity.wren @@ -13,7 +13,7 @@ class Derived is Base { } } -(new Derived).foo(1) +Derived.new().foo(1) // expect: Derived.bar(a) // expect: Base.foo // expect: Base.foo(a) diff --git a/test/language/super/call_other_method.wren b/test/language/super/call_other_method.wren index 4e4d7ab9..ca1ac678 100644 --- a/test/language/super/call_other_method.wren +++ b/test/language/super/call_other_method.wren @@ -11,7 +11,7 @@ class Derived is Base { } } -(new Derived).bar +Derived.new().bar // expect: Derived.bar // expect: Base.foo diff --git a/test/language/super/call_same_method.wren b/test/language/super/call_same_method.wren index b9d162fe..cf765e94 100644 --- a/test/language/super/call_same_method.wren +++ b/test/language/super/call_same_method.wren @@ -11,6 +11,6 @@ class Derived is Base { } } -(new Derived).foo +Derived.new().foo // expect: Derived.foo // expect: Base.foo diff --git a/test/language/super/closure.wren b/test/language/super/closure.wren index e21eec05..8a6c2b84 100644 --- a/test/language/super/closure.wren +++ b/test/language/super/closure.wren @@ -3,9 +3,9 @@ class Base { } class Derived is Base { - getClosure { new Fn { super.toString } } + getClosure { Fn.new { super.toString } } toString { "Derived" } } -var closure = (new Derived).getClosure +var closure = Derived.new().getClosure IO.print(closure.call()) // expect: Base diff --git a/test/language/super/implicit_name.wren b/test/language/super/implicit_name.wren index b59fe1cb..c9ed109c 100644 --- a/test/language/super/implicit_name.wren +++ b/test/language/super/implicit_name.wren @@ -11,6 +11,6 @@ class Derived is Base { } } -(new Derived).foo +Derived.new().foo // expect: Derived.foo // expect: Base.foo diff --git a/test/language/super/indirectly_inherited.wren b/test/language/super/indirectly_inherited.wren index 78407fc1..b9d7706c 100644 --- a/test/language/super/indirectly_inherited.wren +++ b/test/language/super/indirectly_inherited.wren @@ -13,6 +13,6 @@ class C is B { } } -(new C).foo +C.new().foo // expect: C.foo // expect: A.foo diff --git a/test/language/super/no_superclass_method.wren b/test/language/super/no_superclass_method.wren index e10de998..e85c5afa 100644 --- a/test/language/super/no_superclass_method.wren +++ b/test/language/super/no_superclass_method.wren @@ -4,4 +4,4 @@ class Derived is Base { foo { super.doesNotExist(1) } // expect runtime error: Base does not implement 'doesNotExist(_)'. } -(new Derived).foo +Derived.new().foo diff --git a/test/language/super/super_in_closure_in_inherited_method.wren b/test/language/super/super_in_closure_in_inherited_method.wren index 63d1e672..c39c83d2 100644 --- a/test/language/super/super_in_closure_in_inherited_method.wren +++ b/test/language/super/super_in_closure_in_inherited_method.wren @@ -1,6 +1,6 @@ class A { callSuperToString { - return new Fn { super.toString }.call() + return Fn.new { super.toString }.call() } toString { "A.toString" } @@ -8,4 +8,4 @@ class A { class B is A {} -IO.print((new B).callSuperToString) // expect: instance of B +IO.print(B.new().callSuperToString) // expect: instance of B diff --git a/test/language/super/super_in_inherited_method.wren b/test/language/super/super_in_inherited_method.wren index 2ee25599..229fddc8 100644 --- a/test/language/super/super_in_inherited_method.wren +++ b/test/language/super/super_in_inherited_method.wren @@ -6,4 +6,4 @@ class A { class B is A {} -IO.print((new B).callSuperToString) // expect: instance of B +IO.print(B.new().callSuperToString) // expect: instance of B diff --git a/test/language/super/super_in_top_level_function.wren b/test/language/super/super_in_top_level_function.wren index 7daec470..02d9305b 100644 --- a/test/language/super/super_in_top_level_function.wren +++ b/test/language/super/super_in_top_level_function.wren @@ -1,3 +1,3 @@ -new Fn { +Fn.new { super.foo // expect error } diff --git a/test/language/this/closure.wren b/test/language/this/closure.wren index 747214ad..6c220984 100644 --- a/test/language/this/closure.wren +++ b/test/language/this/closure.wren @@ -1,7 +1,7 @@ class Foo { - getClosure { new Fn { toString } } + getClosure { Fn.new { toString } } toString { "Foo" } } -var closure = (new Foo).getClosure +var closure = Foo.new().getClosure IO.print(closure.call()) // expect: Foo diff --git a/test/language/this/nested_class.wren b/test/language/this/nested_class.wren index 9693071a..8efdc1e9 100644 --- a/test/language/this/nested_class.wren +++ b/test/language/this/nested_class.wren @@ -2,7 +2,7 @@ class Outer { method { IO.print(this) // expect: Outer - new Fn { + Fn.new { IO.print(this) // expect: Outer class Inner { @@ -12,11 +12,11 @@ class Outer { toString { "Inner" } } - (new Inner).method + Inner.new().method }.call() } toString { "Outer" } } -(new Outer).method +Outer.new().method diff --git a/test/language/this/nested_closure.wren b/test/language/this/nested_closure.wren index bb12b6bc..9fb5793a 100644 --- a/test/language/this/nested_closure.wren +++ b/test/language/this/nested_closure.wren @@ -1,7 +1,7 @@ class Foo { - getClosure { new Fn { new Fn { new Fn { toString } } } } + getClosure { Fn.new { Fn.new { Fn.new { toString } } } } toString { "Foo" } } -var closure = (new Foo).getClosure +var closure = Foo.new().getClosure IO.print(closure.call().call().call()) // expect: Foo diff --git a/test/language/this/this_in_method.wren b/test/language/this/this_in_method.wren index 8f27f806..af5fddba 100644 --- a/test/language/this/this_in_method.wren +++ b/test/language/this/this_in_method.wren @@ -3,4 +3,4 @@ class Foo { baz { "baz" } } -IO.print((new Foo).bar.baz) // expect: baz +IO.print(Foo.new().bar.baz) // expect: baz diff --git a/test/language/this/this_in_top_level_function.wren b/test/language/this/this_in_top_level_function.wren index ddeb1b8f..269cb215 100644 --- a/test/language/this/this_in_top_level_function.wren +++ b/test/language/this/this_in_top_level_function.wren @@ -1,3 +1,3 @@ -new Fn { +Fn.new { this // expect error } diff --git a/test/language/variable/local_collide_with_function_parameter.wren b/test/language/variable/local_collide_with_function_parameter.wren index 2e64a589..c267a077 100644 --- a/test/language/variable/local_collide_with_function_parameter.wren +++ b/test/language/variable/local_collide_with_function_parameter.wren @@ -1,3 +1,3 @@ -new Fn {|a| +Fn.new {|a| var a = "oops" // expect error } diff --git a/test/language/variable/local_in_middle_of_block.wren b/test/language/variable/local_in_middle_of_block.wren index 803bdcd4..a0f1c819 100644 --- a/test/language/variable/local_in_middle_of_block.wren +++ b/test/language/variable/local_in_middle_of_block.wren @@ -11,4 +11,4 @@ class Foo { } } -(new Foo).bar \ No newline at end of file +Foo.new().bar \ No newline at end of file diff --git a/test/language/variable/outside_method.wren b/test/language/variable/outside_method.wren index 8cb93647..19a77919 100644 --- a/test/language/variable/outside_method.wren +++ b/test/language/variable/outside_method.wren @@ -14,5 +14,5 @@ class Foo { } } -(new Foo).method // expect: method +Foo.new().method // expect: method Foo.classMethod // expect: class method diff --git a/test/language/variable/undefined_local.wren b/test/language/variable/undefined_local.wren index 43933426..a9592bef 100644 --- a/test/language/variable/undefined_local.wren +++ b/test/language/variable/undefined_local.wren @@ -1,3 +1,3 @@ -new Fn { +Fn.new { IO.print(notDefined) // expect error }.call() diff --git a/test/language/while/closure_in_body.wren b/test/language/while/closure_in_body.wren index 61a89932..adc0cf57 100644 --- a/test/language/while/closure_in_body.wren +++ b/test/language/while/closure_in_body.wren @@ -3,7 +3,7 @@ var list = [] var i = 1 while (i < 4) { var j = i + 1 - list.add(new Fn { IO.print(j) }) + list.add(Fn.new { IO.print(j) }) i = i + 1 } diff --git a/test/language/while/return_closure.wren b/test/language/while/return_closure.wren index 82f7007f..89859339 100644 --- a/test/language/while/return_closure.wren +++ b/test/language/while/return_closure.wren @@ -1,7 +1,7 @@ -var f = new Fn { +var f = Fn.new { while (true) { var i = "i" - return new Fn { IO.print(i) } + return Fn.new { IO.print(i) } } } diff --git a/test/language/while/return_inside.wren b/test/language/while/return_inside.wren index 6b9444db..33ec8887 100644 --- a/test/language/while/return_inside.wren +++ b/test/language/while/return_inside.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { while (true) { var i = "i" return i diff --git a/test/limit/long_function.wren b/test/limit/long_function.wren index 3e08015c..61e97836 100644 --- a/test/limit/long_function.wren +++ b/test/limit/long_function.wren @@ -1,4 +1,4 @@ -new Fn { +Fn.new { IO.print(1) // expect: 1 IO.print(2) // expect: 2 IO.print(3) // expect: 3 diff --git a/test/limit/many_constants.wren b/test/limit/many_constants.wren index f7a813a2..6328799c 100644 --- a/test/limit/many_constants.wren +++ b/test/limit/many_constants.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { 1 2 3 diff --git a/test/limit/many_fields.wren b/test/limit/many_fields.wren index f6d47963..a9067663 100644 --- a/test/limit/many_fields.wren +++ b/test/limit/many_fields.wren @@ -1,5 +1,5 @@ class Foo { - new { + this new() { _field1 = 1 _field2 = 2 _field3 = 3 @@ -259,4 +259,4 @@ class Foo { } } -var foo = new Foo // expect: 255 +var foo = Foo.new() // expect: 255 diff --git a/test/limit/many_inherited_fields.wren b/test/limit/many_inherited_fields.wren index 97be268a..f5b668fb 100644 --- a/test/limit/many_inherited_fields.wren +++ b/test/limit/many_inherited_fields.wren @@ -1,5 +1,5 @@ class Foo { - new { + this new() { _field1 = 1 _field2 = 2 _field3 = 3 @@ -137,8 +137,8 @@ class Foo { } class Bar is Foo { - new { - super + this new() { + super() _field129 = 129 _field130 = 130 _field131 = 131 @@ -274,7 +274,7 @@ class Bar is Foo { } } -var bar = new Bar +var bar = Bar.new() bar.foo // expect: 1 // expect: 128 bar.bar // expect: 129 diff --git a/test/limit/too_many_constants.wren b/test/limit/too_many_constants.wren index 5807cb6c..9bdf97f5 100644 --- a/test/limit/too_many_constants.wren +++ b/test/limit/too_many_constants.wren @@ -1,4 +1,4 @@ -var f = new Fn { +var f = Fn.new { 1 2 3 diff --git a/test/limit/too_many_fields.wren b/test/limit/too_many_fields.wren index f60e9fe1..12774ed0 100644 --- a/test/limit/too_many_fields.wren +++ b/test/limit/too_many_fields.wren @@ -1,5 +1,5 @@ class Foo { - new { + this new() { _field1 = 1 _field2 = 2 _field3 = 3 @@ -259,4 +259,4 @@ class Foo { } } -var foo = new Foo +var foo = Foo.new() diff --git a/test/limit/too_many_inherited_fields.wren b/test/limit/too_many_inherited_fields.wren index cb8f5031..067d8d35 100644 --- a/test/limit/too_many_inherited_fields.wren +++ b/test/limit/too_many_inherited_fields.wren @@ -1,5 +1,5 @@ class Foo { - new { + this new() { _field1 = 1 _field2 = 2 _field3 = 3 @@ -137,8 +137,8 @@ class Foo { } class Bar is Foo { // expect runtime error: Class 'Bar' may not have more than 255 fields, including inherited ones. - new { - super + this new() { + super() _field129 = 129 _field130 = 130 _field131 = 131 @@ -275,6 +275,6 @@ class Bar is Foo { // expect runtime error: Class 'Bar' may not have more than 2 } } -var bar = new Bar +var bar = Bar.new() bar.foo bar.bar