X-Git-Url: http://nitlanguage.org diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index 311d917..16e0b48 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -201,8 +201,17 @@ class NaiveInterpreter # Return the integer instance associated with `val`. fun int_instance(val: Int): Instance do - var ic = get_primitive_class("Int") - var instance = new PrimitiveInstance[Int](ic.mclass_type, val) + var t = mainmodule.int_type + var instance = new PrimitiveInstance[Int](t, val) + init_instance_primitive(instance) + return instance + end + + # Return the byte instance associated with `val`. + fun byte_instance(val: Byte): Instance + do + var t = mainmodule.byte_type + var instance = new PrimitiveInstance[Byte](t, val) init_instance_primitive(instance) return instance end @@ -210,8 +219,8 @@ class NaiveInterpreter # Return the char instance associated with `val`. fun char_instance(val: Char): Instance do - var ic = get_primitive_class("Char") - var instance = new PrimitiveInstance[Char](ic.mclass_type, val) + var t = mainmodule.char_type + var instance = new PrimitiveInstance[Char](t, val) init_instance_primitive(instance) return instance end @@ -219,8 +228,8 @@ class NaiveInterpreter # Return the float instance associated with `val`. fun float_instance(val: Float): Instance do - var ic = get_primitive_class("Float") - var instance = new PrimitiveInstance[Float](ic.mclass_type, val) + var t = mainmodule.float_type + var instance = new PrimitiveInstance[Float](t, val) init_instance_primitive(instance) return instance end @@ -239,9 +248,9 @@ class NaiveInterpreter fun array_instance(values: Array[Instance], elttype: MType): Instance do assert not elttype.need_anchor - var nat = new PrimitiveInstance[Array[Instance]](get_primitive_class("NativeArray").get_mtype([elttype]), values) + var nat = new PrimitiveInstance[Array[Instance]](mainmodule.native_array_type(elttype), values) init_instance_primitive(nat) - var mtype = get_primitive_class("Array").get_mtype([elttype]) + var mtype = mainmodule.array_type(elttype) var res = new MutableInstance(mtype) self.init_instance(res) self.send(self.force_get_primitive_method("with_native", mtype), [res, nat, self.int_instance(values.length)]) @@ -268,8 +277,8 @@ class NaiveInterpreter do var val = new FlatBuffer.from(txt) val.add('\0') - var ic = get_primitive_class("NativeString") - var instance = new PrimitiveInstance[Buffer](ic.mclass_type, val) + var t = mainmodule.native_string_type + var instance = new PrimitiveInstance[Buffer](t, val) init_instance_primitive(instance) return instance end @@ -370,42 +379,50 @@ class NaiveInterpreter # This method is used to manage varargs in signatures and returns the real array # of instances to use in the call. # Return `null` if one of the evaluation of the arguments return null. - fun varargize(mpropdef: MMethodDef, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance] + fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance] do var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null) var res = new Array[Instance] res.add(recv) - if args.is_empty then return res + if msignature.arity == 0 then return res + + if map == null then + assert args.length == msignature.arity else debug("Expected {msignature.arity} args, got {args.length}") + for ne in args do + var e = self.expr(ne) + if e == null then return null + res.add e + end + return res + end + + # Eval in order of arguments, not parameters + var exprs = new Array[Instance].with_capacity(args.length) + for ne in args do + var e = self.expr(ne) + if e == null then return null + exprs.add e + end - var vararg_rank = msignature.vararg_rank - var vararg_len = args.length - msignature.arity - if vararg_len < 0 then vararg_len = 0 + # Fill `res` with the result of the evaluation according to the mapping for i in [0..msignature.arity[ do - if i == vararg_rank then - var ne = args[i] - if ne isa AVarargExpr then - var e = self.expr(ne.n_expr) - if e == null then return null - res.add(e) - continue - end - var vararg = new Array[Instance] - for j in [vararg_rank..vararg_rank+vararg_len] do - var e = self.expr(args[j]) - if e == null then return null - vararg.add(e) - end - var elttype = msignature.mparameters[vararg_rank].mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType)) - res.add(self.array_instance(vararg, elttype)) - else - var j = i - if i > vararg_rank then j += vararg_len - var e = self.expr(args[j]) - if e == null then return null - res.add(e) + var param = msignature.mparameters[i] + var j = map.map.get_or_null(i) + if j == null then + # default value + res.add(null_instance) + continue + end + if param.is_vararg and map.vararg_decl > 0 then + var vararg = exprs.sub(j, map.vararg_decl) + var elttype = param.mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType)) + var arg = self.array_instance(vararg, elttype) + res.add(arg) + continue end + res.add exprs[j] end return res end @@ -588,13 +605,6 @@ class NaiveInterpreter # A hook to initialize a `PrimitiveInstance` fun init_instance_primitive(recv: Instance) do end - # Return the primitive `MClass` corresponding to the `name` given in parameter - # `name` : name of the primitive class - fun get_primitive_class(name: String): MClass - do - return mainmodule.get_primitive_class(name) - end - # This function determines the correct type according to the receiver of the current propdef (self). fun unanchor_type(mtype: MType): MType do @@ -631,6 +641,10 @@ abstract class Instance # else aborts fun to_f: Float do abort + # Return the integer value if the instance is a byte. + # else aborts + fun to_b: Byte do abort + # The real value encapsulated if the instance is primitive. # Else aborts. fun val: nullable Object do abort @@ -676,6 +690,8 @@ class PrimitiveInstance[E] redef fun to_i do return val.as(Int) redef fun to_f do return val.as(Float) + + redef fun to_b do return val.as(Byte) end # Information about local variables in a running method @@ -840,6 +856,8 @@ redef class AMethPropdef var recvval = args[0].to_i if pname == "unary -" then return v.int_instance(-args[0].to_i) + else if pname == "unary +" then + return args[0] else if pname == "+" then return v.int_instance(args[0].to_i + args[1].to_i) else if pname == "-" then @@ -864,6 +882,8 @@ redef class AMethPropdef return v.char_instance(args[0].to_i.ascii) else if pname == "to_f" then return v.float_instance(args[0].to_i.to_f) + else if pname == "to_b" then + return v.byte_instance(args[0].to_i.to_b) else if pname == "lshift" then return v.int_instance(args[0].to_i.lshift(args[1].to_i)) else if pname == "rshift" then @@ -891,6 +911,50 @@ redef class AMethPropdef else if pname == "strerror_ext" then return v.native_string_instance(recvval.strerror) end + else if cname == "Byte" then + var recvval = args[0].to_b + if pname == "unary -" then + return v.byte_instance(-args[0].to_b) + else if pname == "unary +" then + return args[0] + else if pname == "+" then + return v.byte_instance(args[0].to_b + args[1].to_b) + else if pname == "-" then + return v.byte_instance(args[0].to_b - args[1].to_b) + else if pname == "*" then + return v.byte_instance(args[0].to_b * args[1].to_b) + else if pname == "%" then + return v.byte_instance(args[0].to_b % args[1].to_b) + else if pname == "/" then + return v.byte_instance(args[0].to_b / args[1].to_b) + else if pname == "<" then + return v.bool_instance(args[0].to_b < args[1].to_b) + else if pname == ">" then + return v.bool_instance(args[0].to_b > args[1].to_b) + else if pname == "<=" then + return v.bool_instance(args[0].to_b <= args[1].to_b) + else if pname == ">=" then + return v.bool_instance(args[0].to_b >= args[1].to_b) + else if pname == "<=>" then + return v.int_instance(args[0].to_b <=> args[1].to_b) + else if pname == "to_f" then + return v.float_instance(args[0].to_b.to_f) + else if pname == "to_i" then + return v.int_instance(args[0].to_b.to_i) + else if pname == "lshift" then + return v.byte_instance(args[0].to_b.lshift(args[1].to_i)) + else if pname == "rshift" then + return v.byte_instance(args[0].to_b.rshift(args[1].to_i)) + else if pname == "byte_to_s_len" then + return v.int_instance(recvval.to_s.length) + else if pname == "native_byte_to_s" then + var s = recvval.to_s + var srecv = args[1].val.as(Buffer) + srecv.clear + srecv.append(s) + srecv.add('\0') + return null + end else if cname == "Char" then var recv = args[0].val.as(Char) if pname == "ascii" then @@ -914,6 +978,8 @@ redef class AMethPropdef var recv = args[0].to_f if pname == "unary -" then return v.float_instance(-recv) + else if pname == "unary +" then + return args[0] else if pname == "+" then return v.float_instance(recv + args[1].to_f) else if pname == "-" then @@ -932,6 +998,8 @@ redef class AMethPropdef return v.bool_instance(recv >= args[1].to_f) else if pname == "to_i" then return v.int_instance(recv.to_i) + else if pname == "to_b" then + return v.byte_instance(recv.to_b) else if pname == "cos" then return v.float_instance(args[0].to_f.cos) else if pname == "sin" then @@ -1008,11 +1076,11 @@ redef class AMethPropdef else if pname == "file_exists" then return v.bool_instance(recvval.to_s.file_exists) else if pname == "file_mkdir" then - recvval.to_s.mkdir - return null + var res = recvval.to_s.mkdir + return v.bool_instance(res == null) else if pname == "file_chdir" then - recvval.to_s.chdir - return null + var res = recvval.to_s.chdir + return v.bool_instance(res == null) else if pname == "file_realpath" then return v.native_string_instance(recvval.to_s.realpath) else if pname == "get_environ" then @@ -1023,6 +1091,9 @@ redef class AMethPropdef return v.int_instance(res) else if pname == "atof" then return v.float_instance(recvval.to_f) + else if pname == "fast_cstring" then + var ns = recvval.to_cstring.to_s.substring_from(args[1].to_i) + return v.native_string_instance(ns) end else if cname == "String" then var cs = v.send(v.force_get_primitive_method("to_cstring", args.first.mtype), [args.first]) @@ -1030,7 +1101,7 @@ redef class AMethPropdef if pname == "files" then var res = new Array[Instance] for f in str.files do res.add v.string_instance(f) - return v.array_instance(res, v.get_primitive_class("String").mclass_type) + return v.array_instance(res, v.mainmodule.string_type) end else if pname == "calloc_string" then return v.native_string_instance("!" * args[1].to_i) @@ -1104,15 +1175,6 @@ redef class AMethPropdef 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) - var mtype: MType - mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.get_primitive_class("ArrayCapable")) - mtype = mtype.arguments.first - var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i) - var instance = new PrimitiveInstance[Array[Instance]](v.get_primitive_class("NativeArray").get_mtype([mtype]), val) - v.init_instance_primitive(instance) - return instance else if pname == "native_argc" then return v.int_instance(v.arguments.length) else if pname == "native_argv" then @@ -1286,14 +1348,16 @@ redef class ABlockExpr end redef class AVardeclExpr - redef fun stmt(v) + redef fun expr(v) do var ne = self.n_expr if ne != null then var i = v.expr(ne) - if i == null then return + if i == null then return null v.write_variable(self.variable.as(not null), i) + return i end + return null end end @@ -1334,6 +1398,14 @@ redef class ASelfExpr end end +redef class AImplicitSelfExpr + redef fun expr(v) + do + if not is_sys then return super + return v.mainobj + end +end + redef class AEscapeExpr redef fun stmt(v) do @@ -1478,6 +1550,19 @@ redef class AForExpr end end +redef class AWithExpr + redef fun stmt(v) + do + var expr = v.expr(self.n_expr) + if expr == null then return + + v.callsite(method_start, [expr]) + v.stmt(self.n_block) + v.is_escape(self.break_mark) # Clear the break + v.callsite(method_finish, [expr]) + end +end + redef class AAssertExpr redef fun stmt(v) do @@ -1553,6 +1638,13 @@ redef class AIntExpr end end +redef class AByteExpr + redef fun expr(v) + do + return v.byte_instance(self.value.as(not null)) + end +end + redef class AFloatExpr redef fun expr(v) do @@ -1606,8 +1698,8 @@ redef class ASuperstringExpr if i == null then return null array.add(i) end - var i = v.array_instance(array, v.get_primitive_class("Object").mclass_type) - var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i]) + var i = v.array_instance(array, v.mainmodule.object_type) + var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i]) assert res != null return res end @@ -1726,7 +1818,7 @@ redef class ASendExpr do var recv = v.expr(self.n_expr) if recv == null then return null - var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments) + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments) if args == null then return null var res = v.callsite(callsite, args) @@ -1739,7 +1831,7 @@ redef class ASendReassignFormExpr do var recv = v.expr(self.n_expr) if recv == null then return - var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments) + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments) if args == null then return var value = v.expr(self.n_value) if value == null then return @@ -1763,29 +1855,35 @@ redef class ASuperExpr var callsite = self.callsite if callsite != null then - var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs) - if args == null then return null - # Add additional arguments for the super init call - if args.length == 1 then + var args + if self.n_args.n_exprs.is_empty then + # Add automatic arguments for the super init call + args = [recv] for i in [0..callsite.msignature.arity[ do args.add(v.frame.arguments[i+1]) end + else + args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs) + if args == null then return null end + # Super init call var res = v.callsite(callsite, args) return res end - # standard call-next-method + # Standard call-next-method var mpropdef = self.mpropdef mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype) - var args = v.varargize(mpropdef, recv, self.n_args.n_exprs) - if args == null then return null - - if args.length == 1 then + var args + if self.n_args.n_exprs.is_empty then args = v.frame.arguments + else + args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs) + if args == null then return null end + var res = v.call(mpropdef, args) return res end @@ -1797,7 +1895,10 @@ redef class ANewExpr var mtype = v.unanchor_type(self.recvtype.as(not null)) var recv: Instance = new MutableInstance(mtype) v.init_instance(recv) - var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs) + var callsite = self.callsite + if callsite == null then return recv + + var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs) if args == null then return null var res2 = v.callsite(callsite, args) if res2 != null then @@ -1859,6 +1960,20 @@ redef class AIssetAttrExpr end end +redef class AVarargExpr + redef fun expr(v) + do + return v.expr(self.n_expr) + end +end + +redef class ANamedargExpr + redef fun expr(v) + do + return v.expr(self.n_expr) + end +end + redef class ADebugTypeExpr redef fun stmt(v) do