Make constructors just methods.

* Eliminate "new" reserved word.
* Allow "this" before a method definition to define a constructor.
* Only create a default constructor for classes that don't define one.
This commit is contained in:
Bob Nystrom
2015-07-10 09:18:22 -07:00
parent 0ddaa2517c
commit 5fb6186d7d
221 changed files with 864 additions and 654 deletions
@@ -0,0 +1,5 @@
class Foo {
this +(value) { // expect error
IO.print("ok")
}
}
@@ -0,0 +1,5 @@
class Foo {
this -(value) { // expect error
IO.print("ok")
}
}
@@ -0,0 +1,5 @@
class Foo {
this name=(value) { // expect error
IO.print("ok")
}
}
@@ -0,0 +1,4 @@
class Foo {
static this new() {} // expect error
this static new() {} // expect error
}
@@ -0,0 +1,5 @@
class Foo {
this [value] { // expect error
IO.print("ok")
}
}
@@ -0,0 +1,5 @@
class Foo {
this ! { // expect error
IO.print("ok")
}
}
@@ -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()'.
+2 -2
View File
@@ -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
@@ -0,0 +1,9 @@
class Foo {
this new() {
IO.print("Foo.new()")
}
}
class Bar is Foo {}
Bar.new() // expect: Foo.new()
@@ -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.
+16
View File
@@ -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
-19
View File
@@ -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
@@ -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()'.
@@ -0,0 +1,5 @@
class Foo {
this new { // expect error
IO.print("ok")
}
}
@@ -0,0 +1,7 @@
class Foo {
this base() {}
}
class Bar is Foo {}
Bar.base() // expect runtime error: Bar metaclass does not implement 'base()'.
+13
View File
@@ -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.
@@ -0,0 +1,7 @@
class A {}
class B is A {
this new() {
super // expect error
}
}
+4 -4
View File
@@ -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