From: Jean Privat Date: Sat, 11 Oct 2014 12:24:15 +0000 (-0400) Subject: Merge: new option --define X-Git-Tag: v0.6.10~34 X-Git-Url: http://nitlanguage.org?hp=-c Merge: new option --define It is standard in compiled programs to be able to setup some program configuration at compile-time. Eg. C compilers accept a command-line option `-D` to define macros that will be used inside programs. It is useful for configuring some string (like `-D PREFIX=/opt/nit/`, or `-D PORT=8081`) or activate some parts (conditional compilation, eg `-D WITH_SSL`). This PR brings an equivalent capability to Nit engines through the new `-D` (`--define`) option. The design behind the -D it to enable specific refinement of top-level functions at link-time. Thus, basically ~~~sh $ cat my_foo.nit import foo redef fun prefix do return "/opt/nit/" $ nitg my_foo.nit ~~~ can be simplified into ~~~sh $ nitg foo.nit -D prefix=/opt/nit/ ~~~ Like `-m`, the `-D` creates a fictive module that refines the main module of the program. `-D` also use the return type of the refined method to know how to interpret the text of the value. Currently only Int, String and Bool is supported. ~~~nit module foo fun str: String do return "test" fun num: Int do return 1 fun flag: Bool do return false print str print num print flag ~~~ ~~~sh $ nitg foo.nit $ ./foo test 1 false $ nitg foo.nit -D str=hello -D num=42 -D flag $ ./foo hello 42 true ~~~ The code of the PR is quite straightforward and show again that the new model is quite robust. As usual, the first commits are some cleanup. The fun stuff is in the latter commits. Pull-Request: #815 Reviewed-by: Lucas Bajolet Reviewed-by: Alexandre Terrasa --- ff3bde9e1cd0e92d08166fc17373f6680c495f28 diff --combined src/compiler/abstract_compiler.nit index a6f6afa,b9987c0..04e0719 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@@ -22,6 -22,7 +22,7 @@@ import semantiz import platform import c_tools private import annotation + import mixin # Add compiling options redef class ToolContext @@@ -310,7 -311,16 +311,16 @@@ class MakefileToolchai fun makefile_name(mainmodule: MModule): String do return "{mainmodule.name}.mk" - fun default_outname(mainmodule: MModule): String do return mainmodule.name + fun default_outname(mainmodule: MModule): String + do + # Search a non fictive module + var res = mainmodule.name + while mainmodule.is_fictive do + mainmodule = mainmodule.in_importation.direct_greaters.first + res = mainmodule.name + end + return res + end # Combine options and platform informations to get the final path of the outfile fun outfile(mainmodule: MModule): String @@@ -891,6 -901,7 +901,7 @@@ extern void nitni_global_ref_decr( stru var cds = mtype.collect_mclassdefs(self.mainmodule).to_a self.mainmodule.linearize_mclassdefs(cds) for cd in cds do + if not self.modelbuilder.mclassdef2nclassdef.has_key(cd) then continue var n = self.modelbuilder.mclassdef2nclassdef[cd] for npropdef in n.n_propdefs do if npropdef isa AAttrPropdef then @@@ -906,6 -917,7 +917,7 @@@ var cds = mtype.collect_mclassdefs(self.mainmodule).to_a self.mainmodule.linearize_mclassdefs(cds) for cd in cds do + if not self.modelbuilder.mclassdef2nclassdef.has_key(cd) then continue var n = self.modelbuilder.mclassdef2nclassdef[cd] for npropdef in n.n_propdefs do if npropdef isa AAttrPropdef then @@@ -1044,7 -1056,7 +1056,7 @@@ abstract class AbstractCompilerVisito fun get_property(name: String, recv: MType): MMethod do assert recv isa MClassType - return self.compiler.modelbuilder.force_get_primitive_method(self.current_node.as(not null), name, recv.mclass, self.compiler.mainmodule) + return self.compiler.modelbuilder.force_get_primitive_method(self.current_node, name, recv.mclass, self.compiler.mainmodule) end fun compile_callsite(callsite: CallSite, arguments: Array[RuntimeVariable]): nullable RuntimeVariable @@@ -1353,6 -1365,18 +1365,18 @@@ return res end + # Generate an integer value + fun bool_instance(value: Bool): RuntimeVariable + do + var res = self.new_var(self.get_class("Bool").mclass_type) + if value then + self.add("{res} = 1;") + else + self.add("{res} = 0;") + end + return res + end + # Generate a string value fun string_instance(string: String): RuntimeVariable do @@@ -1373,6 -1397,19 +1397,19 @@@ return res end + fun value_instance(object: Object): RuntimeVariable + do + if object isa Int then + return int_instance(object) + else if object isa Bool then + return bool_instance(object) + else if object isa String then + return string_instance(object) + else + abort + end + end + # Generate an array value fun array_instance(array: Array[RuntimeVariable], elttype: MType): RuntimeVariable is abstract @@@ -1813,6 -1850,7 +1850,7 @@@ redef class MMethodDe fun compile_inside_to_c(v: VISITOR, arguments: Array[RuntimeVariable]): nullable RuntimeVariable do var modelbuilder = v.compiler.modelbuilder + var val = constant_value if modelbuilder.mpropdef2npropdef.has_key(self) then var npropdef = modelbuilder.mpropdef2npropdef[self] var oldnode = v.current_node @@@ -1827,6 -1865,8 +1865,8 @@@ self.compile_parameter_check(v, arguments) nclassdef.compile_to_c(v, self, arguments) v.current_node = oldnode + else if val != null then + v.ret(v.value_instance(val)) else abort end @@@ -2601,12 -2641,6 +2641,12 @@@ redef class AForExp v.compile_callsite(next_meth, [it]) v.add("\}") v.add("BREAK_{v.escapemark_name(escapemark)}: (void)0;") + + var method_finish = self.method_finish + if method_finish != null then + # TODO: Find a way to call this also in long escape (e.g. return) + v.compile_callsite(method_finish, [it]) + end end end @@@ -3025,9 -3059,6 +3065,6 @@@ en # Create a tool context to handle options and paths var toolcontext = new ToolContext - var opt_mixins = new OptionArray("Additionals module to min-in", "-m") - toolcontext.option_context.add_option(opt_mixins) - toolcontext.tooldescription = "Usage: nitg [OPTION]... file.nit...\nCompiles Nit programs." # We do not add other options, so process them now! @@@ -3046,7 -3077,6 +3083,6 @@@ en # Here we load an process all modules passed on the command line var mmodules = modelbuilder.parse(arguments) - var mixins = modelbuilder.parse(opt_mixins.value) if mmodules.is_empty then return modelbuilder.run_phases @@@ -3054,8 -3084,5 +3090,5 @@@ for mmodule in mmodules do toolcontext.info("*** PROCESS {mmodule} ***", 1) var ms = [mmodule] - if not mixins.is_empty then - ms.add_all mixins - end toolcontext.run_global_phases(ms) end diff --combined src/interpreter/naive_interpreter.nit index 92b658d,01c872d..55c6567 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@@ -20,6 -20,7 +20,7 @@@ module naive_interprete import literal import semantize private import parser::tables + import mixin redef class ToolContext # --discover-call-trace @@@ -247,6 -248,19 +248,19 @@@ class NaiveInterprete return res end + fun value_instance(object: Object): Instance + do + if object isa Int then + return int_instance(object) + else if object isa Bool then + return bool_instance(object) + else if object isa String then + return string_instance(object) + else + abort + end + end + # Return a new native string initialized with `txt` fun native_string_instance(txt: String): Instance do @@@ -256,6 -270,15 +270,15 @@@ return new PrimitiveInstance[Buffer](ic.mclass_type, val) end + # Return a new String instance for `txt` + fun string_instance(txt: String): Instance + do + var nat = native_string_instance(txt) + var res = self.send(self.force_get_primitive_method("to_s_with_length", nat.mtype), [nat, self.int_instance(txt.length)]) + assert res != null + return res + end + # The current frame used to store local variables of the current method executed fun frame: Frame do return frames.first @@@ -366,6 -389,7 +389,7 @@@ # Look for the AST node that implements the property var mproperty = mpropdef.mproperty + var val = mpropdef.constant_value if self.modelbuilder.mpropdef2npropdef.has_key(mpropdef) then var npropdef = self.modelbuilder.mpropdef2npropdef[mpropdef] self.parameter_check(npropdef, mpropdef, args) @@@ -374,6 -398,8 +398,8 @@@ var nclassdef = self.modelbuilder.mclassdef2nclassdef[mpropdef.mclassdef] self.parameter_check(nclassdef, mpropdef, args) return nclassdef.call(self, mpropdef, args) + else if val != null then + return value_instance(val) else fatal("Fatal Error: method {mpropdef} not found in the AST") abort @@@ -495,6 -521,7 +521,7 @@@ var cds = mtype.collect_mclassdefs(self.mainmodule).to_a self.mainmodule.linearize_mclassdefs(cds) for cd in cds do + if not self.modelbuilder.mclassdef2nclassdef.has_key(cd) then continue var n = self.modelbuilder.mclassdef2nclassdef[cd] for npropdef in n.n_propdefs do if npropdef isa AAttrPropdef then @@@ -1330,7 -1357,7 +1357,7 @@@ redef class AForExp #self.debug("iter {iter}") loop var isok = v.callsite(method_is_ok, [iter]).as(not null) - if not isok.is_true then return + if not isok.is_true then break if self.variables.length == 1 then var item = v.callsite(method_item, [iter]).as(not null) #self.debug("item {item}") @@@ -1344,15 -1371,11 +1371,15 @@@ abort end v.stmt(self.n_block) - if v.is_break(self.escapemark) then return + if v.is_break(self.escapemark) then break v.is_continue(self.escapemark) # Clear the break - if v.is_escaping then return + if v.is_escaping then break v.callsite(method_next, [iter]) end + var method_finish = self.method_finish + if method_finish != null then + v.callsite(method_finish, [iter]) + end end end @@@ -1464,9 -1487,7 +1491,7 @@@ redef class AStringFormExp redef fun expr(v) do var txt = self.value.as(not null) - var nat = v.native_string_instance(txt) - var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null) - return res + return v.string_instance(txt) end end diff --combined src/rapid_type_analysis.nit index 6ce94cb,7cbdaf9..897d7b7 --- a/src/rapid_type_analysis.nit +++ b/src/rapid_type_analysis.nit @@@ -244,6 -244,9 +244,9 @@@ class RapidTypeAnalysi if mmethoddef.mproperty.is_root_init and not mmethoddef.is_intro then self.add_super_send(v.receiver, mmethoddef) end + else if mmethoddef.constant_value != null then + # Make the return type live + v.add_type(mmethoddef.msignature.return_mtype.as(MClassType)) else abort end @@@ -675,8 -678,6 +678,8 @@@ redef class AForExp abort end v.add_callsite(self.method_next) + var mf = self.method_finish + if mf != null then v.add_callsite(mf) end end