X-Git-Url: http://nitlanguage.org diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index 4c2d3d8..bb0b3b3 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -21,6 +21,7 @@ import literal import semantize private import parser::tables import mixin +import primitive_types redef class ToolContext # --discover-call-trace @@ -71,10 +72,12 @@ class NaiveInterpreter init do - self.true_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, true) - init_instance_primitive(self.true_instance) - self.false_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, false) - init_instance_primitive(self.false_instance) + if mainmodule.model.get_mclasses_by_name("Bool") != null then + self.true_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, true) + init_instance_primitive(self.true_instance) + self.false_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, false) + init_instance_primitive(self.false_instance) + end self.null_instance = new PrimitiveInstance[nullable Object](mainmodule.model.null_type, null) end @@ -170,14 +173,20 @@ class NaiveInterpreter # If `n` cannot be evaluated, then aborts. fun stmt(n: nullable AExpr) do - if n != null then - var frame = self.frame - var old = frame.current_node - frame.current_node = n - #n.debug("Execute stmt") - n.stmt(self) - frame.current_node = old + if n == null then return + + if n.comprehension != null then + var comprehension = frame.comprehension.as(not null) + var i = expr(n) + if i != null then comprehension.add(i) + return end + + var frame = self.frame + var old = frame.current_node + frame.current_node = n + n.stmt(self) + frame.current_node = old end # Map used to store values of nodes that must be evaluated once in the system (`AOnceExpr`) @@ -401,16 +410,18 @@ class NaiveInterpreter assert args.length == mpropdef.msignature.arity + 1 else debug("Invalid arity for {mpropdef}. {args.length} arguments given.") # 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) - return npropdef.call(self, mpropdef, args) - else if mproperty.is_root_init then - var nclassdef = self.modelbuilder.mclassdef2nclassdef[mpropdef.mclassdef] - self.parameter_check(nclassdef, mpropdef, args) - return nclassdef.call(self, mpropdef, args) + + var node = modelbuilder.mpropdef2node(mpropdef) + if node isa APropdef then + self.parameter_check(node, mpropdef, args) + return node.call(self, mpropdef, args) + else if node isa AClassdef then + self.parameter_check(node, mpropdef, args) + return node.call(self, mpropdef, args) + else if node != null then + fatal("Fatal Error: method {mpropdef} associated to unexpected AST node {node.location}") + abort else if val != null then return value_instance(val) else @@ -447,7 +458,7 @@ class NaiveInterpreter fun send_commons(mproperty: MMethod, args: Array[Instance], mtype: MType): nullable Instance do if mtype isa MNullType then - if mproperty.name == "==" then + if mproperty.name == "==" or mproperty.name == "is_same_instance" then return self.bool_instance(args[0] == args[1]) else if mproperty.name == "!=" then return self.bool_instance(args[0] != args[1]) @@ -536,13 +547,7 @@ 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 - res.add(npropdef) - end - end + res.add_all(modelbuilder.collect_attr_propdef(cd)) end cache[mtype] = res @@ -665,6 +670,7 @@ class Frame var arguments: Array[Instance] # Mapping between a variable and the current value private var map: Map[Variable, Instance] = new HashMap[Variable, Instance] + var comprehension: nullable Array[Instance] = null end redef class ANode @@ -800,6 +806,12 @@ redef class AMethPropdef else if pname == "exit" then exit(args[1].to_i) abort + else if pname == "buffer_mode_full" then + return v.int_instance(sys.buffer_mode_full) + else if pname == "buffer_mode_line" then + return v.int_instance(sys.buffer_mode_line) + else if pname == "buffer_mode_none" then + return v.int_instance(sys.buffer_mode_none) else if pname == "sys" then return v.mainobj else if cname == "Int" then @@ -845,8 +857,15 @@ redef class AMethPropdef 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 == "int_to_s_len" then + return v.int_instance(recvval.to_s.length) else if pname == "native_int_to_s" then - return v.native_string_instance(recvval.to_s) + var s = recvval.to_s + var srecv = args[1].val.as(Buffer) + srecv.clear + srecv.append(s) + srecv.add('\0') + return null else if pname == "strerror_ext" then return v.native_string_instance(recvval.strerror) end @@ -951,13 +970,13 @@ redef class AMethPropdef if fromval < 0 then debug("Illegal access on {recvval} for element {fromval}/{recvval.length}") end - if fromval + lenval >= recvval.length then + if fromval + lenval > recvval.length then debug("Illegal access on {recvval} for element {fromval}+{lenval}/{recvval.length}") end if toval < 0 then debug("Illegal access on {destval} for element {toval}/{destval.length}") end - if toval + lenval >= destval.length then + if toval + lenval > destval.length then debug("Illegal access on {destval} for element {toval}+{lenval}/{destval.length}") end recvval.as(FlatBuffer).copy(fromval, lenval, destval, toval) @@ -1017,43 +1036,51 @@ redef class AMethPropdef end else if cname == "NativeFile" then if pname == "native_stdout" then - var instance = new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdout) + var inst = new PrimitiveNativeFile.native_stdout + var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst) v.init_instance_primitive(instance) return instance else if pname == "native_stdin" then - var instance = new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdin) + var inst = new PrimitiveNativeFile.native_stdin + var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst) v.init_instance_primitive(instance) return instance else if pname == "native_stderr" then - var instance = new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stderr) + var inst = new PrimitiveNativeFile.native_stderr + var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst) v.init_instance_primitive(instance) return instance else if pname == "io_open_read" then var a1 = args[1].val.as(Buffer) - var instance = new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s)) + var inst = new PrimitiveNativeFile.io_open_read(a1.to_s) + var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst) v.init_instance_primitive(instance) return instance else if pname == "io_open_write" then var a1 = args[1].val.as(Buffer) - var instance = new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s)) + var inst = new PrimitiveNativeFile.io_open_write(a1.to_s) + var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst) v.init_instance_primitive(instance) return instance end var recvval = args.first.val if pname == "io_write" then var a1 = args[1].val.as(Buffer) - recvval.as(OStream).write(a1.substring(0, args[2].to_i).to_s) - return args[2] + return v.int_instance(recvval.as(PrimitiveNativeFile).io_write(a1.to_cstring, args[2].to_i)) else if pname == "io_read" then - var str = recvval.as(IStream).read(args[2].to_i) var a1 = args[1].val.as(Buffer) - new FlatBuffer.from(str).copy(0, str.length, a1.as(FlatBuffer), 0) - return v.int_instance(str.length) + var ns = new NativeString(a1.length) + var len = recvval.as(PrimitiveNativeFile).io_read(ns, args[2].to_i) + a1.clear + a1.append(ns.to_s_with_length(len)) + return v.int_instance(len) + else if pname == "flush" then + recvval.as(PrimitiveNativeFile).flush + return null else if pname == "io_close" then - recvval.as(IOS).close - return v.int_instance(0) - else if pname == "address_is_null" then - return v.false_instance + return v.int_instance(recvval.as(PrimitiveNativeFile).io_close) + else if pname == "set_buffering_type" then + return v.int_instance(recvval.as(PrimitiveNativeFile).set_buffering_type(args[1].to_i, args[2].to_i)) end else if pname == "calloc_array" then var recvtype = args.first.mtype.as(MClassType) @@ -1099,6 +1126,10 @@ redef class AMethPropdef else if pname == "errno" then return v.int_instance(sys.errno) else if pname == "address_is_null" then + var recv = args[0] + if recv isa PrimitiveInstance[PrimitiveNativeFile] then + return v.bool_instance(recv.val.address_is_null) + end return v.false_instance end return v.error_instance @@ -1192,7 +1223,7 @@ redef class AExpr # Return a possible value # NOTE: Do not call this method directly, but use `v.expr` # This method is here to be implemented by subclasses. - private fun expr(v: NaiveInterpreter): nullable Instance + protected fun expr(v: NaiveInterpreter): nullable Instance do fatal(v, "NOT YET IMPLEMENTED expr {class_name}") abort @@ -1201,7 +1232,7 @@ redef class AExpr # Evaluate the node as a statement. # NOTE: Do not call this method directly, but use `v.stmt` # This method is here to be implemented by subclasses (no need to return something). - private fun stmt(v: NaiveInterpreter) + protected fun stmt(v: NaiveInterpreter) do expr(v) end @@ -1515,11 +1546,18 @@ redef class AArrayExpr redef fun expr(v) do var val = new Array[Instance] - for nexpr in self.n_exprs.n_exprs do - var i = v.expr(nexpr) - if i == null then return null - val.add(i) + var old_comprehension = v.frame.comprehension + v.frame.comprehension = val + for nexpr in self.n_exprs do + if nexpr isa AForExpr then + v.stmt(nexpr) + else + var i = v.expr(nexpr) + if i == null then return null + val.add(i) + end end + v.frame.comprehension = old_comprehension var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType) var elttype = mtype.arguments.first return v.array_instance(val, elttype)