Property definitions

nitc $ JavaCompiler :: defaultinit
# Compiler that translates Nit code to Java code
class JavaCompiler
	# The main module of the program currently compiled
	var mainmodule: MModule

	# Modelbuilder used to know the model and the AST
	var modelbuilder: ModelBuilder

	# The result of the RTA (used to know live types and methods)
	var runtime_type_analysis: RapidTypeAnalysis

	# Where to generate tmp files
	var compile_dir: String is lazy do
		var dir = modelbuilder.toolcontext.opt_compile_dir.value
		if dir == null then dir = "nitj_compile"
		return dir
	end

	# Name of the generated executable
	var outname: String is lazy do
		var name = modelbuilder.toolcontext.opt_output.value
		if name == null then name = mainmodule.jname
		return name
	end

	# The list of all associated files
	# Used to generate .java files
	var files: Array[JavaCodeFile] = new Array[JavaCodeFile]

	# Force the creation of a new file
	# The point is to avoid contamination between must-be-compiled-separately files
	fun new_file(name: String): JavaCodeFile do
		var file = new JavaCodeFile(name)
		files.add(file)
		return file
	end

	# Kind of visitor to use
	type VISITOR: JavaCompilerVisitor

	# Initialize a visitor specific for the compiler engine
	fun new_visitor(filename: String): VISITOR do
		return new JavaCompilerVisitor(self, new_file(filename))
	end

	# RuntimeModel representation
	private var rt_model: JavaRuntimeModel is lazy do return new JavaRuntimeModel

	# Compile Nit code to Java
	fun do_compilation do
		# compile java classes used to represents the runtime model of the program
		rt_model.compile_rtmodel(self)
		compile_box_kinds

		# compile class structures
		compile_mclasses_to_java

		# compile method structures
		compile_mmethods_to_java

		# compile main
		compile_main_function
	end

	# Prepare the boxes used to represent Java primitive types
	fun compile_box_kinds do
		# Collect all bas box class
		# FIXME: this is not completely fine with a separate compilation scheme
		for classname in ["Int", "Bool", "Byte", "Char", "Float"] do
			var classes = mainmodule.model.get_mclasses_by_name(classname)
			if classes == null then continue
			assert classes.length == 1 else print classes.join(", ")
			box_kinds.add(classes.first.mclass_type)
		end
	end

	# Types of boxes used to represent Java primitive types
	var box_kinds = new Array[MClassType]

	# Generate a `RTClass` for each `MClass` found in model
	#
	# This is a global phase because we need to know all the program to build
	# attributes, fill vft and type table.
	fun compile_mclasses_to_java do
		for mclass in mainmodule.model.mclasses do
			mclass.compile_to_java(new_visitor("{mclass.rt_name}.java"))
		end
	end

	# Generate a `RTMethod` for each `MMethodDef` found in model
	#
	# This is a separate phase.
	fun compile_mmethods_to_java do
		for mmodule in mainmodule.in_importation.greaters do
			for mclassdef in mmodule.mclassdefs do
				for mdef in mclassdef.mpropdefs do
					if mdef isa MMethodDef then
						mdef.compile_to_java(new_visitor("{mdef.rt_name}.java"))
					end
				end
			end
		end
	end

	# Generate Java main that call Sys.main
	fun compile_main_function do
		var v = new_visitor("{mainmodule.jname}_Main.java")
		v.add("public class {mainmodule.jname}_Main \{")
		v.add("  public static void main(String[] args) \{")

		var main_type = mainmodule.sys_type
		if main_type != null then
			var mainmodule = v.compiler.mainmodule
			var glob_sys = v.init_instance(main_type)
			var main_init = mainmodule.try_get_primitive_method("init", main_type.mclass)
			if main_init != null then
				v.send(main_init, [glob_sys])
			end
			var main_method = mainmodule.try_get_primitive_method("run", main_type.mclass) or else
				mainmodule.try_get_primitive_method("main", main_type.mclass)
			if main_method != null then
				v.send(main_method, [glob_sys])
			end
		end
		v.add("  \}")
		v.add("\}")
	end
end
src/compiler/java_compiler.nit:228,1--355,3