ni_nitdoc: added fast copy past utility to signatures.
[nit.git] / src / program.nit
index 6952c42..728b7ce 100644 (file)
@@ -19,7 +19,7 @@ package program
 
 import metamodel
 import icode
-import primitive_info
+private import primitive_info
 import mmloader
 
 redef class ToolContext
@@ -39,7 +39,7 @@ class Program
        readable var _tc: ToolContext
 
        # This module is the 'main' module, the one where we find the 'main' method
-       readable var _module: MMModule
+       readable var _main_module: MMModule
 
        # This method is the entry point of this program
        # There might be no entry point (if in fact we are compiling a library)
@@ -49,15 +49,25 @@ class Program
        # Would be null if there is no main method
        readable var _main_class: nullable MMLocalClass = null
 
-       # When we are using global compilation, we generate _glob files instead
-       # of _sep files so that we do not corrupt separate compilation
-       fun get_file_ending: String do return if tc.global then "_glob" else "_sep"
+       # This method will ensure that all the metamodel is computed before we
+       # start using all the classes
+       private fun finish_processing_classes do
+               var classes = new Array[MMLocalClass]
+               for c in main_module.local_classes do
+                       c.compute_super_classes
+                       classes.add(c)
+               end
+
+               for c in classes do
+                       c.compute_ancestors
+               end
+       end
 
        fun compute_main_method do
                # Check for the 'Sys' class
                var sysname = once "Sys".to_symbol
-               if not module.has_global_class_named(sysname) then return
-               var sys = module.class_by_name(sysname)
+               if not main_module.has_global_class_named(sysname) then return
+               var sys = main_module.class_by_name(sysname)
 
                # Check for 'Sys::main' method
                var entryname = once "main".to_symbol
@@ -70,7 +80,8 @@ class Program
        # Generation of allocation function of this class
        fun generate_allocation_iroutines
        do
-               for c in module.local_classes do
+               for c in main_module.local_classes do
+                       if c.global.is_abstract or c.global.is_interface then continue
                        var pi = c.primitive_info
                        if pi == null then
                                do
@@ -78,17 +89,21 @@ class Program
                                        var iself = new IRegister(c.get_type)
                                        var iselfa = [iself]
                                        var iroutine = new IRoutine(iselfa, null)
-                                       var icb = new ICodeBuilder(module, iroutine)
-
-                                       for g in c.global_properties do
-                                               var p = c[g]
-                                               var t = p.signature.return_type
-                                               if p isa MMAttribute and t != null then
-                                                       var ir = p.iroutine
-                                                       if ir == null then continue
-                                                       # FIXME: Not compatible with sep compilation
-                                                       var e = icb.inline_routine(ir, iselfa, null).as(not null)
-                                                       icb.stmt(new IAttrWrite(p, iself, e))
+                                       var icb = new ICodeBuilder(main_module, iroutine)
+
+                                       for sc in c.che.linear_extension.reversed do
+                                               for g in sc.global_properties do
+                                                       if g.local_class != sc then continue
+                                                       if not g.intro isa MMAttribute then continue
+                                                       var p = c[g]
+                                                       var t = p.signature.return_type
+                                                       if p isa MMAttribute and t != null then
+                                                               var ir = p.iroutine
+                                                               if ir == null then continue
+                                                               # FIXME: Not compatible with sep compilation
+                                                               var e = icb.inline_routine(ir, iselfa, null).as(not null)
+                                                               icb.stmt(new IAttrWrite(p, iself, e))
+                                                       end
                                                end
                                        end
 
@@ -99,8 +114,9 @@ class Program
                                        var iself = new IRegister(c.get_type)
                                        var iselfa = [iself]
                                        var iroutine = new IRoutine(iselfa, null)
-                                       var icb = new ICodeBuilder(module, iroutine)
+                                       var icb = new ICodeBuilder(main_module, iroutine)
                                        for g in c.global_properties do
+                                               if not g.intro isa MMAttribute then continue
                                                var p = c[g]
                                                var t = p.signature.return_type
                                                if p isa MMAttribute and t != null and not t.is_nullable then
@@ -112,9 +128,9 @@ class Program
                                end
 
                                for g in c.global_properties do
-                                       var p = c[g]
                                        # FIXME skip invisible constructors
-                                       if not p.global.is_init_for(c) then continue
+                                       if not g.is_init_for(c) then continue
+                                       var p = c[g]
                                        assert p isa MMMethod
 
                                        var iself = new IRegister(c.get_type)
@@ -122,7 +138,7 @@ class Program
                                        for i in [0..p.signature.arity[ do iparams.add(new IRegister(p.signature[i]))
                                        var iroutine = new IRoutine(iparams, iself)
                                        iroutine.location = p.iroutine.location
-                                       var icb = new ICodeBuilder(module, iroutine)
+                                       var icb = new ICodeBuilder(main_module, iroutine)
 
                                        var inew = new IAllocateInstance(c.get_type)
                                        inew.result = iself
@@ -140,9 +156,73 @@ class Program
                end
        end
 
+       # This function will call the attached block for each IRoutines
+       # in this program
+       fun with_each_iroutines
+               !action(i: IRoutine, m: MMModule)
+       do
+               for m in main_module.mhe.greaters_and_self do
+                       for c in m.local_classes do
+                               var iroutine: nullable IRoutine = null
+
+                               # Process methods and attributes initialization
+                               for p in c.local_local_properties do
+                                       if p isa MMAttribute then
+                                               iroutine = p.iroutine
+                                       else if p isa MMMethod then
+                                               iroutine = p.iroutine
+                                       end
+                                       if iroutine == null then continue
+                                       action(iroutine, m)
+                               end
+
+                               # Process class-specific iroutines
+                               iroutine = c.init_var_iroutine
+                               if iroutine != null then
+                                       action(iroutine, m)
+                               end
+                               iroutine = c.checknew_iroutine
+                               if iroutine != null then
+                                       action(iroutine, m)
+                               end
+                               for i in c.new_instance_iroutine.values do
+                                       action(i, m)
+                               end
+                       end
+               end
+       end
+
+       # This function will call the attached block for each MMMethods
+       # in this program
+       fun with_each_methods
+               !action(m: MMMethod)
+       do
+               for m in main_module.mhe.greaters_and_self do
+                       for c in m.local_classes do
+                               # Process methods and attributes initialization
+                               for p in c.local_local_properties do
+                                       if p isa MMMethod then
+                                               action(p)
+                                       end
+                               end
+                       end
+               end
+       end
+
+       # This function will call the attached block for each live local classes
+       # in this program
+       fun with_each_live_local_classes
+               !action(m: MMLocalClass)
+       do
+               for c in main_module.local_classes do
+                       action(c)
+               end
+       end
+
        init(m: MMModule, toolcontext: ToolContext) do
-               _module = m
+               _main_module = m
                _tc = toolcontext
+               finish_processing_classes
        end
 end