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