X-Git-Url: http://nitlanguage.org diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index 6c65469..01c872d 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -20,6 +20,7 @@ module naive_interpreter import literal import semantize private import parser::tables +import mixin redef class ToolContext # --discover-call-trace @@ -45,32 +46,15 @@ redef class ModelBuilder self.toolcontext.info("*** START INTERPRETING ***", 1) var interpreter = new NaiveInterpreter(self, mainmodule, arguments) - init_naive_interpreter(interpreter, mainmodule) + interpreter.start(mainmodule) var time1 = get_time self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2) end - - private fun init_naive_interpreter(interpreter: NaiveInterpreter, mainmodule: MModule) do - var sys_type = mainmodule.sys_type - if sys_type == null then return # no class Sys - var mainobj = new MutableInstance(sys_type) - interpreter.mainobj = mainobj - interpreter.init_instance(mainobj) - var initprop = mainmodule.try_get_primitive_method("init", sys_type.mclass) - if initprop != null then - interpreter.send(initprop, [mainobj]) - end - var mainprop = mainmodule.try_get_primitive_method("run", sys_type.mclass) or else - mainmodule.try_get_primitive_method("main", sys_type.mclass) - if mainprop != null then - interpreter.send(mainprop, [mainobj]) - end - end end # The visitor that interprets the Nit Program by walking on the AST -private class NaiveInterpreter +class NaiveInterpreter # The modelbuilder that know the AST and its associations with the model var modelbuilder: ModelBuilder @@ -94,6 +78,25 @@ private class NaiveInterpreter self.null_instance = new MutableInstance(mainmodule.model.null_type) end + # Starts the interpreter on the main module of a program + fun start(mainmodule: MModule) do + var interpreter = self + var sys_type = mainmodule.sys_type + if sys_type == null then return # no class Sys + var mainobj = new MutableInstance(sys_type) + interpreter.mainobj = mainobj + interpreter.init_instance(mainobj) + var initprop = mainmodule.try_get_primitive_method("init", sys_type.mclass) + if initprop != null then + interpreter.send(initprop, [mainobj]) + end + var mainprop = mainmodule.try_get_primitive_method("run", sys_type.mclass) or else + mainmodule.try_get_primitive_method("main", sys_type.mclass) + if mainprop != null then + interpreter.send(mainprop, [mainobj]) + end + end + # Subtype test in the context of the mainmodule fun is_subtype(sub, sup: MType): Bool do @@ -245,6 +248,19 @@ private class NaiveInterpreter 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 @@ -254,6 +270,15 @@ private class NaiveInterpreter 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 @@ -364,6 +389,7 @@ private class NaiveInterpreter # 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) @@ -372,6 +398,8 @@ private class NaiveInterpreter 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 @@ -493,6 +521,7 @@ private class NaiveInterpreter 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 @@ -606,7 +635,7 @@ class PrimitiveInstance[E: Object] end # Information about local variables in a running method -private class Frame +class Frame # The current visited node # The node is stored by frame to keep a stack trace var current_node: ANode @@ -616,13 +645,13 @@ private class Frame # Arguments of the method (the first is the receiver) var arguments: Array[Instance] # Mapping between a variable and the current value - var map: Map[Variable, Instance] = new HashMap[Variable, Instance] + private var map: Map[Variable, Instance] = new HashMap[Variable, Instance] end redef class ANode # Aborts the program with a message # `v` is used to know if a colored message is displayed or not - private fun fatal(v: NaiveInterpreter, message: String) + fun fatal(v: NaiveInterpreter, message: String) do if v.modelbuilder.toolcontext.opt_no_color.value == true then sys.stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n") @@ -795,6 +824,8 @@ redef class AMethPropdef return v.int_instance(args[0].to_i.bin_or(args[1].to_i)) else if pname == "bin_xor" then return v.int_instance(args[0].to_i.bin_xor(args[1].to_i)) + else if pname == "bin_not" then + return v.int_instance(args[0].to_i.bin_not) else if pname == "native_int_to_s" then return v.native_string_instance(recvval.to_s) else if pname == "strerror_ext" then @@ -1091,7 +1122,6 @@ redef class AClassdef private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance do if mpropdef.mproperty.is_root_init then - assert self.super_inits == null assert args.length == 1 if not mpropdef.is_intro then # standard call-next-method @@ -1099,27 +1129,9 @@ redef class AClassdef v.call_without_varargs(superpd, args) end return null + else + abort end - - var super_inits = self.super_inits - if super_inits != null then - var args_of_super = args - if args.length > 1 then args_of_super = [args.first] - for su in super_inits do - v.send(su, args_of_super) - end - end - var recv = args.first - assert recv isa MutableInstance - var i = 1 - # Collect undefined attributes - for npropdef in self.n_propdefs do - if npropdef isa AAttrPropdef and not npropdef.noinit and npropdef.n_expr == null then - v.write_attribute(npropdef.mpropdef.mproperty, recv, args[i]) - i += 1 - end - end - return null end end @@ -1475,9 +1487,7 @@ redef class AStringFormExpr 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