import auto_super_init
import frontend
import common_ffi
+private import parser::tables
redef class ToolContext
# --discover-call-trace
return recv.attributes[mproperty]
end
+ # Replace in `recv` the value of the attribute `mproperty` by `value`
+ fun write_attribute(mproperty: MAttribute, recv: Instance, value: Instance)
+ do
+ assert recv isa MutableInstance
+ 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
else if pname == "rand" then
var res = recvval.rand
return v.int_instance(res)
+ else if pname == "bin_and" then
+ return v.int_instance(args[0].to_i.bin_and(args[1].to_i))
+ else if pname == "bin_or" then
+ return v.int_instance(args[0].to_i.bin_or(args[1].to_i))
+ else if pname == "bin_xor" then
+ return v.int_instance(args[0].to_i.bin_xor(args[1].to_i))
else if pname == "native_int_to_s" then
return v.native_string_instance(recvval.to_s)
else if pname == "strerror_ext" then
return v.bool_instance(args[0].to_f.is_inf != 0)
end
else if cname == "NativeString" then
+ if pname == "init" then
+ return v.native_string_instance("!" * args[1].to_i)
+ end
var recvval = args.first.val.as(Buffer)
if pname == "[]" then
var arg1 = args[1].to_i
else if pname == "calloc_string" then
return v.native_string_instance("!" * args[1].to_i)
else if cname == "NativeArray" then
+ if pname == "init" then
+ var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
+ return new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
+ end
var recvval = args.first.val.as(Array[Instance])
if pname == "[]" then
if args[1].to_i >= recvval.length or args[1].to_i < 0 then
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
- recv.attributes[attr] = args[1]
+ 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
- recv.attributes[self.mpropdef.mproperty] = val
+ evaluate_expr(v, recv)
return
end
var mtype = self.mpropdef.static_mtype.as(not null)
mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
if mtype isa MNullableType then
- recv.attributes[self.mpropdef.mproperty] = v.null_instance
+ 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
do
var super_inits = self.super_inits
if super_inits != null then
- assert args.length == 1
+ var args_of_super = args
+ if args.length > 1 then args_of_super = [args.first]
for su in super_inits do
- v.send(su, args)
+ v.send(su, args_of_super)
end
- return null
end
var recv = args.first
assert recv isa MutableInstance
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]
+ if npropdef isa AAttrPropdef and not npropdef.noinit and npropdef.n_expr == null then
+ v.write_attribute(npropdef.mpropdef.mproperty, recv, args[i])
i += 1
end
end
var recv = v.expr(self.n_expr)
if recv == null then return null
var args = [recv]
- for a in self.raw_arguments.as(not null) do
+ for a in self.raw_arguments do
var i = v.expr(a)
if i == null then return null
args.add(i)
var recv = v.expr(self.n_expr)
if recv == null then return
var args = [recv]
- for a in self.raw_arguments.as(not null) do
+ for a in self.raw_arguments do
var i = v.expr(a)
if i == null then return
args.add(i)
var i = v.expr(self.n_value)
if i == null then return
var mproperty = self.mproperty.as(not null)
- assert recv isa MutableInstance
- recv.attributes[mproperty] = i
+ v.write_attribute(mproperty, recv, i)
end
end
var attr = v.read_attribute(mproperty, recv)
var res = v.callsite(reassign_callsite, [attr, value])
assert res != null
- assert recv isa MutableInstance
- recv.attributes[mproperty] = res
+ v.write_attribute(mproperty, recv, res)
end
end
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