package program
import metamodel
+import icode
+import primitive_info
+import mmloader
+
+redef class ToolContext
+ readable writable var _global: Bool = false
+ writable var _use_SFT_optimization: Bool = true
+
+ # We can say that we are using SFT optimization *only* when we are
+ # doing global compilation and we enabled the command line option
+ fun use_SFT_optimization: Bool do return global and _use_SFT_optimization
+end
# Instances of this class represent a program/library that will
# be analyzed/compiled by nitc
class Program
+ # This is the ToolContext associated with this Program
+ # It contains (amongts other things) the command line options
+ 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)
+ readable var _main_method: nullable MMMethod = null
- init(m: MMModule) do
- _module = m
+ # This is the class that contains the main method.
+ # Would be null if there is no main method
+ readable var _main_class: nullable MMLocalClass = null
+
+ # 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 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
+ if not sys.has_global_property_by_name(entryname) then return
+
+ _main_method = sys.select_method(entryname)
+ _main_class = sys
+ end
+
+ # Generation of allocation function of this class
+ fun generate_allocation_iroutines
+ 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
+ # Generate INIT_ATTRIBUTES routine
+ var iself = new IRegister(c.get_type)
+ var iselfa = [iself]
+ var iroutine = new IRoutine(iselfa, null)
+ 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 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
+
+ c.init_var_iroutine = iroutine
+ end
+ do
+ # Compile CHECKNAME
+ var iself = new IRegister(c.get_type)
+ var iselfa = [iself]
+ var iroutine = new IRoutine(iselfa, null)
+ 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
+ icb.add_attr_check(p, iself)
+ end
+ end
+
+ c.checknew_iroutine = iroutine
+ end
+
+ for g in c.global_properties do
+ # FIXME skip invisible constructors
+ if not g.is_init_for(c) then continue
+ var p = c[g]
+ assert p isa MMMethod
+
+ var iself = new IRegister(c.get_type)
+ var iparams = new Array[IRegister]
+ 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(main_module, iroutine)
+
+ var inew = new IAllocateInstance(c.get_type)
+ inew.result = iself
+ icb.stmt(inew)
+ var iargs = [iself]
+ iargs.add_all(iparams)
+
+ icb.stmt(new IInitAttributes(c.get_type, iself))
+ icb.stmt(new IStaticCall(p, iargs))
+ icb.stmt(new ICheckInstance(c.get_type, iself))
+
+ c.new_instance_iroutine[p] = iroutine
+ end
+ end
+ 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 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
+ _main_module = m
+ _tc = toolcontext
+ finish_processing_classes
+ end
+end
+
+redef class MMLocalClass
+ # IRoutine for the initialization of the default attributes (called by IInitAttributes)
+ readable writable var _init_var_iroutine: nullable IRoutine = null
+ # IRoutine to validate the instance after initialization (called by ICheckInstance)
+ readable writable var _checknew_iroutine: nullable IRoutine = null
+ # IRoutines to call to create a new valid instance (memory allocated, object initialized and validated)
+ # These iroutines will call: IAllocateInstance, IInitAttributes, some init function and ICheckInstance
+ # These routines will be called by INew
+ readable var _new_instance_iroutine: HashMap[MMMethod, IRoutine] = new HashMap[MMMethod, IRoutine]
end