typing&engines: accept `is_same_instance` on `null`
[nit.git] / src / interpreter / naive_interpreter.nit
index 74a1929..5cc3892 100644 (file)
@@ -21,6 +21,7 @@ import literal
 import semantize
 private import parser::tables
 import mixin
+import primitive_types
 
 redef class ToolContext
        # --discover-call-trace
@@ -172,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`)
@@ -451,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])
@@ -663,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
@@ -798,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
@@ -1015,43 +1029,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)
@@ -1097,6 +1119,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
@@ -1513,11 +1539,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)