<commit_before># This file is part of NIT ( http://www.nitlanguage.org ).
#
# Copyright 2012 <NAME> <<EMAIL>>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Global compilation of a Nit program
#
# Techniques used are:
#   * heterogeneous generics
#   * customization
#   * switch dispatch
#   * inlining
module global_compiler

import literal
import typing
import auto_super_init
import rapid_type_analysis

redef class ToolContext
	# --output
	var opt_output: OptionString = new OptionString("Output file", "-o", "--output")

	# --no-cc
	var opt_no_cc: OptionBool = new OptionBool("Do not invoke C compiler", "--no-cc")

	# --hardening
	var opt_hardening: OptionBool = new OptionBool("Generate contracts in the C code against bugs in the compiler", "--hardening")

	redef init
	do
		super
		self.option_context.add_option(self.opt_output, self.opt_no_cc, self.opt_hardening)
	end
end

redef class ModelBuilder
	# Entry point to performs a global compilation on the AST of a complete program.
	# `mainmodule` is the main module of the program
	# `runtime_type_analysis` is a already computer type analysis.
	fun run_global_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)
	do
		var time0 = get_time
		self.toolcontext.info("*** COMPILING TO C ***", 1)

		var compiler = new GlobalCompiler(mainmodule, runtime_type_analysis, self)
		var v = new GlobalCompilerVisitor(compiler)

		v.add_decl("#include <stdlib.h>")
		v.add_decl("#include <stdio.h>")
		v.add_decl("#include <string.h>")

		# TODO: Better way to activate the GC
		v.add_decl("#include <gc/gc.h>")
		#v.add_decl("#define GC_MALLOC(x) calloc(1, (x))")

		# Declaration of structures the live Nit types
		# Each live type is generated as an independent C `struct' type.
		# They only share a common first field `classid` used to implement the polymorphism.
		# Usualy, all C variables that refers to a Nit object are typed on the abstract struct `val' that contains only the `classid` field.

		v.add_decl("typedef struct \{int classid;\} val; /* general C type representing a Nit instance. */")
		for t in runtime_type_analysis.live_types do
			compiler.declare_runtimeclass(v, t)
		end

		# Global variable used by the legacy native interface

		v.add_decl("extern int glob_argc;")
		v.add_decl("extern char **glob_argv;")
		v.add_decl("extern val *glob_sys;")

		# Class names (for the class_name and output_class_name methods)

		v.add_decl("extern const char const * class_names[];")
		v.add("const char const * class_names[] = \{")
		for t in runtime_type_analysis.live_types do
			v.add("\"{t}\", /* {compiler.classid(t)} */")
		end
		v.add("\};")
		compiler.header = v

		# Init instance code (allocate and init-arguments)

		for t in runtime_type_analysis.live_types do
			if t.ctype != "val*" then continue # skip primitive types
			compiler.generate_init_instance(t)
		end

		# The main function of the C

		v = new GlobalCompilerVisitor(compiler)
		v.add_decl("int glob_argc;")
		v.add_decl("char **glob_argv;")
		v.add_decl("val *glob_sys;")
		v.add_decl("int main(int argc, char** argv) \{")
		v.add("glob_argc = argc; glob_argv = argv;")
		var main_type = mainmodule.sys_type
		if main_type == null then return # Nothing to compile
		var glob_sys = v.init_instance(main_type)
		v.add("glob_sys = {glob_sys};")
		var main_init = mainmodule.try_get_primitive_method("init", main_type)
		if main_init != null then
			v.send(main_init, [glob_sys])
		end
		var main_method = mainmodule.try_get_primitive_method("main", main_type)
		if main_method != null then
			v.send(main_method, [glob_sys])
		end
		v.add("\}")

		# Compile until all runtime_functions are visited
