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