Looked at http://jenkins.gresil.org/jenkins/job/nit/tasks and did some work.
Pull-Request: #1077
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
self.realmainmodule = mainmodule
end
+ # Do the full code generation of the program `mainmodule`
+ # It is the main method usually called after the instantiation
+ fun do_compilation is abstract
+
# Force the creation of a new file
# The point is to avoid contamination between must-be-compiled-separately files
fun new_file(name: String): CodeFile
self.require_declaration(s)
end
- # look for a needed .h and .c file for a given .nit source-file
- # FIXME: bad API, parameter should be a `MModule`, not its source-file
- fun add_extern(file: String)
+ # Look for a needed .h and .c file for a given module
+ # This is used for the legacy FFI
+ fun add_extern(mmodule: MModule)
do
+ var file = mmodule.location.file.filename
file = file.strip_extension(".nit")
var tryfile = file + ".nit.h"
if tryfile.file_exists then
do
var externname
var at = self.get_single_annotation("extern", v.compiler.modelbuilder)
- if at != null then
+ if at != null and at.n_args.length == 1 then
externname = at.arg_as_string(v.compiler.modelbuilder)
if externname == null then return false
else
return false
end
- if location.file != null then
- var file = location.file.filename
- v.add_extern(file)
- end
+ v.add_extern(mpropdef.mclassdef.mmodule)
var res: nullable RuntimeVariable = null
var ret = mpropdef.msignature.return_mtype
if ret != null then
else
return false
end
- if location.file != null then
- var file = location.file.filename
- v.add_extern(file)
- end
+ v.add_extern(mpropdef.mclassdef.mmodule)
v.adapt_signature(mpropdef, arguments)
v.unbox_signature_extern(mpropdef, arguments)
var ret = arguments.first.mtype
self.toolcontext.info("*** GENERATING C ***", 1)
var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis)
+ compiler.do_compilation
+ compiler.display_stats
+
+ var time1 = get_time
+ self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
+ write_and_make(compiler)
+ end
+
+ # Count number of invocations by VFT
+ private var nb_invok_by_tables = 0
+ # Count number of invocations by direct call
+ private var nb_invok_by_direct = 0
+ # Count number of invocations by inlining
+ private var nb_invok_by_inline = 0
+end
+
+# Singleton that store the knowledge about the separate compilation process
+class SeparateCompiler
+ super AbstractCompiler
+
+ redef type VISITOR: SeparateCompilerVisitor
+
+ # The result of the RTA (used to know live types and methods)
+ var runtime_type_analysis: nullable RapidTypeAnalysis
+
+ private var undead_types: Set[MType] = new HashSet[MType]
+ private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]]
+
+ private var type_ids: Map[MType, Int] is noinit
+ private var type_colors: Map[MType, Int] is noinit
+ private var opentype_colors: Map[MType, Int] is noinit
+ protected var method_colors: Map[PropertyLayoutElement, Int] is noinit
+ protected var attr_colors: Map[MAttribute, Int] is noinit
+
+ init do
+ var file = new_file("nit.common")
+ self.header = new CodeWriter(file)
+ self.compile_box_kinds
+ end
+
+ redef fun do_compilation
+ do
+ var compiler = self
compiler.compile_header
var c_name = mainmodule.c_name
# compile class structures
- self.toolcontext.info("Property coloring", 2)
+ modelbuilder.toolcontext.info("Property coloring", 2)
compiler.new_file("{c_name}.classes")
compiler.do_property_coloring
for m in mainmodule.in_importation.greaters do
# compile methods
for m in mainmodule.in_importation.greaters do
- self.toolcontext.info("Generate C for module {m.full_name}", 2)
+ modelbuilder.toolcontext.info("Generate C for module {m.full_name}", 2)
compiler.new_file("{m.c_name}.sep")
compiler.compile_module_to_c(m)
end
# compile live & cast type structures
- self.toolcontext.info("Type coloring", 2)
+ modelbuilder.toolcontext.info("Type coloring", 2)
compiler.new_file("{c_name}.types")
+ compiler.compile_types
+ end
+
+ # Color and compile type structures and cast information
+ fun compile_types
+ do
+ var compiler = self
+
var mtypes = compiler.do_type_coloring
for t in mtypes do
compiler.compile_type_to_c(t)
compiler.compile_type_to_c(t)
end
- compiler.display_stats
-
- var time1 = get_time
- self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
- write_and_make(compiler)
- end
-
- # Count number of invocations by VFT
- private var nb_invok_by_tables = 0
- # Count number of invocations by direct call
- private var nb_invok_by_direct = 0
- # Count number of invocations by inlining
- private var nb_invok_by_inline = 0
-end
-
-# Singleton that store the knowledge about the separate compilation process
-class SeparateCompiler
- super AbstractCompiler
-
- redef type VISITOR: SeparateCompilerVisitor
-
- # The result of the RTA (used to know live types and methods)
- var runtime_type_analysis: nullable RapidTypeAnalysis
-
- private var undead_types: Set[MType] = new HashSet[MType]
- private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]]
-
- private var type_ids: Map[MType, Int] is noinit
- private var type_colors: Map[MType, Int] is noinit
- private var opentype_colors: Map[MType, Int] is noinit
- protected var method_colors: Map[PropertyLayoutElement, Int] is noinit
- protected var attr_colors: Map[MAttribute, Int] is noinit
-
- init do
- var file = new_file("nit.common")
- self.header = new CodeWriter(file)
- self.compile_box_kinds
end
redef fun compile_header_structs do
do
var rta = compiler.runtime_type_analysis
var mmethod = callsite.mproperty
- # TODO: Inlining of new-style constructors
- if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and not mmethod.is_root_init then
+ # TODO: Inlining of new-style constructors with initializers
+ if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and callsite.mpropdef.initializers.is_empty then
var tgs = rta.live_targets(callsite)
if tgs.length == 1 then
# DIRECT CALL
if toolcontext.opt_only_parse.value then
self.toolcontext.info("*** ONLY PARSE...", 1)
+ exit(0)
+ end
+
+ return mmodules.to_a
+ end
+
+ # Load recursively all modules of the group `mgroup`.
+ # See `parse` for details.
+ fun parse_group(mgroup: MGroup): Array[MModule]
+ do
+ var res = new Array[MModule]
+ visit_group(mgroup)
+ for mg in mgroup.in_nesting.smallers do
+ for mp in mg.module_paths do
+ var nmodule = self.load_module(mp.filepath)
+ if nmodule == null then continue # Skip error
+ # Load imported module
+ build_module_importation(nmodule)
+
+ res.add(nmodule.mmodule.as(not null))
+ end
+ end
+ return res
+ end
+
+ # Load a bunch of modules and groups.
+ # Each name can be a module or a group.
+ # If it is a group then recursively all its modules are parsed.
+ # See `parse` for details.
+ fun parse_full(names: Sequence[String]): Array[MModule]
+ do
+ var time0 = get_time
+ # Parse and recursively load
+ self.toolcontext.info("*** PARSE ***", 1)
+ var mmodules = new ArraySet[MModule]
+ for a in names do
+ var mgroup = self.get_mgroup(a)
+ if mgroup != null then
+ mmodules.add_all parse_group(mgroup)
+ continue
+ end
+ var nmodule = self.load_module(a)
+ if nmodule == null then continue # Skip error
+ # Load imported module
+ build_module_importation(nmodule)
+
+ mmodules.add(nmodule.mmodule.as(not null))
+ end
+ var time1 = get_time
+ self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2)
+
+ self.toolcontext.check_errors
+
+ if toolcontext.opt_only_parse.value then
+ self.toolcontext.info("*** ONLY PARSE...", 1)
exit(0)
end
do
# Check the module name
var decl = nmodule.n_moduledecl
- if decl == null then
- #warning(nmodule, "Warning: Missing 'module' keyword") #FIXME: NOT YET FOR COMPATIBILITY
- else
+ if decl != null then
var decl_name = decl.n_name.n_id.text
if decl_name != mod_name then
error(decl.n_name, "Error: module name missmatch; declared {decl_name} file named {mod_name}")
var nmodules = new Array[AModule]
# Register the nmodule associated to each mmodule
- # FIXME: why not refine the `MModule` class with a nullable attribute?
- var mmodule2nmodule = new HashMap[MModule, AModule]
+ #
+ # Public clients need to use `mmodule2node` to access stuff.
+ private var mmodule2nmodule = new HashMap[MModule, AModule]
+
+ # Retrieve the associated AST node of a mmodule.
+ # This method is used to associate model entity with syntactic entities.
+ #
+ # If the module is not associated with a node, returns null.
+ fun mmodule2node(mmodule: MModule): nullable AModule
+ do
+ return mmodule2nmodule.get_or_null(mmodule)
+ end
end
# File-system location of a module (file) that is identified but not always loaded.
var args = toolcontext.option_context.rest
-var mmodules = modelbuilder.parse(args)
+var mmodules = modelbuilder.parse_full(args)
modelbuilder.run_phases
if opt_full.value then mmodules = model.mmodules
if opt_last_line.value != 0 then v.last_line = opt_last_line.value
if opt_ast.value then v.with_ast = true
var page = null
- var m = modelbuilder.mmodule2nmodule[mm]
+ var m = modelbuilder.mmodule2node(mm)
+ assert m != null
if not opt_fragment.value then
page = new HTMLTag("html")
page.add_raw_html """<head>