1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Interpretation of a Nit program directly on the AST
18 module naive_interpreter
22 private import parser
::tables
24 private import model
::serialize_model
25 private import frontend
::explain_assert_api
27 redef class ToolContext
28 # --discover-call-trace
29 var opt_discover_call_trace
= new OptionBool("Trace calls of the first invocation of methods", "--discover-call-trace")
34 self.option_context
.add_option
(self.opt_discover_call_trace
)
38 redef class ModelBuilder
39 # Execute the program from the entry point (`Sys::main`) of the `mainmodule`
40 # `arguments` are the command-line arguments in order
42 # 1. the AST is fully loaded.
43 # 2. the model is fully built.
44 # 3. the instructions are fully analysed.
45 fun run_naive_interpreter
(mainmodule
: MModule, arguments
: Array[String])
48 self.toolcontext
.info
("*** START INTERPRETING ***", 1)
50 var interpreter
= new NaiveInterpreter(self, mainmodule
, arguments
)
51 interpreter
.start
(mainmodule
)
54 self.toolcontext
.info
("*** END INTERPRETING: {time1-time0} ***", 2)
58 # The visitor that interprets the Nit Program by walking on the AST
59 class NaiveInterpreter
60 # The modelbuilder that know the AST and its associations with the model
61 var modelbuilder
: ModelBuilder
63 # The main module of the program (used to lookup method)
64 var mainmodule
: MModule is writable
66 # The command line arguments of the interpreted program
67 # arguments.first is the program name
68 # arguments[1] is the first argument
69 var arguments
: Array[String]
71 # The main Sys instance
72 var mainobj
: nullable Instance is noinit
74 # Name of all supported functional names
75 var routine_types
: Set[String] = new HashSet[String]
79 if mainmodule
.model
.get_mclasses_by_name
("Bool") != null then
80 self.true_instance
= new PrimitiveInstance[Bool](mainmodule
.bool_type
, true)
81 init_instance_primitive
(self.true_instance
)
82 self.false_instance
= new PrimitiveInstance[Bool](mainmodule
.bool_type
, false)
83 init_instance_primitive
(self.false_instance
)
85 self.null_instance
= new PrimitiveInstance[nullable Object](mainmodule
.model
.null_type
, null)
87 routine_types
.add
("RoutineRef")
88 for name
in ["Proc", "Fun", "ProcRef", "FunRef"] do
89 # 20 is a magic number = upper limit of the arity of each functional class.
90 # i.e. Proc0, Proc1, ... Proc19
92 routine_types
.add
("{name}{i}")
97 # Starts the interpreter on the main module of a program
98 fun start
(mainmodule
: MModule) do
99 var interpreter
= self
100 var sys_type
= mainmodule
.sys_type
101 if sys_type
== null then return # no class Sys
102 var mainobj
= new MutableInstance(sys_type
)
103 interpreter
.mainobj
= mainobj
104 interpreter
.init_instance
(mainobj
)
105 var initprop
= mainmodule
.try_get_primitive_method
("init", sys_type
.mclass
)
106 if initprop
!= null then
107 interpreter
.send
(initprop
, [mainobj
])
109 var mainprop
= mainmodule
.try_get_primitive_method
("run", sys_type
.mclass
) or else
110 mainmodule
.try_get_primitive_method
("main", sys_type
.mclass
)
111 if mainprop
!= null then
112 interpreter
.send
(mainprop
, [mainobj
])
116 # Subtype test in the context of the mainmodule
117 fun is_subtype
(sub
, sup
: MType): Bool
119 return sub
.is_subtype
(self.mainmodule
, current_receiver_class
, sup
)
122 # Get a primitive method in the context of the main module
123 fun force_get_primitive_method
(name
: String, recv
: MType): MMethod
125 assert recv
isa MClassType
126 return self.modelbuilder
.force_get_primitive_method
(current_node
, name
, recv
.mclass
, self.mainmodule
)
129 # Is a return, a break or a continue executed?
130 # Set this mark to skip the evaluation until a labeled statement catch it with `is_escape`
131 var escapemark
: nullable EscapeMark = null
133 # The count of `catch` blocs that have been encountered and can catch an abort
134 var catch_count
= 0 is writable
136 # The last error thrown on abort/runtime error where catch_count > 0
137 var last_error
: nullable FatalError = null
139 # Is a return or a break or a continue executed?
140 # Use this function to know if you must skip the evaluation of statements
141 fun is_escaping
: Bool do return escapemark
!= null
143 # The value associated with the current return/break/continue, if any.
144 # Set the value when you set a escapemark.
145 # Read the value when you catch a mark or reach the end of a method
146 var escapevalue
: nullable Instance = null
148 # If there is a break/continue and is associated with `escapemark`, then return true and clear the mark.
149 # If there is no break/continue or if `escapemark` is null then return false.
150 # Use this function to catch a potential break/continue.
151 fun is_escape
(escapemark
: nullable EscapeMark): Bool
153 if escapemark
!= null and self.escapemark
== escapemark
then
154 self.escapemark
= null
161 # Evaluate `n` as an expression in the current context.
162 # Return the value of the expression.
163 # If `n` cannot be evaluated, then aborts.
164 fun expr
(n
: AExpr): nullable Instance
166 var frame
= self.frame
167 var old
= frame
.current_node
168 frame
.current_node
= n
169 #n.debug("IN Execute expr")
171 if i
== null and not self.is_escaping
then
172 n
.debug
("inconsitance: no value and not escaping.")
174 var implicit_cast_to
= n
.implicit_cast_to
175 if i
!= null and implicit_cast_to
!= null then
176 var mtype
= self.unanchor_type
(implicit_cast_to
)
177 if not self.is_subtype
(i
.mtype
, mtype
) then n
.fatal
(self, "Cast failed. Expected `{implicit_cast_to}`, got `{i.mtype}`")
180 #n.debug("OUT Execute expr: value is {i}")
181 #if not is_subtype(i.mtype, n.mtype.as(not null)) then n.debug("Expected {n.mtype.as(not null)} got {i}")
182 frame
.current_node
= old
186 # Evaluate `n` as a statement in the current context.
187 # Do nothing if `n` is null.
188 # If `n` cannot be evaluated, then aborts.
189 fun stmt
(n
: nullable AExpr)
191 if n
== null then return
193 if n
.comprehension
!= null then
194 var comprehension
= frame
.comprehension
.as(not null)
196 if i
!= null then comprehension
.add
(i
)
200 var frame
= self.frame
201 var old
= frame
.current_node
202 frame
.current_node
= n
204 frame
.current_node
= old
207 # Map used to store values of nodes that must be evaluated once in the system (`AOnceExpr`)
208 var onces
: Map[ANode, Instance] = new HashMap[ANode, Instance]
210 # Return the boolean instance associated with `val`.
211 fun bool_instance
(val
: Bool): Instance
213 if val
then return self.true_instance
else return self.false_instance
216 # Return the integer instance associated with `val`.
217 fun int_instance
(val
: Int): Instance
219 var t
= mainmodule
.int_type
220 var instance
= new PrimitiveInstance[Int](t
, val
)
221 init_instance_primitive
(instance
)
225 # Return the byte instance associated with `val`.
226 fun byte_instance
(val
: Byte): Instance
228 var t
= mainmodule
.byte_type
229 var instance
= new PrimitiveInstance[Byte](t
, val
)
230 init_instance_primitive
(instance
)
234 # Return the int8 instance associated with `val`.
235 fun int8_instance
(val
: Int8): Instance
237 var t
= mainmodule
.int8_type
238 var instance
= new PrimitiveInstance[Int8](t
, val
)
239 init_instance_primitive
(instance
)
243 # Return the int16 instance associated with `val`.
244 fun int16_instance
(val
: Int16): Instance
246 var t
= mainmodule
.int16_type
247 var instance
= new PrimitiveInstance[Int16](t
, val
)
248 init_instance_primitive
(instance
)
252 # Return the uint16 instance associated with `val`.
253 fun uint16_instance
(val
: UInt16): Instance
255 var t
= mainmodule
.uint16_type
256 var instance
= new PrimitiveInstance[UInt16](t
, val
)
257 init_instance_primitive
(instance
)
261 # Return the int32 instance associated with `val`.
262 fun int32_instance
(val
: Int32): Instance
264 var t
= mainmodule
.int32_type
265 var instance
= new PrimitiveInstance[Int32](t
, val
)
266 init_instance_primitive
(instance
)
270 # Return the uint32 instance associated with `val`.
271 fun uint32_instance
(val
: UInt32): Instance
273 var t
= mainmodule
.uint32_type
274 var instance
= new PrimitiveInstance[UInt32](t
, val
)
275 init_instance_primitive
(instance
)
279 # Return the char instance associated with `val`.
280 fun char_instance
(val
: Char): Instance
282 var t
= mainmodule
.char_type
283 var instance
= new PrimitiveInstance[Char](t
, val
)
284 init_instance_primitive
(instance
)
288 # Return the float instance associated with `val`.
289 fun float_instance
(val
: Float): Instance
291 var t
= mainmodule
.float_type
292 var instance
= new PrimitiveInstance[Float](t
, val
)
293 init_instance_primitive
(instance
)
297 # The unique instance of the `true` value.
298 var true_instance
: Instance is noinit
300 # The unique instance of the `false` value.
301 var false_instance
: Instance is noinit
303 # The unique instance of the `null` value.
304 var null_instance
: Instance is noinit
306 # Return a new array made of `values`.
307 # The dynamic type of the result is Array[elttype].
308 fun array_instance
(values
: Array[Instance], elttype
: MType): Instance
310 assert not elttype
.need_anchor
311 var nat
= new PrimitiveInstance[Array[Instance]](mainmodule
.native_array_type
(elttype
), values
)
312 init_instance_primitive
(nat
)
313 var mtype
= mainmodule
.array_type
(elttype
)
314 var res
= new MutableInstance(mtype
)
315 self.init_instance
(res
)
316 self.send
(self.force_get_primitive_method
("with_native", mtype
), [res
, nat
, self.int_instance
(values
.length
)])
320 # Return a instance associated to a primitive class
321 # Current primitive classes are `Int`, `Bool`, and `String`
322 fun value_instance
(object
: Object): Instance
324 if object
isa Int then
325 return int_instance
(object
)
326 else if object
isa Bool then
327 return bool_instance
(object
)
328 else if object
isa String then
329 return string_instance
(object
)
335 # Return a new C string initialized with `txt`
336 fun c_string_instance
(txt
: String): Instance
338 var instance
= c_string_instance_len
(txt
.byte_length
+1)
339 var val
= instance
.val
340 val
[txt
.byte_length
] = 0
341 txt
.to_cstring
.copy_to
(val
, txt
.byte_length
, 0, 0)
346 # Return a new C string initialized with `txt`
347 fun c_string_instance_from_ns
(txt
: CString, len
: Int): Instance
349 var instance
= c_string_instance_len
(len
)
350 var val
= instance
.val
351 txt
.copy_to
(val
, len
, 0, 0)
356 # Return a new C string instance sharing the same data space as `txt`
357 fun c_string_instance_fast_cstr
(txt
: CString, from
: Int): Instance
359 var ncstr
= txt
.fast_cstring
(from
)
360 var t
= mainmodule
.c_string_type
362 var instance
= new PrimitiveInstance[CString](t
, ncstr
)
363 init_instance_primitive
(instance
)
368 # Return a new C string initialized of `length`
369 fun c_string_instance_len
(length
: Int): PrimitiveInstance[CString]
371 var val
= new CString(length
)
373 var t
= mainmodule
.c_string_type
374 var instance
= new PrimitiveInstance[CString](t
, val
)
375 init_instance_primitive
(instance
)
379 # Return a new String instance for `txt`
380 fun string_instance
(txt
: String): Instance
382 var nat
= c_string_instance
(txt
)
383 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
])
388 # The virtual type of the frames used in the execution engine
391 # The current frame used to store local variables of the current method executed
392 fun frame
: FRAME do return frames
.first
394 # The stack of all frames. The first one is the current one.
395 var frames
= new List[FRAME]
397 # Return a stack trace. One line per function
398 fun stack_trace
: String
400 var b
= new FlatBuffer
401 b
.append
(",---- Stack trace -- - - -\n")
403 b
.append
("| {f.mpropdef} ({f.current_node.location})\n")
405 b
.append
("`------------------- - - -")
409 # The current node, used to print errors, debug and stack-traces
410 fun current_node
: nullable ANode
412 if frames
.is_empty
then return null
413 return frames
.first
.current_node
416 # The dynamic type of the current `self`
417 fun current_receiver_class
: MClassType
419 return frames
.first
.arguments
.first
.mtype
.as(MClassType)
422 # Initialize the environment for a call and return a new Frame
423 # *`node` The AST node
424 # *`mpropdef` The corresponding mpropdef
425 # *`args` Arguments of the call
426 fun new_frame
(node
: ANode, mpropdef
: MPropDef, args
: Array[Instance]): FRAME
428 return new InterpreterFrame(node
, mpropdef
, args
)
431 # Exit the program with a message
432 fun fatal
(message
: String)
434 var node
= current_node
438 node
.fatal
(self, message
)
443 # Debug on the current node
444 fun debug
(message
: String)
446 var node
= current_node
454 # Retrieve the value of the variable in the current frame
455 fun read_variable
(v
: Variable): Instance
457 var f
= frames
.first
.as(InterpreterFrame)
461 # Assign the value of the variable in the current frame
462 fun write_variable
(v
: Variable, value
: Instance)
464 var f
= frames
.first
.as(InterpreterFrame)
468 # Store known methods, used to trace methods as they are reached
469 var discover_call_trace
: Set[MMethodDef] = new HashSet[MMethodDef]
471 # Consumes an iterator of expressions and tries to map each element to
472 # its corresponding Instance.
474 # If any AExprs doesn't resolve to an Instance, then it returns null.
475 # Otherwise return an array of instances
476 fun aexprs_to_instances
(aexprs
: Iterator[AExpr]): nullable Array[Instance]
478 var accumulator
= new Array[Instance]
479 for aexpr
in aexprs
do
480 var instance
= expr
(aexpr
)
481 if instance
== null then return null
482 accumulator
.push
(instance
)
487 # Evaluate `args` as expressions in the call of `mpropdef` on `recv`.
488 # This method is used to manage varargs in signatures and returns the real array
489 # of instances to use in the call.
490 # Return `null` if one of the evaluation of the arguments return null.
491 fun varargize
(mpropdef
: MMethodDef, map
: nullable SignatureMap, recv
: Instance, args
: SequenceRead[AExpr]): nullable Array[Instance]
493 var msignature
= mpropdef
.new_msignature
or else mpropdef
.msignature
.as(not null)
494 var res
= new Array[Instance]
497 if msignature
.arity
== 0 then return res
500 assert args
.length
== msignature
.arity
else debug
("Expected {msignature.arity} args, got {args.length}")
501 var rest_args
= aexprs_to_instances
(args
.iterator
)
502 if rest_args
== null then return null
503 res
.append
(rest_args
)
507 # Eval in order of arguments, not parameters
508 var exprs
= aexprs_to_instances
(args
.iterator
)
509 if exprs
== null then return null
511 # Fill `res` with the result of the evaluation according to the mapping
512 for i
in [0..msignature
.arity
[ do
513 var param
= msignature
.mparameters
[i
]
514 var j
= map
.map
.get_or_null
(i
)
517 res
.add
(null_instance
)
520 if param
.is_vararg
and args
[i
].vararg_decl
> 0 then
521 var vararg
= exprs
.sub
(j
, args
[i
].vararg_decl
)
522 var elttype
= param
.mtype
.anchor_to
(self.mainmodule
, recv
.mtype
.as(MClassType))
523 var arg
= self.array_instance
(vararg
, elttype
)
532 # Execute `mpropdef` for a `args` (where `args[0]` is the receiver).
533 # Return a value if `mpropdef` is a function, or null if it is a procedure.
534 # The call is direct/static. There is no message-sending/late-binding.
535 fun call
(mpropdef
: MMethodDef, args
: Array[Instance]): nullable Instance
537 if self.modelbuilder
.toolcontext
.opt_discover_call_trace
.value
and not self.discover_call_trace
.has
(mpropdef
) then
538 self.discover_call_trace
.add mpropdef
539 self.debug
("Discovered {mpropdef}")
541 assert args
.length
== mpropdef
.msignature
.arity
+ 1 else debug
("Invalid arity for {mpropdef}. {args.length} arguments given.")
543 # Look for the AST node that implements the property
544 var val
= mpropdef
.constant_value
546 var node
= modelbuilder
.mpropdef2node
(mpropdef
)
547 if mpropdef
.is_abstract
then
549 self.frames
.unshift new_frame
(node
, mpropdef
, args
)
551 fatal
("Abstract method `{mpropdef.mproperty.name}` called on `{args.first.mtype}`")
555 if node
isa APropdef then
556 self.parameter_check
(node
, mpropdef
, args
)
557 return node
.call
(self, mpropdef
, args
)
558 else if node
isa AClassdef then
559 self.parameter_check
(node
, mpropdef
, args
)
560 return node
.call
(self, mpropdef
, args
)
561 else if node
!= null then
562 fatal
("Fatal Error: method {mpropdef} associated to unexpected AST node {node.location}")
564 else if val
!= null then
565 return value_instance
(val
)
567 fatal
("Fatal Error: method {mpropdef} not found in the AST")
572 # Execute type checks of covariant parameters
573 fun parameter_check
(node
: ANode, mpropdef
: MMethodDef, args
: Array[Instance])
575 var msignature
= mpropdef
.msignature
.as(not null)
576 for i
in [0..msignature
.arity
[ do
577 var mp
= msignature
.mparameters
[i
]
579 # skip test for vararg since the array is instantiated with the correct polymorphic type
580 if mp
.is_vararg
then continue
582 # skip if the cast is not required
583 var origmtype
= mpropdef
.mproperty
.intro
.msignature
.mparameters
[i
].mtype
584 if not origmtype
.need_anchor
then continue
586 #print "{mpropdef}: {mpropdef.mproperty.intro.msignature.mparameters[i]}"
588 # get the parameter type
590 var anchor
= args
.first
.mtype
.as(MClassType)
591 var amtype
= mtype
.anchor_to
(self.mainmodule
, anchor
)
592 if not args
[i
+1].mtype
.is_subtype
(self.mainmodule
, anchor
, amtype
) then
593 node
.fatal
(self, "Cast failed. Expected `{mtype}`, got `{args[i+1].mtype}`")
598 # Common code for runtime injected calls and normal calls
599 fun send_commons
(mproperty
: MMethod, args
: Array[Instance], mtype
: MType): nullable Instance
601 if mtype
isa MNullType then
602 if mproperty
.name
== "==" or mproperty
.name
== "is_same_instance" then
603 return self.bool_instance
(args
[0] == args
[1])
604 else if mproperty
.name
== "!=" then
605 return self.bool_instance
(args
[0] != args
[1])
607 #fatal("Receiver is null. {mproperty}. {args.join(" ")} {self.frame.current_node.class_name}")
608 fatal
("Receiver is null")
613 # Execute a full `callsite` for given `args`
614 # Use this method, instead of `send` to execute and control the additional behavior of the call-sites
615 fun callsite
(callsite
: nullable CallSite, arguments
: Array[Instance]): nullable Instance
617 if callsite
== null then return null
618 var initializers
= callsite
.mpropdef
.initializers
619 if not initializers
.is_empty
then
620 var recv
= arguments
.first
622 for p
in initializers
do
623 if p
isa MMethod then
625 for x
in p
.intro
.msignature
.mparameters
do
626 args
.add arguments
[i
]
630 else if p
isa MAttribute then
631 assert recv
isa MutableInstance
632 write_attribute
(p
, recv
, arguments
[i
])
636 assert i
== arguments
.length
638 return send
(callsite
.mproperty
, [recv
])
640 return send
(callsite
.mproperty
, arguments
)
643 # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
644 # Return a value if `mproperty` is a function, or null if it is a procedure.
645 # The call is polymorphic. There is a message-sending/late-binding according to the receiver (args[0]).
646 fun send
(mproperty
: MMethod, args
: Array[Instance]): nullable Instance
648 var recv
= args
.first
649 var mtype
= recv
.mtype
650 var ret
= send_commons
(mproperty
, args
, mtype
)
651 if ret
!= null then return ret
652 var propdef
= mproperty
.lookup_first_definition
(self.mainmodule
, mtype
)
653 return self.call
(propdef
, args
)
656 # Read the attribute `mproperty` of an instance `recv` and return its value.
657 # If the attribute in not yet initialized, then aborts with an error message.
658 fun read_attribute
(mproperty
: MAttribute, recv
: Instance): Instance
660 assert recv
isa MutableInstance
661 if not recv
.attributes
.has_key
(mproperty
) then
662 fatal
("Uninitialized attribute {mproperty.name}")
665 return recv
.attributes
[mproperty
]
668 # Replace in `recv` the value of the attribute `mproperty` by `value`
669 fun write_attribute
(mproperty
: MAttribute, recv
: Instance, value
: Instance)
671 assert recv
isa MutableInstance
672 recv
.attributes
[mproperty
] = value
675 # Is the attribute `mproperty` initialized the instance `recv`?
676 fun isset_attribute
(mproperty
: MAttribute, recv
: Instance): Bool
678 assert recv
isa MutableInstance
679 return recv
.attributes
.has_key
(mproperty
)
682 # Collect attributes of a type in the order of their init
683 fun collect_attr_propdef
(mtype
: MType): Array[AAttrPropdef]
685 var cache
= self.collect_attr_propdef_cache
686 if cache
.has_key
(mtype
) then return cache
[mtype
]
688 var res
= new Array[AAttrPropdef]
689 var cds
= mtype
.collect_mclassdefs
(self.mainmodule
).to_a
690 self.mainmodule
.linearize_mclassdefs
(cds
)
692 res
.add_all
(modelbuilder
.collect_attr_propdef
(cd
))
699 private var collect_attr_propdef_cache
= new HashMap[MType, Array[AAttrPropdef]]
701 # Fill the initial values of the newly created instance `recv`.
702 # `recv.mtype` is used to know what must be filled.
703 fun init_instance
(recv
: Instance)
705 for npropdef
in collect_attr_propdef
(recv
.mtype
) do
706 npropdef
.init_expr
(self, recv
)
710 # A hook to initialize a `PrimitiveInstance`
711 fun init_instance_primitive
(recv
: Instance) do end
713 # This function determines the correct type according to the receiver of the current propdef (self).
714 fun unanchor_type
(mtype
: MType): MType
716 return mtype
.anchor_to
(self.mainmodule
, current_receiver_class
)
719 # Placebo instance used to mark internal error result when `null` already have a meaning.
720 # TODO: replace with multiple return or something better
721 var error_instance
= new MutableInstance(modelbuilder
.model
.null_type
) is lazy
729 # The problematic node, if any
730 var node
: nullable ANode
733 # An instance represents a value of the executed program.
734 abstract class Instance
735 # The dynamic type of the instance
736 # ASSERT: not self.mtype.is_anchored
739 # Return `true` if the instance is the `true` value.
741 # Return `false` if the instance is the `false` value.
742 # Abort if the instance is not a boolean value.
743 fun is_true
: Bool do abort
745 # Return `true` if the instance is null.
746 # Return `false` otherwise.
747 fun is_null
: Bool do return mtype
isa MNullType
749 # Return true if `self` IS `o` (using the Nit semantic of is)
750 fun eq_is
(o
: Instance): Bool do return self.is_same_instance
(o
)
752 # Human readable object identity "Type#number"
753 redef fun to_s
do return "{mtype}"
755 # Return the integer value if the instance is an integer.
757 fun to_i
: Int do abort
759 # Return the integer value if the instance is a float.
761 fun to_f
: Float do abort
763 # Return the integer value if the instance is a byte.
765 fun to_b
: Byte do abort
767 # Return the integer value if the instance is a int8.
769 fun to_i8
: Int8 do abort
771 # Return the integer value if the instance is a int16.
773 fun to_i16
: Int16 do abort
775 # Return the integer value if the instance is a uint16.
777 fun to_u16
: UInt16 do abort
779 # Return the integer value if the instance is a int32.
781 fun to_i32
: Int32 do abort
783 # Return the integer value if the instance is a uint32.
785 fun to_u32
: UInt32 do abort
787 # The real value encapsulated if the instance is primitive.
789 fun val
: nullable Object do abort
792 # A instance with attribute (standards objects)
793 class MutableInstance
796 # The values of the attributes
797 var attributes
: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
800 # An instance with the original receiver and callsite (for function reference)
801 class CallrefInstance
804 # The original receiver
808 # var f = &a.toto # `a` is the original receiver
812 # The original callsite
816 # var f = &a.toto # `toto` is the original callsite
818 var callsite
: CallSite
821 # Special instance to handle primitives values (int, bool, etc.)
822 # The trick is just to encapsulate the “real” value.
823 class PrimitiveInstance[E
]
826 # The real value encapsulated
831 if val
== true then return true
832 if val
== false then return false
838 if not o
isa PrimitiveInstance[nullable Object] then return false
839 return self.val
== o
.val
844 if not o
isa PrimitiveInstance[nullable Object] then return false
845 return self.val
.is_same_instance
(o
.val
)
848 redef fun to_s
do return "{mtype}#{val.object_id}({val or else "null"})"
850 redef fun to_i
do return val
.as(Int)
852 redef fun to_f
do return val
.as(Float)
854 redef fun to_b
do return val
.as(Byte)
856 redef fun to_i8
do return val
.as(Int8)
858 redef fun to_i16
do return val
.as(Int16)
860 redef fun to_u16
do return val
.as(UInt16)
862 redef fun to_i32
do return val
.as(Int32)
864 redef fun to_u32
do return val
.as(UInt32)
867 # Information about local variables in a running method
869 # The current visited node
870 # The node is stored by frame to keep a stack trace
871 var current_node
: ANode
872 # The executed property.
873 # A Method in case of a call, an attribute in case of a default initialization.
874 var mpropdef
: MPropDef
875 # Arguments of the method (the first is the receiver)
876 var arguments
: Array[Instance]
877 # Indicate if the expression has an array comprehension form
878 var comprehension
: nullable Array[Instance] = null
881 # Implementation of a Frame with a Hashmap to store local variables
882 class InterpreterFrame
885 # Mapping between a variable and the current value
886 var map
: Map[Variable, Instance] = new HashMap[Variable, Instance]
890 # Aborts the program with a message
891 # `v` is used to know if a colored message is displayed or not
892 fun fatal
(v
: NaiveInterpreter, message
: String)
894 # Abort if there is a `catch` block
895 if v
.catch_count
> 0 then
896 v
.last_error
= new FatalError(message
, self)
900 if v
.modelbuilder
.toolcontext
.opt_no_color
.value
then
901 sys
.stderr
.write
("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
903 sys
.stderr
.write
("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
904 sys
.stderr
.write
(v
.stack_trace
)
905 sys
.stderr
.write
("\n")
912 # Execute a `mpropdef` associated with the current node.
913 private fun call
(v
: NaiveInterpreter, mpropdef
: MMethodDef, args
: Array[Instance]): nullable Instance
915 fatal
(v
, "NOT YET IMPLEMENTED method kind {class_name}. {mpropdef}")
920 redef class AMethPropdef
923 redef fun call
(v
, mpropdef
, args
)
925 var f
= v
.new_frame
(self, mpropdef
, args
)
926 var res
= call_commons
(v
, mpropdef
, args
, f
)
928 if v
.is_escape
(self.return_mark
) then
935 # Execution of the body of the method
937 # It handle the common special cases: super, intern, extern
938 fun call_commons
(v
: NaiveInterpreter, mpropdef
: MMethodDef, arguments
: Array[Instance], f
: Frame): nullable Instance
942 for i
in [0..mpropdef
.msignature
.arity
[ do
943 var variable
= self.n_signature
.n_params
[i
].variable
944 assert variable
!= null
945 v
.write_variable
(variable
, arguments
[i
+1])
948 # Call the implicit super-init
949 var auto_super_inits
= self.auto_super_inits
950 if auto_super_inits
!= null then
951 var args
= [arguments
.first
]
952 for auto_super_init
in auto_super_inits
do
954 for i
in [0..auto_super_init
.msignature
.arity
+1[ do
955 args
.add
(arguments
[i
])
957 assert auto_super_init
.mproperty
!= mpropdef
.mproperty
958 v
.callsite
(auto_super_init
, args
)
961 if auto_super_call
then
962 # standard call-next-method
963 var superpd
= mpropdef
.lookup_next_definition
(v
.mainmodule
, arguments
.first
.mtype
)
964 v
.call
(superpd
, arguments
)
968 if mpropdef
.is_intern
or mpropdef
.is_extern
then
969 var res
= intern_call
(v
, mpropdef
, arguments
)
970 if res
!= v
.error_instance
then return res
973 if mpropdef
.is_extern
then
974 var res
= call_extern
(v
, mpropdef
, arguments
, f
)
975 if res
!= v
.error_instance
then return res
978 if n_block
!= null then
983 # Fail if nothing succeed
984 if mpropdef
.is_intern
then
985 fatal
(v
, "NOT YET IMPLEMENTED intern {mpropdef}")
986 else if mpropdef
.is_extern
then
987 fatal
(v
, "NOT YET IMPLEMENTED extern {mpropdef}")
989 fatal
(v
, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
994 # Call this extern method
995 protected fun call_extern
(v
: NaiveInterpreter, mpropdef
: MMethodDef, arguments
: Array[Instance], f
: Frame): nullable Instance
997 return v
.error_instance
1000 # Interprets a intern or a shortcut extern method.
1001 # Returns the result for a function, `null` for a procedure, or `error_instance` if the method is unknown.
1002 private fun intern_call
(v
: NaiveInterpreter, mpropdef
: MMethodDef, args
: Array[Instance]): nullable Instance
1004 var pname
= mpropdef
.mproperty
.name
1005 var cname
= mpropdef
.mclassdef
.mclass
.name
1007 if pname
== "call" and v
.routine_types
.has
(cname
) then
1008 var routine
= args
.shift
1009 assert routine
isa CallrefInstance
1010 # Swap the receiver position with the original recv of the call form.
1011 args
.unshift routine
.recv
1012 var res
= v
.callsite
(routine
.callsite
, args
)
1013 # recover the old args state
1015 args
.unshift routine
1019 if pname
== "output" then
1020 var recv
= args
.first
1023 else if pname
== "object_id" then
1024 var recv
= args
.first
1025 if recv
isa PrimitiveInstance[Object] then
1026 return v
.int_instance
(recv
.val
.object_id
)
1028 return v
.int_instance
(recv
.object_id
)
1030 else if pname
== "output_class_name" then
1031 var recv
= args
.first
1034 else if pname
== "native_class_name" then
1035 var recv
= args
.first
1036 var txt
= recv
.mtype
.to_s
1037 return v
.c_string_instance
(txt
)
1038 else if pname
== "==" then
1039 # == is correctly redefined for instances
1040 return v
.bool_instance
(args
[0] == args
[1])
1041 else if pname
== "!=" then
1042 return v
.bool_instance
(args
[0] != args
[1])
1043 else if pname
== "is_same_type" then
1044 return v
.bool_instance
(args
[0].mtype
== args
[1].mtype
)
1045 else if pname
== "is_same_instance" then
1046 return v
.bool_instance
(args
[0].eq_is
(args
[1]))
1047 else if pname
== "class_inheritance_metamodel_json" then
1048 return v
.c_string_instance
(v
.mainmodule
.flatten_mclass_hierarchy
.to_thin_json
)
1049 else if pname
== "exit" then
1052 else if pname
== "buffer_mode_full" then
1053 return v
.int_instance
(sys
.buffer_mode_full
)
1054 else if pname
== "buffer_mode_line" then
1055 return v
.int_instance
(sys
.buffer_mode_line
)
1056 else if pname
== "buffer_mode_none" then
1057 return v
.int_instance
(sys
.buffer_mode_none
)
1058 else if pname
== "sys" then
1060 else if cname
== "Int" then
1061 var recvval
= args
[0].to_i
1062 if pname
== "unary -" then
1063 return v
.int_instance
(-recvval
)
1064 else if pname
== "unary +" then
1066 else if pname
== "+" then
1067 return v
.int_instance
(recvval
+ args
[1].to_i
)
1068 else if pname
== "-" then
1069 return v
.int_instance
(recvval
- args
[1].to_i
)
1070 else if pname
== "*" then
1071 return v
.int_instance
(recvval
* args
[1].to_i
)
1072 else if pname
== "%" then
1073 return v
.int_instance
(recvval
% args
[1].to_i
)
1074 else if pname
== "/" then
1075 return v
.int_instance
(recvval
/ args
[1].to_i
)
1076 else if pname
== "<" then
1077 return v
.bool_instance
(recvval
< args
[1].to_i
)
1078 else if pname
== ">" then
1079 return v
.bool_instance
(recvval
> args
[1].to_i
)
1080 else if pname
== "<=" then
1081 return v
.bool_instance
(recvval
<= args
[1].to_i
)
1082 else if pname
== ">=" then
1083 return v
.bool_instance
(recvval
>= args
[1].to_i
)
1084 else if pname
== "<=>" then
1085 return v
.int_instance
(recvval
<=> args
[1].to_i
)
1086 else if pname
== "&" then
1087 return v
.int_instance
(recvval
& args
[1].to_i
)
1088 else if pname
== "|" then
1089 return v
.int_instance
(recvval
| args
[1].to_i
)
1090 else if pname
== "to_f" then
1091 return v
.float_instance
(recvval
.to_f
)
1092 else if pname
== "to_b" then
1093 return v
.byte_instance
(recvval
.to_b
)
1094 else if pname
== "<<" then
1095 return v
.int_instance
(recvval
<< args
[1].to_i
)
1096 else if pname
== ">>" then
1097 return v
.int_instance
(recvval
>> args
[1].to_i
)
1098 else if pname
== "to_i8" then
1099 return v
.int8_instance
(recvval
.to_i8
)
1100 else if pname
== "to_i16" then
1101 return v
.int16_instance
(recvval
.to_i16
)
1102 else if pname
== "to_u16" then
1103 return v
.uint16_instance
(recvval
.to_u16
)
1104 else if pname
== "to_i32" then
1105 return v
.int32_instance
(recvval
.to_i32
)
1106 else if pname
== "to_u32" then
1107 return v
.uint32_instance
(recvval
.to_u32
)
1109 else if cname
== "Byte" then
1110 var recvval
= args
[0].to_b
1111 if pname
== "unary -" then
1112 return v
.byte_instance
(-recvval
)
1113 else if pname
== "unary +" then
1115 else if pname
== "+" then
1116 return v
.byte_instance
(recvval
+ args
[1].to_b
)
1117 else if pname
== "-" then
1118 return v
.byte_instance
(recvval
- args
[1].to_b
)
1119 else if pname
== "*" then
1120 return v
.byte_instance
(recvval
* args
[1].to_b
)
1121 else if pname
== "%" then
1122 return v
.byte_instance
(recvval
% args
[1].to_b
)
1123 else if pname
== "/" then
1124 return v
.byte_instance
(recvval
/ args
[1].to_b
)
1125 else if pname
== "<" then
1126 return v
.bool_instance
(recvval
< args
[1].to_b
)
1127 else if pname
== ">" then
1128 return v
.bool_instance
(recvval
> args
[1].to_b
)
1129 else if pname
== "<=" then
1130 return v
.bool_instance
(recvval
<= args
[1].to_b
)
1131 else if pname
== ">=" then
1132 return v
.bool_instance
(recvval
>= args
[1].to_b
)
1133 else if pname
== "<=>" then
1134 return v
.int_instance
(recvval
<=> args
[1].to_b
)
1135 else if pname
== "&" then
1136 return v
.byte_instance
(recvval
& args
[1].to_b
)
1137 else if pname
== "|" then
1138 return v
.byte_instance
(recvval
| args
[1].to_b
)
1139 else if pname
== "to_f" then
1140 return v
.float_instance
(recvval
.to_f
)
1141 else if pname
== "to_i" then
1142 return v
.int_instance
(recvval
.to_i
)
1143 else if pname
== "<<" then
1144 return v
.byte_instance
(recvval
<< args
[1].to_i
)
1145 else if pname
== ">>" then
1146 return v
.byte_instance
(recvval
>> args
[1].to_i
)
1147 else if pname
== "to_i8" then
1148 return v
.int8_instance
(recvval
.to_i8
)
1149 else if pname
== "to_i16" then
1150 return v
.int16_instance
(recvval
.to_i16
)
1151 else if pname
== "to_u16" then
1152 return v
.uint16_instance
(recvval
.to_u16
)
1153 else if pname
== "to_i32" then
1154 return v
.int32_instance
(recvval
.to_i32
)
1155 else if pname
== "to_u32" then
1156 return v
.uint32_instance
(recvval
.to_u32
)
1157 else if pname
== "byte_to_s_len" then
1158 return v
.int_instance
(recvval
.to_s
.length
)
1160 else if cname
== "Char" then
1161 var recv
= args
[0].val
.as(Char)
1162 if pname
== "successor" then
1163 return v
.char_instance
(recv
.successor
(args
[1].to_i
))
1164 else if pname
== "predecessor" then
1165 return v
.char_instance
(recv
.predecessor
(args
[1].to_i
))
1166 else if pname
== "<" then
1167 return v
.bool_instance
(recv
< args
[1].val
.as(Char))
1168 else if pname
== ">" then
1169 return v
.bool_instance
(recv
> args
[1].val
.as(Char))
1170 else if pname
== "<=" then
1171 return v
.bool_instance
(recv
<= args
[1].val
.as(Char))
1172 else if pname
== ">=" then
1173 return v
.bool_instance
(recv
>= args
[1].val
.as(Char))
1174 else if pname
== "<=>" then
1175 return v
.int_instance
(recv
<=> args
[1].val
.as(Char))
1177 else if cname
== "Float" then
1178 var recv
= args
[0].to_f
1179 if pname
== "unary -" then
1180 return v
.float_instance
(-recv
)
1181 else if pname
== "unary +" then
1183 else if pname
== "+" then
1184 return v
.float_instance
(recv
+ args
[1].to_f
)
1185 else if pname
== "-" then
1186 return v
.float_instance
(recv
- args
[1].to_f
)
1187 else if pname
== "*" then
1188 return v
.float_instance
(recv
* args
[1].to_f
)
1189 else if pname
== "/" then
1190 return v
.float_instance
(recv
/ args
[1].to_f
)
1191 else if pname
== "<" then
1192 return v
.bool_instance
(recv
< args
[1].to_f
)
1193 else if pname
== ">" then
1194 return v
.bool_instance
(recv
> args
[1].to_f
)
1195 else if pname
== "<=" then
1196 return v
.bool_instance
(recv
<= args
[1].to_f
)
1197 else if pname
== ">=" then
1198 return v
.bool_instance
(recv
>= args
[1].to_f
)
1199 else if pname
== "to_i" then
1200 return v
.int_instance
(recv
.to_i
)
1201 else if pname
== "to_b" then
1202 return v
.byte_instance
(recv
.to_b
)
1203 else if pname
== "to_i8" then
1204 return v
.int8_instance
(recv
.to_i8
)
1205 else if pname
== "to_i16" then
1206 return v
.int16_instance
(recv
.to_i16
)
1207 else if pname
== "to_u16" then
1208 return v
.uint16_instance
(recv
.to_u16
)
1209 else if pname
== "to_i32" then
1210 return v
.int32_instance
(recv
.to_i32
)
1211 else if pname
== "to_u32" then
1212 return v
.uint32_instance
(recv
.to_u32
)
1213 else if pname
== "cos" then
1214 return v
.float_instance
(args
[0].to_f
.cos
)
1215 else if pname
== "sin" then
1216 return v
.float_instance
(args
[0].to_f
.sin
)
1217 else if pname
== "tan" then
1218 return v
.float_instance
(args
[0].to_f
.tan
)
1219 else if pname
== "acos" then
1220 return v
.float_instance
(args
[0].to_f
.acos
)
1221 else if pname
== "asin" then
1222 return v
.float_instance
(args
[0].to_f
.asin
)
1223 else if pname
== "atan" then
1224 return v
.float_instance
(args
[0].to_f
.atan
)
1225 else if pname
== "sqrt" then
1226 return v
.float_instance
(args
[0].to_f
.sqrt
)
1227 else if pname
== "exp" then
1228 return v
.float_instance
(args
[0].to_f
.exp
)
1229 else if pname
== "log" then
1230 return v
.float_instance
(args
[0].to_f
.log
)
1231 else if pname
== "pow" then
1232 return v
.float_instance
(args
[0].to_f
.pow
(args
[1].to_f
))
1233 else if pname
== "abs" then
1234 return v
.float_instance
(args
[0].to_f
.abs
)
1235 else if pname
== "hypot_with" then
1236 return v
.float_instance
(args
[0].to_f
.hypot_with
(args
[1].to_f
))
1237 else if pname
== "is_nan" then
1238 return v
.bool_instance
(args
[0].to_f
.is_nan
)
1239 else if pname
== "is_inf_extern" then
1240 return v
.bool_instance
(args
[0].to_f
.is_inf
!= 0)
1241 else if pname
== "round" then
1242 return v
.float_instance
(args
[0].to_f
.round
)
1244 else if cname
== "CString" then
1245 if pname
== "new" then
1246 return v
.c_string_instance_len
(args
[1].to_i
)
1248 var recvval
= args
.first
.val
.as(CString)
1249 if pname
== "[]" then
1250 var arg1
= args
[1].to_i
1251 return v
.int_instance
(recvval
[arg1
])
1252 else if pname
== "[]=" then
1253 var arg1
= args
[1].to_i
1254 recvval
[arg1
] = args
[2].val
.as(Int)
1256 else if pname
== "copy_to" then
1257 # sig= copy_to(dest: CString, length: Int, from: Int, to: Int)
1258 var destval
= args
[1].val
.as(CString)
1259 var lenval
= args
[2].to_i
1260 var fromval
= args
[3].to_i
1261 var toval
= args
[4].to_i
1262 recvval
.copy_to
(destval
, lenval
, fromval
, toval
)
1264 else if pname
== "atoi" then
1265 return v
.int_instance
(recvval
.atoi
)
1266 else if pname
== "fast_cstring" then
1267 return v
.c_string_instance_fast_cstr
(args
[0].val
.as(CString), args
[1].to_i
)
1268 else if pname
== "fetch_4_chars" then
1269 return v
.uint32_instance
(args
[0].val
.as(CString).fetch_4_chars
(args
[1].to_i
))
1270 else if pname
== "fetch_4_hchars" then
1271 return v
.uint32_instance
(args
[0].val
.as(CString).fetch_4_hchars
(args
[1].to_i
))
1272 else if pname
== "utf8_length" then
1273 return v
.int_instance
(args
[0].val
.as(CString).utf8_length
(args
[1].to_i
, args
[2].to_i
))
1275 else if cname
== "NativeArray" then
1276 if pname
== "new" then
1277 var val
= new Array[Instance].filled_with
(v
.null_instance
, args
[1].to_i
)
1278 var instance
= new PrimitiveInstance[Array[Instance]](args
[0].mtype
, val
)
1279 v
.init_instance_primitive
(instance
)
1282 var recvval
= args
.first
.val
.as(Array[Instance])
1283 if pname
== "[]" then
1284 return recvval
[args
[1].to_i
]
1285 else if pname
== "[]=" then
1286 recvval
[args
[1].to_i
] = args
[2]
1288 else if pname
== "length" then
1289 return v
.int_instance
(recvval
.length
)
1290 else if pname
== "copy_to" then
1291 recvval
.copy_to
(0, args
[2].to_i
, args
[1].val
.as(Array[Instance]), 0)
1294 else if cname
== "Int8" then
1295 var recvval
= args
[0].to_i8
1296 if pname
== "unary -" then
1297 return v
.int8_instance
(-recvval
)
1298 else if pname
== "unary +" then
1300 else if pname
== "+" then
1301 return v
.int8_instance
(recvval
+ args
[1].to_i8
)
1302 else if pname
== "-" then
1303 return v
.int8_instance
(recvval
- args
[1].to_i8
)
1304 else if pname
== "*" then
1305 return v
.int8_instance
(recvval
* args
[1].to_i8
)
1306 else if pname
== "%" then
1307 return v
.int8_instance
(recvval
% args
[1].to_i8
)
1308 else if pname
== "/" then
1309 return v
.int8_instance
(recvval
/ args
[1].to_i8
)
1310 else if pname
== "<" then
1311 return v
.bool_instance
(recvval
< args
[1].to_i8
)
1312 else if pname
== ">" then
1313 return v
.bool_instance
(recvval
> args
[1].to_i8
)
1314 else if pname
== "<=" then
1315 return v
.bool_instance
(recvval
<= args
[1].to_i8
)
1316 else if pname
== ">=" then
1317 return v
.bool_instance
(recvval
>= args
[1].to_i8
)
1318 else if pname
== "<=>" then
1319 return v
.int_instance
(recvval
<=> args
[1].to_i8
)
1320 else if pname
== "to_f" then
1321 return v
.float_instance
(recvval
.to_f
)
1322 else if pname
== "to_i" then
1323 return v
.int_instance
(recvval
.to_i
)
1324 else if pname
== "to_b" then
1325 return v
.byte_instance
(recvval
.to_b
)
1326 else if pname
== "to_i16" then
1327 return v
.int16_instance
(recvval
.to_i16
)
1328 else if pname
== "to_u16" then
1329 return v
.uint16_instance
(recvval
.to_u16
)
1330 else if pname
== "to_i32" then
1331 return v
.int32_instance
(recvval
.to_i32
)
1332 else if pname
== "to_u32" then
1333 return v
.uint32_instance
(recvval
.to_u32
)
1334 else if pname
== "<<" then
1335 return v
.int8_instance
(recvval
<< (args
[1].to_i
))
1336 else if pname
== ">>" then
1337 return v
.int8_instance
(recvval
>> (args
[1].to_i
))
1338 else if pname
== "&" then
1339 return v
.int8_instance
(recvval
& args
[1].to_i8
)
1340 else if pname
== "|" then
1341 return v
.int8_instance
(recvval
| args
[1].to_i8
)
1342 else if pname
== "^" then
1343 return v
.int8_instance
(recvval ^ args
[1].to_i8
)
1344 else if pname
== "unary ~" then
1345 return v
.int8_instance
(~recvval
)
1347 else if cname
== "Int16" then
1348 var recvval
= args
[0].to_i16
1349 if pname
== "unary -" then
1350 return v
.int16_instance
(-recvval
)
1351 else if pname
== "unary +" then
1353 else if pname
== "+" then
1354 return v
.int16_instance
(recvval
+ args
[1].to_i16
)
1355 else if pname
== "-" then
1356 return v
.int16_instance
(recvval
- args
[1].to_i16
)
1357 else if pname
== "*" then
1358 return v
.int16_instance
(recvval
* args
[1].to_i16
)
1359 else if pname
== "%" then
1360 return v
.int16_instance
(recvval
% args
[1].to_i16
)
1361 else if pname
== "/" then
1362 return v
.int16_instance
(recvval
/ args
[1].to_i16
)
1363 else if pname
== "<" then
1364 return v
.bool_instance
(recvval
< args
[1].to_i16
)
1365 else if pname
== ">" then
1366 return v
.bool_instance
(recvval
> args
[1].to_i16
)
1367 else if pname
== "<=" then
1368 return v
.bool_instance
(recvval
<= args
[1].to_i16
)
1369 else if pname
== ">=" then
1370 return v
.bool_instance
(recvval
>= args
[1].to_i16
)
1371 else if pname
== "<=>" then
1372 return v
.int_instance
(recvval
<=> args
[1].to_i16
)
1373 else if pname
== "to_f" then
1374 return v
.float_instance
(recvval
.to_f
)
1375 else if pname
== "to_i" then
1376 return v
.int_instance
(recvval
.to_i
)
1377 else if pname
== "to_b" then
1378 return v
.byte_instance
(recvval
.to_b
)
1379 else if pname
== "to_i8" then
1380 return v
.int8_instance
(recvval
.to_i8
)
1381 else if pname
== "to_u16" then
1382 return v
.uint16_instance
(recvval
.to_u16
)
1383 else if pname
== "to_i32" then
1384 return v
.int32_instance
(recvval
.to_i32
)
1385 else if pname
== "to_u32" then
1386 return v
.uint32_instance
(recvval
.to_u32
)
1387 else if pname
== "<<" then
1388 return v
.int16_instance
(recvval
<< (args
[1].to_i
))
1389 else if pname
== ">>" then
1390 return v
.int16_instance
(recvval
>> (args
[1].to_i
))
1391 else if pname
== "&" then
1392 return v
.int16_instance
(recvval
& args
[1].to_i16
)
1393 else if pname
== "|" then
1394 return v
.int16_instance
(recvval
| args
[1].to_i16
)
1395 else if pname
== "^" then
1396 return v
.int16_instance
(recvval ^ args
[1].to_i16
)
1397 else if pname
== "unary ~" then
1398 return v
.int16_instance
(~recvval
)
1400 else if cname
== "UInt16" then
1401 var recvval
= args
[0].to_u16
1402 if pname
== "unary -" then
1403 return v
.uint16_instance
(-recvval
)
1404 else if pname
== "unary +" then
1406 else if pname
== "+" then
1407 return v
.uint16_instance
(recvval
+ args
[1].to_u16
)
1408 else if pname
== "-" then
1409 return v
.uint16_instance
(recvval
- args
[1].to_u16
)
1410 else if pname
== "*" then
1411 return v
.uint16_instance
(recvval
* args
[1].to_u16
)
1412 else if pname
== "%" then
1413 return v
.uint16_instance
(recvval
% args
[1].to_u16
)
1414 else if pname
== "/" then
1415 return v
.uint16_instance
(recvval
/ args
[1].to_u16
)
1416 else if pname
== "<" then
1417 return v
.bool_instance
(recvval
< args
[1].to_u16
)
1418 else if pname
== ">" then
1419 return v
.bool_instance
(recvval
> args
[1].to_u16
)
1420 else if pname
== "<=" then
1421 return v
.bool_instance
(recvval
<= args
[1].to_u16
)
1422 else if pname
== ">=" then
1423 return v
.bool_instance
(recvval
>= args
[1].to_u16
)
1424 else if pname
== "<=>" then
1425 return v
.int_instance
(recvval
<=> args
[1].to_u16
)
1426 else if pname
== "to_f" then
1427 return v
.float_instance
(recvval
.to_f
)
1428 else if pname
== "to_i" then
1429 return v
.int_instance
(recvval
.to_i
)
1430 else if pname
== "to_b" then
1431 return v
.byte_instance
(recvval
.to_b
)
1432 else if pname
== "to_i8" then
1433 return v
.int8_instance
(recvval
.to_i8
)
1434 else if pname
== "to_i16" then
1435 return v
.int16_instance
(recvval
.to_i16
)
1436 else if pname
== "to_i32" then
1437 return v
.int32_instance
(recvval
.to_i32
)
1438 else if pname
== "to_u32" then
1439 return v
.uint32_instance
(recvval
.to_u32
)
1440 else if pname
== "<<" then
1441 return v
.uint16_instance
(recvval
<< (args
[1].to_i
))
1442 else if pname
== ">>" then
1443 return v
.uint16_instance
(recvval
>> (args
[1].to_i
))
1444 else if pname
== "&" then
1445 return v
.uint16_instance
(recvval
& args
[1].to_u16
)
1446 else if pname
== "|" then
1447 return v
.uint16_instance
(recvval
| args
[1].to_u16
)
1448 else if pname
== "^" then
1449 return v
.uint16_instance
(recvval ^ args
[1].to_u16
)
1450 else if pname
== "unary ~" then
1451 return v
.uint16_instance
(~recvval
)
1453 else if cname
== "Int32" then
1454 var recvval
= args
[0].to_i32
1455 if pname
== "unary -" then
1456 return v
.int32_instance
(-recvval
)
1457 else if pname
== "unary +" then
1459 else if pname
== "+" then
1460 return v
.int32_instance
(recvval
+ args
[1].to_i32
)
1461 else if pname
== "-" then
1462 return v
.int32_instance
(recvval
- args
[1].to_i32
)
1463 else if pname
== "*" then
1464 return v
.int32_instance
(recvval
* args
[1].to_i32
)
1465 else if pname
== "%" then
1466 return v
.int32_instance
(recvval
% args
[1].to_i32
)
1467 else if pname
== "/" then
1468 return v
.int32_instance
(recvval
/ args
[1].to_i32
)
1469 else if pname
== "<" then
1470 return v
.bool_instance
(recvval
< args
[1].to_i32
)
1471 else if pname
== ">" then
1472 return v
.bool_instance
(recvval
> args
[1].to_i32
)
1473 else if pname
== "<=" then
1474 return v
.bool_instance
(recvval
<= args
[1].to_i32
)
1475 else if pname
== ">=" then
1476 return v
.bool_instance
(recvval
>= args
[1].to_i32
)
1477 else if pname
== "<=>" then
1478 return v
.int_instance
(recvval
<=> args
[1].to_i32
)
1479 else if pname
== "to_f" then
1480 return v
.float_instance
(recvval
.to_f
)
1481 else if pname
== "to_i" then
1482 return v
.int_instance
(recvval
.to_i
)
1483 else if pname
== "to_b" then
1484 return v
.byte_instance
(recvval
.to_b
)
1485 else if pname
== "to_i8" then
1486 return v
.int8_instance
(recvval
.to_i8
)
1487 else if pname
== "to_i16" then
1488 return v
.int16_instance
(recvval
.to_i16
)
1489 else if pname
== "to_u16" then
1490 return v
.uint16_instance
(recvval
.to_u16
)
1491 else if pname
== "to_u32" then
1492 return v
.uint32_instance
(recvval
.to_u32
)
1493 else if pname
== "<<" then
1494 return v
.int32_instance
(recvval
<< (args
[1].to_i
))
1495 else if pname
== ">>" then
1496 return v
.int32_instance
(recvval
>> (args
[1].to_i
))
1497 else if pname
== "&" then
1498 return v
.int32_instance
(recvval
& args
[1].to_i32
)
1499 else if pname
== "|" then
1500 return v
.int32_instance
(recvval
| args
[1].to_i32
)
1501 else if pname
== "^" then
1502 return v
.int32_instance
(recvval ^ args
[1].to_i32
)
1503 else if pname
== "unary ~" then
1504 return v
.int32_instance
(~recvval
)
1506 else if cname
== "UInt32" then
1507 var recvval
= args
[0].to_u32
1508 if pname
== "unary -" then
1509 return v
.uint32_instance
(-recvval
)
1510 else if pname
== "unary +" then
1512 else if pname
== "+" then
1513 return v
.uint32_instance
(recvval
+ args
[1].to_u32
)
1514 else if pname
== "-" then
1515 return v
.uint32_instance
(recvval
- args
[1].to_u32
)
1516 else if pname
== "*" then
1517 return v
.uint32_instance
(recvval
* args
[1].to_u32
)
1518 else if pname
== "%" then
1519 return v
.uint32_instance
(recvval
% args
[1].to_u32
)
1520 else if pname
== "/" then
1521 return v
.uint32_instance
(recvval
/ args
[1].to_u32
)
1522 else if pname
== "<" then
1523 return v
.bool_instance
(recvval
< args
[1].to_u32
)
1524 else if pname
== ">" then
1525 return v
.bool_instance
(recvval
> args
[1].to_u32
)
1526 else if pname
== "<=" then
1527 return v
.bool_instance
(recvval
<= args
[1].to_u32
)
1528 else if pname
== ">=" then
1529 return v
.bool_instance
(recvval
>= args
[1].to_u32
)
1530 else if pname
== "<=>" then
1531 return v
.int_instance
(recvval
<=> args
[1].to_u32
)
1532 else if pname
== "to_f" then
1533 return v
.float_instance
(recvval
.to_f
)
1534 else if pname
== "to_i" then
1535 return v
.int_instance
(recvval
.to_i
)
1536 else if pname
== "to_b" then
1537 return v
.byte_instance
(recvval
.to_b
)
1538 else if pname
== "to_i8" then
1539 return v
.int8_instance
(recvval
.to_i8
)
1540 else if pname
== "to_i16" then
1541 return v
.int16_instance
(recvval
.to_i16
)
1542 else if pname
== "to_u16" then
1543 return v
.uint16_instance
(recvval
.to_u16
)
1544 else if pname
== "to_i32" then
1545 return v
.int32_instance
(recvval
.to_i32
)
1546 else if pname
== "<<" then
1547 return v
.uint32_instance
(recvval
<< (args
[1].to_i
))
1548 else if pname
== ">>" then
1549 return v
.uint32_instance
(recvval
>> (args
[1].to_i
))
1550 else if pname
== "&" then
1551 return v
.uint32_instance
(recvval
& args
[1].to_u32
)
1552 else if pname
== "|" then
1553 return v
.uint32_instance
(recvval
| args
[1].to_u32
)
1554 else if pname
== "^" then
1555 return v
.uint32_instance
(recvval ^ args
[1].to_u32
)
1556 else if pname
== "unary ~" then
1557 return v
.uint32_instance
(~recvval
)
1559 else if pname
== "native_argc" then
1560 return v
.int_instance
(v
.arguments
.length
)
1561 else if pname
== "native_argv" then
1562 var txt
= v
.arguments
[args
[1].to_i
]
1563 return v
.c_string_instance
(txt
)
1564 else if pname
== "lexer_goto" then
1565 return v
.int_instance
(lexer_goto
(args
[1].to_i
, args
[2].to_i
))
1566 else if pname
== "lexer_accept" then
1567 return v
.int_instance
(lexer_accept
(args
[1].to_i
))
1568 else if pname
== "parser_goto" then
1569 return v
.int_instance
(parser_goto
(args
[1].to_i
, args
[2].to_i
))
1570 else if pname
== "parser_action" then
1571 return v
.int_instance
(parser_action
(args
[1].to_i
, args
[2].to_i
))
1573 return v
.error_instance
1577 redef class AAttrPropdef
1578 redef fun call
(v
, mpropdef
, args
)
1580 var recv
= args
.first
1581 assert recv
isa MutableInstance
1582 var attr
= self.mpropdef
.mproperty
1583 if mpropdef
== mreadpropdef
then
1584 assert args
.length
== 1
1585 if not is_lazy
or v
.isset_attribute
(attr
, recv
) then return v
.read_attribute
(attr
, recv
)
1586 var f
= v
.new_frame
(self, mpropdef
, args
)
1587 return evaluate_expr
(v
, recv
, f
)
1588 else if mpropdef
== mwritepropdef
then
1589 assert args
.length
== 2
1591 if is_optional
and arg
.is_null
then
1592 var f
= v
.new_frame
(self, mpropdef
, args
)
1593 arg
= evaluate_expr
(v
, recv
, f
)
1595 v
.write_attribute
(attr
, recv
, arg
)
1602 # Evaluate and set the default value of the attribute in `recv`
1603 private fun init_expr
(v
: NaiveInterpreter, recv
: Instance)
1605 if is_lazy
or is_optional
then return
1607 var f
= v
.new_frame
(self, mreadpropdef
.as(not null), [recv
])
1608 evaluate_expr
(v
, recv
, f
)
1611 var mpropdef
= self.mpropdef
1612 if mpropdef
== null then return
1613 var mtype
= self.mtype
.as(not null)
1614 mtype
= mtype
.anchor_to
(v
.mainmodule
, recv
.mtype
.as(MClassType))
1615 if mtype
isa MNullableType then
1616 v
.write_attribute
(self.mpropdef
.mproperty
, recv
, v
.null_instance
)
1620 private fun evaluate_expr
(v
: NaiveInterpreter, recv
: Instance, f
: Frame): Instance
1622 assert recv
isa MutableInstance
1627 var nexpr
= self.n_expr
1628 var nblock
= self.n_block
1629 if nexpr
!= null then
1631 else if nblock
!= null then
1633 assert v
.escapemark
== return_mark
1642 assert not v
.is_escaping
1643 v
.write_attribute
(self.mpropdef
.mproperty
, recv
, val
)
1648 redef class AClassdef
1649 # Execute an implicit `mpropdef` associated with the current node.
1650 private fun call
(v
: NaiveInterpreter, mpropdef
: MMethodDef, arguments
: Array[Instance]): nullable Instance
1652 if mpropdef
.mproperty
.is_root_init
then
1653 assert arguments
.length
== 1
1654 if not mpropdef
.is_intro
then
1655 # standard call-next-method
1656 var superpd
= mpropdef
.lookup_next_definition
(v
.mainmodule
, arguments
.first
.mtype
)
1657 v
.call
(superpd
, arguments
)
1667 # Evaluate the node as a possible expression.
1668 # Return a possible value
1669 # NOTE: Do not call this method directly, but use `v.expr`
1670 # This method is here to be implemented by subclasses.
1671 protected fun expr
(v
: NaiveInterpreter): nullable Instance
1673 fatal
(v
, "NOT YET IMPLEMENTED expr {class_name}")
1677 # Evaluate the node as a statement.
1678 # NOTE: Do not call this method directly, but use `v.stmt`
1679 # This method is here to be implemented by subclasses (no need to return something).
1680 protected fun stmt
(v
: NaiveInterpreter)
1687 redef class ABlockExpr
1690 var last
= self.n_expr
.last
1691 for e
in self.n_expr
do
1692 if e
== last
then break
1694 if v
.is_escaping
then return null
1701 for e
in self.n_expr
do
1703 if v
.is_escaping
then return
1708 redef class AVardeclExpr
1711 var ne
= self.n_expr
1714 if i
== null then return null
1715 v
.write_variable
(self.variable
.as(not null), i
)
1722 redef class AVarExpr
1725 return v
.read_variable
(self.variable
.as(not null))
1729 redef class AVarAssignExpr
1732 var i
= v
.expr
(self.n_value
)
1733 if i
== null then return null
1734 v
.write_variable
(self.variable
.as(not null), i
)
1739 redef class AVarReassignExpr
1742 var variable
= self.variable
.as(not null)
1743 var vari
= v
.read_variable
(variable
)
1744 var value
= v
.expr
(self.n_value
)
1745 if value
== null then return
1746 var res
= v
.callsite
(reassign_callsite
, [vari
, value
])
1748 v
.write_variable
(variable
, res
)
1752 redef class ASelfExpr
1755 return v
.frame
.arguments
.first
1759 redef class AImplicitSelfExpr
1762 if not is_sys
then return super
1767 redef class AEscapeExpr
1770 var ne
= self.n_expr
1773 if i
== null then return
1776 v
.escapevalue
= null
1778 v
.escapemark
= self.escapemark
1782 redef class AAbortExpr
1793 var cond
= v
.expr
(self.n_expr
)
1794 if cond
== null then return null
1795 if cond
.is_true
then
1796 return v
.expr
(self.n_then
.as(not null))
1798 return v
.expr
(self.n_else
.as(not null))
1804 var cond
= v
.expr
(self.n_expr
)
1805 if cond
== null then return
1806 if cond
.is_true
then
1814 redef class AIfexprExpr
1817 var cond
= v
.expr
(self.n_expr
)
1818 if cond
== null then return null
1819 if cond
.is_true
then
1820 return v
.expr
(self.n_then
)
1822 return v
.expr
(self.n_else
)
1830 # If this bloc has a catch, handle it with a do ... catch ... end
1831 if self.n_catch
!= null then
1835 v
.stmt
(self.n_block
)
1836 v
.is_escape
(self.break_mark
) # Clear the break (if any)
1839 # Restore the current frame if needed
1840 while v
.frame
!= frame
do v
.frames
.shift
1842 v
.stmt
(self.n_catch
)
1845 v
.stmt
(self.n_block
)
1846 v
.is_escape
(self.break_mark
)
1851 redef class AWhileExpr
1855 var cond
= v
.expr
(self.n_expr
)
1856 if cond
== null then return
1857 if not cond
.is_true
then return
1858 v
.stmt
(self.n_block
)
1859 if v
.is_escape
(self.break_mark
) then return
1860 v
.is_escape
(self.continue_mark
) # Clear the break
1861 if v
.is_escaping
then return
1866 redef class ALoopExpr
1870 v
.stmt
(self.n_block
)
1871 if v
.is_escape
(self.break_mark
) then return
1872 v
.is_escape
(self.continue_mark
) # Clear the break
1873 if v
.is_escaping
then return
1878 redef class AForExpr
1881 var iters
= new Array[Instance]
1883 for g
in n_groups
do
1884 var col
= v
.expr
(g
.n_expr
)
1885 if col
== null then return
1886 if col
.is_null
then fatal
(v
, "Receiver is null")
1888 var iter
= v
.callsite
(g
.method_iterator
, [col
]).as(not null)
1893 for g
in n_groups
, iter
in iters
do
1894 var isok
= v
.callsite
(g
.method_is_ok
, [iter
]).as(not null)
1895 if not isok
.is_true
then break label
1896 if g
.variables
.length
== 1 then
1897 var item
= v
.callsite
(g
.method_item
, [iter
]).as(not null)
1898 #self.debug("item {item}")
1899 v
.write_variable
(g
.variables
.first
, item
)
1900 else if g
.variables
.length
== 2 then
1901 var key
= v
.callsite
(g
.method_key
, [iter
]).as(not null)
1902 v
.write_variable
(g
.variables
[0], key
)
1903 var item
= v
.callsite
(g
.method_item
, [iter
]).as(not null)
1904 v
.write_variable
(g
.variables
[1], item
)
1909 v
.stmt
(self.n_block
)
1910 if v
.is_escape
(self.break_mark
) then break
1911 v
.is_escape
(self.continue_mark
) # Clear the break
1912 if v
.is_escaping
then break
1913 for g
in n_groups
, iter
in iters
do
1914 v
.callsite
(g
.method_next
, [iter
])
1917 for g
in n_groups
, iter
in iters
do
1918 var method_finish
= g
.method_finish
1919 if method_finish
!= null then
1920 v
.callsite
(method_finish
, [iter
])
1926 redef class AWithExpr
1929 var expr
= v
.expr
(self.n_expr
)
1930 if expr
== null then return
1932 v
.callsite
(method_start
, [expr
])
1933 v
.stmt
(self.n_block
)
1934 v
.is_escape
(self.break_mark
) # Clear the break
1936 # Execute the finally without an escape
1937 var old_mark
= v
.escapemark
1939 v
.callsite
(method_finish
, [expr
])
1940 # Restore the escape unless another escape was provided
1941 if v
.escapemark
== null then v
.escapemark
= old_mark
1945 redef class AAssertExpr
1948 var cond
= v
.expr
(self.n_expr
)
1949 if cond
== null then return
1950 if not cond
.is_true
then
1952 if v
.is_escaping
then return
1954 # Explain assert if it fails
1955 var explain_assert_str
= explain_assert_str
1956 if explain_assert_str
!= null then
1957 var i
= v
.expr
(explain_assert_str
)
1958 if i
isa MutableInstance then
1959 var res
= v
.send
(v
.force_get_primitive_method
("to_cstring", i
.mtype
), [i
])
1963 print_error
"Runtime assert: {val.to_s}"
1971 fatal
(v
, "Assert '{nid.text}' failed")
1973 fatal
(v
, "Assert failed")
1983 var cond
= v
.expr
(self.n_expr
)
1984 if cond
== null then return null
1985 if cond
.is_true
then return cond
1986 return v
.expr
(self.n_expr2
)
1990 redef class AImpliesExpr
1993 var cond
= v
.expr
(self.n_expr
)
1994 if cond
== null then return null
1995 if not cond
.is_true
then return v
.true_instance
1996 return v
.expr
(self.n_expr2
)
2000 redef class AAndExpr
2003 var cond
= v
.expr
(self.n_expr
)
2004 if cond
== null then return null
2005 if not cond
.is_true
then return cond
2006 return v
.expr
(self.n_expr2
)
2010 redef class ANotExpr
2013 var cond
= v
.expr
(self.n_expr
)
2014 if cond
== null then return null
2015 return v
.bool_instance
(not cond
.is_true
)
2019 redef class AOrElseExpr
2022 var i
= v
.expr
(self.n_expr
)
2023 if i
== null then return null
2024 if i
!= v
.null_instance
then return i
2025 return v
.expr
(self.n_expr2
)
2029 redef class AIntegerExpr
2032 if value
isa Int then return v
.int_instance
(value
.as(Int))
2033 if value
isa Byte then return v
.byte_instance
(value
.as(Byte))
2034 if value
isa Int8 then return v
.int8_instance
(value
.as(Int8))
2035 if value
isa Int16 then return v
.int16_instance
(value
.as(Int16))
2036 if value
isa UInt16 then return v
.uint16_instance
(value
.as(UInt16))
2037 if value
isa Int32 then return v
.int32_instance
(value
.as(Int32))
2038 if value
isa UInt32 then return v
.uint32_instance
(value
.as(UInt32))
2043 redef class AFloatExpr
2046 return v
.float_instance
(self.value
.as(not null))
2050 redef class ACharExpr
2053 if is_code_point
then
2054 return v
.int_instance
(self.value
.as(not null).code_point
)
2056 return v
.char_instance
(self.value
.as(not null))
2060 redef class AArrayExpr
2063 var val
= new Array[Instance]
2064 var old_comprehension
= v
.frame
.comprehension
2065 v
.frame
.comprehension
= val
2066 for nexpr
in self.n_exprs
do
2067 if nexpr
isa AForExpr then
2070 var i
= v
.expr
(nexpr
)
2071 if i
== null then return null
2075 v
.frame
.comprehension
= old_comprehension
2076 var mtype
= v
.unanchor_type
(self.mtype
.as(not null)).as(MClassType)
2077 var elttype
= mtype
.arguments
.first
2078 return v
.array_instance
(val
, elttype
)
2082 redef class AugmentedStringFormExpr
2083 # Factorize the making of a `Regex` object from a literal prefixed string
2084 fun make_re
(v
: NaiveInterpreter, rs
: Instance): nullable Instance do
2087 var res
= v
.callsite
(tore
, [rs
])
2089 print
"Cannot call property `to_re` on {self}"
2092 for j
in suffix
.chars
do
2094 var prop
= ignore_case
2096 v
.callsite
(prop
, [res
, v
.bool_instance
(true)])
2102 v
.callsite
(prop
, [res
, v
.bool_instance
(true)])
2108 v
.callsite
(prop
, [res
, v
.bool_instance
(false)])
2111 # Should not happen, this needs to be updated
2112 # along with the addition of new suffixes
2119 redef class AStringFormExpr
2120 redef fun expr
(v
) do return v
.string_instance
(value
)
2123 redef class AStringExpr
2124 redef fun expr
(v
) do
2125 var s
= v
.string_instance
(value
)
2126 if is_string
then return s
2127 if is_bytestring
then
2128 var ns
= v
.c_string_instance_from_ns
(bytes
.items
, bytes
.length
)
2129 var ln
= v
.int_instance
(bytes
.length
)
2130 var prop
= to_bytes_with_copy
2132 var res
= v
.callsite
(prop
, [ns
, ln
])
2134 print
"Cannot call property `to_bytes` on {self}"
2139 var res
= make_re
(v
, s
)
2143 print
"Unimplemented prefix or suffix for {self}"
2150 redef class ASuperstringExpr
2153 var array
= new Array[Instance]
2154 for nexpr
in n_exprs
do
2155 var i
= v
.expr
(nexpr
)
2156 if i
== null then return null
2159 var i
= v
.array_instance
(array
, v
.mainmodule
.object_type
)
2160 var res
= v
.send
(v
.force_get_primitive_method
("plain_to_s", i
.mtype
), [i
])
2162 if is_re
then res
= make_re
(v
, res
)
2167 redef class ACrangeExpr
2170 var e1
= v
.expr
(self.n_expr
)
2171 if e1
== null then return null
2172 var e2
= v
.expr
(self.n_expr2
)
2173 if e2
== null then return null
2174 var mtype
= v
.unanchor_type
(self.mtype
.as(not null))
2175 var res
= new MutableInstance(mtype
)
2176 v
.init_instance
(res
)
2177 v
.callsite
(init_callsite
, [res
, e1
, e2
])
2182 redef class AOrangeExpr
2185 var e1
= v
.expr
(self.n_expr
)
2186 if e1
== null then return null
2187 var e2
= v
.expr
(self.n_expr2
)
2188 if e2
== null then return null
2189 var mtype
= v
.unanchor_type
(self.mtype
.as(not null))
2190 var res
= new MutableInstance(mtype
)
2191 v
.init_instance
(res
)
2192 v
.callsite
(init_callsite
, [res
, e1
, e2
])
2197 redef class ATrueExpr
2200 return v
.bool_instance
(true)
2204 redef class AFalseExpr
2207 return v
.bool_instance
(false)
2211 redef class ANullExpr
2214 return v
.null_instance
2218 redef class AIsaExpr
2221 var i
= v
.expr
(self.n_expr
)
2222 if i
== null then return null
2223 var mtype
= v
.unanchor_type
(self.cast_type
.as(not null))
2224 return v
.bool_instance
(v
.is_subtype
(i
.mtype
, mtype
))
2228 redef class AAsCastExpr
2231 var i
= v
.expr
(self.n_expr
)
2232 if i
== null then return null
2233 var mtype
= self.mtype
.as(not null)
2234 var amtype
= v
.unanchor_type
(mtype
)
2235 if not v
.is_subtype
(i
.mtype
, amtype
) then
2236 fatal
(v
, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
2242 redef class AAsNotnullExpr
2245 var i
= v
.expr
(self.n_expr
)
2246 if i
== null then return null
2248 fatal
(v
, "Cast failed")
2254 redef class AParExpr
2257 return v
.expr
(self.n_expr
)
2261 redef class AOnceExpr
2264 if v
.onces
.has_key
(self) then
2265 return v
.onces
[self]
2267 var res
= v
.expr
(self.n_expr
)
2268 if res
== null then return null
2275 redef class ASendExpr
2278 var recv
= v
.expr
(self.n_expr
)
2279 if recv
== null then return null
2281 # Safe call shortcut if recv is null
2282 if is_safe
and recv
.is_null
then
2286 var args
= v
.varargize
(callsite
.mpropdef
, callsite
.signaturemap
, recv
, self.raw_arguments
)
2287 if args
== null then return null
2288 var res
= v
.callsite
(callsite
, args
)
2293 redef class ACallrefExpr
2296 var recv
= v
.expr
(self.n_expr
)
2297 if recv
== null then return null
2298 var mtype
= self.mtype
2299 assert mtype
!= null
2300 # In case we are in generic class where formal parameter can not
2302 var mtype2
= v
.unanchor_type
(mtype
)
2303 var inst
= new CallrefInstance(mtype2
, recv
, callsite
.as(not null))
2308 redef class ASendReassignFormExpr
2311 var recv
= v
.expr
(self.n_expr
)
2312 if recv
== null then return
2313 var args
= v
.varargize
(callsite
.mpropdef
, callsite
.signaturemap
, recv
, self.raw_arguments
)
2314 if args
== null then return
2315 var value
= v
.expr
(self.n_value
)
2316 if value
== null then return
2318 var read
= v
.callsite
(callsite
, args
)
2321 var write
= v
.callsite
(reassign_callsite
, [read
, value
])
2322 assert write
!= null
2326 v
.callsite
(write_callsite
, args
)
2330 redef class ASuperExpr
2333 var recv
= v
.frame
.arguments
.first
2335 var callsite
= self.callsite
2336 if callsite
!= null then
2338 if self.n_args
.n_exprs
.is_empty
then
2339 # Add automatic arguments for the super init call
2341 for i
in [0..callsite
.msignature
.arity
[ do
2342 args
.add
(v
.frame
.arguments
[i
+1])
2345 args
= v
.varargize
(callsite
.mpropdef
, callsite
.signaturemap
, recv
, self.n_args
.n_exprs
)
2346 if args
== null then return null
2350 var res
= v
.callsite
(callsite
, args
)
2354 # Standard call-next-method
2355 var mpropdef
= self.mpropdef
2356 mpropdef
= mpropdef
.lookup_next_definition
(v
.mainmodule
, recv
.mtype
)
2359 if self.n_args
.n_exprs
.is_empty
then
2360 args
= v
.frame
.arguments
2362 args
= v
.varargize
(mpropdef
, signaturemap
, recv
, self.n_args
.n_exprs
)
2363 if args
== null then return null
2366 var res
= v
.call
(mpropdef
, args
)
2371 redef class ANewExpr
2374 var mtype
= v
.unanchor_type
(self.recvtype
.as(not null))
2375 var recv
: Instance = new MutableInstance(mtype
)
2376 v
.init_instance
(recv
)
2377 var callsite
= self.callsite
2378 if callsite
== null then return recv
2380 var args
= v
.varargize
(callsite
.mpropdef
, callsite
.signaturemap
, recv
, self.n_args
.n_exprs
)
2381 if args
== null then return null
2382 var res2
= v
.callsite
(callsite
, args
)
2383 if res2
!= null then
2384 #self.debug("got {res2} from {mproperty}. drop {recv}")
2391 redef class AAttrExpr
2394 var recv
= v
.expr
(self.n_expr
)
2395 if recv
== null then return null
2396 if recv
.is_null
then fatal
(v
, "Receiver is null")
2397 var mproperty
= self.mproperty
.as(not null)
2398 return v
.read_attribute
(mproperty
, recv
)
2402 redef class AAttrAssignExpr
2405 var recv
= v
.expr
(self.n_expr
)
2406 if recv
== null then return
2407 if recv
.is_null
then fatal
(v
, "Receiver is null")
2408 var i
= v
.expr
(self.n_value
)
2409 if i
== null then return
2410 var mproperty
= self.mproperty
.as(not null)
2411 v
.write_attribute
(mproperty
, recv
, i
)
2415 redef class AAttrReassignExpr
2418 var recv
= v
.expr
(self.n_expr
)
2419 if recv
== null then return
2420 if recv
.is_null
then fatal
(v
, "Receiver is null")
2421 var value
= v
.expr
(self.n_value
)
2422 if value
== null then return
2423 var mproperty
= self.mproperty
.as(not null)
2424 var attr
= v
.read_attribute
(mproperty
, recv
)
2425 var res
= v
.callsite
(reassign_callsite
, [attr
, value
])
2427 v
.write_attribute
(mproperty
, recv
, res
)
2431 redef class AIssetAttrExpr
2434 var recv
= v
.expr
(self.n_expr
)
2435 if recv
== null then return null
2436 if recv
.is_null
then fatal
(v
, "Receiver is null")
2437 var mproperty
= self.mproperty
.as(not null)
2438 return v
.bool_instance
(v
.isset_attribute
(mproperty
, recv
))
2442 redef class AVarargExpr
2445 return v
.expr
(self.n_expr
)
2449 redef class ASafeExpr
2452 return v
.expr
(self.n_expr
)
2456 redef class ANamedargExpr
2459 return v
.expr
(self.n_expr
)
2463 redef class ADebugTypeExpr