I reworked the constructor syntax/semantics and updated the test suite. From the Fan perspective there are three basic method types: constructors, statics, and instance methods. Instance and static methods are just like Java - instance methods have an implicit this as arg0 and static methods don't. Constructors are really a combination of both: from inside the constructor it looks like an instance method with an implicit this and a void return type. From outside the constructor at the call site it looks like a static method with no implicit this and it returns an instance of the declaring class. The new operator effectively ceases to exist and becomes a method modifier. Constructors cannot declare a return type, but are named like normal methods with no overloading supported. Simple example in Fan:
class Foo
{
new make(Int x) { this.x = x }
Int x
Int y := 3
static Int z := 4
static Foo f() { return make(2) }
}
This example shows both instance and static field initialization, a constructor called "make", and a constructor call inside the "f" method". Note that we don't need to scope make since it defaults to class scope just like a static method. The fcode generated:
As you can see a constructor looks like an instance method with the exception that it is marked with the "new" flag. The constructor call site in f() uses the CallNew opcode. Also note that an fcode file can contain two special methods both called "new". If the static flag is set it is called a staticNew block and contains the static initializer code. If the static flag is clear, then it is an instanceNew block and contains the initializer code to run on every new instance. Note this is different than Java where it inlines the instance init code into each constructor.
The Java code always creates one no-arg constructor which runs the instanceNew block (if available). Then for each constructor it generates a static factory method and a static constructor method. The above code would generate something like:
class Foo
{
// factory target for CallNew
static Foo make(Int x)
{
Foo self = new Foo();
make(self);
return self;
}
// implementation of fcode
static void make(Foo self, Int x)
{
self.x = x
}
// instanceNew inserted into <init>
Foo() { this.y = 3; }
// staticNew inserted into <clint>
static { z = 4; }
Int x, y;
static Int z := 4
static Foo f() { return make(2) }
}
Anyways, I'm pretty pleased with the design. I really like how constructors are more like a hybrid static/instance method. A couple of issues which need to be addressed:
1) If you don't provide a constructor, I auto-generate one for you
called "make" - although if you have another slot called "make",
then it is a compile time error.
2) What should the rule be for automatically and explicitly calling
your super class constructors? It is inverse of Java - we can have
many no arg constructors with different names. Do we match on name?
Just force it to be explicit all the time (that's my leaning)?
3) What syntax should we use for calling super constructor - did we agree
on the "super" keyword? If not scoped with a name, then it defaults to
use name of declaring method.
4) Andy and I debated on the new keyword versus using it as the standard
name of the method (and using ctor as the keyword). The big thing against
this was that new is a Java/C# keyword and wouldn't be easily callable.
Any more thoughts on this?
brian Sat 31 Dec 2005
I reworked the constructor syntax/semantics and updated the test suite. From the Fan perspective there are three basic method types: constructors, statics, and instance methods. Instance and static methods are just like Java - instance methods have an implicit this as arg0 and static methods don't. Constructors are really a combination of both: from inside the constructor it looks like an instance method with an implicit this and a void return type. From outside the constructor at the call site it looks like a static method with no implicit this and it returns an instance of the declaring class. The new operator effectively ceases to exist and becomes a method modifier. Constructors cannot declare a return type, but are named like normal methods with no overloading supported. Simple example in Fan:
This example shows both instance and static field initialization, a constructor called "make", and a constructor call inside the "f" method". Note that we don't need to scope make since it defaults to class scope just like a static method. The fcode generated:
As you can see a constructor looks like an instance method with the exception that it is marked with the "new" flag. The constructor call site in f() uses the CallNew opcode. Also note that an fcode file can contain two special methods both called "new". If the static flag is set it is called a staticNew block and contains the static initializer code. If the static flag is clear, then it is an instanceNew block and contains the initializer code to run on every new instance. Note this is different than Java where it inlines the instance init code into each constructor.
The Java code always creates one no-arg constructor which runs the instanceNew block (if available). Then for each constructor it generates a static factory method and a static constructor method. The above code would generate something like:
Anyways, I'm pretty pleased with the design. I really like how constructors are more like a hybrid static/instance method. A couple of issues which need to be addressed:
1) If you don't provide a constructor, I auto-generate one for you
2) What should the rule be for automatically and explicitly calling
3) What syntax should we use for calling super constructor - did we agree
4) Andy and I debated on the new keyword versus using it as the standard