Merge: New constructors
authorJean Privat <jean@pryen.org>
Tue, 26 Aug 2014 00:55:47 +0000 (20:55 -0400)
committerJean Privat <jean@pryen.org>
Tue, 26 Aug 2014 00:55:47 +0000 (20:55 -0400)
commit9d4906d5c4132a8bde55f12fe534a03cc57e63bc
tree96dcc5d7e4e8c3f192092fce23083ac687519ef0
parent2daff6accf3f01c8246b6ec6de61870420628faf
parent4c0f8c01e4454dd0e917b9cdda1cb7d88f93dc43
Merge: New constructors

A very long development for a very important but experimental feature: the new-style constructors.

Most of the cleaning and other stuff was committed under interdependent PR.
So what remain here is the hardcore fundamental stuff.

I didn't find a simple way to have nice commits. So I went for some kind of incremental features.

## First commit

It is the worse since it introduces the new-style constructors in the model, semantic analysis and engines.

With the new-style constructors, the point is to understand that the syntax `var a = new A(some_b)` is in fact the following sequence

~~~
var a = ALLOC_INSTANCE(A)
a.b=(some_b)
a.init()
~~~

Where the `a.b=` part is a standard method call for the accessor `b=`.
Therefore, each constructor has a sequence of methods to call, they are called `initializers`.
Since redefinitions of constructor can provide different initializers, the initializers are attached to the MMethodDef class.

Because of this, a MMethodDef for a new-style constructor has two signatures, the real empty msigntature seen by the programmer that implements the constructor, and the one seen by the programmer that uses it to instantiate objects trough `new`, so called `new_msignature`.

~~~
class A
  var b: B
  # here, an implicit init, with, by rule of inheritance, the empty signature
end
var a = new A(some_b) # here the `new` takes a single B
~~~

Note that the `new_msignature` has to be conform with the `inititializers` since the arguments of the `new` are used for the invocations of the inititializers.

Modules `modelize_property` (and `auto_super_init` in a lesser extend) is modified to use new-style constructors for the default/automatic/free/implicit constructors.
Explicit constructors (named or not) use the old-style-constructors.
The code in these two modules is quite complex because it has to deal with the various implicit combinations of the old-style and new-style constructors.

For the engines (and rta), modifications are made to handle correctly the implementations of:

1. the invocation of the new-style constructors. by invoking each initializer, and
2. the implicit body of the new-style default/automatic/free/implicit constructors; they do just a call to super since the initializations of the attributes is done outside the init: in the sequence code of the new.

While user-defined constructor is not present in this commit, all the implicit init are converted.
The boostrap still works, and most tests pass.

## Second commit

Just introduce (and use) the annotation `old_style_init` that is used to mark explicit constructors to use the old semantic (and implementation).
The annotation can be put on a single `init`, or on the whole module.

## Third commit

'simple' `init` are those defined without name nor parameters (and that are public).
They are converted to the new-style constructors.
This is just magic because things, like the boostrap and most tests, still work as expected.

Now, programmers can use the default init and get the initializers automatically called.
Basically, instead of writing

~~~
class A
  var b: B
  init(b: B)
  do
    self.b = b
    rest_of_init
  end
end
var a = new A(some_b)
~~~

just write

~~~
class A
  var b: B
  init
  do
    rest_of_init
  end
end
var a = new A(some_b) # Same client, but less code in the A class
~~~

And simple subclasses get easier

~~~
class SubA
  super A
  var c: C
  init
  do
    some_other_stuff
  end
end
var sa = new SubA(some_b, some_c)
# Done in order:
# 1. set b
# 2. set c
# 3. rest_of_init
# 4. some_other_stuff
~~~

## Fourth commit

Update existing tests.

## Last commit

add a new test that illustrates combination and the linearization of the simple init

## What is next?

### User-definer initializers

Conflict on initializers are detected, but currently there is no simple way for the used to define its own sequence of initializers.

* what syntax to use? something like `init is initializers(a,b,c) do ...`?
* what rules? are any sequence allowed?

### Not-simple constructors

The status of the constructors that remains is still unclear.

* named constructors are the simpler case since the proposed specification want to have them working like standard method but usable with a new. In fact, they will behave as a simple version of the old-style-constructors, with less shenanigans.
* init with parameters, still accepted for compatibility but they should be migrated. If not migratable, more investigation and thinking will be required
* private init. Since the root `init` of Object is public, subclasses cannot change its visibility. So how to indicate that a class cannot be instantiated publicly? Again, more investigation and thinking.

Pull-Request: #679
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>