interpreter: add `Instance::is_null` to simplify code
[nit.git] / src / interpreter / naive_interpreter.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 # Interpretation of a Nit program directly on the AST
18 module naive_interpreter
19
20 import literal
21 import semantize
22 private import parser::tables
23 import mixin
24 private import model::serialize_model
25 private import frontend::explain_assert_api
26
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")
30
31 redef init
32 do
33 super
34 self.option_context.add_option(self.opt_discover_call_trace)
35 end
36 end
37
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
41 # REQUIRE that:
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])
46 do
47 var time0 = get_time
48 self.toolcontext.info("*** START INTERPRETING ***", 1)
49
50 var interpreter = new NaiveInterpreter(self, mainmodule, arguments)
51 interpreter.start(mainmodule)
52
53 var time1 = get_time
54 self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
55 end
56 end
57
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
62
63 # The main module of the program (used to lookup method)
64 var mainmodule: MModule is writable
65
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]
70
71 # The main Sys instance
72 var mainobj: nullable Instance is noinit
73
74 init
75 do
76 if mainmodule.model.get_mclasses_by_name("Bool") != null then
77 self.true_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, true)
78 init_instance_primitive(self.true_instance)
79 self.false_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, false)
80 init_instance_primitive(self.false_instance)
81 end
82 self.null_instance = new PrimitiveInstance[nullable Object](mainmodule.model.null_type, null)
83 end
84
85 # Starts the interpreter on the main module of a program
86 fun start(mainmodule: MModule) do
87 var interpreter = self
88 var sys_type = mainmodule.sys_type
89 if sys_type == null then return # no class Sys
90 var mainobj = new MutableInstance(sys_type)
91 interpreter.mainobj = mainobj
92 interpreter.init_instance(mainobj)
93 var initprop = mainmodule.try_get_primitive_method("init", sys_type.mclass)
94 if initprop != null then
95 interpreter.send(initprop, [mainobj])
96 end
97 var mainprop = mainmodule.try_get_primitive_method("run", sys_type.mclass) or else
98 mainmodule.try_get_primitive_method("main", sys_type.mclass)
99 if mainprop != null then
100 interpreter.send(mainprop, [mainobj])
101 end
102 end
103
104 # Subtype test in the context of the mainmodule
105 fun is_subtype(sub, sup: MType): Bool
106 do
107 return sub.is_subtype(self.mainmodule, current_receiver_class, sup)
108 end
109
110 # Get a primitive method in the context of the main module
111 fun force_get_primitive_method(name: String, recv: MType): MMethod
112 do
113 assert recv isa MClassType
114 return self.modelbuilder.force_get_primitive_method(current_node, name, recv.mclass, self.mainmodule)
115 end
116
117 # Is a return, a break or a continue executed?
118 # Set this mark to skip the evaluation until a labeled statement catch it with `is_escape`
119 var escapemark: nullable EscapeMark = null
120
121 # The count of `catch` blocs that have been encountered and can catch an abort
122 var catch_count = 0 is writable
123
124 # The last error thrown on abort/runtime error where catch_count > 0
125 var last_error: nullable FatalError = null
126
127 # Is a return or a break or a continue executed?
128 # Use this function to know if you must skip the evaluation of statements
129 fun is_escaping: Bool do return escapemark != null
130
131 # The value associated with the current return/break/continue, if any.
132 # Set the value when you set a escapemark.
133 # Read the value when you catch a mark or reach the end of a method
134 var escapevalue: nullable Instance = null
135
136 # If there is a break/continue and is associated with `escapemark`, then return true and clear the mark.
137 # If there is no break/continue or if `escapemark` is null then return false.
138 # Use this function to catch a potential break/continue.
139 fun is_escape(escapemark: nullable EscapeMark): Bool
140 do
141 if escapemark != null and self.escapemark == escapemark then
142 self.escapemark = null
143 return true
144 else
145 return false
146 end
147 end
148
149 # Evaluate `n` as an expression in the current context.
150 # Return the value of the expression.
151 # If `n` cannot be evaluated, then aborts.
152 fun expr(n: AExpr): nullable Instance
153 do
154 var frame = self.frame
155 var old = frame.current_node
156 frame.current_node = n
157 #n.debug("IN Execute expr")
158 var i = n.expr(self)
159 if i == null and not self.is_escaping then
160 n.debug("inconsitance: no value and not escaping.")
161 end
162 var implicit_cast_to = n.implicit_cast_to
163 if i != null and implicit_cast_to != null then
164 var mtype = self.unanchor_type(implicit_cast_to)
165 if not self.is_subtype(i.mtype, mtype) then n.fatal(self, "Cast failed. Expected `{implicit_cast_to}`, got `{i.mtype}`")
166 end
167
168 #n.debug("OUT Execute expr: value is {i}")
169 #if not is_subtype(i.mtype, n.mtype.as(not null)) then n.debug("Expected {n.mtype.as(not null)} got {i}")
170 frame.current_node = old
171 return i
172 end
173
174 # Evaluate `n` as a statement in the current context.
175 # Do nothing if `n` is null.
176 # If `n` cannot be evaluated, then aborts.
177 fun stmt(n: nullable AExpr)
178 do
179 if n == null then return
180
181 if n.comprehension != null then
182 var comprehension = frame.comprehension.as(not null)
183 var i = expr(n)
184 if i != null then comprehension.add(i)
185 return
186 end
187
188 var frame = self.frame
189 var old = frame.current_node
190 frame.current_node = n
191 n.stmt(self)
192 frame.current_node = old
193 end
194
195 # Map used to store values of nodes that must be evaluated once in the system (`AOnceExpr`)
196 var onces: Map[ANode, Instance] = new HashMap[ANode, Instance]
197
198 # Return the boolean instance associated with `val`.
199 fun bool_instance(val: Bool): Instance
200 do
201 if val then return self.true_instance else return self.false_instance
202 end
203
204 # Return the integer instance associated with `val`.
205 fun int_instance(val: Int): Instance
206 do
207 var t = mainmodule.int_type
208 var instance = new PrimitiveInstance[Int](t, val)
209 init_instance_primitive(instance)
210 return instance
211 end
212
213 # Return the byte instance associated with `val`.
214 fun byte_instance(val: Byte): Instance
215 do
216 var t = mainmodule.byte_type
217 var instance = new PrimitiveInstance[Byte](t, val)
218 init_instance_primitive(instance)
219 return instance
220 end
221
222 # Return the int8 instance associated with `val`.
223 fun int8_instance(val: Int8): Instance
224 do
225 var t = mainmodule.int8_type
226 var instance = new PrimitiveInstance[Int8](t, val)
227 init_instance_primitive(instance)
228 return instance
229 end
230
231 # Return the int16 instance associated with `val`.
232 fun int16_instance(val: Int16): Instance
233 do
234 var t = mainmodule.int16_type
235 var instance = new PrimitiveInstance[Int16](t, val)
236 init_instance_primitive(instance)
237 return instance
238 end
239
240 # Return the uint16 instance associated with `val`.
241 fun uint16_instance(val: UInt16): Instance
242 do
243 var t = mainmodule.uint16_type
244 var instance = new PrimitiveInstance[UInt16](t, val)
245 init_instance_primitive(instance)
246 return instance
247 end
248
249 # Return the int32 instance associated with `val`.
250 fun int32_instance(val: Int32): Instance
251 do
252 var t = mainmodule.int32_type
253 var instance = new PrimitiveInstance[Int32](t, val)
254 init_instance_primitive(instance)
255 return instance
256 end
257
258 # Return the uint32 instance associated with `val`.
259 fun uint32_instance(val: UInt32): Instance
260 do
261 var t = mainmodule.uint32_type
262 var instance = new PrimitiveInstance[UInt32](t, val)
263 init_instance_primitive(instance)
264 return instance
265 end
266
267 # Return the char instance associated with `val`.
268 fun char_instance(val: Char): Instance
269 do
270 var t = mainmodule.char_type
271 var instance = new PrimitiveInstance[Char](t, val)
272 init_instance_primitive(instance)
273 return instance
274 end
275
276 # Return the float instance associated with `val`.
277 fun float_instance(val: Float): Instance
278 do
279 var t = mainmodule.float_type
280 var instance = new PrimitiveInstance[Float](t, val)
281 init_instance_primitive(instance)
282 return instance
283 end
284
285 # The unique instance of the `true` value.
286 var true_instance: Instance is noinit
287
288 # The unique instance of the `false` value.
289 var false_instance: Instance is noinit
290
291 # The unique instance of the `null` value.
292 var null_instance: Instance is noinit
293
294 # Return a new array made of `values`.
295 # The dynamic type of the result is Array[elttype].
296 fun array_instance(values: Array[Instance], elttype: MType): Instance
297 do
298 assert not elttype.need_anchor
299 var nat = new PrimitiveInstance[Array[Instance]](mainmodule.native_array_type(elttype), values)
300 init_instance_primitive(nat)
301 var mtype = mainmodule.array_type(elttype)
302 var res = new MutableInstance(mtype)
303 self.init_instance(res)
304 self.send(self.force_get_primitive_method("with_native", mtype), [res, nat, self.int_instance(values.length)])
305 return res
306 end
307
308 # Return a instance associated to a primitive class
309 # Current primitive classes are `Int`, `Bool`, and `String`
310 fun value_instance(object: Object): Instance
311 do
312 if object isa Int then
313 return int_instance(object)
314 else if object isa Bool then
315 return bool_instance(object)
316 else if object isa String then
317 return string_instance(object)
318 else
319 abort
320 end
321 end
322
323 # Return a new C string initialized with `txt`
324 fun c_string_instance(txt: String): Instance
325 do
326 var instance = c_string_instance_len(txt.byte_length+1)
327 var val = instance.val
328 val[txt.byte_length] = 0
329 txt.to_cstring.copy_to(val, txt.byte_length, 0, 0)
330
331 return instance
332 end
333
334 # Return a new C string initialized with `txt`
335 fun c_string_instance_from_ns(txt: CString, len: Int): Instance
336 do
337 var instance = c_string_instance_len(len)
338 var val = instance.val
339 txt.copy_to(val, len, 0, 0)
340
341 return instance
342 end
343
344 # Return a new C string instance sharing the same data space as `txt`
345 fun c_string_instance_fast_cstr(txt: CString, from: Int): Instance
346 do
347 var ncstr = txt.fast_cstring(from)
348 var t = mainmodule.c_string_type
349
350 var instance = new PrimitiveInstance[CString](t, ncstr)
351 init_instance_primitive(instance)
352
353 return instance
354 end
355
356 # Return a new C string initialized of `length`
357 fun c_string_instance_len(length: Int): PrimitiveInstance[CString]
358 do
359 var val = new CString(length)
360
361 var t = mainmodule.c_string_type
362 var instance = new PrimitiveInstance[CString](t, val)
363 init_instance_primitive(instance)
364 return instance
365 end
366
367 # Return a new String instance for `txt`
368 fun string_instance(txt: String): Instance
369 do
370 var nat = c_string_instance(txt)
371 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])
372 assert res != null
373 return res
374 end
375
376 # The virtual type of the frames used in the execution engine
377 type FRAME: Frame
378
379 # The current frame used to store local variables of the current method executed
380 fun frame: FRAME do return frames.first
381
382 # The stack of all frames. The first one is the current one.
383 var frames = new List[FRAME]
384
385 # Return a stack trace. One line per function
386 fun stack_trace: String
387 do
388 var b = new FlatBuffer
389 b.append(",---- Stack trace -- - - -\n")
390 for f in frames do
391 b.append("| {f.mpropdef} ({f.current_node.location})\n")
392 end
393 b.append("`------------------- - - -")
394 return b.to_s
395 end
396
397 # The current node, used to print errors, debug and stack-traces
398 fun current_node: nullable ANode
399 do
400 if frames.is_empty then return null
401 return frames.first.current_node
402 end
403
404 # The dynamic type of the current `self`
405 fun current_receiver_class: MClassType
406 do
407 return frames.first.arguments.first.mtype.as(MClassType)
408 end
409
410 # Initialize the environment for a call and return a new Frame
411 # *`node` The AST node
412 # *`mpropdef` The corresponding mpropdef
413 # *`args` Arguments of the call
414 fun new_frame(node: ANode, mpropdef: MPropDef, args: Array[Instance]): FRAME
415 do
416 return new InterpreterFrame(node, mpropdef, args)
417 end
418
419 # Exit the program with a message
420 fun fatal(message: String)
421 do
422 var node = current_node
423 if node == null then
424 print message
425 else
426 node.fatal(self, message)
427 end
428 exit(1)
429 end
430
431 # Debug on the current node
432 fun debug(message: String)
433 do
434 var node = current_node
435 if node == null then
436 print message
437 else
438 node.debug(message)
439 end
440 end
441
442 # Retrieve the value of the variable in the current frame
443 fun read_variable(v: Variable): Instance
444 do
445 var f = frames.first.as(InterpreterFrame)
446 return f.map[v]
447 end
448
449 # Assign the value of the variable in the current frame
450 fun write_variable(v: Variable, value: Instance)
451 do
452 var f = frames.first.as(InterpreterFrame)
453 f.map[v] = value
454 end
455
456 # Store known methods, used to trace methods as they are reached
457 var discover_call_trace: Set[MMethodDef] = new HashSet[MMethodDef]
458
459 # Evaluate `args` as expressions in the call of `mpropdef` on `recv`.
460 # This method is used to manage varargs in signatures and returns the real array
461 # of instances to use in the call.
462 # Return `null` if one of the evaluation of the arguments return null.
463 fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance]
464 do
465 var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
466 var res = new Array[Instance]
467 res.add(recv)
468
469 if msignature.arity == 0 then return res
470
471 if map == null then
472 assert args.length == msignature.arity else debug("Expected {msignature.arity} args, got {args.length}")
473 for ne in args do
474 var e = self.expr(ne)
475 if e == null then return null
476 res.add e
477 end
478 return res
479 end
480
481 # Eval in order of arguments, not parameters
482 var exprs = new Array[Instance].with_capacity(args.length)
483 for ne in args do
484 var e = self.expr(ne)
485 if e == null then return null
486 exprs.add e
487 end
488
489
490 # Fill `res` with the result of the evaluation according to the mapping
491 for i in [0..msignature.arity[ do
492 var param = msignature.mparameters[i]
493 var j = map.map.get_or_null(i)
494 if j == null then
495 # default value
496 res.add(null_instance)
497 continue
498 end
499 if param.is_vararg and args[i].vararg_decl > 0 then
500 var vararg = exprs.sub(j, args[i].vararg_decl)
501 var elttype = param.mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType))
502 var arg = self.array_instance(vararg, elttype)
503 res.add(arg)
504 continue
505 end
506 res.add exprs[j]
507 end
508 return res
509 end
510
511 # Execute `mpropdef` for a `args` (where `args[0]` is the receiver).
512 # Return a value if `mpropdef` is a function, or null if it is a procedure.
513 # The call is direct/static. There is no message-sending/late-binding.
514 fun call(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
515 do
516 if self.modelbuilder.toolcontext.opt_discover_call_trace.value and not self.discover_call_trace.has(mpropdef) then
517 self.discover_call_trace.add mpropdef
518 self.debug("Discovered {mpropdef}")
519 end
520 assert args.length == mpropdef.msignature.arity + 1 else debug("Invalid arity for {mpropdef}. {args.length} arguments given.")
521
522 # Look for the AST node that implements the property
523 var val = mpropdef.constant_value
524
525 var node = modelbuilder.mpropdef2node(mpropdef)
526 if mpropdef.is_abstract then
527 if node != null then
528 self.frames.unshift new_frame(node, mpropdef, args)
529 end
530 fatal("Abstract method `{mpropdef.mproperty.name}` called on `{args.first.mtype}`")
531 abort
532 end
533
534 if node isa APropdef then
535 self.parameter_check(node, mpropdef, args)
536 return node.call(self, mpropdef, args)
537 else if node isa AClassdef then
538 self.parameter_check(node, mpropdef, args)
539 return node.call(self, mpropdef, args)
540 else if node != null then
541 fatal("Fatal Error: method {mpropdef} associated to unexpected AST node {node.location}")
542 abort
543 else if val != null then
544 return value_instance(val)
545 else
546 fatal("Fatal Error: method {mpropdef} not found in the AST")
547 abort
548 end
549 end
550
551 # Execute type checks of covariant parameters
552 fun parameter_check(node: ANode, mpropdef: MMethodDef, args: Array[Instance])
553 do
554 var msignature = mpropdef.msignature.as(not null)
555 for i in [0..msignature.arity[ do
556 var mp = msignature.mparameters[i]
557
558 # skip test for vararg since the array is instantiated with the correct polymorphic type
559 if mp.is_vararg then continue
560
561 # skip if the cast is not required
562 var origmtype = mpropdef.mproperty.intro.msignature.mparameters[i].mtype
563 if not origmtype.need_anchor then continue
564
565 #print "{mpropdef}: {mpropdef.mproperty.intro.msignature.mparameters[i]}"
566
567 # get the parameter type
568 var mtype = mp.mtype
569 var anchor = args.first.mtype.as(MClassType)
570 var amtype = mtype.anchor_to(self.mainmodule, anchor)
571 if not args[i+1].mtype.is_subtype(self.mainmodule, anchor, amtype) then
572 node.fatal(self, "Cast failed. Expected `{mtype}`, got `{args[i+1].mtype}`")
573 end
574 end
575 end
576
577 # Common code for runtime injected calls and normal calls
578 fun send_commons(mproperty: MMethod, args: Array[Instance], mtype: MType): nullable Instance
579 do
580 if mtype isa MNullType then
581 if mproperty.name == "==" or mproperty.name == "is_same_instance" then
582 return self.bool_instance(args[0] == args[1])
583 else if mproperty.name == "!=" then
584 return self.bool_instance(args[0] != args[1])
585 end
586 #fatal("Receiver is null. {mproperty}. {args.join(" ")} {self.frame.current_node.class_name}")
587 fatal("Receiver is null")
588 end
589 return null
590 end
591
592 # Execute a full `callsite` for given `args`
593 # Use this method, instead of `send` to execute and control the additional behavior of the call-sites
594 fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
595 do
596 if callsite == null then return null
597 var initializers = callsite.mpropdef.initializers
598 if not initializers.is_empty then
599 var recv = arguments.first
600 var i = 1
601 for p in initializers do
602 if p isa MMethod then
603 var args = [recv]
604 for x in p.intro.msignature.mparameters do
605 args.add arguments[i]
606 i += 1
607 end
608 self.send(p, args)
609 else if p isa MAttribute then
610 assert recv isa MutableInstance
611 write_attribute(p, recv, arguments[i])
612 i += 1
613 else abort
614 end
615 assert i == arguments.length
616
617 return send(callsite.mproperty, [recv])
618 end
619 return send(callsite.mproperty, arguments)
620 end
621
622 # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
623 # Return a value if `mproperty` is a function, or null if it is a procedure.
624 # The call is polymorphic. There is a message-sending/late-binding according to the receiver (args[0]).
625 fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
626 do
627 var recv = args.first
628 var mtype = recv.mtype
629 var ret = send_commons(mproperty, args, mtype)
630 if ret != null then return ret
631 var propdef = mproperty.lookup_first_definition(self.mainmodule, mtype)
632 return self.call(propdef, args)
633 end
634
635 # Read the attribute `mproperty` of an instance `recv` and return its value.
636 # If the attribute in not yet initialized, then aborts with an error message.
637 fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
638 do
639 assert recv isa MutableInstance
640 if not recv.attributes.has_key(mproperty) then
641 fatal("Uninitialized attribute {mproperty.name}")
642 abort
643 end
644 return recv.attributes[mproperty]
645 end
646
647 # Replace in `recv` the value of the attribute `mproperty` by `value`
648 fun write_attribute(mproperty: MAttribute, recv: Instance, value: Instance)
649 do
650 assert recv isa MutableInstance
651 recv.attributes[mproperty] = value
652 end
653
654 # Is the attribute `mproperty` initialized the instance `recv`?
655 fun isset_attribute(mproperty: MAttribute, recv: Instance): Bool
656 do
657 assert recv isa MutableInstance
658 return recv.attributes.has_key(mproperty)
659 end
660
661 # Collect attributes of a type in the order of their init
662 fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]
663 do
664 var cache = self.collect_attr_propdef_cache
665 if cache.has_key(mtype) then return cache[mtype]
666
667 var res = new Array[AAttrPropdef]
668 var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
669 self.mainmodule.linearize_mclassdefs(cds)
670 for cd in cds do
671 res.add_all(modelbuilder.collect_attr_propdef(cd))
672 end
673
674 cache[mtype] = res
675 return res
676 end
677
678 private var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
679
680 # Fill the initial values of the newly created instance `recv`.
681 # `recv.mtype` is used to know what must be filled.
682 fun init_instance(recv: Instance)
683 do
684 for npropdef in collect_attr_propdef(recv.mtype) do
685 npropdef.init_expr(self, recv)
686 end
687 end
688
689 # A hook to initialize a `PrimitiveInstance`
690 fun init_instance_primitive(recv: Instance) do end
691
692 # This function determines the correct type according to the receiver of the current propdef (self).
693 fun unanchor_type(mtype: MType): MType
694 do
695 return mtype.anchor_to(self.mainmodule, current_receiver_class)
696 end
697
698 # Placebo instance used to mark internal error result when `null` already have a meaning.
699 # TODO: replace with multiple return or something better
700 var error_instance = new MutableInstance(modelbuilder.model.null_type) is lazy
701 end
702
703 # A runtime error
704 class FatalError
705 # The error message
706 var message: String
707
708 # The problematic node, if any
709 var node: nullable ANode
710 end
711
712 # An instance represents a value of the executed program.
713 abstract class Instance
714 # The dynamic type of the instance
715 # ASSERT: not self.mtype.is_anchored
716 var mtype: MType
717
718 # Return `true` if the instance is the `true` value.
719 #
720 # Return `false` if the instance is the `false` value.
721 # Abort if the instance is not a boolean value.
722 fun is_true: Bool do abort
723
724 # Return `true` if the instance is null.
725 # Return `false` otherwise.
726 fun is_null: Bool do return mtype isa MNullType
727
728 # Return true if `self` IS `o` (using the Nit semantic of is)
729 fun eq_is(o: Instance): Bool do return self.is_same_instance(o)
730
731 # Human readable object identity "Type#number"
732 redef fun to_s do return "{mtype}"
733
734 # Return the integer value if the instance is an integer.
735 # else aborts
736 fun to_i: Int do abort
737
738 # Return the integer value if the instance is a float.
739 # else aborts
740 fun to_f: Float do abort
741
742 # Return the integer value if the instance is a byte.
743 # else aborts
744 fun to_b: Byte do abort
745
746 # Return the integer value if the instance is a int8.
747 # else aborts
748 fun to_i8: Int8 do abort
749
750 # Return the integer value if the instance is a int16.
751 # else aborts
752 fun to_i16: Int16 do abort
753
754 # Return the integer value if the instance is a uint16.
755 # else aborts
756 fun to_u16: UInt16 do abort
757
758 # Return the integer value if the instance is a int32.
759 # else aborts
760 fun to_i32: Int32 do abort
761
762 # Return the integer value if the instance is a uint32.
763 # else aborts
764 fun to_u32: UInt32 do abort
765
766 # The real value encapsulated if the instance is primitive.
767 # Else aborts.
768 fun val: nullable Object do abort
769 end
770
771 # A instance with attribute (standards objects)
772 class MutableInstance
773 super Instance
774
775 # The values of the attributes
776 var attributes: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
777 end
778
779 # Special instance to handle primitives values (int, bool, etc.)
780 # The trick is just to encapsulate the “real” value.
781 class PrimitiveInstance[E]
782 super Instance
783
784 # The real value encapsulated
785 redef var val: E
786
787 redef fun is_true
788 do
789 if val == true then return true
790 if val == false then return false
791 abort
792 end
793
794 redef fun ==(o)
795 do
796 if not o isa PrimitiveInstance[nullable Object] then return false
797 return self.val == o.val
798 end
799
800 redef fun eq_is(o)
801 do
802 if not o isa PrimitiveInstance[nullable Object] then return false
803 return self.val.is_same_instance(o.val)
804 end
805
806 redef fun to_s do return "{mtype}#{val.object_id}({val or else "null"})"
807
808 redef fun to_i do return val.as(Int)
809
810 redef fun to_f do return val.as(Float)
811
812 redef fun to_b do return val.as(Byte)
813
814 redef fun to_i8 do return val.as(Int8)
815
816 redef fun to_i16 do return val.as(Int16)
817
818 redef fun to_u16 do return val.as(UInt16)
819
820 redef fun to_i32 do return val.as(Int32)
821
822 redef fun to_u32 do return val.as(UInt32)
823 end
824
825 # Information about local variables in a running method
826 abstract class Frame
827 # The current visited node
828 # The node is stored by frame to keep a stack trace
829 var current_node: ANode
830 # The executed property.
831 # A Method in case of a call, an attribute in case of a default initialization.
832 var mpropdef: MPropDef
833 # Arguments of the method (the first is the receiver)
834 var arguments: Array[Instance]
835 # Indicate if the expression has an array comprehension form
836 var comprehension: nullable Array[Instance] = null
837 end
838
839 # Implementation of a Frame with a Hashmap to store local variables
840 class InterpreterFrame
841 super Frame
842
843 # Mapping between a variable and the current value
844 var map: Map[Variable, Instance] = new HashMap[Variable, Instance]
845 end
846
847 redef class ANode
848 # Aborts the program with a message
849 # `v` is used to know if a colored message is displayed or not
850 fun fatal(v: NaiveInterpreter, message: String)
851 do
852 # Abort if there is a `catch` block
853 if v.catch_count > 0 then
854 v.last_error = new FatalError(message, self)
855 abort
856 end
857
858 if v.modelbuilder.toolcontext.opt_no_color.value then
859 sys.stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
860 else
861 sys.stderr.write("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
862 sys.stderr.write(v.stack_trace)
863 sys.stderr.write("\n")
864 end
865 exit(1)
866 end
867 end
868
869 redef class APropdef
870 # Execute a `mpropdef` associated with the current node.
871 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
872 do
873 fatal(v, "NOT YET IMPLEMENTED method kind {class_name}. {mpropdef}")
874 abort
875 end
876 end
877
878 redef class AMethPropdef
879 super TablesCapable
880
881 redef fun call(v, mpropdef, args)
882 do
883 var f = v.new_frame(self, mpropdef, args)
884 var res = call_commons(v, mpropdef, args, f)
885 v.frames.shift
886 if v.is_escape(self.return_mark) then
887 res = v.escapevalue
888 return res
889 end
890 return res
891 end
892
893 # Execution of the body of the method
894 #
895 # It handle the common special cases: super, intern, extern
896 fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
897 do
898 v.frames.unshift(f)
899
900 for i in [0..mpropdef.msignature.arity[ do
901 var variable = self.n_signature.n_params[i].variable
902 assert variable != null
903 v.write_variable(variable, arguments[i+1])
904 end
905
906 # Call the implicit super-init
907 var auto_super_inits = self.auto_super_inits
908 if auto_super_inits != null then
909 var args = [arguments.first]
910 for auto_super_init in auto_super_inits do
911 args.clear
912 for i in [0..auto_super_init.msignature.arity+1[ do
913 args.add(arguments[i])
914 end
915 assert auto_super_init.mproperty != mpropdef.mproperty
916 v.callsite(auto_super_init, args)
917 end
918 end
919 if auto_super_call then
920 # standard call-next-method
921 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
922 v.call(superpd, arguments)
923 end
924
925 # First, try intern
926 if mpropdef.is_intern or mpropdef.is_extern then
927 var res = intern_call(v, mpropdef, arguments)
928 if res != v.error_instance then return res
929 end
930 # Then, try extern
931 if mpropdef.is_extern then
932 var res = call_extern(v, mpropdef, arguments, f)
933 if res != v.error_instance then return res
934 end
935 # Else try block
936 if n_block != null then
937 v.stmt(self.n_block)
938 return null
939 end
940
941 # Fail if nothing succeed
942 if mpropdef.is_intern then
943 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
944 else if mpropdef.is_extern then
945 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
946 else
947 fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
948 end
949 abort
950 end
951
952 # Call this extern method
953 protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
954 do
955 return v.error_instance
956 end
957
958 # Interprets a intern or a shortcut extern method.
959 # Returns the result for a function, `null` for a procedure, or `error_instance` if the method is unknown.
960 private fun intern_call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
961 do
962 var pname = mpropdef.mproperty.name
963 var cname = mpropdef.mclassdef.mclass.name
964 if pname == "output" then
965 var recv = args.first
966 recv.val.output
967 return null
968 else if pname == "object_id" then
969 var recv = args.first
970 if recv isa PrimitiveInstance[Object] then
971 return v.int_instance(recv.val.object_id)
972 else
973 return v.int_instance(recv.object_id)
974 end
975 else if pname == "output_class_name" then
976 var recv = args.first
977 print recv.mtype
978 return null
979 else if pname == "native_class_name" then
980 var recv = args.first
981 var txt = recv.mtype.to_s
982 return v.c_string_instance(txt)
983 else if pname == "==" then
984 # == is correctly redefined for instances
985 return v.bool_instance(args[0] == args[1])
986 else if pname == "!=" then
987 return v.bool_instance(args[0] != args[1])
988 else if pname == "is_same_type" then
989 return v.bool_instance(args[0].mtype == args[1].mtype)
990 else if pname == "is_same_instance" then
991 return v.bool_instance(args[0].eq_is(args[1]))
992 else if pname == "class_inheritance_metamodel_json" then
993 return v.c_string_instance(v.mainmodule.flatten_mclass_hierarchy.to_thin_json)
994 else if pname == "exit" then
995 exit(args[1].to_i)
996 abort
997 else if pname == "buffer_mode_full" then
998 return v.int_instance(sys.buffer_mode_full)
999 else if pname == "buffer_mode_line" then
1000 return v.int_instance(sys.buffer_mode_line)
1001 else if pname == "buffer_mode_none" then
1002 return v.int_instance(sys.buffer_mode_none)
1003 else if pname == "sys" then
1004 return v.mainobj
1005 else if cname == "Int" then
1006 var recvval = args[0].to_i
1007 if pname == "unary -" then
1008 return v.int_instance(-recvval)
1009 else if pname == "unary +" then
1010 return args[0]
1011 else if pname == "+" then
1012 return v.int_instance(recvval + args[1].to_i)
1013 else if pname == "-" then
1014 return v.int_instance(recvval - args[1].to_i)
1015 else if pname == "*" then
1016 return v.int_instance(recvval * args[1].to_i)
1017 else if pname == "%" then
1018 return v.int_instance(recvval % args[1].to_i)
1019 else if pname == "/" then
1020 return v.int_instance(recvval / args[1].to_i)
1021 else if pname == "<" then
1022 return v.bool_instance(recvval < args[1].to_i)
1023 else if pname == ">" then
1024 return v.bool_instance(recvval > args[1].to_i)
1025 else if pname == "<=" then
1026 return v.bool_instance(recvval <= args[1].to_i)
1027 else if pname == ">=" then
1028 return v.bool_instance(recvval >= args[1].to_i)
1029 else if pname == "<=>" then
1030 return v.int_instance(recvval <=> args[1].to_i)
1031 else if pname == "&" then
1032 return v.int_instance(recvval & args[1].to_i)
1033 else if pname == "|" then
1034 return v.int_instance(recvval | args[1].to_i)
1035 else if pname == "to_f" then
1036 return v.float_instance(recvval.to_f)
1037 else if pname == "to_b" then
1038 return v.byte_instance(recvval.to_b)
1039 else if pname == "<<" then
1040 return v.int_instance(recvval << args[1].to_i)
1041 else if pname == ">>" then
1042 return v.int_instance(recvval >> args[1].to_i)
1043 else if pname == "to_i8" then
1044 return v.int8_instance(recvval.to_i8)
1045 else if pname == "to_i16" then
1046 return v.int16_instance(recvval.to_i16)
1047 else if pname == "to_u16" then
1048 return v.uint16_instance(recvval.to_u16)
1049 else if pname == "to_i32" then
1050 return v.int32_instance(recvval.to_i32)
1051 else if pname == "to_u32" then
1052 return v.uint32_instance(recvval.to_u32)
1053 end
1054 else if cname == "Byte" then
1055 var recvval = args[0].to_b
1056 if pname == "unary -" then
1057 return v.byte_instance(-recvval)
1058 else if pname == "unary +" then
1059 return args[0]
1060 else if pname == "+" then
1061 return v.byte_instance(recvval + args[1].to_b)
1062 else if pname == "-" then
1063 return v.byte_instance(recvval - args[1].to_b)
1064 else if pname == "*" then
1065 return v.byte_instance(recvval * args[1].to_b)
1066 else if pname == "%" then
1067 return v.byte_instance(recvval % args[1].to_b)
1068 else if pname == "/" then
1069 return v.byte_instance(recvval / args[1].to_b)
1070 else if pname == "<" then
1071 return v.bool_instance(recvval < args[1].to_b)
1072 else if pname == ">" then
1073 return v.bool_instance(recvval > args[1].to_b)
1074 else if pname == "<=" then
1075 return v.bool_instance(recvval <= args[1].to_b)
1076 else if pname == ">=" then
1077 return v.bool_instance(recvval >= args[1].to_b)
1078 else if pname == "<=>" then
1079 return v.int_instance(recvval <=> args[1].to_b)
1080 else if pname == "&" then
1081 return v.byte_instance(recvval & args[1].to_b)
1082 else if pname == "|" then
1083 return v.byte_instance(recvval | args[1].to_b)
1084 else if pname == "to_f" then
1085 return v.float_instance(recvval.to_f)
1086 else if pname == "to_i" then
1087 return v.int_instance(recvval.to_i)
1088 else if pname == "<<" then
1089 return v.byte_instance(recvval << args[1].to_i)
1090 else if pname == ">>" then
1091 return v.byte_instance(recvval >> args[1].to_i)
1092 else if pname == "to_i8" then
1093 return v.int8_instance(recvval.to_i8)
1094 else if pname == "to_i16" then
1095 return v.int16_instance(recvval.to_i16)
1096 else if pname == "to_u16" then
1097 return v.uint16_instance(recvval.to_u16)
1098 else if pname == "to_i32" then
1099 return v.int32_instance(recvval.to_i32)
1100 else if pname == "to_u32" then
1101 return v.uint32_instance(recvval.to_u32)
1102 else if pname == "byte_to_s_len" then
1103 return v.int_instance(recvval.to_s.length)
1104 end
1105 else if cname == "Char" then
1106 var recv = args[0].val.as(Char)
1107 if pname == "successor" then
1108 return v.char_instance(recv.successor(args[1].to_i))
1109 else if pname == "predecessor" then
1110 return v.char_instance(recv.predecessor(args[1].to_i))
1111 else if pname == "<" then
1112 return v.bool_instance(recv < args[1].val.as(Char))
1113 else if pname == ">" then
1114 return v.bool_instance(recv > args[1].val.as(Char))
1115 else if pname == "<=" then
1116 return v.bool_instance(recv <= args[1].val.as(Char))
1117 else if pname == ">=" then
1118 return v.bool_instance(recv >= args[1].val.as(Char))
1119 else if pname == "<=>" then
1120 return v.int_instance(recv <=> args[1].val.as(Char))
1121 end
1122 else if cname == "Float" then
1123 var recv = args[0].to_f
1124 if pname == "unary -" then
1125 return v.float_instance(-recv)
1126 else if pname == "unary +" then
1127 return args[0]
1128 else if pname == "+" then
1129 return v.float_instance(recv + args[1].to_f)
1130 else if pname == "-" then
1131 return v.float_instance(recv - args[1].to_f)
1132 else if pname == "*" then
1133 return v.float_instance(recv * args[1].to_f)
1134 else if pname == "/" then
1135 return v.float_instance(recv / args[1].to_f)
1136 else if pname == "<" then
1137 return v.bool_instance(recv < args[1].to_f)
1138 else if pname == ">" then
1139 return v.bool_instance(recv > args[1].to_f)
1140 else if pname == "<=" then
1141 return v.bool_instance(recv <= args[1].to_f)
1142 else if pname == ">=" then
1143 return v.bool_instance(recv >= args[1].to_f)
1144 else if pname == "to_i" then
1145 return v.int_instance(recv.to_i)
1146 else if pname == "to_b" then
1147 return v.byte_instance(recv.to_b)
1148 else if pname == "to_i8" then
1149 return v.int8_instance(recv.to_i8)
1150 else if pname == "to_i16" then
1151 return v.int16_instance(recv.to_i16)
1152 else if pname == "to_u16" then
1153 return v.uint16_instance(recv.to_u16)
1154 else if pname == "to_i32" then
1155 return v.int32_instance(recv.to_i32)
1156 else if pname == "to_u32" then
1157 return v.uint32_instance(recv.to_u32)
1158 else if pname == "cos" then
1159 return v.float_instance(args[0].to_f.cos)
1160 else if pname == "sin" then
1161 return v.float_instance(args[0].to_f.sin)
1162 else if pname == "tan" then
1163 return v.float_instance(args[0].to_f.tan)
1164 else if pname == "acos" then
1165 return v.float_instance(args[0].to_f.acos)
1166 else if pname == "asin" then
1167 return v.float_instance(args[0].to_f.asin)
1168 else if pname == "atan" then
1169 return v.float_instance(args[0].to_f.atan)
1170 else if pname == "sqrt" then
1171 return v.float_instance(args[0].to_f.sqrt)
1172 else if pname == "exp" then
1173 return v.float_instance(args[0].to_f.exp)
1174 else if pname == "log" then
1175 return v.float_instance(args[0].to_f.log)
1176 else if pname == "pow" then
1177 return v.float_instance(args[0].to_f.pow(args[1].to_f))
1178 else if pname == "abs" then
1179 return v.float_instance(args[0].to_f.abs)
1180 else if pname == "hypot_with" then
1181 return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
1182 else if pname == "is_nan" then
1183 return v.bool_instance(args[0].to_f.is_nan)
1184 else if pname == "is_inf_extern" then
1185 return v.bool_instance(args[0].to_f.is_inf != 0)
1186 else if pname == "round" then
1187 return v.float_instance(args[0].to_f.round)
1188 end
1189 else if cname == "CString" then
1190 if pname == "new" then
1191 return v.c_string_instance_len(args[1].to_i)
1192 end
1193 var recvval = args.first.val.as(CString)
1194 if pname == "[]" then
1195 var arg1 = args[1].to_i
1196 return v.int_instance(recvval[arg1])
1197 else if pname == "[]=" then
1198 var arg1 = args[1].to_i
1199 recvval[arg1] = args[2].val.as(Int)
1200 return null
1201 else if pname == "copy_to" then
1202 # sig= copy_to(dest: CString, length: Int, from: Int, to: Int)
1203 var destval = args[1].val.as(CString)
1204 var lenval = args[2].to_i
1205 var fromval = args[3].to_i
1206 var toval = args[4].to_i
1207 recvval.copy_to(destval, lenval, fromval, toval)
1208 return null
1209 else if pname == "atoi" then
1210 return v.int_instance(recvval.atoi)
1211 else if pname == "fast_cstring" then
1212 return v.c_string_instance_fast_cstr(args[0].val.as(CString), args[1].to_i)
1213 else if pname == "fetch_4_chars" then
1214 return v.uint32_instance(args[0].val.as(CString).fetch_4_chars(args[1].to_i))
1215 else if pname == "fetch_4_hchars" then
1216 return v.uint32_instance(args[0].val.as(CString).fetch_4_hchars(args[1].to_i))
1217 else if pname == "utf8_length" then
1218 return v.int_instance(args[0].val.as(CString).utf8_length(args[1].to_i, args[2].to_i))
1219 end
1220 else if cname == "NativeArray" then
1221 if pname == "new" then
1222 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
1223 var instance = new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
1224 v.init_instance_primitive(instance)
1225 return instance
1226 end
1227 var recvval = args.first.val.as(Array[Instance])
1228 if pname == "[]" then
1229 return recvval[args[1].to_i]
1230 else if pname == "[]=" then
1231 recvval[args[1].to_i] = args[2]
1232 return null
1233 else if pname == "length" then
1234 return v.int_instance(recvval.length)
1235 else if pname == "copy_to" then
1236 recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
1237 return null
1238 end
1239 else if cname == "Int8" then
1240 var recvval = args[0].to_i8
1241 if pname == "unary -" then
1242 return v.int8_instance(-recvval)
1243 else if pname == "unary +" then
1244 return args[0]
1245 else if pname == "+" then
1246 return v.int8_instance(recvval + args[1].to_i8)
1247 else if pname == "-" then
1248 return v.int8_instance(recvval - args[1].to_i8)
1249 else if pname == "*" then
1250 return v.int8_instance(recvval * args[1].to_i8)
1251 else if pname == "%" then
1252 return v.int8_instance(recvval % args[1].to_i8)
1253 else if pname == "/" then
1254 return v.int8_instance(recvval / args[1].to_i8)
1255 else if pname == "<" then
1256 return v.bool_instance(recvval < args[1].to_i8)
1257 else if pname == ">" then
1258 return v.bool_instance(recvval > args[1].to_i8)
1259 else if pname == "<=" then
1260 return v.bool_instance(recvval <= args[1].to_i8)
1261 else if pname == ">=" then
1262 return v.bool_instance(recvval >= args[1].to_i8)
1263 else if pname == "<=>" then
1264 return v.int_instance(recvval <=> args[1].to_i8)
1265 else if pname == "to_f" then
1266 return v.float_instance(recvval.to_f)
1267 else if pname == "to_i" then
1268 return v.int_instance(recvval.to_i)
1269 else if pname == "to_b" then
1270 return v.byte_instance(recvval.to_b)
1271 else if pname == "to_i16" then
1272 return v.int16_instance(recvval.to_i16)
1273 else if pname == "to_u16" then
1274 return v.uint16_instance(recvval.to_u16)
1275 else if pname == "to_i32" then
1276 return v.int32_instance(recvval.to_i32)
1277 else if pname == "to_u32" then
1278 return v.uint32_instance(recvval.to_u32)
1279 else if pname == "<<" then
1280 return v.int8_instance(recvval << (args[1].to_i))
1281 else if pname == ">>" then
1282 return v.int8_instance(recvval >> (args[1].to_i))
1283 else if pname == "&" then
1284 return v.int8_instance(recvval & args[1].to_i8)
1285 else if pname == "|" then
1286 return v.int8_instance(recvval | args[1].to_i8)
1287 else if pname == "^" then
1288 return v.int8_instance(recvval ^ args[1].to_i8)
1289 else if pname == "unary ~" then
1290 return v.int8_instance(~recvval)
1291 end
1292 else if cname == "Int16" then
1293 var recvval = args[0].to_i16
1294 if pname == "unary -" then
1295 return v.int16_instance(-recvval)
1296 else if pname == "unary +" then
1297 return args[0]
1298 else if pname == "+" then
1299 return v.int16_instance(recvval + args[1].to_i16)
1300 else if pname == "-" then
1301 return v.int16_instance(recvval - args[1].to_i16)
1302 else if pname == "*" then
1303 return v.int16_instance(recvval * args[1].to_i16)
1304 else if pname == "%" then
1305 return v.int16_instance(recvval % args[1].to_i16)
1306 else if pname == "/" then
1307 return v.int16_instance(recvval / args[1].to_i16)
1308 else if pname == "<" then
1309 return v.bool_instance(recvval < args[1].to_i16)
1310 else if pname == ">" then
1311 return v.bool_instance(recvval > args[1].to_i16)
1312 else if pname == "<=" then
1313 return v.bool_instance(recvval <= args[1].to_i16)
1314 else if pname == ">=" then
1315 return v.bool_instance(recvval >= args[1].to_i16)
1316 else if pname == "<=>" then
1317 return v.int_instance(recvval <=> args[1].to_i16)
1318 else if pname == "to_f" then
1319 return v.float_instance(recvval.to_f)
1320 else if pname == "to_i" then
1321 return v.int_instance(recvval.to_i)
1322 else if pname == "to_b" then
1323 return v.byte_instance(recvval.to_b)
1324 else if pname == "to_i8" then
1325 return v.int8_instance(recvval.to_i8)
1326 else if pname == "to_u16" then
1327 return v.uint16_instance(recvval.to_u16)
1328 else if pname == "to_i32" then
1329 return v.int32_instance(recvval.to_i32)
1330 else if pname == "to_u32" then
1331 return v.uint32_instance(recvval.to_u32)
1332 else if pname == "<<" then
1333 return v.int16_instance(recvval << (args[1].to_i))
1334 else if pname == ">>" then
1335 return v.int16_instance(recvval >> (args[1].to_i))
1336 else if pname == "&" then
1337 return v.int16_instance(recvval & args[1].to_i16)
1338 else if pname == "|" then
1339 return v.int16_instance(recvval | args[1].to_i16)
1340 else if pname == "^" then
1341 return v.int16_instance(recvval ^ args[1].to_i16)
1342 else if pname == "unary ~" then
1343 return v.int16_instance(~recvval)
1344 end
1345 else if cname == "UInt16" then
1346 var recvval = args[0].to_u16
1347 if pname == "unary -" then
1348 return v.uint16_instance(-recvval)
1349 else if pname == "unary +" then
1350 return args[0]
1351 else if pname == "+" then
1352 return v.uint16_instance(recvval + args[1].to_u16)
1353 else if pname == "-" then
1354 return v.uint16_instance(recvval - args[1].to_u16)
1355 else if pname == "*" then
1356 return v.uint16_instance(recvval * args[1].to_u16)
1357 else if pname == "%" then
1358 return v.uint16_instance(recvval % args[1].to_u16)
1359 else if pname == "/" then
1360 return v.uint16_instance(recvval / args[1].to_u16)
1361 else if pname == "<" then
1362 return v.bool_instance(recvval < args[1].to_u16)
1363 else if pname == ">" then
1364 return v.bool_instance(recvval > args[1].to_u16)
1365 else if pname == "<=" then
1366 return v.bool_instance(recvval <= args[1].to_u16)
1367 else if pname == ">=" then
1368 return v.bool_instance(recvval >= args[1].to_u16)
1369 else if pname == "<=>" then
1370 return v.int_instance(recvval <=> args[1].to_u16)
1371 else if pname == "to_f" then
1372 return v.float_instance(recvval.to_f)
1373 else if pname == "to_i" then
1374 return v.int_instance(recvval.to_i)
1375 else if pname == "to_b" then
1376 return v.byte_instance(recvval.to_b)
1377 else if pname == "to_i8" then
1378 return v.int8_instance(recvval.to_i8)
1379 else if pname == "to_i16" then
1380 return v.int16_instance(recvval.to_i16)
1381 else if pname == "to_i32" then
1382 return v.int32_instance(recvval.to_i32)
1383 else if pname == "to_u32" then
1384 return v.uint32_instance(recvval.to_u32)
1385 else if pname == "<<" then
1386 return v.uint16_instance(recvval << (args[1].to_i))
1387 else if pname == ">>" then
1388 return v.uint16_instance(recvval >> (args[1].to_i))
1389 else if pname == "&" then
1390 return v.uint16_instance(recvval & args[1].to_u16)
1391 else if pname == "|" then
1392 return v.uint16_instance(recvval | args[1].to_u16)
1393 else if pname == "^" then
1394 return v.uint16_instance(recvval ^ args[1].to_u16)
1395 else if pname == "unary ~" then
1396 return v.uint16_instance(~recvval)
1397 end
1398 else if cname == "Int32" then
1399 var recvval = args[0].to_i32
1400 if pname == "unary -" then
1401 return v.int32_instance(-recvval)
1402 else if pname == "unary +" then
1403 return args[0]
1404 else if pname == "+" then
1405 return v.int32_instance(recvval + args[1].to_i32)
1406 else if pname == "-" then
1407 return v.int32_instance(recvval - args[1].to_i32)
1408 else if pname == "*" then
1409 return v.int32_instance(recvval * args[1].to_i32)
1410 else if pname == "%" then
1411 return v.int32_instance(recvval % args[1].to_i32)
1412 else if pname == "/" then
1413 return v.int32_instance(recvval / args[1].to_i32)
1414 else if pname == "<" then
1415 return v.bool_instance(recvval < args[1].to_i32)
1416 else if pname == ">" then
1417 return v.bool_instance(recvval > args[1].to_i32)
1418 else if pname == "<=" then
1419 return v.bool_instance(recvval <= args[1].to_i32)
1420 else if pname == ">=" then
1421 return v.bool_instance(recvval >= args[1].to_i32)
1422 else if pname == "<=>" then
1423 return v.int_instance(recvval <=> args[1].to_i32)
1424 else if pname == "to_f" then
1425 return v.float_instance(recvval.to_f)
1426 else if pname == "to_i" then
1427 return v.int_instance(recvval.to_i)
1428 else if pname == "to_b" then
1429 return v.byte_instance(recvval.to_b)
1430 else if pname == "to_i8" then
1431 return v.int8_instance(recvval.to_i8)
1432 else if pname == "to_i16" then
1433 return v.int16_instance(recvval.to_i16)
1434 else if pname == "to_u16" then
1435 return v.uint16_instance(recvval.to_u16)
1436 else if pname == "to_u32" then
1437 return v.uint32_instance(recvval.to_u32)
1438 else if pname == "<<" then
1439 return v.int32_instance(recvval << (args[1].to_i))
1440 else if pname == ">>" then
1441 return v.int32_instance(recvval >> (args[1].to_i))
1442 else if pname == "&" then
1443 return v.int32_instance(recvval & args[1].to_i32)
1444 else if pname == "|" then
1445 return v.int32_instance(recvval | args[1].to_i32)
1446 else if pname == "^" then
1447 return v.int32_instance(recvval ^ args[1].to_i32)
1448 else if pname == "unary ~" then
1449 return v.int32_instance(~recvval)
1450 end
1451 else if cname == "UInt32" then
1452 var recvval = args[0].to_u32
1453 if pname == "unary -" then
1454 return v.uint32_instance(-recvval)
1455 else if pname == "unary +" then
1456 return args[0]
1457 else if pname == "+" then
1458 return v.uint32_instance(recvval + args[1].to_u32)
1459 else if pname == "-" then
1460 return v.uint32_instance(recvval - args[1].to_u32)
1461 else if pname == "*" then
1462 return v.uint32_instance(recvval * args[1].to_u32)
1463 else if pname == "%" then
1464 return v.uint32_instance(recvval % args[1].to_u32)
1465 else if pname == "/" then
1466 return v.uint32_instance(recvval / args[1].to_u32)
1467 else if pname == "<" then
1468 return v.bool_instance(recvval < args[1].to_u32)
1469 else if pname == ">" then
1470 return v.bool_instance(recvval > args[1].to_u32)
1471 else if pname == "<=" then
1472 return v.bool_instance(recvval <= args[1].to_u32)
1473 else if pname == ">=" then
1474 return v.bool_instance(recvval >= args[1].to_u32)
1475 else if pname == "<=>" then
1476 return v.int_instance(recvval <=> args[1].to_u32)
1477 else if pname == "to_f" then
1478 return v.float_instance(recvval.to_f)
1479 else if pname == "to_i" then
1480 return v.int_instance(recvval.to_i)
1481 else if pname == "to_b" then
1482 return v.byte_instance(recvval.to_b)
1483 else if pname == "to_i8" then
1484 return v.int8_instance(recvval.to_i8)
1485 else if pname == "to_i16" then
1486 return v.int16_instance(recvval.to_i16)
1487 else if pname == "to_u16" then
1488 return v.uint16_instance(recvval.to_u16)
1489 else if pname == "to_i32" then
1490 return v.int32_instance(recvval.to_i32)
1491 else if pname == "<<" then
1492 return v.uint32_instance(recvval << (args[1].to_i))
1493 else if pname == ">>" then
1494 return v.uint32_instance(recvval >> (args[1].to_i))
1495 else if pname == "&" then
1496 return v.uint32_instance(recvval & args[1].to_u32)
1497 else if pname == "|" then
1498 return v.uint32_instance(recvval | args[1].to_u32)
1499 else if pname == "^" then
1500 return v.uint32_instance(recvval ^ args[1].to_u32)
1501 else if pname == "unary ~" then
1502 return v.uint32_instance(~recvval)
1503 end
1504 else if pname == "native_argc" then
1505 return v.int_instance(v.arguments.length)
1506 else if pname == "native_argv" then
1507 var txt = v.arguments[args[1].to_i]
1508 return v.c_string_instance(txt)
1509 else if pname == "lexer_goto" then
1510 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
1511 else if pname == "lexer_accept" then
1512 return v.int_instance(lexer_accept(args[1].to_i))
1513 else if pname == "parser_goto" then
1514 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
1515 else if pname == "parser_action" then
1516 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
1517 end
1518 return v.error_instance
1519 end
1520 end
1521
1522 redef class AAttrPropdef
1523 redef fun call(v, mpropdef, args)
1524 do
1525 var recv = args.first
1526 assert recv isa MutableInstance
1527 var attr = self.mpropdef.mproperty
1528 if mpropdef == mreadpropdef then
1529 assert args.length == 1
1530 if not is_lazy or v.isset_attribute(attr, recv) then return v.read_attribute(attr, recv)
1531 var f = v.new_frame(self, mpropdef, args)
1532 return evaluate_expr(v, recv, f)
1533 else if mpropdef == mwritepropdef then
1534 assert args.length == 2
1535 var arg = args[1]
1536 if is_optional and arg.is_null then
1537 var f = v.new_frame(self, mpropdef, args)
1538 arg = evaluate_expr(v, recv, f)
1539 end
1540 v.write_attribute(attr, recv, arg)
1541 return null
1542 else
1543 abort
1544 end
1545 end
1546
1547 # Evaluate and set the default value of the attribute in `recv`
1548 private fun init_expr(v: NaiveInterpreter, recv: Instance)
1549 do
1550 if is_lazy or is_optional then return
1551 if has_value then
1552 var f = v.new_frame(self, mreadpropdef.as(not null), [recv])
1553 evaluate_expr(v, recv, f)
1554 return
1555 end
1556 var mpropdef = self.mpropdef
1557 if mpropdef == null then return
1558 var mtype = self.mtype.as(not null)
1559 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1560 if mtype isa MNullableType then
1561 v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
1562 end
1563 end
1564
1565 private fun evaluate_expr(v: NaiveInterpreter, recv: Instance, f: Frame): Instance
1566 do
1567 assert recv isa MutableInstance
1568 v.frames.unshift(f)
1569
1570 var val
1571
1572 var nexpr = self.n_expr
1573 var nblock = self.n_block
1574 if nexpr != null then
1575 val = v.expr(nexpr)
1576 else if nblock != null then
1577 v.stmt(nblock)
1578 assert v.escapemark == return_mark
1579 val = v.escapevalue
1580 v.escapemark = null
1581 else
1582 abort
1583 end
1584 assert val != null
1585
1586 v.frames.shift
1587 assert not v.is_escaping
1588 v.write_attribute(self.mpropdef.mproperty, recv, val)
1589 return val
1590 end
1591 end
1592
1593 redef class AClassdef
1594 # Execute an implicit `mpropdef` associated with the current node.
1595 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance]): nullable Instance
1596 do
1597 if mpropdef.mproperty.is_root_init then
1598 assert arguments.length == 1
1599 if not mpropdef.is_intro then
1600 # standard call-next-method
1601 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
1602 v.call(superpd, arguments)
1603 end
1604 return null
1605 else
1606 abort
1607 end
1608 end
1609 end
1610
1611 redef class AExpr
1612 # Evaluate the node as a possible expression.
1613 # Return a possible value
1614 # NOTE: Do not call this method directly, but use `v.expr`
1615 # This method is here to be implemented by subclasses.
1616 protected fun expr(v: NaiveInterpreter): nullable Instance
1617 do
1618 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1619 abort
1620 end
1621
1622 # Evaluate the node as a statement.
1623 # NOTE: Do not call this method directly, but use `v.stmt`
1624 # This method is here to be implemented by subclasses (no need to return something).
1625 protected fun stmt(v: NaiveInterpreter)
1626 do
1627 expr(v)
1628 end
1629
1630 end
1631
1632 redef class ABlockExpr
1633 redef fun expr(v)
1634 do
1635 var last = self.n_expr.last
1636 for e in self.n_expr do
1637 if e == last then break
1638 v.stmt(e)
1639 if v.is_escaping then return null
1640 end
1641 return last.expr(v)
1642 end
1643
1644 redef fun stmt(v)
1645 do
1646 for e in self.n_expr do
1647 v.stmt(e)
1648 if v.is_escaping then return
1649 end
1650 end
1651 end
1652
1653 redef class AVardeclExpr
1654 redef fun expr(v)
1655 do
1656 var ne = self.n_expr
1657 if ne != null then
1658 var i = v.expr(ne)
1659 if i == null then return null
1660 v.write_variable(self.variable.as(not null), i)
1661 return i
1662 end
1663 return null
1664 end
1665 end
1666
1667 redef class AVarExpr
1668 redef fun expr(v)
1669 do
1670 return v.read_variable(self.variable.as(not null))
1671 end
1672 end
1673
1674 redef class AVarAssignExpr
1675 redef fun expr(v)
1676 do
1677 var i = v.expr(self.n_value)
1678 if i == null then return null
1679 v.write_variable(self.variable.as(not null), i)
1680 return i
1681 end
1682 end
1683
1684 redef class AVarReassignExpr
1685 redef fun stmt(v)
1686 do
1687 var variable = self.variable.as(not null)
1688 var vari = v.read_variable(variable)
1689 var value = v.expr(self.n_value)
1690 if value == null then return
1691 var res = v.callsite(reassign_callsite, [vari, value])
1692 assert res != null
1693 v.write_variable(variable, res)
1694 end
1695 end
1696
1697 redef class ASelfExpr
1698 redef fun expr(v)
1699 do
1700 return v.frame.arguments.first
1701 end
1702 end
1703
1704 redef class AImplicitSelfExpr
1705 redef fun expr(v)
1706 do
1707 if not is_sys then return super
1708 return v.mainobj
1709 end
1710 end
1711
1712 redef class AEscapeExpr
1713 redef fun stmt(v)
1714 do
1715 var ne = self.n_expr
1716 if ne != null then
1717 var i = v.expr(ne)
1718 if i == null then return
1719 v.escapevalue = i
1720 else
1721 v.escapevalue = null
1722 end
1723 v.escapemark = self.escapemark
1724 end
1725 end
1726
1727 redef class AAbortExpr
1728 redef fun stmt(v)
1729 do
1730 fatal(v, "Aborted")
1731 exit(1)
1732 end
1733 end
1734
1735 redef class AIfExpr
1736 redef fun expr(v)
1737 do
1738 var cond = v.expr(self.n_expr)
1739 if cond == null then return null
1740 if cond.is_true then
1741 return v.expr(self.n_then.as(not null))
1742 else
1743 return v.expr(self.n_else.as(not null))
1744 end
1745 end
1746
1747 redef fun stmt(v)
1748 do
1749 var cond = v.expr(self.n_expr)
1750 if cond == null then return
1751 if cond.is_true then
1752 v.stmt(self.n_then)
1753 else
1754 v.stmt(self.n_else)
1755 end
1756 end
1757 end
1758
1759 redef class AIfexprExpr
1760 redef fun expr(v)
1761 do
1762 var cond = v.expr(self.n_expr)
1763 if cond == null then return null
1764 if cond.is_true then
1765 return v.expr(self.n_then)
1766 else
1767 return v.expr(self.n_else)
1768 end
1769 end
1770 end
1771
1772 redef class ADoExpr
1773 redef fun stmt(v)
1774 do
1775 # If this bloc has a catch, handle it with a do ... catch ... end
1776 if self.n_catch != null then
1777 var frame = v.frame
1778 v.catch_count += 1
1779 do
1780 v.stmt(self.n_block)
1781 v.is_escape(self.break_mark) # Clear the break (if any)
1782 v.catch_count -= 1
1783 catch
1784 # Restore the current frame if needed
1785 while v.frame != frame do v.frames.shift
1786 v.catch_count -= 1
1787 v.stmt(self.n_catch)
1788 end
1789 else
1790 v.stmt(self.n_block)
1791 v.is_escape(self.break_mark)
1792 end
1793 end
1794 end
1795
1796 redef class AWhileExpr
1797 redef fun stmt(v)
1798 do
1799 loop
1800 var cond = v.expr(self.n_expr)
1801 if cond == null then return
1802 if not cond.is_true then return
1803 v.stmt(self.n_block)
1804 if v.is_escape(self.break_mark) then return
1805 v.is_escape(self.continue_mark) # Clear the break
1806 if v.is_escaping then return
1807 end
1808 end
1809 end
1810
1811 redef class ALoopExpr
1812 redef fun stmt(v)
1813 do
1814 loop
1815 v.stmt(self.n_block)
1816 if v.is_escape(self.break_mark) then return
1817 v.is_escape(self.continue_mark) # Clear the break
1818 if v.is_escaping then return
1819 end
1820 end
1821 end
1822
1823 redef class AForExpr
1824 redef fun stmt(v)
1825 do
1826 var iters = new Array[Instance]
1827
1828 for g in n_groups do
1829 var col = v.expr(g.n_expr)
1830 if col == null then return
1831 if col.is_null then fatal(v, "Receiver is null")
1832
1833 var iter = v.callsite(g.method_iterator, [col]).as(not null)
1834 iters.add iter
1835 end
1836
1837 loop
1838 for g in n_groups, iter in iters do
1839 var isok = v.callsite(g.method_is_ok, [iter]).as(not null)
1840 if not isok.is_true then break label
1841 if g.variables.length == 1 then
1842 var item = v.callsite(g.method_item, [iter]).as(not null)
1843 #self.debug("item {item}")
1844 v.write_variable(g.variables.first, item)
1845 else if g.variables.length == 2 then
1846 var key = v.callsite(g.method_key, [iter]).as(not null)
1847 v.write_variable(g.variables[0], key)
1848 var item = v.callsite(g.method_item, [iter]).as(not null)
1849 v.write_variable(g.variables[1], item)
1850 else
1851 abort
1852 end
1853 end
1854 v.stmt(self.n_block)
1855 if v.is_escape(self.break_mark) then break
1856 v.is_escape(self.continue_mark) # Clear the break
1857 if v.is_escaping then break
1858 for g in n_groups, iter in iters do
1859 v.callsite(g.method_next, [iter])
1860 end
1861 end label
1862 for g in n_groups, iter in iters do
1863 var method_finish = g.method_finish
1864 if method_finish != null then
1865 v.callsite(method_finish, [iter])
1866 end
1867 end
1868 end
1869 end
1870
1871 redef class AWithExpr
1872 redef fun stmt(v)
1873 do
1874 var expr = v.expr(self.n_expr)
1875 if expr == null then return
1876
1877 v.callsite(method_start, [expr])
1878 v.stmt(self.n_block)
1879 v.is_escape(self.break_mark) # Clear the break
1880
1881 # Execute the finally without an escape
1882 var old_mark = v.escapemark
1883 v.escapemark = null
1884 v.callsite(method_finish, [expr])
1885 # Restore the escape unless another escape was provided
1886 if v.escapemark == null then v.escapemark = old_mark
1887 end
1888 end
1889
1890 redef class AAssertExpr
1891 redef fun stmt(v)
1892 do
1893 var cond = v.expr(self.n_expr)
1894 if cond == null then return
1895 if not cond.is_true then
1896 v.stmt(self.n_else)
1897 if v.is_escaping then return
1898
1899 # Explain assert if it fails
1900 var explain_assert_str = explain_assert_str
1901 if explain_assert_str != null then
1902 var i = v.expr(explain_assert_str)
1903 if i isa MutableInstance then
1904 var res = v.send(v.force_get_primitive_method("to_cstring", i.mtype), [i])
1905 if res != null then
1906 var val = res.val
1907 if val != null then
1908 print_error "Runtime assert: {val.to_s}"
1909 end
1910 end
1911 end
1912 end
1913
1914 var nid = self.n_id
1915 if nid != null then
1916 fatal(v, "Assert '{nid.text}' failed")
1917 else
1918 fatal(v, "Assert failed")
1919 end
1920 exit(1)
1921 end
1922 end
1923 end
1924
1925 redef class AOrExpr
1926 redef fun expr(v)
1927 do
1928 var cond = v.expr(self.n_expr)
1929 if cond == null then return null
1930 if cond.is_true then return cond
1931 return v.expr(self.n_expr2)
1932 end
1933 end
1934
1935 redef class AImpliesExpr
1936 redef fun expr(v)
1937 do
1938 var cond = v.expr(self.n_expr)
1939 if cond == null then return null
1940 if not cond.is_true then return v.true_instance
1941 return v.expr(self.n_expr2)
1942 end
1943 end
1944
1945 redef class AAndExpr
1946 redef fun expr(v)
1947 do
1948 var cond = v.expr(self.n_expr)
1949 if cond == null then return null
1950 if not cond.is_true then return cond
1951 return v.expr(self.n_expr2)
1952 end
1953 end
1954
1955 redef class ANotExpr
1956 redef fun expr(v)
1957 do
1958 var cond = v.expr(self.n_expr)
1959 if cond == null then return null
1960 return v.bool_instance(not cond.is_true)
1961 end
1962 end
1963
1964 redef class AOrElseExpr
1965 redef fun expr(v)
1966 do
1967 var i = v.expr(self.n_expr)
1968 if i == null then return null
1969 if i != v.null_instance then return i
1970 return v.expr(self.n_expr2)
1971 end
1972 end
1973
1974 redef class AIntegerExpr
1975 redef fun expr(v)
1976 do
1977 if value isa Int then return v.int_instance(value.as(Int))
1978 if value isa Byte then return v.byte_instance(value.as(Byte))
1979 if value isa Int8 then return v.int8_instance(value.as(Int8))
1980 if value isa Int16 then return v.int16_instance(value.as(Int16))
1981 if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
1982 if value isa Int32 then return v.int32_instance(value.as(Int32))
1983 if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
1984 return null
1985 end
1986 end
1987
1988 redef class AFloatExpr
1989 redef fun expr(v)
1990 do
1991 return v.float_instance(self.value.as(not null))
1992 end
1993 end
1994
1995 redef class ACharExpr
1996 redef fun expr(v)
1997 do
1998 if is_code_point then
1999 return v.int_instance(self.value.as(not null).code_point)
2000 end
2001 return v.char_instance(self.value.as(not null))
2002 end
2003 end
2004
2005 redef class AArrayExpr
2006 redef fun expr(v)
2007 do
2008 var val = new Array[Instance]
2009 var old_comprehension = v.frame.comprehension
2010 v.frame.comprehension = val
2011 for nexpr in self.n_exprs do
2012 if nexpr isa AForExpr then
2013 v.stmt(nexpr)
2014 else
2015 var i = v.expr(nexpr)
2016 if i == null then return null
2017 val.add(i)
2018 end
2019 end
2020 v.frame.comprehension = old_comprehension
2021 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
2022 var elttype = mtype.arguments.first
2023 return v.array_instance(val, elttype)
2024 end
2025 end
2026
2027 redef class AugmentedStringFormExpr
2028 # Factorize the making of a `Regex` object from a literal prefixed string
2029 fun make_re(v: NaiveInterpreter, rs: Instance): nullable Instance do
2030 var tore = to_re
2031 assert tore != null
2032 var res = v.callsite(tore, [rs])
2033 if res == null then
2034 print "Cannot call property `to_re` on {self}"
2035 abort
2036 end
2037 for j in suffix.chars do
2038 if j == 'i' then
2039 var prop = ignore_case
2040 assert prop != null
2041 v.callsite(prop, [res, v.bool_instance(true)])
2042 continue
2043 end
2044 if j == 'm' then
2045 var prop = newline
2046 assert prop != null
2047 v.callsite(prop, [res, v.bool_instance(true)])
2048 continue
2049 end
2050 if j == 'b' then
2051 var prop = extended
2052 assert prop != null
2053 v.callsite(prop, [res, v.bool_instance(false)])
2054 continue
2055 end
2056 # Should not happen, this needs to be updated
2057 # along with the addition of new suffixes
2058 abort
2059 end
2060 return res
2061 end
2062 end
2063
2064 redef class AStringFormExpr
2065 redef fun expr(v) do return v.string_instance(value)
2066 end
2067
2068 redef class AStringExpr
2069 redef fun expr(v) do
2070 var s = v.string_instance(value)
2071 if is_string then return s
2072 if is_bytestring then
2073 var ns = v.c_string_instance_from_ns(bytes.items, bytes.length)
2074 var ln = v.int_instance(bytes.length)
2075 var prop = to_bytes_with_copy
2076 assert prop != null
2077 var res = v.callsite(prop, [ns, ln])
2078 if res == null then
2079 print "Cannot call property `to_bytes` on {self}"
2080 abort
2081 end
2082 s = res
2083 else if is_re then
2084 var res = make_re(v, s)
2085 assert res != null
2086 s = res
2087 else
2088 print "Unimplemented prefix or suffix for {self}"
2089 abort
2090 end
2091 return s
2092 end
2093 end
2094
2095 redef class ASuperstringExpr
2096 redef fun expr(v)
2097 do
2098 var array = new Array[Instance]
2099 for nexpr in n_exprs do
2100 var i = v.expr(nexpr)
2101 if i == null then return null
2102 array.add(i)
2103 end
2104 var i = v.array_instance(array, v.mainmodule.object_type)
2105 var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i])
2106 assert res != null
2107 if is_re then res = make_re(v, res)
2108 return res
2109 end
2110 end
2111
2112 redef class ACrangeExpr
2113 redef fun expr(v)
2114 do
2115 var e1 = v.expr(self.n_expr)
2116 if e1 == null then return null
2117 var e2 = v.expr(self.n_expr2)
2118 if e2 == null then return null
2119 var mtype = v.unanchor_type(self.mtype.as(not null))
2120 var res = new MutableInstance(mtype)
2121 v.init_instance(res)
2122 v.callsite(init_callsite, [res, e1, e2])
2123 return res
2124 end
2125 end
2126
2127 redef class AOrangeExpr
2128 redef fun expr(v)
2129 do
2130 var e1 = v.expr(self.n_expr)
2131 if e1 == null then return null
2132 var e2 = v.expr(self.n_expr2)
2133 if e2 == null then return null
2134 var mtype = v.unanchor_type(self.mtype.as(not null))
2135 var res = new MutableInstance(mtype)
2136 v.init_instance(res)
2137 v.callsite(init_callsite, [res, e1, e2])
2138 return res
2139 end
2140 end
2141
2142 redef class ATrueExpr
2143 redef fun expr(v)
2144 do
2145 return v.bool_instance(true)
2146 end
2147 end
2148
2149 redef class AFalseExpr
2150 redef fun expr(v)
2151 do
2152 return v.bool_instance(false)
2153 end
2154 end
2155
2156 redef class ANullExpr
2157 redef fun expr(v)
2158 do
2159 return v.null_instance
2160 end
2161 end
2162
2163 redef class AIsaExpr
2164 redef fun expr(v)
2165 do
2166 var i = v.expr(self.n_expr)
2167 if i == null then return null
2168 var mtype = v.unanchor_type(self.cast_type.as(not null))
2169 return v.bool_instance(v.is_subtype(i.mtype, mtype))
2170 end
2171 end
2172
2173 redef class AAsCastExpr
2174 redef fun expr(v)
2175 do
2176 var i = v.expr(self.n_expr)
2177 if i == null then return null
2178 var mtype = self.mtype.as(not null)
2179 var amtype = v.unanchor_type(mtype)
2180 if not v.is_subtype(i.mtype, amtype) then
2181 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
2182 end
2183 return i
2184 end
2185 end
2186
2187 redef class AAsNotnullExpr
2188 redef fun expr(v)
2189 do
2190 var i = v.expr(self.n_expr)
2191 if i == null then return null
2192 if i.is_null then
2193 fatal(v, "Cast failed")
2194 end
2195 return i
2196 end
2197 end
2198
2199 redef class AParExpr
2200 redef fun expr(v)
2201 do
2202 return v.expr(self.n_expr)
2203 end
2204 end
2205
2206 redef class AOnceExpr
2207 redef fun expr(v)
2208 do
2209 if v.onces.has_key(self) then
2210 return v.onces[self]
2211 else
2212 var res = v.expr(self.n_expr)
2213 if res == null then return null
2214 v.onces[self] = res
2215 return res
2216 end
2217 end
2218 end
2219
2220 redef class ASendExpr
2221 redef fun expr(v)
2222 do
2223 var recv = v.expr(self.n_expr)
2224 if recv == null then return null
2225 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2226 if args == null then return null
2227
2228 var res = v.callsite(callsite, args)
2229 return res
2230 end
2231 end
2232
2233 redef class ASendReassignFormExpr
2234 redef fun stmt(v)
2235 do
2236 var recv = v.expr(self.n_expr)
2237 if recv == null then return
2238 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2239 if args == null then return
2240 var value = v.expr(self.n_value)
2241 if value == null then return
2242
2243 var read = v.callsite(callsite, args)
2244 assert read != null
2245
2246 var write = v.callsite(reassign_callsite, [read, value])
2247 assert write != null
2248
2249 args.add(write)
2250
2251 v.callsite(write_callsite, args)
2252 end
2253 end
2254
2255 redef class ASuperExpr
2256 redef fun expr(v)
2257 do
2258 var recv = v.frame.arguments.first
2259
2260 var callsite = self.callsite
2261 if callsite != null then
2262 var args
2263 if self.n_args.n_exprs.is_empty then
2264 # Add automatic arguments for the super init call
2265 args = [recv]
2266 for i in [0..callsite.msignature.arity[ do
2267 args.add(v.frame.arguments[i+1])
2268 end
2269 else
2270 args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2271 if args == null then return null
2272 end
2273
2274 # Super init call
2275 var res = v.callsite(callsite, args)
2276 return res
2277 end
2278
2279 # Standard call-next-method
2280 var mpropdef = self.mpropdef
2281 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
2282
2283 var args
2284 if self.n_args.n_exprs.is_empty then
2285 args = v.frame.arguments
2286 else
2287 args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
2288 if args == null then return null
2289 end
2290
2291 var res = v.call(mpropdef, args)
2292 return res
2293 end
2294 end
2295
2296 redef class ANewExpr
2297 redef fun expr(v)
2298 do
2299 var mtype = v.unanchor_type(self.recvtype.as(not null))
2300 var recv: Instance = new MutableInstance(mtype)
2301 v.init_instance(recv)
2302 var callsite = self.callsite
2303 if callsite == null then return recv
2304
2305 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2306 if args == null then return null
2307 var res2 = v.callsite(callsite, args)
2308 if res2 != null then
2309 #self.debug("got {res2} from {mproperty}. drop {recv}")
2310 return res2
2311 end
2312 return recv
2313 end
2314 end
2315
2316 redef class AAttrExpr
2317 redef fun expr(v)
2318 do
2319 var recv = v.expr(self.n_expr)
2320 if recv == null then return null
2321 if recv.is_null then fatal(v, "Receiver is null")
2322 var mproperty = self.mproperty.as(not null)
2323 return v.read_attribute(mproperty, recv)
2324 end
2325 end
2326
2327 redef class AAttrAssignExpr
2328 redef fun stmt(v)
2329 do
2330 var recv = v.expr(self.n_expr)
2331 if recv == null then return
2332 if recv.is_null then fatal(v, "Receiver is null")
2333 var i = v.expr(self.n_value)
2334 if i == null then return
2335 var mproperty = self.mproperty.as(not null)
2336 v.write_attribute(mproperty, recv, i)
2337 end
2338 end
2339
2340 redef class AAttrReassignExpr
2341 redef fun stmt(v)
2342 do
2343 var recv = v.expr(self.n_expr)
2344 if recv == null then return
2345 if recv.is_null then fatal(v, "Receiver is null")
2346 var value = v.expr(self.n_value)
2347 if value == null then return
2348 var mproperty = self.mproperty.as(not null)
2349 var attr = v.read_attribute(mproperty, recv)
2350 var res = v.callsite(reassign_callsite, [attr, value])
2351 assert res != null
2352 v.write_attribute(mproperty, recv, res)
2353 end
2354 end
2355
2356 redef class AIssetAttrExpr
2357 redef fun expr(v)
2358 do
2359 var recv = v.expr(self.n_expr)
2360 if recv == null then return null
2361 if recv.is_null then fatal(v, "Receiver is null")
2362 var mproperty = self.mproperty.as(not null)
2363 return v.bool_instance(v.isset_attribute(mproperty, recv))
2364 end
2365 end
2366
2367 redef class AVarargExpr
2368 redef fun expr(v)
2369 do
2370 return v.expr(self.n_expr)
2371 end
2372 end
2373
2374 redef class ANamedargExpr
2375 redef fun expr(v)
2376 do
2377 return v.expr(self.n_expr)
2378 end
2379 end
2380
2381 redef class ADebugTypeExpr
2382 redef fun stmt(v)
2383 do
2384 # do nothing
2385 end
2386 end