Doc review on newmodel.
[nit.git] / src / static / gitweb.js
diff --git a/src/naiveinterpreter.nit b/src/naiveinterpreter.nit
deleted file mode 100644 (file)
index cb2e61b..0000000
+++ /dev/null
@@ -1,1409 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2012 Jean Privat <jean@pryen.org>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Interpretation of a Nit program directly on the AST
-module naiveinterpreter
-
-import literal
-import typing
-import auto_super_init
-
-redef class ModelBuilder
-       # Execute the program from the entry point (Sys::main) of the `mainmodule'
-       # `arguments' are the command-line arguments in order
-       # REQUIRE that:
-       #   1. the AST is fully loaded.
-       #   2. the model is fully built.
-       #   3. the instructions are fully analysed.
-       fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])
-       do
-               var time0 = get_time
-               self.toolcontext.info("*** START INTERPRETING ***", 1)
-
-               var interpreter = new NaiveInterpreter(self, mainmodule, arguments)
-               var mainclasses = model.get_mclasses_by_name("Sys")
-               if mainclasses == null then return
-               assert mainclasses.length == 1
-               var mainclass = mainclasses.first
-               var props = model.get_mproperties_by_name("main")
-               assert props.length == 1
-               var methods = props.first.lookup_definitions(mainmodule, mainclass.mclass_type)
-               assert methods.length == 1 else print methods.join(", ")
-               var mainobj = new Instance(mainclass.mclass_type)
-               interpreter.mainobj = mainobj
-               interpreter.init_instance(mainobj)
-               var initprop = try_get_mproperty_by_name2(nmodules.first, mainmodule, mainclass.mclass_type, "init")
-               if initprop != null then
-                       assert initprop isa MMethod
-                       interpreter.send(initprop, [mainobj])
-               end
-               interpreter.check_init_instance(mainobj)
-               interpreter.send(interpreter.get_property("main", mainobj), [mainobj])
-
-               var time1 = get_time
-               self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
-       end
-end
-
-# The visitor that interprets the Nit Program by walking on the AST
-private class NaiveInterpreter
-       # The modelbuilder that know the AST and its associations with the model
-       var modelbuilder: ModelBuilder
-
-       # The main moduleof the program (used to lookup methoda
-       var mainmodule: MModule
-
-       # The command line arguments of the interpreted program
-       # arguments.first is the program name
-       # arguments[1] is the first argument
-       var arguments: Array[String]
-
-       var mainobj: nullable Instance
-
-       init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])
-       do
-               self.modelbuilder = modelbuilder
-               self.mainmodule = mainmodule
-               self.arguments = arguments
-               self.true_instance = new PrimitiveInstance[Bool](get_class("Bool").mclass_type, true)
-               self.false_instance = new PrimitiveInstance[Bool](get_class("Bool").mclass_type, false)
-               self.null_instance = new Instance(mainmodule.model.null_type)
-       end
-
-       # Force to get the primitive class named `name' or abort
-       fun get_class(name: String): MClass
-       do
-               var cla = mainmodule.model.get_mclasses_by_name(name)
-               if cla == null then
-                       if name == "Bool" then
-                               var c = new MClass(mainmodule, name, 0, enum_kind, public_visibility)
-                               var cladef = new MClassDef(mainmodule, c.mclass_type, new Location(null, 0,0,0,0), new Array[String])
-                               return c
-                       end
-                       fatal("Fatal Error: no primitive class {name}")
-                       abort
-               end
-               assert cla.length == 1 else print cla.join(", ")
-               return cla.first
-       end
-
-       # Force to get the primitive property named `name' in the instance `recv' or abort
-       fun get_property(name: String, recv: Instance): MMethod
-       do
-               var props = self.mainmodule.model.get_mproperties_by_name(name)
-               if props == null then
-                       fatal("Fatal Error: no primitive property {name} on {recv}")
-                       abort
-               end
-               var mtype = recv.mtype
-               var res: nullable MMethod = null
-               for mprop in props do
-                       assert mprop isa MMethod
-                       if not mtype.has_mproperty(self.mainmodule, mprop) then continue
-                       if res == null then
-                               res = mprop
-                       else
-                               fatal("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
-                               abort
-                       end
-               end
-               if res == null then
-                       fatal("Fatal Error: no primitive property {name} on {recv}")
-                       abort
-               end
-               return res
-       end
-
-       # Subtype test in the context of the mainmodule
-       fun is_subtype(sub, sup: MType): Bool
-       do
-               return sub.is_subtype(self.mainmodule, self.frame.arguments.first.mtype.as(MClassType), sup)
-       end
-
-       # Is a return executed?
-       # Set this mark to skip the evaluation until the end of the current method
-       var returnmark: Bool = false
-
-       # Is a break executed?
-       # Set this mark to skip the evaluation until a labeled statement catch it with `is_break'
-       var breakmark: nullable EscapeMark = null
-
-       # Is a continue executed?
-       # Set this mark to skip the evaluation until a labeled statement catch it with `is_continue'
-       var continuemark: nullable EscapeMark = null
-
-       # Is a return or a break or a continue executed?
-       # Use this function to know if you must skip the evaluation of statements
-       fun is_escaping: Bool do return returnmark or breakmark != null or continuemark != null
-
-       # The value associated with the current return/break/continue, if any.
-       # Set the value when you set a escapemark.
-       # Read the value when you catch a mark or reach the end of a method
-       var escapevalue: nullable Instance = null
-
-       # If there is a break and is associated with `escapemark', then return true an clear the mark.
-       # If there is no break or if `escapemark' is null then return false.
-       # Use this function to catch a potential break.
-       fun is_break(escapemark: nullable EscapeMark): Bool
-       do
-               if escapemark != null and self.breakmark == escapemark then
-                       self.breakmark = null
-                       return true
-               else
-                       return false
-               end
-       end
-
-       # If there is a continue and is associated with `escapemark', then return true an clear the mark.
-       # If there is no continue or if `escapemark' is null then return false.
-       # Use this function to catch a potential continue.
-       fun is_continue(escapemark: nullable EscapeMark): Bool
-       do
-               if escapemark != null and self.continuemark == escapemark then
-                       self.continuemark = null
-                       return true
-               else
-                       return false
-               end
-       end
-
-       # Evaluate `n' as an expression in the current context.
-       # Return the value of the expression.
-       # If `n' cannot be evaluated, then aborts.
-       fun expr(n: AExpr): Instance
-       do
-               var old = self.frame.current_node
-               self.frame.current_node = n
-               #n.debug("IN Execute expr")
-               var i = n.expr(self).as(not null)
-               #n.debug("OUT Execute expr: value is {i}")
-               #if not is_subtype(i.mtype, n.mtype.as(not null)) then n.debug("Expected {n.mtype.as(not null)} got {i}")
-               self.frame.current_node = old
-               return i
-       end
-
-       # Evaluate `n' as a statement in the current context.
-       # Do nothing if `n' is sull.
-       # If `n' cannot be evaluated, then aborts.
-       fun stmt(n: nullable AExpr)
-       do
-               if n != null then
-                       var old = self.frame.current_node
-                       self.frame.current_node = n
-                       #n.debug("Execute stmt")
-                       n.stmt(self)
-                       self.frame.current_node = old
-               end
-       end
-
-       # Map used to store values of nodes that must be evaluated once in the system (AOnceExpr)
-       var onces: Map[ANode, Instance] = new HashMap[ANode, Instance]
-
-       # Return the boolean instance associated with `val'.
-       fun bool_instance(val: Bool): Instance
-       do
-               if val then return self.true_instance else return self.false_instance
-       end
-
-       # Return the integer instance associated with `val'.
-       fun int_instance(val: Int): Instance
-       do
-               var ic = get_class("Int")
-               return new PrimitiveInstance[Int](ic.mclass_type, val)
-       end
-
-       # Return the char instance associated with `val'.
-       fun char_instance(val: Char): Instance
-       do
-               var ic = get_class("Char")
-               return new PrimitiveInstance[Char](ic.mclass_type, val)
-       end
-
-       # Return the float instance associated with `val'.
-       fun float_instance(val: Float): Instance
-       do
-               var ic = get_class("Float")
-               return new PrimitiveInstance[Float](ic.mclass_type, val)
-       end
-
-       # The unique intance of the `true' value.
-       var true_instance: Instance
-
-       # The unique intance of the `false' value.
-       var false_instance: Instance
-
-       # The unique intance of the `null' value.
-       var null_instance: Instance
-
-       # Return a new array made of `values'.
-       # The dynamic type of the result is Array[elttype].
-       fun array_instance(values: Array[Instance], elttype: MType): Instance
-       do
-               assert not elttype.need_anchor
-               var nat = new PrimitiveInstance[Array[Instance]](self.get_class("NativeArray").get_mtype([elttype]), values)
-               var mtype = self.get_class("Array").get_mtype([elttype])
-               var res = new Instance(mtype)
-               self.init_instance(res)
-               self.send(self.get_property("with_native", res), [res, nat, self.int_instance(values.length)])
-               self.check_init_instance(res)
-               return res
-       end
-
-       # Return a new native string initialized with `txt'
-       fun native_string_instance(txt: String): Instance
-       do
-               var val = new Buffer.from(txt)
-               var ic = get_class("NativeString")
-               return new PrimitiveInstance[Buffer](ic.mclass_type, val)
-       end
-
-       # The current frame used to store local variables of the current method executed
-       fun frame: Frame do return frames.first
-
-       # The stack of all frames. The first one is the current one.
-       var frames: List[Frame] = new List[Frame]
-
-       # Return a stack stace. One line per function
-       fun stack_trace: String
-       do
-               var b = new Buffer
-               b.append(",---- Stack trace -- - -  -\n")
-               for f in frames do
-                       b.append("| {f.mpropdef} ({f.current_node.location})\n")
-               end
-               b.append("`------------------- - -  -")
-               return b.to_s
-       end
-
-       # Exit the program with a message
-       fun fatal(message: String)
-       do
-               if frames.is_empty then
-                       print message
-               else
-                       self.frame.current_node.fatal(self, message)
-               end
-               exit(1)
-       end
-
-       # Execute `mpropdef' for a `args' (where args[0] is the receiver).
-       # Return a falue if `mpropdef' is a function, or null if it is a procedure.
-       # The call is direct/static. There is no message-seding/late-bindng.
-       fun call(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
-       do
-               var vararg_rank = mpropdef.msignature.vararg_rank
-               if vararg_rank >= 0 then
-                       assert args.length >= mpropdef.msignature.arity + 1 # because of self
-                       var rawargs = args
-                       args = new Array[Instance]
-
-                       args.add(rawargs.first) # recv
-
-                       for i in [0..vararg_rank[ do
-                               args.add(rawargs[i+1])
-                       end
-
-                       var vararg_lastrank = vararg_rank + rawargs.length-1-mpropdef.msignature.arity
-                       var vararg = new Array[Instance]
-                       for i in [vararg_rank..vararg_lastrank] do
-                               vararg.add(rawargs[i+1])
-                       end
-                       # FIXME: its it to late to determine the vararg type, this should have been done during a previous analysis
-                       var elttype = mpropdef.msignature.parameter_mtypes[vararg_rank].anchor_to(self.mainmodule, args.first.mtype.as(MClassType))
-                       args.add(self.array_instance(vararg, elttype))
-
-                       for i in [vararg_lastrank+1..rawargs.length-1[ do
-                               args.add(rawargs[i+1])
-                       end
-               end
-               assert args.length == mpropdef.msignature.arity + 1 # because of self
-
-               # Look for the AST node that implements the property
-               var mproperty = mpropdef.mproperty
-               if self.modelbuilder.mpropdef2npropdef.has_key(mpropdef) then
-                       var npropdef = self.modelbuilder.mpropdef2npropdef[mpropdef]
-                       return npropdef.call(self, mpropdef, args)
-               else if mproperty.name == "init" then
-                       var nclassdef = self.modelbuilder.mclassdef2nclassdef[mpropdef.mclassdef]
-                       return nclassdef.call(self, mpropdef, args)
-               else
-                       fatal("Fatal Error: method {mpropdef} not found in the AST")
-                       abort
-               end
-       end
-
-       # Execute `mproperty' for a `args' (where args[0] is the receiver).
-       # Return a falue if `mproperty' is a function, or null if it is a procedure.
-       # The call is polimotphic. There is a message-seding/late-bindng according to te receiver (args[0]).
-       fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
-       do
-               var recv = args.first
-               var mtype = recv.mtype
-               if mtype isa MNullType then
-                       if mproperty.name == "==" then
-                               return self.bool_instance(args[0] == args[1])
-                       else if mproperty.name == "!=" then
-                               return self.bool_instance(args[0] != args[1])
-                       end
-                       #fatal("Reciever is null. {mproperty}. {args.join(" ")} {self.frame.current_node.class_name}")
-                       fatal("Reciever is null")
-                       abort
-               end
-               var propdefs = mproperty.lookup_definitions(self.mainmodule, mtype)
-               if propdefs.length > 1 then
-                       fatal("NOT YET IMPLEMETED ERROR: Property conflict: {propdefs.join(", ")}")
-                       abort
-               end
-               assert propdefs.length == 1 else
-                       fatal("Fatal Error: No property '{mproperty}' for '{recv}'")
-                       abort
-               end
-               var propdef = propdefs.first
-               return self.call(propdef, args)
-       end
-
-       # Read the attribute `mproperty' of an instance `recv' and return its value.
-       # If the attribute in not yet initialized, then aborts with an error message.
-       fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
-       do
-               if not recv.attributes.has_key(mproperty) then
-                       fatal("Uninitialized attribute {mproperty.name}")
-                       abort
-               end
-               return recv.attributes[mproperty]
-       end
-
-       # Fill the initial values of the newly created instance `recv'.
-       # `recv.mtype' is used to know what must be filled.
-       fun init_instance(recv: Instance)
-       do
-               for cd in recv.mtype.collect_mclassdefs(self.mainmodule)
-               do
-                       var n = self.modelbuilder.mclassdef2nclassdef[cd]
-                       for npropdef in n.n_propdefs do
-                               if npropdef isa AAttrPropdef then
-                                       npropdef.init_expr(self, recv)
-                               end
-                       end
-               end
-       end
-
-       # Check that non nullable attributes of `recv' are correctly initialized.
-       # This function is used as the last instruction of a new
-       # FIXME: this will work better once there is nullable types
-       fun check_init_instance(recv: Instance)
-       do
-               for cd in recv.mtype.collect_mclassdefs(self.mainmodule)
-               do
-                       var n = self.modelbuilder.mclassdef2nclassdef[cd]
-                       for npropdef in n.n_propdefs do
-                               if npropdef isa AAttrPropdef and npropdef.n_expr == null then
-                                       # Force read to check the initialization
-                                       self.read_attribute(npropdef.mpropdef.mproperty, recv)
-                               end
-                       end
-               end
-       end
-
-       # This function determine the correct type according the reciever of the current definition (self).
-       fun unanchor_type(mtype: MType): MType
-       do
-               return mtype.anchor_to(self.mainmodule, self.frame.arguments.first.mtype.as(MClassType))
-       end
-end
-
-# An instance represents a value of the executed program.
-class Instance
-       # The dynamic type of the instance
-       # ASSERT: not self.mtype.is_anchored
-       var mtype: MType
-
-       # The values of the attributes
-       var attributes: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
-
-       # return true if the instance is the true value.
-       # return false if the instance is the true value.
-       # else aborts
-       fun is_true: Bool do abort
-
-       # Return true if `self' IS `o' (using the Nit semantic of is)
-       fun eq_is(o: Instance): Bool do return self is o
-
-       # Human readable object identity "Type#number"
-       redef fun to_s do return "{mtype}#{object_id}"
-
-       # Return the integer valur is the instance is an integer.
-       # else aborts
-       fun to_i: Int do abort
-
-       # The real value encapsulated if the instance is primitive.
-       # Else aborts.
-       fun val: Object do abort
-end
-
-# Special instance to handle primitives values (int, bool, etc.)
-# The trick it just to encapsulate the <<real>> value
-class PrimitiveInstance[E: Object]
-       super Instance
-
-       # The real value encapsulated
-       redef var val: E
-
-       init(mtype: MType, val: E)
-       do
-               super(mtype)
-               self.val = val
-       end
-
-       redef fun is_true
-       do
-               if val == true then return true
-               if val == false then return false
-               abort
-       end
-
-       redef fun ==(o)
-       do
-               if not o isa PrimitiveInstance[Object] then return false
-               return self.val == o.val
-       end
-
-       redef fun eq_is(o)
-       do
-               if not o isa PrimitiveInstance[Object] then return false
-               return self.val is o.val
-       end
-
-       redef fun to_s do return "{mtype}#{val.object_id}({val})"
-
-       redef fun to_i do return val.as(Int)
-end
-
-# Information about local variables in a running method
-private class Frame
-       # The current visited node
-       # The node is stored by frame to keep a stack trace
-       var current_node: ANode
-       # The executed property.
-       # A Method in case of a call, an attribute in case of a default initialization.
-       var mpropdef: MPropDef
-       # Arguments of the method (the first is te receiver
-       var arguments: Array[Instance]
-       # Mapping betwen a variable an the current value
-       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)
-       do
-               if v.modelbuilder.toolcontext.opt_no_color.value == true then
-                       print("{message} ({location.file.filename}:{location.line_start})")
-               else
-                       print("{location}: {message}\n{location.colored_line("0;31")}")
-                       print(v.stack_trace)
-               end
-               exit(1)
-       end
-end
-
-redef class APropdef
-       # Execute a `mpropdef' associated with the current node.
-       private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
-       do
-               fatal(v, "Unimplemented {mpropdef}")
-               abort
-       end
-end
-
-redef class AConcreteMethPropdef
-       redef fun call(v, mpropdef, args)
-       do
-               var f = new Frame(self, self.mpropdef.as(not null), args)
-               for i in [0..mpropdef.msignature.arity[ do
-                       var variable = self.n_signature.n_params[i].variable
-                       assert variable != null
-                       f.map[variable] = args[i+1]
-               end
-
-               v.frames.unshift(f)
-
-               # Call the implicit super-init
-               var auto_super_inits = self.auto_super_inits
-               if auto_super_inits != null then
-                       var selfarg = [args.first]
-                       for auto_super_init in auto_super_inits do
-                               if auto_super_init.intro.msignature.arity == 0 then
-                                       v.send(auto_super_init, selfarg)
-                               else
-                                       v.send(auto_super_init, args)
-                               end
-                       end
-               end
-
-               v.stmt(self.n_block)
-               v.frames.shift
-               v.returnmark = false
-               var res = v.escapevalue
-               v.escapevalue = null
-               return res
-       end
-end
-
-redef class AInternMethPropdef
-       redef fun call(v, mpropdef, args)
-       do
-               var pname = mpropdef.mproperty.name
-               var cname = mpropdef.mclassdef.mclass.name
-               if pname == "output" then
-                       var recv = args.first
-                       recv.val.output
-                       return null
-               else if pname == "object_id" then
-                       var recv = args.first
-                       if recv isa PrimitiveInstance[Object] then
-                               return v.int_instance(recv.val.object_id)
-                       else
-                               return v.int_instance(recv.object_id)
-                       end
-               else if pname == "output_class_name" then
-                       var recv = args.first
-                       print recv.mtype.as(MClassType).mclass
-                       return null
-               else if pname == "native_class_name" then
-                       var recv = args.first
-                       var txt = recv.mtype.as(MClassType).mclass.to_s
-                       return v.native_string_instance(txt)
-               else if pname == "==" then
-                       # == is correclt redefined for instances
-                       return v.bool_instance(args[0] == args[1])
-               else if pname == "!=" then
-                       return v.bool_instance(args[0] != args[1])
-               else if pname == "is_same_type" then
-                       return v.bool_instance(args[0].mtype == args[1].mtype)
-               else if pname == "exit" then
-                       exit(args[1].to_i)
-                       abort
-               else if pname == "sys" then
-                       return v.mainobj
-               else if cname == "Int" then
-                       if pname == "unary -" then
-                               return v.int_instance(-args[0].to_i)
-                       else if pname == "succ" then
-                               return v.int_instance(args[0].to_i + 1)
-                       else if pname == "prec" then
-                               return v.int_instance(args[0].to_i - 1)
-                       else if pname == "+" then
-                               return v.int_instance(args[0].to_i + args[1].to_i)
-                       else if pname == "-" then
-                               return v.int_instance(args[0].to_i - args[1].to_i)
-                       else if pname == "*" then
-                               return v.int_instance(args[0].to_i * args[1].to_i)
-                       else if pname == "%" then
-                               return v.int_instance(args[0].to_i % args[1].to_i)
-                       else if pname == "/" then
-                               return v.int_instance(args[0].to_i / args[1].to_i)
-                       else if pname == "<" then
-                               return v.bool_instance(args[0].to_i < args[1].to_i)
-                       else if pname == ">" then
-                               return v.bool_instance(args[0].to_i > args[1].to_i)
-                       else if pname == "<=" then
-                               return v.bool_instance(args[0].to_i <= args[1].to_i)
-                       else if pname == ">=" then
-                               return v.bool_instance(args[0].to_i >= args[1].to_i)
-                       else if pname == "<=>" then
-                               return v.int_instance(args[0].to_i <=> args[1].to_i)
-                       else if pname == "ascii" then
-                               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 == "lshift" then
-                               return v.int_instance(args[0].to_i.lshift(args[1].to_i))
-                       else if pname == "rshift" then
-                               return v.int_instance(args[0].to_i.rshift(args[1].to_i))
-                       end
-               else if cname == "Char" then
-                       var recv = args[0].val.as(Char)
-                       if pname == "ascii" then
-                               return v.int_instance(recv.ascii)
-                       else if pname == "succ" then
-                               return v.char_instance(recv.succ)
-                       else if pname == "prec" then
-                               return v.char_instance(recv.prec)
-                       else if pname == "<" then
-                               return v.bool_instance(recv < args[1].val.as(Char))
-                       else if pname == ">" then
-                               return v.bool_instance(recv > args[1].val.as(Char))
-                       else if pname == "<=" then
-                               return v.bool_instance(recv <= args[1].val.as(Char))
-                       else if pname == ">=" then
-                               return v.bool_instance(recv >= args[1].val.as(Char))
-                       else if pname == "<=>" then
-                               return v.int_instance(recv <=> args[1].val.as(Char))
-                       end
-               else if cname == "Float" then
-                       if pname == "+" then
-                               return v.float_instance(args[0].val.as(Float) + args[1].val.as(Float))
-                       else if pname == "-" then
-                               return v.float_instance(args[0].val.as(Float) - args[1].val.as(Float))
-                       else if pname == "*" then
-                               return v.float_instance(args[0].val.as(Float) * args[1].val.as(Float))
-                       else if pname == "/" then
-                               return v.float_instance(args[0].val.as(Float) / args[1].val.as(Float))
-                       else if pname == "to_i" then
-                               return v.int_instance(args[0].val.as(Float).to_i)
-                       end
-               else if cname == "NativeString" then
-                       var recvval = args.first.val.as(Buffer)
-                       if pname == "[]" then
-                               return v.char_instance(recvval[args[1].to_i])
-                       else if pname == "[]=" then
-                               recvval[args[1].to_i] = args[2].val.as(Char)
-                               return null
-                       else if pname == "copy_to" then
-                               # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
-                               recvval.copy(args[3].to_i, args[2].to_i, args[1].val.as(Buffer), args[4].to_i)
-                               return null
-                       else if pname == "atoi" then
-                               return v.int_instance(recvval.to_i)
-                       end
-               else if pname == "calloc_string" then
-                       return v.native_string_instance("!" * args[1].to_i)
-               else if cname == "NativeArray" then
-                       var recvval = args.first.val.as(Array[Instance])
-                       if pname == "[]" then
-                               if args[1].to_i >= recvval.length then
-                                       debug("Illegal access on {recvval} for element {args[1].to_i}/{recvval.length}")
-                               end
-                               return recvval[args[1].to_i]
-                       else if pname == "[]=" then
-                               recvval[args[1].to_i] = args[2]
-                               return null
-                       else if pname == "copy_to" then
-                               recvval.copy(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
-                               return null
-                       end
-               else if pname == "calloc_array" then
-                       var recvtype = args.first.mtype.as(MClassType)
-                       var mtype: MType = recvtype.supertype_to(v.mainmodule, recvtype, v.get_class("ArrayCapable"))
-                       mtype = mtype.as(MGenericType).arguments.first
-                       var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
-                       return new PrimitiveInstance[Array[Instance]](v.get_class("NativeArray").get_mtype([mtype]), val)
-               end
-               fatal(v, "Unimplemented intern {mpropdef}")
-               abort
-       end
-end
-
-redef class AbstractArray[E]
-       fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
-       do
-               self.copy_to(start, len, dest, new_start)
-       end
-end
-
-redef class AExternInitPropdef
-       redef fun call(v, mpropdef, args)
-       do
-               var pname = mpropdef.mproperty.name
-               var cname = mpropdef.mclassdef.mclass.name
-               if pname == "native_stdout" then
-                       return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stdout)
-               else if pname == "native_stdin" then
-                       return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, stdin)
-               else if pname == "native_stderr" then
-                       return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stderr)
-               else if pname == "io_open_read" then
-                       var a1 = args[1].val.as(Buffer)
-                       return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
-               else if pname == "io_open_write" then
-                       var a1 = args[1].val.as(Buffer)
-                       return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
-               end
-               fatal(v, "Unimplemented extern init {mpropdef}")
-               abort
-       end
-end
-
-redef class AExternMethPropdef
-       super TablesCapable
-       redef fun call(v, mpropdef, args)
-       do
-               var pname = mpropdef.mproperty.name
-               var cname = mpropdef.mclassdef.mclass.name
-               if cname == "NativeFile" then
-                       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))
-                               return args[2]
-                       else if pname == "io_read" then
-                               var str = recvval.as(IStream).read(args[2].to_i)
-                               var a1 = args[1].val.as(Buffer)
-                               new Buffer.from(str).copy(0, str.length, a1, 0)
-                               return v.int_instance(str.length)
-                       else if pname == "io_close" then
-                               recvval.as(IOS).close
-                               return v.int_instance(0)
-                       end
-               else if cname == "NativeString" then
-                       var recvval = args.first.val.as(Buffer)
-                       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
-                       else if pname == "get_environ" then
-                               var txt = args.first.val.as(Buffer).to_s.to_symbol.environ
-                               return v.native_string_instance(txt)
-                       end
-               else if pname == "native_argc" then
-                       return v.int_instance(v.arguments.length)
-               else if pname == "native_argv" then
-                       var txt = v.arguments[args[1].to_i]
-                       return v.native_string_instance(txt)
-               else if pname == "get_time" then
-                       return v.int_instance(get_time)
-               else if pname == "lexer_goto" then
-                       return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
-               else if pname == "lexer_accept" then
-                       return v.int_instance(lexer_accept(args[1].to_i))
-               else if pname == "parser_goto" then
-                       return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
-               else if pname == "parser_action" then
-                       return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
-               end
-               fatal(v, "Unimplemented extern {mpropdef}")
-               abort
-       end
-end
-
-redef class AAttrPropdef
-       redef fun call(v, mpropdef, args)
-       do
-               var attr = self.mpropdef.mproperty
-               if args.length == 1 then
-                       return v.read_attribute(attr, args.first)
-               else
-                       assert args.length == 2
-                       args.first.attributes[attr] = args[1]
-                       return null
-               end
-       end
-
-       # Evaluate and set the default value of the attribute in `recv'
-       private fun init_expr(v: NaiveInterpreter, recv: Instance)
-       do
-               var nexpr = self.n_expr
-               if nexpr != null then
-                       var f = new Frame(self, self.mpropdef.as(not null), [recv])
-                       v.frames.unshift(f)
-                       var val = v.expr(nexpr)
-                       v.frames.shift
-                       assert not v.is_escaping
-                       recv.attributes[self.mpropdef.mproperty] = val
-                       return
-               end
-               var mtype = self.mpropdef.static_mtype.as(not null)
-               # TODO The needinit info is statically computed, move it to modelbuilder or whatever
-               mtype = mtype.resolve_for(self.mpropdef.mclassdef.bound_mtype, self.mpropdef.mclassdef.bound_mtype, self.mpropdef.mclassdef.mmodule, true)
-               if mtype isa MNullableType then
-                       recv.attributes[self.mpropdef.mproperty] = v.null_instance
-               end
-       end
-end
-
-redef class AClassdef
-       # Execute an implicit `mpropdef' associated with the current node.
-       private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
-       do
-               var super_inits = self.super_inits
-               if super_inits != null then
-                       assert args.length == 1
-                       for su in super_inits do
-                               v.send(su, args)
-                       end
-                       return null
-               end
-               var recv = args.first
-               var i = 1
-               # Collect undefined attributes
-               for npropdef in self.n_propdefs do
-                       if npropdef isa AAttrPropdef and npropdef.n_expr == null then
-                               recv.attributes[npropdef.mpropdef.mproperty] = args[i]
-                               i += 1
-                       end
-               end
-               return null
-       end
-end
-
-redef class AExpr
-       # Evaluate the node as a possible expression.
-       # 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
-       do
-               fatal(v, "Unimplemented expr {class_name}")
-               abort
-       end
-
-       # 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)
-       do
-               expr(v)
-       end
-
-end
-
-redef class ABlockExpr
-       redef fun stmt(v)
-       do
-               for e in self.n_expr do
-                       v.stmt(e)
-                       if v.is_escaping then return
-               end
-       end
-end
-
-redef class AVardeclExpr
-       redef fun stmt(v)
-       do
-               var ne = self.n_expr
-               if ne != null then
-                       var i = v.expr(ne)
-                       v.frame.map[self.variable.as(not null)] = i
-               end
-       end
-end
-
-redef class AVarExpr
-       redef fun expr(v)
-       do
-               return v.frame.map[self.variable.as(not null)]
-       end
-end
-
-redef class AVarAssignExpr
-       redef fun stmt(v)
-       do
-               var i = v.expr(self.n_value)
-               v.frame.map[self.variable.as(not null)] = i
-       end
-end
-
-redef class AVarReassignExpr
-       redef fun stmt(v)
-       do
-               var vari = v.frame.map[self.variable.as(not null)]
-               var value = v.expr(self.n_value)
-               var res = v.send(reassign_property.mproperty, [vari, value])
-               assert res != null
-               v.frame.map[self.variable.as(not null)] = res
-       end
-end
-
-redef class ASelfExpr
-       redef fun expr(v)
-       do
-               return v.frame.arguments.first
-       end
-end
-
-redef class AContinueExpr
-       redef fun stmt(v)
-       do
-               v.continuemark = self.escapemark
-       end
-end
-
-redef class ABreakExpr
-       redef fun stmt(v)
-       do
-               v.breakmark = self.escapemark
-       end
-end
-
-redef class AReturnExpr
-       redef fun stmt(v)
-       do
-               var ne = self.n_expr
-               if ne != null then
-                       var i = v.expr(ne)
-                       v.escapevalue = i
-               end
-               v.returnmark = true
-       end
-end
-
-redef class AAbortExpr
-       redef fun stmt(v)
-       do
-               fatal(v, "Aborted")
-               exit(1)
-       end
-end
-
-redef class AIfExpr
-       redef fun stmt(v)
-       do
-               var cond = v.expr(self.n_expr)
-               if cond.is_true then
-                       v.stmt(self.n_then)
-               else
-                       v.stmt(self.n_else)
-               end
-       end
-end
-
-redef class AIfexprExpr
-       redef fun expr(v)
-       do
-               var cond = v.expr(self.n_expr)
-               if cond.is_true then
-                       return v.expr(self.n_then)
-               else
-                       return v.expr(self.n_else)
-               end
-       end
-end
-
-redef class ADoExpr
-       redef fun stmt(v)
-       do
-               v.stmt(self.n_block)
-               v.is_break(self.escapemark) # Clear the break (if any)
-       end
-end
-
-redef class AWhileExpr
-       redef fun stmt(v)
-       do
-               loop
-                       var cond = v.expr(self.n_expr)
-                       if not cond.is_true then return
-                       v.stmt(self.n_block)
-                       if v.is_break(self.escapemark) then return
-                       v.is_continue(self.escapemark) # Clear the break
-                       if v.is_escaping then return
-               end
-       end
-end
-
-redef class ALoopExpr
-       redef fun stmt(v)
-       do
-               loop
-                       v.stmt(self.n_block)
-                       if v.is_break(self.escapemark) then return
-                       v.is_continue(self.escapemark) # Clear the break
-                       if v.is_escaping then return
-               end
-       end
-end
-
-redef class AForExpr
-       redef fun stmt(v)
-       do
-               var col = v.expr(self.n_expr)
-               #self.debug("col {col}")
-               var iter = v.send(v.get_property("iterator", col), [col]).as(not null)
-               #self.debug("iter {iter}")
-               loop
-                       var isok = v.send(v.get_property("is_ok", iter), [iter]).as(not null)
-                       if not isok.is_true then return
-                       var item = v.send(v.get_property("item", iter), [iter]).as(not null)
-                       #self.debug("item {item}")
-                       v.frame.map[self.variables.first] = item
-                       v.stmt(self.n_block)
-                       if v.is_break(self.escapemark) then return
-                       v.is_continue(self.escapemark) # Clear the break
-                       if v.is_escaping then return
-                       v.send(v.get_property("next", iter), [iter])
-               end
-       end
-end
-
-redef class AAssertExpr
-       redef fun stmt(v)
-       do
-               var cond = v.expr(self.n_expr)
-               if not cond.is_true then
-                       v.stmt(self.n_else)
-                       if v.is_escaping then return
-                       var nid = self.n_id
-                       if nid != null then
-                               fatal(v, "Assert '{nid.text}' failed")
-                       else
-                               fatal(v, "Assert failed")
-                       end
-                       exit(1)
-               end
-       end
-end
-
-redef class AOrExpr
-       redef fun expr(v)
-       do
-               var cond = v.expr(self.n_expr)
-               if cond.is_true then return cond
-               return v.expr(self.n_expr2)
-       end
-end
-
-redef class AAndExpr
-       redef fun expr(v)
-       do
-               var cond = v.expr(self.n_expr)
-               if not cond.is_true then return cond
-               return v.expr(self.n_expr2)
-       end
-end
-
-redef class ANotExpr
-       redef fun expr(v)
-       do
-               var cond = v.expr(self.n_expr)
-               return v.bool_instance(not cond.is_true)
-       end
-end
-
-redef class AOrElseExpr
-       redef fun expr(v)
-       do
-               var i = v.expr(self.n_expr)
-               if i != v.null_instance then return i
-               return v.expr(self.n_expr2)
-       end
-end
-
-redef class AEeExpr
-       redef fun expr(v)
-       do
-               var i = v.expr(self.n_expr)
-               var i2 = v.expr(self.n_expr2)
-               return v.bool_instance(i.eq_is(i2))
-       end
-end
-
-redef class AIntExpr
-       redef fun expr(v)
-       do
-               return v.int_instance(self.value.as(not null))
-       end
-end
-
-redef class AFloatExpr
-       redef fun expr(v)
-       do
-               return v.float_instance(self.value.as(not null))
-       end
-end
-
-redef class ACharExpr
-       redef fun expr(v)
-       do
-               return v.char_instance(self.value.as(not null))
-       end
-end
-
-redef class AArrayExpr
-       redef fun expr(v)
-       do
-               var val = new Array[Instance]
-               for nexpr in self.n_exprs.n_exprs do
-                       val.add(v.expr(nexpr))
-               end
-               var mtype = v.unanchor_type(self.mtype.as(not null)).as(MGenericType)
-               var elttype = mtype.arguments.first
-               return v.array_instance(val, elttype)
-       end
-end
-
-redef class AStringFormExpr
-       redef fun expr(v)
-       do
-               var txt = self.value.as(not null)
-               var nat = v.native_string_instance(txt)
-               var res = new Instance(v.get_class("String").mclass_type)
-               v.init_instance(res)
-               v.send(v.get_property("from_cstring", res), [res, nat])
-               v.check_init_instance(res)
-               return res
-       end
-end
-
-redef class ASuperstringExpr
-       redef fun expr(v)
-       do
-               var array = new Array[Instance]
-               for nexpr in n_exprs do
-                       array.add(v.expr(nexpr))
-               end
-               var i = v.array_instance(array, v.get_class("Object").mclass_type)
-               var res = v.send(v.get_property("to_s", i), [i])
-               assert res != null
-               return res
-       end
-end
-
-redef class ACrangeExpr
-       redef fun expr(v)
-       do
-               var e1 = v.expr(self.n_expr)
-               var e2 = v.expr(self.n_expr2)
-               var mtype = v.unanchor_type(self.mtype.as(not null))
-               var res = new Instance(mtype)
-               v.init_instance(res)
-               v.send(v.get_property("init", res), [res, e1, e2])
-               v.check_init_instance(res)
-               return res
-       end
-end
-
-redef class AOrangeExpr
-       redef fun expr(v)
-       do
-               var e1 = v.expr(self.n_expr)
-               var e2 = v.expr(self.n_expr2)
-               var mtype = v.unanchor_type(self.mtype.as(not null))
-               var res = new Instance(mtype)
-               v.init_instance(res)
-               v.send(v.get_property("without_last", res), [res, e1, e2])
-               v.check_init_instance(res)
-               return res
-       end
-end
-
-redef class ATrueExpr
-       redef fun expr(v)
-       do
-               return v.bool_instance(true)
-       end
-end
-
-redef class AFalseExpr
-       redef fun expr(v)
-       do
-               return v.bool_instance(false)
-       end
-end
-
-redef class ANullExpr
-       redef fun expr(v)
-       do
-               return v.null_instance
-       end
-end
-
-redef class AIsaExpr
-       redef fun expr(v)
-       do
-               var i = v.expr(self.n_expr)
-               var mtype = v.unanchor_type(self.cast_type.as(not null))
-               return v.bool_instance(v.is_subtype(i.mtype, mtype))
-       end
-end
-
-redef class AAsCastExpr
-       redef fun expr(v)
-       do
-               var i = v.expr(self.n_expr)
-               var mtype = v.unanchor_type(self.mtype.as(not null))
-               if not v.is_subtype(i.mtype, mtype) then
-                       #fatal(v, "Cast failed expected {mtype}, got {i}")
-                       fatal(v, "Cast failed")
-               end
-               return i
-       end
-end
-
-redef class AAsNotnullExpr
-       redef fun expr(v)
-       do
-               var i = v.expr(self.n_expr)
-               var mtype = v.unanchor_type(self.mtype.as(not null))
-               if i.mtype isa MNullType then
-                       fatal(v, "Cast failed")
-               end
-               return i
-       end
-end
-
-redef class AParExpr
-       redef fun expr(v)
-       do
-               return v.expr(self.n_expr)
-       end
-end
-
-redef class AOnceExpr
-       redef fun expr(v)
-       do
-               if v.onces.has_key(self) then
-                       return v.onces[self]
-               else
-                       var res = v.expr(self.n_expr)
-                       v.onces[self] = res
-                       return res
-               end
-       end
-end
-
-redef class ASendExpr
-       redef fun expr(v)
-       do
-               var recv = v.expr(self.n_expr)
-               var args = [recv]
-               for a in compute_raw_arguments do
-                       args.add(v.expr(a))
-               end
-               var mproperty = self.mproperty.as(not null)
-               return v.send(mproperty, args)
-       end
-end
-
-redef class ASendReassignFormExpr
-       redef fun stmt(v)
-       do
-               var recv = v.expr(self.n_expr)
-               var args = [recv]
-               for a in compute_raw_arguments do
-                       args.add(v.expr(a))
-               end
-               var value = v.expr(self.n_value)
-
-               var mproperty = self.mproperty.as(not null)
-               var read = v.send(mproperty, args)
-               assert read != null
-
-               var write = v.send(self.reassign_property.mproperty, [read, value])
-               assert write != null
-
-               args.add(write)
-
-               v.send(self.write_mproperty.as(not null), args)
-       end
-end
-
-redef class ASuperExpr
-       redef fun expr(v)
-       do
-               var recv = v.frame.arguments.first
-               var args = [recv]
-               for a in self.n_args.n_exprs do
-                       args.add(v.expr(a))
-               end
-               if args.length == 1 then
-                       args = v.frame.arguments
-               end
-
-               var mproperty = self.mproperty
-               if mproperty != null then
-                       if mproperty.intro.msignature.arity == 0 then
-                               args = [recv]
-                       end
-                       # Super init call
-                       var res = v.send(mproperty, args)
-                       return res
-               end
-
-               # stantard call-next-method
-               var mpropdef = v.frame.mpropdef
-               # FIXME: we do not want an ugly static call!
-               var mpropdefs = mpropdef.mproperty.lookup_super_definitions(mpropdef.mclassdef.mmodule, mpropdef.mclassdef.bound_mtype)
-               if mpropdefs.length != 1 then
-                       debug("MPRODFEFS for super {mpropdef} for {recv}: {mpropdefs.join(", ")}")
-               end
-               mpropdef = mpropdefs.first
-               assert mpropdef isa MMethodDef
-               var res = v.call(mpropdef, args)
-               return res
-       end
-end
-
-redef class ANewExpr
-       redef fun expr(v)
-       do
-               var mtype = v.unanchor_type(self.mtype.as(not null))
-               var recv = new Instance(mtype)
-               v.init_instance(recv)
-               var args = [recv]
-               for a in self.n_args.n_exprs do
-                       args.add(v.expr(a))
-               end
-               var mproperty = self.mproperty.as(not null)
-               var res2 = v.send(mproperty, args)
-               if res2 != null then
-                       #self.debug("got {res2} from {mproperty}. drop {recv}")
-                       return res2
-               end
-               v.check_init_instance(recv)
-               return recv
-       end
-end
-
-redef class AAttrExpr
-       redef fun expr(v)
-       do
-               var recv = v.expr(self.n_expr)
-               var mproperty = self.mproperty.as(not null)
-               return v.read_attribute(mproperty, recv)
-       end
-end
-
-redef class AAttrAssignExpr
-       redef fun stmt(v)
-       do
-               var recv = v.expr(self.n_expr)
-               var i = v.expr(self.n_value)
-               var mproperty = self.mproperty.as(not null)
-               recv.attributes[mproperty] = i
-       end
-end
-
-redef class AAttrReassignExpr
-       redef fun stmt(v)
-       do
-               var recv = v.expr(self.n_expr)
-               var value = v.expr(self.n_value)
-               var mproperty = self.mproperty.as(not null)
-               var attr = v.read_attribute(mproperty, recv)
-               var res = v.send(reassign_property.mproperty, [attr, value])
-               assert res != null
-               recv.attributes[mproperty] = res
-       end
-end
-
-redef class AIssetAttrExpr
-       redef fun expr(v)
-       do
-               var recv = v.expr(self.n_expr)
-               var mproperty = self.mproperty.as(not null)
-               return v.bool_instance(recv.attributes.has_key(mproperty))
-       end
-end
-
-redef class ADebugTypeExpr
-       redef fun stmt(v)
-       do
-               # do nothing
-       end
-end