var modelbuilder: ModelBuilder
# The main module of the program (used to lookup method)
- var mainmodule: MModule
+ var mainmodule: MModule is writable
# The command line arguments of the interpreted program
# arguments.first is the program name
var escapemark: nullable EscapeMark = null
# The count of `catch` blocs that have been encountered and can catch an abort
- var catch_count = 0
+ var catch_count = 0 is writable
+
+ # The last error thrown on abort/runtime error where catch_count > 0
+ var last_error: nullable FatalError = null
# Is a return or a break or a continue executed?
# Use this function to know if you must skip the evaluation of statements
end
end
- # Return a new native string initialized with `txt`
- fun native_string_instance(txt: String): Instance
+ # Return a new C string initialized with `txt`
+ fun c_string_instance(txt: String): Instance
do
- var instance = native_string_instance_len(txt.byte_length+1)
+ var instance = c_string_instance_len(txt.byte_length+1)
var val = instance.val
val[txt.byte_length] = 0u8
txt.to_cstring.copy_to(val, txt.byte_length, 0, 0)
return instance
end
- # Return a new native string initialized with `txt`
- fun native_string_instance_from_ns(txt: CString, len: Int): Instance
+ # Return a new C string initialized with `txt`
+ fun c_string_instance_from_ns(txt: CString, len: Int): Instance
do
- var instance = native_string_instance_len(len)
+ var instance = c_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[CString]
+ # Return a new C string initialized of `length`
+ fun c_string_instance_len(length: Int): PrimitiveInstance[CString]
do
var val = new CString(length)
- var t = mainmodule.native_string_type
+ var t = mainmodule.c_string_type
var instance = new PrimitiveInstance[CString](t, val)
init_instance_primitive(instance)
return instance
# Return a new String instance for `txt`
fun string_instance(txt: String): Instance
do
- var nat = native_string_instance(txt)
- var res = self.send(self.force_get_primitive_method("to_s_full", nat.mtype), [nat, self.int_instance(txt.byte_length), self.int_instance(txt.length)])
+ var nat = c_string_instance(txt)
+ var res = self.send(self.force_get_primitive_method("to_s_unsafe", nat.mtype), [nat, self.int_instance(txt.byte_length), self.int_instance(txt.length), self.false_instance, self.false_instance])
assert res != null
return res
end
var error_instance = new MutableInstance(modelbuilder.model.null_type) is lazy
end
+# A runtime error
+class FatalError
+ # The error message
+ var message: String
+
+ # The problematic node, if any
+ var node: nullable ANode
+end
+
# An instance represents a value of the executed program.
abstract class Instance
# The dynamic type of the instance
# ASSERT: not self.mtype.is_anchored
var mtype: MType
- # return true if the instance is the true value.
- # return false if the instance is the true value.
- # else aborts
+ # Return `true` if the instance is the `true` value.
+ #
+ # Return `false` if the instance is the `false` value.
+ # Abort if the instance is not a boolean value.
fun is_true: Bool do abort
# Return true if `self` IS `o` (using the Nit semantic of is)
end
# Special instance to handle primitives values (int, bool, etc.)
-# The trick it just to encapsulate the <<real>> value
+# The trick is just to encapsulate the “real” value.
class PrimitiveInstance[E]
super Instance
# `v` is used to know if a colored message is displayed or not
fun fatal(v: NaiveInterpreter, message: String)
do
- if v.modelbuilder.toolcontext.opt_no_color.value == true then
+ # Abort if there is a `catch` block
+ if v.catch_count > 0 then
+ v.last_error = new FatalError(message, self)
+ abort
+ end
+
+ if v.modelbuilder.toolcontext.opt_no_color.value then
sys.stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
else
sys.stderr.write("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
else if pname == "native_class_name" then
var recv = args.first
var txt = recv.mtype.to_s
- return v.native_string_instance(txt)
+ return v.c_string_instance(txt)
else if pname == "==" then
# == is correctly redefined for instances
return v.bool_instance(args[0] == args[1])
else if pname == "is_same_instance" then
return v.bool_instance(args[0].eq_is(args[1]))
else if pname == "class_inheritance_metamodel_json" then
- return v.native_string_instance(v.mainmodule.flatten_mclass_hierarchy.to_thin_json)
+ return v.c_string_instance(v.mainmodule.flatten_mclass_hierarchy.to_thin_json)
else if pname == "exit" then
exit(args[1].to_i)
abort
end
else if cname == "CString" then
if pname == "new" then
- return v.native_string_instance_len(args[1].to_i)
+ return v.c_string_instance_len(args[1].to_i)
end
var recvval = args.first.val.as(CString)
if pname == "[]" then
return v.int_instance(recvval.atoi)
else if pname == "fast_cstring" then
var ns = recvval.fast_cstring(args[1].to_i)
- return v.native_string_instance(ns.to_s)
+ return v.c_string_instance(ns.to_s)
else if pname == "fetch_4_chars" then
- return v.int_instance(args[0].val.as(CString).fetch_4_chars(args[1].to_i))
+ return v.uint32_instance(args[0].val.as(CString).fetch_4_chars(args[1].to_i))
else if pname == "fetch_4_hchars" then
- return v.int_instance(args[0].val.as(CString).fetch_4_hchars(args[1].to_i))
+ return v.uint32_instance(args[0].val.as(CString).fetch_4_hchars(args[1].to_i))
else if pname == "utf8_length" then
return v.int_instance(args[0].val.as(CString).utf8_length(args[1].to_i, args[2].to_i))
end
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)
+ return v.c_string_instance(txt)
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
redef class AAbortExpr
redef fun stmt(v)
do
- # Abort as asked if there is no `catch` bloc
- if v.catch_count <= 0 then
- fatal(v, "Aborted")
- exit(1)
- else
- abort
- end
+ fatal(v, "Aborted")
+ exit(1)
end
end
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 ns = v.c_string_instance_from_ns(bytes.items, bytes.length)
var ln = v.int_instance(bytes.length)
var prop = to_bytes_with_copy
assert prop != null