<commit_msg>nitg: generated main returns 0 on success<commit_after># This file is part of NIT ( http://www.nitlanguage.org ).
#
# Copyright 2012 <NAME> <<EMAIL>>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Global compilation of a Nit program
#
# Techniques used are:
#   * heterogeneous generics
#   * customization
#   * switch dispatch
#   * inlining
module global_compiler

import literal
import typing
import auto_super_init
import rapid_type_analysis

redef class ToolContext
	# --output
	var opt_output: OptionString = new OptionString("Output file", "-o", "--output")

	# --no-cc
	var opt_no_cc: OptionBool = new OptionBool("Do not invoke C compiler", "--no-cc")

	# --hardening
	var opt_hardening: OptionBool = new OptionBool("Generate contracts in the C code against bugs in the compiler", "--hardening")

	redef init
	do
		super
		self.option_context.add_option(self.opt_output, self.opt_no_cc, self.opt_hardening)
	end
end

redef class ModelBuilder
	# Entry point to performs a global compilation on the AST of a complete program.
	# `mainmodule` is the main module of the program
	# `runtime_type_analysis` is a already computer type analysis.
	fun run_global_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)
	do
		var time0 = get_time
		self.toolcontext.info("*** COMPILING TO C ***", 1)

		var compiler = new GlobalCompiler(mainmodule, runtime_type_analysis, self)
		var v = new GlobalCompilerVisitor(compiler)

		v.add_decl("#include <stdlib.h>")
		v.add_decl("#include <stdio.h>")
		v.add_decl("#include <string.h>")

		# TODO: Better way to activate the GC
		v.add_decl("#include <gc/gc.h>")
		#v.add_decl("#define GC_MALLOC(x) calloc(1, (x))")

		# Declaration of structures the live Nit types
		# Each live type is generated as an independent C `struct' type.
		# They only share a common first field `classid` used to implement the polymorphism.
		# Usualy, all C variables that refers to a Nit object are typed on the abstract struct `val' that contains only the `classid` field.

		v.add_decl("typedef struct \{int classid;\} val; /* general C type representing a Nit instance. */")
		for t in runtime_type_analysis.live_types do
			compiler.declare_runtimeclass(v, t)
		end

		# Global variable used by the legacy native interface

		v.add_decl("extern int glob_argc;")
		v.add_decl("extern char **glob_argv;")
		v.add_decl("extern val *glob_sys;")

		# Class names (for the class_name and output_class_name methods)

		v.add_decl("extern const char const * class_names[];")
		v.add("const char const * class_names[] = \{")
		for t in runtime_type_analysis.live_types do
			v.add("\"{t}\", /* {compiler.classid(t)} */")
		end
		v.add("\};")
		compiler.header = v

		# Init instance code (allocate and init-arguments)

		for t in runtime_type_analysis.live_types do
			if t.ctype != "val*" then continue # skip primitive types
			compiler.generate_init_instance(t)
		end

		# The main function of the C

		v = new GlobalCompilerVisitor(compiler)
		v.add_decl("int glob_argc;")
		v.add_decl("char **glob_argv;")
		v.add_decl("val *glob_sys;")
		v.add_decl("int main(int argc, char** argv) \{")
		v.add("glob_argc = argc; glob_argv = argv;")
		var main_type = mainmodule.sys_type
		if main_type == null then return # Nothing to compile
		var glob_sys = v.init_instance(main_type)
		v.add("glob_sys = {glob_sys};")
		var main_init = mainmodule.try_get_primitive_method("init", main_type)
		if main_init != null then
			v.send(main_init, [glob_sys])
		end
		var main_method = mainmodule.try_get_primitive_method("main", main_type)
		if main_method != null then
			v.send(main_method, [glob_sys])
		end
		v.add("return 0;")
		v.add("\}")

		# Compile until all runtime_functions are visited

{'fraction_non_alphanumeric': 0.10679842838433147, 'fraction_numerical': 0.0028574830336944874, 'mean_word_length': 4.289672544080605, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7425837', 'n_tokens_mistral': 2818, 'n_tokens_neox': 2620, 'n_words': 904}