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:
Bob Nystrom
2013-12-19 15:02:27 +00:00
parent f5a61e4241
commit 0e70d98169
30 changed files with 171 additions and 190 deletions
+3 -1
View File
@@ -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
+1 -1
View File
@@ -8,7 +8,7 @@ var foo = null
}
}
foo = Foo.new
foo = new Foo
}
foo.method // expect: local
+1 -1
View File
@@ -6,5 +6,5 @@
}
}
Foo.new.method // expect: local
(new Foo).method // expect: local
}
+1 -1
View File
@@ -11,5 +11,5 @@ class Foo {
}
}
Foo.new.method // expect: global
(new Foo).method // expect: global
Foo.classMethod // expect: global
+1 -1
View File
@@ -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
-20
View File
@@ -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
+7 -8
View File
@@ -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
+12 -10
View File
@@ -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
+1 -1
View File
@@ -2,4 +2,4 @@ class Foo {
write { io.write(_field) }
}
Foo.new.write // expect: null
(new Foo).write // expect: null
+1 -1
View File
@@ -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
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -4,4 +4,4 @@ class Foo {
}
}
io.write(Foo.new.thisHasAMethodNameThatIsExactly64CharactersLongWhichIsTheMaximum) // expect: result
io.write((new Foo).thisHasAMethodNameThatIsExactly64CharactersLongWhichIsTheMaximum) // expect: result
+1 -1
View File
@@ -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
+4 -5
View File
@@ -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
+1 -1
View File
@@ -11,7 +11,7 @@ class Derived is Base {
}
}
Derived.new.bar
(new Derived).bar
// expect: Derived.bar
// expect: Base.foo
+1 -1
View File
@@ -11,6 +11,6 @@ class Derived is Base {
}
}
Derived.new.foo
(new Derived).foo
// expect: Derived.foo
// expect: Base.foo
+1 -1
View File
@@ -13,6 +13,6 @@ class C is B {
}
}
C.new.foo
(new C).foo
// expect: C.foo
// expect: A.foo
+1 -1
View File
@@ -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
+1 -1
View File
@@ -11,4 +11,4 @@ class Foo {
}
}
Foo.new.bar
(new Foo).bar