refactor: replace Foo.new constructor syntax with new Foo and simplify superclass constructor calls
Remove the `this new` constructor declaration syntax in favor of a `new` keyword that creates instances directly. Superclass constructors are now invoked via bare `super(args)` instead of `super.new(args)`, eliminating the semantic weirdness of calling a constructor on a partially-constructed instance. Update the compiler to treat `new` as a keyword token, replace the `isMethod` flag with `methodName`/`methodLength` fields, and change the VM's `NEW` opcode to pop the class from the stack before creating the instance. Add a default `new` native method on Object that returns `this`. Update all benchmarks and tests to use the new syntax.
This commit is contained in:
+3
-1
@@ -1,4 +1,6 @@
|
||||
class Foo {}
|
||||
|
||||
var foo = Foo.new
|
||||
var foo = new Foo
|
||||
io.write(foo is Foo) // expect: true
|
||||
|
||||
// TODO: Test precedence and grammar of what follows "new".
|
||||
|
||||
@@ -8,5 +8,5 @@ class Foo {
|
||||
}
|
||||
}
|
||||
|
||||
Foo.new.method("param")
|
||||
(new Foo).method("param")
|
||||
f.call // expect: param
|
||||
|
||||
@@ -8,7 +8,7 @@ var foo = null
|
||||
}
|
||||
}
|
||||
|
||||
foo = Foo.new
|
||||
foo = new Foo
|
||||
}
|
||||
|
||||
foo.method // expect: local
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
}
|
||||
}
|
||||
|
||||
Foo.new.method // expect: local
|
||||
(new Foo).method // expect: local
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@ class Foo {
|
||||
}
|
||||
}
|
||||
|
||||
Foo.new.method // expect: global
|
||||
(new Foo).method // expect: global
|
||||
Foo.classMethod // expect: global
|
||||
|
||||
@@ -3,7 +3,7 @@ class Foo {
|
||||
}
|
||||
|
||||
// A class with no constructors gets an argument-less "new" one by default.
|
||||
var foo = Foo.new
|
||||
var foo = new Foo
|
||||
io.write(foo is Foo) // expect: true
|
||||
io.write(foo.toString) // expect: Foo
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
class Foo {
|
||||
this bar { io.write("this bar") }
|
||||
this baz { io.write("this baz") }
|
||||
this bar(arg) { io.write("this bar " + arg) }
|
||||
|
||||
toString { return "Foo" }
|
||||
}
|
||||
|
||||
// Different names.
|
||||
Foo.bar // expect: this bar
|
||||
Foo.baz // expect: this baz
|
||||
|
||||
// Can overload by arity.
|
||||
Foo.bar // expect: this bar
|
||||
Foo.bar("one") // expect: this bar one
|
||||
|
||||
// Returns the new instance.
|
||||
var foo = Foo.bar // expect: this bar
|
||||
io.write(foo is Foo) // expect: true
|
||||
io.write(foo.toString) // expect: Foo
|
||||
@@ -1,18 +1,17 @@
|
||||
class Foo {
|
||||
// TODO: Do we want to require an explicit "new" here?
|
||||
this new { io.write("zero") }
|
||||
this new(a) { io.write(a) }
|
||||
this new(a, b) { io.write(a + b) }
|
||||
new { io.write("zero") }
|
||||
new(a) { io.write(a) }
|
||||
new(a, b) { io.write(a + b) }
|
||||
|
||||
toString { return "Foo" }
|
||||
}
|
||||
|
||||
// Can overload by arity.
|
||||
Foo.new // expect: zero
|
||||
Foo.new("one") // expect: one
|
||||
Foo.new("one", "two") // expect: onetwo
|
||||
new Foo // expect: zero
|
||||
new Foo("one") // expect: one
|
||||
new Foo("one", "two") // expect: onetwo
|
||||
|
||||
// Returns the new instance.
|
||||
var foo = Foo.new // expect: zero
|
||||
var foo = new Foo // expect: zero
|
||||
io.write(foo is Foo) // expect: true
|
||||
io.write(foo.toString) // expect: Foo
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class A {
|
||||
this new(arg) {
|
||||
io.write("A.new " + arg)
|
||||
new(arg) {
|
||||
io.write("new A " + arg)
|
||||
_field = arg
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ class A {
|
||||
}
|
||||
|
||||
class B is A {
|
||||
this otherName(arg1, arg2) super.new(arg2) {
|
||||
io.write("B.otherName " + arg1)
|
||||
new(arg1, arg2) {
|
||||
super(arg2)
|
||||
io.write("new B " + arg1)
|
||||
_field = arg1
|
||||
}
|
||||
|
||||
@@ -17,18 +18,19 @@ class B is A {
|
||||
}
|
||||
|
||||
class C is B {
|
||||
this create super.otherName("one", "two") {
|
||||
io.write("C.create")
|
||||
new {
|
||||
super("one", "two")
|
||||
io.write("new C")
|
||||
_field = "c"
|
||||
}
|
||||
|
||||
cField { return _field }
|
||||
}
|
||||
|
||||
var c = C.create
|
||||
// expect: A.new two
|
||||
// expect: B.otherName one
|
||||
// expect: C.create
|
||||
var c = new C
|
||||
// expect: new A two
|
||||
// expect: new B one
|
||||
// expect: new C
|
||||
io.write(c is A) // expect: true
|
||||
io.write(c is B) // expect: true
|
||||
io.write(c is C) // expect: true
|
||||
|
||||
@@ -2,4 +2,4 @@ class Foo {
|
||||
write { io.write(_field) }
|
||||
}
|
||||
|
||||
Foo.new.write // expect: null
|
||||
(new Foo).write // expect: null
|
||||
|
||||
@@ -15,7 +15,7 @@ class Foo {
|
||||
}
|
||||
}
|
||||
|
||||
var foo = Foo.new
|
||||
var foo = new Foo
|
||||
foo.set(1, 2, 3, 4, 5)
|
||||
foo.write
|
||||
// expect: 1
|
||||
|
||||
@@ -19,15 +19,15 @@ class Node {
|
||||
}
|
||||
}
|
||||
|
||||
var a = Node.new
|
||||
var a = new Node
|
||||
a.set(null, "a", null)
|
||||
var b = Node.new
|
||||
var b = new Node
|
||||
b.set(null, "b", null)
|
||||
var c = Node.new
|
||||
var c = new Node
|
||||
c.set(a, "c", b)
|
||||
a = null
|
||||
b = null
|
||||
var d = Node.new
|
||||
var d = new Node
|
||||
d.set(c, "d", null)
|
||||
c = null
|
||||
d.write
|
||||
|
||||
@@ -3,7 +3,7 @@ class Foo {
|
||||
init { _field = "value" } // ...before an assignment to it.
|
||||
}
|
||||
|
||||
var foo = Foo.new
|
||||
var foo = new Foo
|
||||
// But invoke them in the right order.
|
||||
foo.init
|
||||
foo.write // expect: value
|
||||
|
||||
@@ -22,7 +22,7 @@ class Bar is Foo {
|
||||
}
|
||||
}
|
||||
|
||||
var bar = Bar.new
|
||||
var bar = new Bar
|
||||
bar.foo("foo 1", "foo 2")
|
||||
bar.bar("bar 1", "bar 2")
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class Bar is Foo {
|
||||
override { io.write("bar") }
|
||||
}
|
||||
|
||||
var bar = Bar.new
|
||||
var bar = new Bar
|
||||
bar.methodOnFoo // expect: foo
|
||||
bar.methodOnBar // expect: bar
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
class A {}
|
||||
class B is A {}
|
||||
class C is B {}
|
||||
var a = A.new
|
||||
var b = B.new
|
||||
var c = C.new
|
||||
var a = new A
|
||||
var b = new B
|
||||
var c = new C
|
||||
|
||||
io.write(a is A) // expect: true
|
||||
io.write(a is B) // expect: false
|
||||
|
||||
@@ -18,7 +18,7 @@ class Foo {
|
||||
method(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) { return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p}
|
||||
}
|
||||
|
||||
var foo = Foo.new
|
||||
var foo = new Foo
|
||||
io.write(foo.method) // expect: 0
|
||||
io.write(foo.method(1)) // expect: 1
|
||||
io.write(foo.method(1, 2)) // expect: 3
|
||||
|
||||
@@ -4,4 +4,4 @@ class Foo {
|
||||
}
|
||||
}
|
||||
|
||||
io.write(Foo.new.thisHasAMethodNameThatIsExactly64CharactersLongWhichIsTheMaximum) // expect: result
|
||||
io.write((new Foo).thisHasAMethodNameThatIsExactly64CharactersLongWhichIsTheMaximum) // expect: result
|
||||
|
||||
@@ -15,7 +15,7 @@ class Foo {
|
||||
- { return "prefix -" }
|
||||
}
|
||||
|
||||
var foo = Foo.new
|
||||
var foo = new Foo
|
||||
io.write(foo + "a") // expect: infix + a
|
||||
io.write(foo - "a") // expect: infix - a
|
||||
io.write(foo * "a") // expect: infix * a
|
||||
|
||||
@@ -6,8 +6,7 @@ class Foo {
|
||||
static bar(arg) { return "on metaclass " + arg }
|
||||
}
|
||||
|
||||
io.write("on metaclass " + "arg") // expect: on metaclass arg
|
||||
io.write(Foo.new.bar) // expect: on instance
|
||||
io.write(Foo.bar) // expect: on metaclass
|
||||
io.write(Foo.new.bar("arg")) // expect: on instance arg
|
||||
io.write(Foo.bar("arg")) // expect: on metaclass arg
|
||||
io.write((new Foo).bar) // expect: on instance
|
||||
io.write(Foo.bar) // expect: on metaclass
|
||||
io.write((new Foo).bar("arg")) // expect: on instance arg
|
||||
io.write(Foo.bar("arg")) // expect: on metaclass arg
|
||||
|
||||
@@ -11,7 +11,7 @@ class Derived is Base {
|
||||
}
|
||||
}
|
||||
|
||||
Derived.new.bar
|
||||
(new Derived).bar
|
||||
// expect: Derived.bar
|
||||
// expect: Base.foo
|
||||
|
||||
|
||||
@@ -11,6 +11,6 @@ class Derived is Base {
|
||||
}
|
||||
}
|
||||
|
||||
Derived.new.foo
|
||||
(new Derived).foo
|
||||
// expect: Derived.foo
|
||||
// expect: Base.foo
|
||||
|
||||
@@ -13,6 +13,6 @@ class C is B {
|
||||
}
|
||||
}
|
||||
|
||||
C.new.foo
|
||||
(new C).foo
|
||||
// expect: C.foo
|
||||
// expect: A.foo
|
||||
|
||||
@@ -3,4 +3,4 @@ class Foo {
|
||||
baz { return "baz" }
|
||||
}
|
||||
|
||||
io.write(Foo.new.bar.baz) // expect: baz
|
||||
io.write((new Foo).bar.baz) // expect: baz
|
||||
|
||||
@@ -11,4 +11,4 @@ class Foo {
|
||||
}
|
||||
}
|
||||
|
||||
Foo.new.bar
|
||||
(new Foo).bar
|
||||
Reference in New Issue
Block a user