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