return instance
end
+ # Return a new native string initialized with `txt`
+ fun native_string_instance_from_ns(txt: NativeString, len: Int): Instance
+ do
+ var instance = native_string_instance_len(len)
+ var val = instance.val
+ txt.copy_to(val, len, 0, 0)
+
+ return instance
+ end
+
# Return a new native string initialized of `length`
fun native_string_instance_len(length: Int): PrimitiveInstance[NativeString]
do
res.add(null_instance)
continue
end
- if param.is_vararg and map.vararg_decl > 0 then
- var vararg = exprs.sub(j, map.vararg_decl)
+ if param.is_vararg and args[i].vararg_decl > 0 then
+ var vararg = exprs.sub(j, args[i].vararg_decl)
var elttype = param.mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType))
var arg = self.array_instance(vararg, elttype)
res.add(arg)
do
var msignature = mpropdef.msignature.as(not null)
for i in [0..msignature.arity[ do
+ var mp = msignature.mparameters[i]
+
# skip test for vararg since the array is instantiated with the correct polymorphic type
- if msignature.vararg_rank == i then continue
+ if mp.is_vararg then continue
# skip if the cast is not required
var origmtype = mpropdef.mproperty.intro.msignature.mparameters[i].mtype
#print "{mpropdef}: {mpropdef.mproperty.intro.msignature.mparameters[i]}"
# get the parameter type
- var mtype = msignature.mparameters[i].mtype
+ var mtype = mp.mtype
var anchor = args.first.mtype.as(MClassType)
var amtype = mtype.anchor_to(self.mainmodule, anchor)
if not args[i+1].mtype.is_subtype(self.mainmodule, anchor, amtype) then
v.call(superpd, arguments)
end
+ # First, try intern
if mpropdef.is_intern or mpropdef.is_extern then
var res = intern_call(v, mpropdef, arguments)
if res != v.error_instance then return res
end
-
+ # Then, try extern
+ if mpropdef.is_extern then
+ var res = call_extern(v, mpropdef, arguments, f)
+ if res != v.error_instance then return res
+ end
+ # Else try block
if n_block != null then
v.stmt(self.n_block)
return null
end
+ # Fail if nothing succeed
if mpropdef.is_intern then
fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
else if mpropdef.is_extern then
- var res = call_extern(v, mpropdef, arguments, f)
- if res != v.error_instance then return res
+ fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
else
fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
end
# Call this extern method
protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
do
- fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
return v.error_instance
end
return v.bool_instance(recvval >= args[1].to_i)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_i)
+ else if pname == "&" then
+ return v.int_instance(recvval & args[1].to_i)
+ else if pname == "|" then
+ return v.int_instance(recvval | args[1].to_i)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_b" then
return v.int32_instance(recvval.to_i32)
else if pname == "to_u32" then
return v.uint32_instance(recvval.to_u32)
- else if pname == "rand" then
- var res = recvval.rand
- return v.int_instance(res)
end
else if cname == "Byte" then
var recvval = args[0].to_b
return v.bool_instance(recvval >= args[1].to_b)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_b)
+ else if pname == "&" then
+ return v.byte_instance(recvval & args[1].to_b)
+ else if pname == "|" then
+ return v.byte_instance(recvval | args[1].to_b)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_i" then
return v.float_instance(args[0].to_f.log)
else if pname == "pow" then
return v.float_instance(args[0].to_f.pow(args[1].to_f))
- else if pname == "rand" then
- return v.float_instance(args[0].to_f.rand)
else if pname == "abs" then
return v.float_instance(args[0].to_f.abs)
else if pname == "hypot_with" then
else if pname == "fast_cstring" then
var ns = recvval.fast_cstring(args[1].to_i)
return v.native_string_instance(ns.to_s)
+ else if pname == "fetch_4_chars" then
+ return v.int_instance(args[0].val.as(NativeString).fetch_4_chars(args[1].to_i))
+ else if pname == "fetch_4_hchars" then
+ return v.int_instance(args[0].val.as(NativeString).fetch_4_hchars(args[1].to_i))
+ else if pname == "utf8_length" then
+ return v.int_instance(args[0].val.as(NativeString).utf8_length(args[1].to_i, args[2].to_i))
end
else if pname == "calloc_string" then
return v.native_string_instance_len(args[1].to_i)
return evaluate_expr(v, recv, f)
else if mpropdef == mwritepropdef then
assert args.length == 2
- v.write_attribute(attr, recv, args[1])
+ var arg = args[1]
+ if is_optional and arg.mtype isa MNullType then
+ var f = v.new_frame(self, mpropdef, args)
+ arg = evaluate_expr(v, recv, f)
+ end
+ v.write_attribute(attr, recv, arg)
return null
else
abort
redef class AClassdef
# Execute an implicit `mpropdef` associated with the current node.
- private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
+ private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance]): nullable Instance
do
if mpropdef.mproperty.is_root_init then
- assert args.length == 1
+ assert arguments.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(superpd, args)
+ var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
+ v.call(superpd, arguments)
end
return null
else
v.callsite(method_start, [expr])
v.stmt(self.n_block)
v.is_escape(self.break_mark) # Clear the break
+
+ # Execute the finally without an escape
+ var old_mark = v.escapemark
+ v.escapemark = null
v.callsite(method_finish, [expr])
+ # Restore the escape unless another escape was provided
+ if v.escapemark == null then v.escapemark = old_mark
end
end
redef class ACharExpr
redef fun expr(v)
do
+ if is_ascii then return v.byte_instance(self.value.as(not null).ascii)
+ if is_code_point then return v.int_instance(self.value.as(not null).code_point)
return v.char_instance(self.value.as(not null))
end
end
end
end
+redef class AugmentedStringFormExpr
+ # Factorize the making of a `Regex` object from a literal prefixed string
+ fun make_re(v: NaiveInterpreter, rs: Instance): nullable Instance do
+ var tore = to_re
+ assert tore != null
+ var res = v.callsite(tore, [rs])
+ if res == null then
+ print "Cannot call property `to_re` on {self}"
+ abort
+ end
+ for j in suffix.chars do
+ if j == 'i' then
+ var prop = ignore_case
+ assert prop != null
+ v.callsite(prop, [res, v.bool_instance(true)])
+ continue
+ end
+ if j == 'm' then
+ var prop = newline
+ assert prop != null
+ v.callsite(prop, [res, v.bool_instance(true)])
+ continue
+ end
+ if j == 'b' then
+ var prop = extended
+ assert prop != null
+ v.callsite(prop, [res, v.bool_instance(false)])
+ continue
+ end
+ # Should not happen, this needs to be updated
+ # along with the addition of new suffixes
+ abort
+ end
+ return res
+ end
+end
+
redef class AStringFormExpr
- redef fun expr(v)
- do
- var txt = self.value.as(not null)
- return v.string_instance(txt)
+ redef fun expr(v) do return v.string_instance(value)
+end
+
+redef class AStringExpr
+ redef fun expr(v) do
+ var s = v.string_instance(value)
+ if is_string then return s
+ if is_bytestring then
+ var ns = v.native_string_instance_from_ns(bytes.items, bytes.length)
+ var ln = v.int_instance(bytes.length)
+ var prop = to_bytes_with_copy
+ assert prop != null
+ var res = v.callsite(prop, [ns, ln])
+ if res == null then
+ print "Cannot call property `to_bytes` on {self}"
+ abort
+ end
+ s = res
+ else if is_re then
+ var res = make_re(v, s)
+ assert res != null
+ s = res
+ else
+ print "Unimplemented prefix or suffix for {self}"
+ abort
+ end
+ return s
end
end
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
+ if is_re then res = make_re(v, res)
return res
end
end