Automatic constructors.
authorJean Privat <jean@pryen.org>
Sat, 27 Dec 2008 18:43:26 +0000 (13:43 -0500)
committerJean Privat <jean@pryen.org>
Sat, 27 Dec 2008 18:43:26 +0000 (13:43 -0500)
Automatic constructors are implicit anonymous init that collects unassigned
attributes in their signatures.

src/compiling/compiling_methods.nit
src/syntax/mmbuilder.nit
src/syntax/syntax_base.nit

index ea4414f..57c8fd5 100644 (file)
@@ -373,6 +373,33 @@ redef class MMMethSrcMethod
        end
 end
 
+redef class MMImplicitInit
+       redef meth do_compile_inside(v, params)
+       do
+               var f = params.length - unassigned_attributes.length
+               var recv = params.first
+               for sp in super_inits do
+                       assert sp isa MMMethod
+                       var args_recv = [recv]
+                       if sp == super_init then
+                               var args = new Array[String].with_capacity(f)
+                               args.add(recv)
+                               for i in [1..f[ do
+                                       args.add(params[i])
+                               end
+                               sp.compile_call(v, args)
+                       else
+                               sp.compile_call(v, args_recv)
+                       end
+               end
+               for i in [f..params.length[ do
+                       var attribute = unassigned_attributes[i-f]
+                       v.add_assignment(attribute.compile_access(v, recv), params[i])
+               end
+               return null
+       end
+end
+
 redef class MMType
        # Compile a subtype check to self
        # Return a NIT Bool
index 3a16ada..4bd9af5 100644 (file)
@@ -168,6 +168,7 @@ redef class MMSrcLocalClass
                end
 
                # Collect visible constructors in super stateful classes
+               var super_inits = new ArraySet[MMLocalProperty]
                var super_constructors = new ArraySet[MMGlobalProperty]
                for sc in che.direct_greaters do
                        if sc.global.is_universal or sc.global.is_interface then continue
@@ -175,6 +176,20 @@ redef class MMSrcLocalClass
                                if not gp.is_init then continue
                                super_constructors.add(gp)
                        end
+                       var gp = sc.get_property_by_name(once ("init".to_symbol))
+                       if gp != null then
+                               super_inits.add(self[gp])
+                       end
+               end
+
+               # Collect unassigned attributes
+               var unassigned_attributes = new Array[MMSrcAttribute]
+               for a in src_local_properties do
+                       if a isa MMSrcAttribute then
+                               var n = a.node
+                               assert n isa AAttrPropdef
+                               if n.n_expr == null then unassigned_attributes.add(a)
+                       end
                end
 
                if not super_constructors.is_empty then
@@ -208,6 +223,13 @@ redef class MMSrcLocalClass
                                end
                        end
                        _is_mixin = true
+               else
+                       # v.error(nodes.first, "Error, constructor required in {self} since no anonimous init found in {sc}.")
+
+                       # unassigned attributes, then implicit consructors are generated
+                       var p = new MMImplicitInit(self, unassigned_attributes, super_inits.to_a)
+                       add_src_local_property(v, p)
+                       #print("Create implicit init {p} in {self} from {super_inits.join(", ")} + {unassigned_attributes.length} args")
                end
        end
 
@@ -245,6 +267,39 @@ redef class MMLocalProperty
        do
        end
 end
+
+redef class MMImplicitInit
+       readable attr _super_init: MMLocalProperty = null
+       redef meth accept_property_visitor(v)
+       do
+               var base: MMLocalProperty = null
+               for p in super_inits do
+                       if p.signature.arity > 0 then
+                               if base == null then
+                                       base = p
+                               else
+                                       v.error(null, "Error: explicit constructor needed in {local_class} since both super-constructor {base.full_name} and {p.full_name} have paramters")
+                                       return
+                               end
+                       end
+               end
+               _super_init = base
+
+               var params = new Array[MMType]
+               if base != null then
+                       var sig = base.signature
+                       for i in [0..sig.arity[ do
+                               params.add(sig[i])
+                       end
+               end
+               for a in unassigned_attributes do
+                       params.add(a.signature.return_type)
+               end
+               signature = new MMSignature(params, null, local_class.get_type)
+       end
+end
+
+
 # Concrete NIT class specialization relation
 class MMSrcAncestor
 special MMAncestor
index 7d22308..d6ebe97 100644 (file)
@@ -176,6 +176,19 @@ special MMTypeProperty
        end
 end
 
+# Concrete NIT implicit constructor
+class MMImplicitInit
+special MMMethSrcMethod
+       redef meth is_init do return true
+       readable attr _unassigned_attributes: Array[MMSrcAttribute]
+       readable attr _super_inits: Array[MMLocalProperty]
+       init(cla: MMLocalClass, unassigned_attributes: Array[MMSrcAttribute], super_inits: Array[MMLocalProperty])
+       do
+               super(once "init".to_symbol, cla, null)
+               _unassigned_attributes = unassigned_attributes
+               _super_inits = super_inits
+       end
+end
 
 # Local variable and method parameter
 class Variable