module naive_interpreter
import literal
-import typing
-import auto_super_init
-import frontend
import common_ffi
+import semantize
+private import parser::tables
redef class ToolContext
# --discover-call-trace
if initprop != null then
interpreter.send(initprop, [mainobj])
end
- var mainprop = mainmodule.try_get_primitive_method("main", sys_type.mclass)
+ 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
# Use this method, instead of `send` to execute and control the aditionnal behavior of the call-sites
fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
do
+ var initializers = callsite.mpropdef.initializers
+ if not initializers.is_empty then
+ assert initializers.length == arguments.length - 1 else debug("expected {initializers.length} got {arguments.length - 1}")
+ var recv = arguments.first
+ var i = 1
+ for p in initializers do
+ if p isa MMethod then
+ self.send(p, [recv, arguments[i]])
+ else if p isa MAttribute then
+ assert recv isa MutableInstance
+ recv.attributes[p] = arguments[i]
+ else abort
+ i += 1
+ end
+ return send(callsite.mproperty, [recv])
+ end
return send(callsite.mproperty, arguments)
end
recv.attributes[mproperty] = value
end
+ # Is the attribute `mproperty` initialized the instance `recv`?
+ fun isset_attribute(mproperty: MAttribute, recv: Instance): Bool
+ do
+ assert recv isa MutableInstance
+ return recv.attributes.has_key(mproperty)
+ end
+
# Collect attributes of a type in the order of their init
fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]
do
for i in [0..auto_super_init.msignature.arity+1[ do
args.add(arguments[i])
end
+ assert auto_super_init.mproperty != mpropdef.mproperty
v.callsite(auto_super_init, args)
end
end
+ if auto_super_call then
+ # standard call-next-method
+ var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
+ v.call_without_varargs(superpd, arguments)
+ end
if n_block != null then
v.stmt(self.n_block)
var recv = args.first
assert recv isa MutableInstance
var attr = self.mpropdef.mproperty
- if args.length == 1 then
- return v.read_attribute(attr, recv)
- else
+ if mpropdef == mreadpropdef then
+ assert args.length == 1
+ if not is_lazy or v.isset_attribute(attr, recv) then return v.read_attribute(attr, recv)
+ return evaluate_expr(v, recv)
+ else if mpropdef == mwritepropdef then
assert args.length == 2
v.write_attribute(attr, recv, args[1])
return null
+ else
+ abort
end
end
# Evaluate and set the default value of the attribute in `recv`
private fun init_expr(v: NaiveInterpreter, recv: Instance)
do
- assert recv isa MutableInstance
+ if is_lazy then return
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)
- assert val != null
- v.frames.shift
- assert not v.is_escaping
- v.write_attribute(self.mpropdef.mproperty, recv, val)
+ evaluate_expr(v, recv)
return
end
var mtype = self.mpropdef.static_mtype.as(not null)
v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
end
end
+
+ private fun evaluate_expr(v: NaiveInterpreter, recv: Instance): Instance
+ do
+ assert recv isa MutableInstance
+ var nexpr = self.n_expr
+ assert nexpr != null
+ var f = new Frame(self, self.mpropdef.as(not null), [recv])
+ v.frames.unshift(f)
+ var val = v.expr(nexpr)
+ assert val != null
+ v.frames.shift
+ assert not v.is_escaping
+ v.write_attribute(self.mpropdef.mproperty, recv, val)
+ return val
+ 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
+ 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
+ var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
+ v.call_without_varargs(superpd, args)
+ end
+ return null
+ end
+
var super_inits = self.super_inits
if super_inits != null then
var args_of_super = args
if recv == null then return null
if recv.mtype isa MNullType then fatal(v, "Receiver is null")
var mproperty = self.mproperty.as(not null)
- assert recv isa MutableInstance
- return v.bool_instance(recv.attributes.has_key(mproperty))
+ return v.bool_instance(v.isset_attribute(mproperty, recv))
end
end