engine: handle the compilation/interpretation of multiple varargs
[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 var mp = msignature.mparameters[i]
532
533 # skip test for vararg since the array is instantiated with the correct polymorphic type
534 if mp.is_vararg then continue
535
536 # skip if the cast is not required
537 var origmtype = mpropdef.mproperty.intro.msignature.mparameters[i].mtype
538 if not origmtype.need_anchor then continue
539
540 #print "{mpropdef}: {mpropdef.mproperty.intro.msignature.mparameters[i]}"
541
542 # get the parameter type
543 var mtype = mp.mtype
544 var anchor = args.first.mtype.as(MClassType)
545 var amtype = mtype.anchor_to(self.mainmodule, anchor)
546 if not args[i+1].mtype.is_subtype(self.mainmodule, anchor, amtype) then
547 node.fatal(self, "Cast failed. Expected `{mtype}`, got `{args[i+1].mtype}`")
548 end
549 end
550 end
551
552 # Common code for runtime injected calls and normal calls
553 fun send_commons(mproperty: MMethod, args: Array[Instance], mtype: MType): nullable Instance
554 do
555 if mtype isa MNullType then
556 if mproperty.name == "==" or mproperty.name == "is_same_instance" then
557 return self.bool_instance(args[0] == args[1])
558 else if mproperty.name == "!=" then
559 return self.bool_instance(args[0] != args[1])
560 end
561 #fatal("Receiver is null. {mproperty}. {args.join(" ")} {self.frame.current_node.class_name}")
562 fatal("Receiver is null")
563 end
564 return null
565 end
566
567 # Execute a full `callsite` for given `args`
568 # Use this method, instead of `send` to execute and control the additional behavior of the call-sites
569 fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
570 do
571 if callsite == null then return null
572 var initializers = callsite.mpropdef.initializers
573 if not initializers.is_empty then
574 var recv = arguments.first
575 var i = 1
576 for p in initializers do
577 if p isa MMethod then
578 var args = [recv]
579 for x in p.intro.msignature.mparameters do
580 args.add arguments[i]
581 i += 1
582 end
583 self.send(p, args)
584 else if p isa MAttribute then
585 assert recv isa MutableInstance
586 write_attribute(p, recv, arguments[i])
587 i += 1
588 else abort
589 end
590 assert i == arguments.length
591
592 return send(callsite.mproperty, [recv])
593 end
594 return send(callsite.mproperty, arguments)
595 end
596
597 # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
598 # Return a value if `mproperty` is a function, or null if it is a procedure.
599 # The call is polymorphic. There is a message-sending/late-binding according to the receiver (args[0]).
600 fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
601 do
602 var recv = args.first
603 var mtype = recv.mtype
604 var ret = send_commons(mproperty, args, mtype)
605 if ret != null then return ret
606 var propdef = mproperty.lookup_first_definition(self.mainmodule, mtype)
607 return self.call(propdef, args)
608 end
609
610 # Read the attribute `mproperty` of an instance `recv` and return its value.
611 # If the attribute in not yet initialized, then aborts with an error message.
612 fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
613 do
614 assert recv isa MutableInstance
615 if not recv.attributes.has_key(mproperty) then
616 fatal("Uninitialized attribute {mproperty.name}")
617 abort
618 end
619 return recv.attributes[mproperty]
620 end
621
622 # Replace in `recv` the value of the attribute `mproperty` by `value`
623 fun write_attribute(mproperty: MAttribute, recv: Instance, value: Instance)
624 do
625 assert recv isa MutableInstance
626 recv.attributes[mproperty] = value
627 end
628
629 # Is the attribute `mproperty` initialized the instance `recv`?
630 fun isset_attribute(mproperty: MAttribute, recv: Instance): Bool
631 do
632 assert recv isa MutableInstance
633 return recv.attributes.has_key(mproperty)
634 end
635
636 # Collect attributes of a type in the order of their init
637 fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]
638 do
639 var cache = self.collect_attr_propdef_cache
640 if cache.has_key(mtype) then return cache[mtype]
641
642 var res = new Array[AAttrPropdef]
643 var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
644 self.mainmodule.linearize_mclassdefs(cds)
645 for cd in cds do
646 res.add_all(modelbuilder.collect_attr_propdef(cd))
647 end
648
649 cache[mtype] = res
650 return res
651 end
652
653 private var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
654
655 # Fill the initial values of the newly created instance `recv`.
656 # `recv.mtype` is used to know what must be filled.
657 fun init_instance(recv: Instance)
658 do
659 for npropdef in collect_attr_propdef(recv.mtype) do
660 npropdef.init_expr(self, recv)
661 end
662 end
663
664 # A hook to initialize a `PrimitiveInstance`
665 fun init_instance_primitive(recv: Instance) do end
666
667 # This function determines the correct type according to the receiver of the current propdef (self).
668 fun unanchor_type(mtype: MType): MType
669 do
670 return mtype.anchor_to(self.mainmodule, current_receiver_class)
671 end
672
673 # Placebo instance used to mark internal error result when `null` already have a meaning.
674 # TODO: replace with multiple return or something better
675 var error_instance = new MutableInstance(modelbuilder.model.null_type) is lazy
676 end
677
678 # An instance represents a value of the executed program.
679 abstract class Instance
680 # The dynamic type of the instance
681 # ASSERT: not self.mtype.is_anchored
682 var mtype: MType
683
684 # return true if the instance is the true value.
685 # return false if the instance is the true value.
686 # else aborts
687 fun is_true: Bool do abort
688
689 # Return true if `self` IS `o` (using the Nit semantic of is)
690 fun eq_is(o: Instance): Bool do return self.is_same_instance(o)
691
692 # Human readable object identity "Type#number"
693 redef fun to_s do return "{mtype}"
694
695 # Return the integer value if the instance is an integer.
696 # else aborts
697 fun to_i: Int do abort
698
699 # Return the integer value if the instance is a float.
700 # else aborts
701 fun to_f: Float do abort
702
703 # Return the integer value if the instance is a byte.
704 # else aborts
705 fun to_b: Byte do abort
706
707 # Return the integer value if the instance is a int8.
708 # else aborts
709 fun to_i8: Int8 do abort
710
711 # Return the integer value if the instance is a int16.
712 # else aborts
713 fun to_i16: Int16 do abort
714
715 # Return the integer value if the instance is a uint16.
716 # else aborts
717 fun to_u16: UInt16 do abort
718
719 # Return the integer value if the instance is a int32.
720 # else aborts
721 fun to_i32: Int32 do abort
722
723 # Return the integer value if the instance is a uint32.
724 # else aborts
725 fun to_u32: UInt32 do abort
726
727 # The real value encapsulated if the instance is primitive.
728 # Else aborts.
729 fun val: nullable Object do abort
730 end
731
732 # A instance with attribute (standards objects)
733 class MutableInstance
734 super Instance
735
736 # The values of the attributes
737 var attributes: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
738 end
739
740 # Special instance to handle primitives values (int, bool, etc.)
741 # The trick it just to encapsulate the <<real>> value
742 class PrimitiveInstance[E]
743 super Instance
744
745 # The real value encapsulated
746 redef var val: E
747
748 redef fun is_true
749 do
750 if val == true then return true
751 if val == false then return false
752 abort
753 end
754
755 redef fun ==(o)
756 do
757 if not o isa PrimitiveInstance[nullable Object] then return false
758 return self.val == o.val
759 end
760
761 redef fun eq_is(o)
762 do
763 if not o isa PrimitiveInstance[nullable Object] then return false
764 return self.val.is_same_instance(o.val)
765 end
766
767 redef fun to_s do return "{mtype}#{val.object_id}({val or else "null"})"
768
769 redef fun to_i do return val.as(Int)
770
771 redef fun to_f do return val.as(Float)
772
773 redef fun to_b do return val.as(Byte)
774
775 redef fun to_i8 do return val.as(Int8)
776
777 redef fun to_i16 do return val.as(Int16)
778
779 redef fun to_u16 do return val.as(UInt16)
780
781 redef fun to_i32 do return val.as(Int32)
782
783 redef fun to_u32 do return val.as(UInt32)
784 end
785
786 # Information about local variables in a running method
787 abstract class Frame
788 # The current visited node
789 # The node is stored by frame to keep a stack trace
790 var current_node: ANode
791 # The executed property.
792 # A Method in case of a call, an attribute in case of a default initialization.
793 var mpropdef: MPropDef
794 # Arguments of the method (the first is the receiver)
795 var arguments: Array[Instance]
796 # Indicate if the expression has an array comprehension form
797 var comprehension: nullable Array[Instance] = null
798 end
799
800 # Implementation of a Frame with a Hashmap to store local variables
801 class InterpreterFrame
802 super Frame
803
804 # Mapping between a variable and the current value
805 private var map: Map[Variable, Instance] = new HashMap[Variable, Instance]
806 end
807
808 redef class ANode
809 # Aborts the program with a message
810 # `v` is used to know if a colored message is displayed or not
811 fun fatal(v: NaiveInterpreter, message: String)
812 do
813 if v.modelbuilder.toolcontext.opt_no_color.value == true then
814 sys.stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
815 else
816 sys.stderr.write("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
817 sys.stderr.write(v.stack_trace)
818 sys.stderr.write("\n")
819 end
820 exit(1)
821 end
822 end
823
824 redef class APropdef
825 # Execute a `mpropdef` associated with the current node.
826 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
827 do
828 fatal(v, "NOT YET IMPLEMENTED method kind {class_name}. {mpropdef}")
829 abort
830 end
831 end
832
833 redef class AMethPropdef
834 super TablesCapable
835
836 redef fun call(v, mpropdef, args)
837 do
838 var f = v.new_frame(self, mpropdef, args)
839 var res = call_commons(v, mpropdef, args, f)
840 v.frames.shift
841 if v.returnmark == f then
842 v.returnmark = null
843 res = v.escapevalue
844 v.escapevalue = null
845 return res
846 end
847 return res
848 end
849
850 private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
851 do
852 v.frames.unshift(f)
853
854 for i in [0..mpropdef.msignature.arity[ do
855 var variable = self.n_signature.n_params[i].variable
856 assert variable != null
857 v.write_variable(variable, arguments[i+1])
858 end
859
860 # Call the implicit super-init
861 var auto_super_inits = self.auto_super_inits
862 if auto_super_inits != null then
863 var args = [arguments.first]
864 for auto_super_init in auto_super_inits do
865 args.clear
866 for i in [0..auto_super_init.msignature.arity+1[ do
867 args.add(arguments[i])
868 end
869 assert auto_super_init.mproperty != mpropdef.mproperty
870 v.callsite(auto_super_init, args)
871 end
872 end
873 if auto_super_call then
874 # standard call-next-method
875 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
876 v.call(superpd, arguments)
877 end
878
879 if mpropdef.is_intern or mpropdef.is_extern then
880 var res = intern_call(v, mpropdef, arguments)
881 if res != v.error_instance then return res
882 end
883
884 if n_block != null then
885 v.stmt(self.n_block)
886 return null
887 end
888
889 if mpropdef.is_intern then
890 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
891 else if mpropdef.is_extern then
892 var res = call_extern(v, mpropdef, arguments, f)
893 if res != v.error_instance then return res
894 else
895 fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
896 end
897 abort
898 end
899
900 # Call this extern method
901 protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
902 do
903 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
904 return v.error_instance
905 end
906
907 # Interprets a intern or a shortcut extern method.
908 # Returns the result for a function, `null` for a procedure, or `error_instance` if the method is unknown.
909 private fun intern_call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
910 do
911 var pname = mpropdef.mproperty.name
912 var cname = mpropdef.mclassdef.mclass.name
913 if pname == "output" then
914 var recv = args.first
915 recv.val.output
916 return null
917 else if pname == "object_id" then
918 var recv = args.first
919 if recv isa PrimitiveInstance[Object] then
920 return v.int_instance(recv.val.object_id)
921 else
922 return v.int_instance(recv.object_id)
923 end
924 else if pname == "output_class_name" then
925 var recv = args.first
926 print recv.mtype
927 return null
928 else if pname == "native_class_name" then
929 var recv = args.first
930 var txt = recv.mtype.to_s
931 return v.native_string_instance(txt)
932 else if pname == "==" then
933 # == is correctly redefined for instances
934 return v.bool_instance(args[0] == args[1])
935 else if pname == "!=" then
936 return v.bool_instance(args[0] != args[1])
937 else if pname == "is_same_type" then
938 return v.bool_instance(args[0].mtype == args[1].mtype)
939 else if pname == "is_same_instance" then
940 return v.bool_instance(args[0].eq_is(args[1]))
941 else if pname == "exit" then
942 exit(args[1].to_i)
943 abort
944 else if pname == "buffer_mode_full" then
945 return v.int_instance(sys.buffer_mode_full)
946 else if pname == "buffer_mode_line" then
947 return v.int_instance(sys.buffer_mode_line)
948 else if pname == "buffer_mode_none" then
949 return v.int_instance(sys.buffer_mode_none)
950 else if pname == "sys" then
951 return v.mainobj
952 else if cname == "Int" then
953 var recvval = args[0].to_i
954 if pname == "unary -" then
955 return v.int_instance(-recvval)
956 else if pname == "unary +" then
957 return args[0]
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.int_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.bool_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 == "to_f" then
979 return v.float_instance(recvval.to_f)
980 else if pname == "to_b" then
981 return v.byte_instance(recvval.to_b)
982 else if pname == "<<" then
983 return v.int_instance(recvval << args[1].to_i)
984 else if pname == ">>" then
985 return v.int_instance(recvval >> args[1].to_i)
986 else if pname == "to_i8" then
987 return v.int8_instance(recvval.to_i8)
988 else if pname == "to_i16" then
989 return v.int16_instance(recvval.to_i16)
990 else if pname == "to_u16" then
991 return v.uint16_instance(recvval.to_u16)
992 else if pname == "to_i32" then
993 return v.int32_instance(recvval.to_i32)
994 else if pname == "to_u32" then
995 return v.uint32_instance(recvval.to_u32)
996 else if pname == "rand" then
997 var res = recvval.rand
998 return v.int_instance(res)
999 end
1000 else if cname == "Byte" then
1001 var recvval = args[0].to_b
1002 if pname == "unary -" then
1003 return v.byte_instance(-recvval)
1004 else if pname == "unary +" then
1005 return args[0]
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.byte_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.bool_instance(recvval >= args[1].to_b)
1024 else if pname == "<=>" then
1025 return v.int_instance(recvval <=> args[1].to_b)
1026 else if pname == "to_f" then
1027 return v.float_instance(recvval.to_f)
1028 else if pname == "to_i" then
1029 return v.int_instance(recvval.to_i)
1030 else if pname == "<<" then
1031 return v.byte_instance(recvval << args[1].to_i)
1032 else if pname == ">>" then
1033 return v.byte_instance(recvval >> args[1].to_i)
1034 else if pname == "to_i8" then
1035 return v.int8_instance(recvval.to_i8)
1036 else if pname == "to_i16" then
1037 return v.int16_instance(recvval.to_i16)
1038 else if pname == "to_u16" then
1039 return v.uint16_instance(recvval.to_u16)
1040 else if pname == "to_i32" then
1041 return v.int32_instance(recvval.to_i32)
1042 else if pname == "to_u32" then
1043 return v.uint32_instance(recvval.to_u32)
1044 else if pname == "byte_to_s_len" then
1045 return v.int_instance(recvval.to_s.length)
1046 end
1047 else if cname == "Char" then
1048 var recv = args[0].val.as(Char)
1049 if pname == "successor" then
1050 return v.char_instance(recv.successor(args[1].to_i))
1051 else if pname == "predecessor" then
1052 return v.char_instance(recv.predecessor(args[1].to_i))
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.bool_instance(recv >= args[1].val.as(Char))
1061 else if pname == "<=>" then
1062 return v.int_instance(recv <=> args[1].val.as(Char))
1063 end
1064 else if cname == "Float" then
1065 var recv = args[0].to_f
1066 if pname == "unary -" then
1067 return v.float_instance(-recv)
1068 else if pname == "unary +" then
1069 return args[0]
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.float_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 == ">=" then
1085 return v.bool_instance(recv >= args[1].to_f)
1086 else if pname == "to_i" then
1087 return v.int_instance(recv.to_i)
1088 else if pname == "to_b" then
1089 return v.byte_instance(recv.to_b)
1090 else if pname == "to_i8" then
1091 return v.int8_instance(recv.to_i8)
1092 else if pname == "to_i16" then
1093 return v.int16_instance(recv.to_i16)
1094 else if pname == "to_u16" then
1095 return v.uint16_instance(recv.to_u16)
1096 else if pname == "to_i32" then
1097 return v.int32_instance(recv.to_i32)
1098 else if pname == "to_u32" then
1099 return v.uint32_instance(recv.to_u32)
1100 else if pname == "cos" then
1101 return v.float_instance(args[0].to_f.cos)
1102 else if pname == "sin" then
1103 return v.float_instance(args[0].to_f.sin)
1104 else if pname == "tan" then
1105 return v.float_instance(args[0].to_f.tan)
1106 else if pname == "acos" then
1107 return v.float_instance(args[0].to_f.acos)
1108 else if pname == "asin" then
1109 return v.float_instance(args[0].to_f.asin)
1110 else if pname == "atan" then
1111 return v.float_instance(args[0].to_f.atan)
1112 else if pname == "sqrt" then
1113 return v.float_instance(args[0].to_f.sqrt)
1114 else if pname == "exp" then
1115 return v.float_instance(args[0].to_f.exp)
1116 else if pname == "log" then
1117 return v.float_instance(args[0].to_f.log)
1118 else if pname == "pow" then
1119 return v.float_instance(args[0].to_f.pow(args[1].to_f))
1120 else if pname == "rand" then
1121 return v.float_instance(args[0].to_f.rand)
1122 else if pname == "abs" then
1123 return v.float_instance(args[0].to_f.abs)
1124 else if pname == "hypot_with" then
1125 return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
1126 else if pname == "is_nan" then
1127 return v.bool_instance(args[0].to_f.is_nan)
1128 else if pname == "is_inf_extern" then
1129 return v.bool_instance(args[0].to_f.is_inf != 0)
1130 else if pname == "round" then
1131 return v.float_instance(args[0].to_f.round)
1132 end
1133 else if cname == "NativeString" then
1134 if pname == "new" then
1135 return v.native_string_instance_len(args[1].to_i)
1136 end
1137 var recvval = args.first.val.as(NativeString)
1138 if pname == "[]" then
1139 var arg1 = args[1].to_i
1140 return v.byte_instance(recvval[arg1])
1141 else if pname == "[]=" then
1142 var arg1 = args[1].to_i
1143 recvval[arg1] = args[2].val.as(Byte)
1144 return null
1145 else if pname == "copy_to" then
1146 # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
1147 var destval = args[1].val.as(NativeString)
1148 var lenval = args[2].to_i
1149 var fromval = args[3].to_i
1150 var toval = args[4].to_i
1151 recvval.copy_to(destval, lenval, fromval, toval)
1152 return null
1153 else if pname == "atoi" then
1154 return v.int_instance(recvval.atoi)
1155 else if pname == "fast_cstring" then
1156 var ns = recvval.fast_cstring(args[1].to_i)
1157 return v.native_string_instance(ns.to_s)
1158 end
1159 else if pname == "calloc_string" then
1160 return v.native_string_instance_len(args[1].to_i)
1161 else if cname == "NativeArray" then
1162 if pname == "new" then
1163 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
1164 var instance = new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
1165 v.init_instance_primitive(instance)
1166 return instance
1167 end
1168 var recvval = args.first.val.as(Array[Instance])
1169 if pname == "[]" then
1170 return recvval[args[1].to_i]
1171 else if pname == "[]=" then
1172 recvval[args[1].to_i] = args[2]
1173 return null
1174 else if pname == "length" then
1175 return v.int_instance(recvval.length)
1176 else if pname == "copy_to" then
1177 recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
1178 return null
1179 end
1180 else if cname == "Int8" then
1181 var recvval = args[0].to_i8
1182 if pname == "unary -" then
1183 return v.int8_instance(-recvval)
1184 else if pname == "unary +" then
1185 return args[0]
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.int8_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.bool_instance(recvval >= args[1].to_i8)
1204 else if pname == "<=>" then
1205 return v.int_instance(recvval <=> args[1].to_i8)
1206 else if pname == "to_f" then
1207 return v.float_instance(recvval.to_f)
1208 else if pname == "to_i" then
1209 return v.int_instance(recvval.to_i)
1210 else if pname == "to_b" then
1211 return v.byte_instance(recvval.to_b)
1212 else if pname == "to_i16" then
1213 return v.int16_instance(recvval.to_i16)
1214 else if pname == "to_u16" then
1215 return v.uint16_instance(recvval.to_u16)
1216 else if pname == "to_i32" then
1217 return v.int32_instance(recvval.to_i32)
1218 else if pname == "to_u32" then
1219 return v.uint32_instance(recvval.to_u32)
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_i))
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 == "^" then
1229 return v.int8_instance(recvval ^ args[1].to_i8)
1230 else if pname == "unary ~" then
1231 return v.int8_instance(~recvval)
1232 end
1233 else if cname == "Int16" then
1234 var recvval = args[0].to_i16
1235 if pname == "unary -" then
1236 return v.int16_instance(-recvval)
1237 else if pname == "unary +" then
1238 return args[0]
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.int16_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.bool_instance(recvval >= args[1].to_i16)
1257 else if pname == "<=>" then
1258 return v.int_instance(recvval <=> args[1].to_i16)
1259 else if pname == "to_f" then
1260 return v.float_instance(recvval.to_f)
1261 else if pname == "to_i" then
1262 return v.int_instance(recvval.to_i)
1263 else if pname == "to_b" then
1264 return v.byte_instance(recvval.to_b)
1265 else if pname == "to_i8" then
1266 return v.int8_instance(recvval.to_i8)
1267 else if pname == "to_u16" then
1268 return v.uint16_instance(recvval.to_u16)
1269 else if pname == "to_i32" then
1270 return v.int32_instance(recvval.to_i32)
1271 else if pname == "to_u32" then
1272 return v.uint32_instance(recvval.to_u32)
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_i))
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 == "^" then
1282 return v.int16_instance(recvval ^ args[1].to_i16)
1283 else if pname == "unary ~" then
1284 return v.int16_instance(~recvval)
1285 end
1286 else if cname == "UInt16" then
1287 var recvval = args[0].to_u16
1288 if pname == "unary -" then
1289 return v.uint16_instance(-recvval)
1290 else if pname == "unary +" then
1291 return args[0]
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.uint16_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.bool_instance(recvval >= args[1].to_u16)
1310 else if pname == "<=>" then
1311 return v.int_instance(recvval <=> args[1].to_u16)
1312 else if pname == "to_f" then
1313 return v.float_instance(recvval.to_f)
1314 else if pname == "to_i" then
1315 return v.int_instance(recvval.to_i)
1316 else if pname == "to_b" then
1317 return v.byte_instance(recvval.to_b)
1318 else if pname == "to_i8" then
1319 return v.int8_instance(recvval.to_i8)
1320 else if pname == "to_i16" then
1321 return v.int16_instance(recvval.to_i16)
1322 else if pname == "to_i32" then
1323 return v.int32_instance(recvval.to_i32)
1324 else if pname == "to_u32" then
1325 return v.uint32_instance(recvval.to_u32)
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_i))
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 == "^" then
1335 return v.uint16_instance(recvval ^ args[1].to_u16)
1336 else if pname == "unary ~" then
1337 return v.uint16_instance(~recvval)
1338 end
1339 else if cname == "Int32" then
1340 var recvval = args[0].to_i32
1341 if pname == "unary -" then
1342 return v.int32_instance(-recvval)
1343 else if pname == "unary +" then
1344 return args[0]
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.int32_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.bool_instance(recvval >= args[1].to_i32)
1363 else if pname == "<=>" then
1364 return v.int_instance(recvval <=> args[1].to_i32)
1365 else if pname == "to_f" then
1366 return v.float_instance(recvval.to_f)
1367 else if pname == "to_i" then
1368 return v.int_instance(recvval.to_i)
1369 else if pname == "to_b" then
1370 return v.byte_instance(recvval.to_b)
1371 else if pname == "to_i8" then
1372 return v.int8_instance(recvval.to_i8)
1373 else if pname == "to_i16" then
1374 return v.int16_instance(recvval.to_i16)
1375 else if pname == "to_u16" then
1376 return v.uint16_instance(recvval.to_u16)
1377 else if pname == "to_u32" then
1378 return v.uint32_instance(recvval.to_u32)
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_i))
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 == "^" then
1388 return v.int32_instance(recvval ^ args[1].to_i32)
1389 else if pname == "unary ~" then
1390 return v.int32_instance(~recvval)
1391 end
1392 else if cname == "UInt32" then
1393 var recvval = args[0].to_u32
1394 if pname == "unary -" then
1395 return v.uint32_instance(-recvval)
1396 else if pname == "unary +" then
1397 return args[0]
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.uint32_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.bool_instance(recvval >= args[1].to_u32)
1416 else if pname == "<=>" then
1417 return v.int_instance(recvval <=> args[1].to_u32)
1418 else if pname == "to_f" then
1419 return v.float_instance(recvval.to_f)
1420 else if pname == "to_i" then
1421 return v.int_instance(recvval.to_i)
1422 else if pname == "to_b" then
1423 return v.byte_instance(recvval.to_b)
1424 else if pname == "to_i8" then
1425 return v.int8_instance(recvval.to_i8)
1426 else if pname == "to_i16" then
1427 return v.int16_instance(recvval.to_i16)
1428 else if pname == "to_u16" then
1429 return v.uint16_instance(recvval.to_u16)
1430 else if pname == "to_i32" then
1431 return v.int32_instance(recvval.to_i32)
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_i))
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 == "^" then
1441 return v.uint32_instance(recvval ^ args[1].to_u32)
1442 else if pname == "unary ~" then
1443 return v.uint32_instance(~recvval)
1444 end
1445 else if pname == "native_argc" then
1446 return v.int_instance(v.arguments.length)
1447 else if pname == "native_argv" then
1448 var txt = v.arguments[args[1].to_i]
1449 return v.native_string_instance(txt)
1450 else if pname == "native_argc" then
1451 return v.int_instance(v.arguments.length)
1452 else if pname == "native_argv" then
1453 var txt = v.arguments[args[1].to_i]
1454 return v.native_string_instance(txt)
1455 else if pname == "lexer_goto" then
1456 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
1457 else if pname == "lexer_accept" then
1458 return v.int_instance(lexer_accept(args[1].to_i))
1459 else if pname == "parser_goto" then
1460 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
1461 else if pname == "parser_action" then
1462 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
1463 end
1464 return v.error_instance
1465 end
1466 end
1467
1468 redef class AAttrPropdef
1469 redef fun call(v, mpropdef, args)
1470 do
1471 var recv = args.first
1472 assert recv isa MutableInstance
1473 var attr = self.mpropdef.mproperty
1474 if mpropdef == mreadpropdef then
1475 assert args.length == 1
1476 if not is_lazy or v.isset_attribute(attr, recv) then return v.read_attribute(attr, recv)
1477 var f = v.new_frame(self, mpropdef, args)
1478 return evaluate_expr(v, recv, f)
1479 else if mpropdef == mwritepropdef then
1480 assert args.length == 2
1481 v.write_attribute(attr, recv, args[1])
1482 return null
1483 else
1484 abort
1485 end
1486 end
1487
1488 # Evaluate and set the default value of the attribute in `recv`
1489 private fun init_expr(v: NaiveInterpreter, recv: Instance)
1490 do
1491 if is_lazy then return
1492 if has_value then
1493 var f = v.new_frame(self, mreadpropdef.as(not null), [recv])
1494 evaluate_expr(v, recv, f)
1495 return
1496 end
1497 var mpropdef = self.mpropdef
1498 if mpropdef == null then return
1499 var mtype = self.mtype.as(not null)
1500 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1501 if mtype isa MNullableType then
1502 v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
1503 end
1504 end
1505
1506 private fun evaluate_expr(v: NaiveInterpreter, recv: Instance, f: Frame): Instance
1507 do
1508 assert recv isa MutableInstance
1509 v.frames.unshift(f)
1510
1511 var val
1512
1513 var nexpr = self.n_expr
1514 var nblock = self.n_block
1515 if nexpr != null then
1516 val = v.expr(nexpr)
1517 else if nblock != null then
1518 v.stmt(nblock)
1519 assert v.returnmark == f
1520 val = v.escapevalue
1521 v.returnmark = null
1522 v.escapevalue = null
1523 else
1524 abort
1525 end
1526 assert val != null
1527
1528 v.frames.shift
1529 assert not v.is_escaping
1530 v.write_attribute(self.mpropdef.mproperty, recv, val)
1531 return val
1532 end
1533 end
1534
1535 redef class AClassdef
1536 # Execute an implicit `mpropdef` associated with the current node.
1537 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
1538 do
1539 if mpropdef.mproperty.is_root_init then
1540 assert args.length == 1
1541 if not mpropdef.is_intro then
1542 # standard call-next-method
1543 var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
1544 v.call(superpd, args)
1545 end
1546 return null
1547 else
1548 abort
1549 end
1550 end
1551 end
1552
1553 redef class AExpr
1554 # Evaluate the node as a possible expression.
1555 # Return a possible value
1556 # NOTE: Do not call this method directly, but use `v.expr`
1557 # This method is here to be implemented by subclasses.
1558 protected fun expr(v: NaiveInterpreter): nullable Instance
1559 do
1560 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1561 abort
1562 end
1563
1564 # Evaluate the node as a statement.
1565 # NOTE: Do not call this method directly, but use `v.stmt`
1566 # This method is here to be implemented by subclasses (no need to return something).
1567 protected fun stmt(v: NaiveInterpreter)
1568 do
1569 expr(v)
1570 end
1571
1572 end
1573
1574 redef class ABlockExpr
1575 redef fun expr(v)
1576 do
1577 var last = self.n_expr.last
1578 for e in self.n_expr do
1579 if e == last then break
1580 v.stmt(e)
1581 if v.is_escaping then return null
1582 end
1583 return last.expr(v)
1584 end
1585
1586 redef fun stmt(v)
1587 do
1588 for e in self.n_expr do
1589 v.stmt(e)
1590 if v.is_escaping then return
1591 end
1592 end
1593 end
1594
1595 redef class AVardeclExpr
1596 redef fun expr(v)
1597 do
1598 var ne = self.n_expr
1599 if ne != null then
1600 var i = v.expr(ne)
1601 if i == null then return null
1602 v.write_variable(self.variable.as(not null), i)
1603 return i
1604 end
1605 return null
1606 end
1607 end
1608
1609 redef class AVarExpr
1610 redef fun expr(v)
1611 do
1612 return v.read_variable(self.variable.as(not null))
1613 end
1614 end
1615
1616 redef class AVarAssignExpr
1617 redef fun expr(v)
1618 do
1619 var i = v.expr(self.n_value)
1620 if i == null then return null
1621 v.write_variable(self.variable.as(not null), i)
1622 return i
1623 end
1624 end
1625
1626 redef class AVarReassignExpr
1627 redef fun stmt(v)
1628 do
1629 var variable = self.variable.as(not null)
1630 var vari = v.read_variable(variable)
1631 var value = v.expr(self.n_value)
1632 if value == null then return
1633 var res = v.callsite(reassign_callsite, [vari, value])
1634 assert res != null
1635 v.write_variable(variable, res)
1636 end
1637 end
1638
1639 redef class ASelfExpr
1640 redef fun expr(v)
1641 do
1642 return v.frame.arguments.first
1643 end
1644 end
1645
1646 redef class AImplicitSelfExpr
1647 redef fun expr(v)
1648 do
1649 if not is_sys then return super
1650 return v.mainobj
1651 end
1652 end
1653
1654 redef class AEscapeExpr
1655 redef fun stmt(v)
1656 do
1657 var ne = self.n_expr
1658 if ne != null then
1659 var i = v.expr(ne)
1660 if i == null then return
1661 v.escapevalue = i
1662 end
1663 v.escapemark = self.escapemark
1664 end
1665 end
1666
1667 redef class AReturnExpr
1668 redef fun stmt(v)
1669 do
1670 var ne = self.n_expr
1671 if ne != null then
1672 var i = v.expr(ne)
1673 if i == null then return
1674 v.escapevalue = i
1675 end
1676 v.returnmark = v.frame
1677 end
1678 end
1679
1680 redef class AAbortExpr
1681 redef fun stmt(v)
1682 do
1683 fatal(v, "Aborted")
1684 exit(1)
1685 end
1686 end
1687
1688 redef class AIfExpr
1689 redef fun expr(v)
1690 do
1691 var cond = v.expr(self.n_expr)
1692 if cond == null then return null
1693 if cond.is_true then
1694 return v.expr(self.n_then.as(not null))
1695 else
1696 return v.expr(self.n_else.as(not null))
1697 end
1698 end
1699
1700 redef fun stmt(v)
1701 do
1702 var cond = v.expr(self.n_expr)
1703 if cond == null then return
1704 if cond.is_true then
1705 v.stmt(self.n_then)
1706 else
1707 v.stmt(self.n_else)
1708 end
1709 end
1710 end
1711
1712 redef class AIfexprExpr
1713 redef fun expr(v)
1714 do
1715 var cond = v.expr(self.n_expr)
1716 if cond == null then return null
1717 if cond.is_true then
1718 return v.expr(self.n_then)
1719 else
1720 return v.expr(self.n_else)
1721 end
1722 end
1723 end
1724
1725 redef class ADoExpr
1726 redef fun stmt(v)
1727 do
1728 v.stmt(self.n_block)
1729 v.is_escape(self.break_mark) # Clear the break (if any)
1730 end
1731 end
1732
1733 redef class AWhileExpr
1734 redef fun stmt(v)
1735 do
1736 loop
1737 var cond = v.expr(self.n_expr)
1738 if cond == null then return
1739 if not cond.is_true then return
1740 v.stmt(self.n_block)
1741 if v.is_escape(self.break_mark) then return
1742 v.is_escape(self.continue_mark) # Clear the break
1743 if v.is_escaping then return
1744 end
1745 end
1746 end
1747
1748 redef class ALoopExpr
1749 redef fun stmt(v)
1750 do
1751 loop
1752 v.stmt(self.n_block)
1753 if v.is_escape(self.break_mark) then return
1754 v.is_escape(self.continue_mark) # Clear the break
1755 if v.is_escaping then return
1756 end
1757 end
1758 end
1759
1760 redef class AForExpr
1761 redef fun stmt(v)
1762 do
1763 var iters = new Array[Instance]
1764
1765 for g in n_groups do
1766 var col = v.expr(g.n_expr)
1767 if col == null then return
1768 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1769
1770 var iter = v.callsite(g.method_iterator, [col]).as(not null)
1771 iters.add iter
1772 end
1773
1774 loop
1775 for g in n_groups, iter in iters do
1776 var isok = v.callsite(g.method_is_ok, [iter]).as(not null)
1777 if not isok.is_true then break label
1778 if g.variables.length == 1 then
1779 var item = v.callsite(g.method_item, [iter]).as(not null)
1780 #self.debug("item {item}")
1781 v.write_variable(g.variables.first, item)
1782 else if g.variables.length == 2 then
1783 var key = v.callsite(g.method_key, [iter]).as(not null)
1784 v.write_variable(g.variables[0], key)
1785 var item = v.callsite(g.method_item, [iter]).as(not null)
1786 v.write_variable(g.variables[1], item)
1787 else
1788 abort
1789 end
1790 end
1791 v.stmt(self.n_block)
1792 if v.is_escape(self.break_mark) then break
1793 v.is_escape(self.continue_mark) # Clear the break
1794 if v.is_escaping then break
1795 for g in n_groups, iter in iters do
1796 v.callsite(g.method_next, [iter])
1797 end
1798 end label
1799 for g in n_groups, iter in iters do
1800 var method_finish = g.method_finish
1801 if method_finish != null then
1802 v.callsite(method_finish, [iter])
1803 end
1804 end
1805 end
1806 end
1807
1808 redef class AWithExpr
1809 redef fun stmt(v)
1810 do
1811 var expr = v.expr(self.n_expr)
1812 if expr == null then return
1813
1814 v.callsite(method_start, [expr])
1815 v.stmt(self.n_block)
1816 v.is_escape(self.break_mark) # Clear the break
1817 v.callsite(method_finish, [expr])
1818 end
1819 end
1820
1821 redef class AAssertExpr
1822 redef fun stmt(v)
1823 do
1824 var cond = v.expr(self.n_expr)
1825 if cond == null then return
1826 if not cond.is_true then
1827 v.stmt(self.n_else)
1828 if v.is_escaping then return
1829 var nid = self.n_id
1830 if nid != null then
1831 fatal(v, "Assert '{nid.text}' failed")
1832 else
1833 fatal(v, "Assert failed")
1834 end
1835 exit(1)
1836 end
1837 end
1838 end
1839
1840 redef class AOrExpr
1841 redef fun expr(v)
1842 do
1843 var cond = v.expr(self.n_expr)
1844 if cond == null then return null
1845 if cond.is_true then return cond
1846 return v.expr(self.n_expr2)
1847 end
1848 end
1849
1850 redef class AImpliesExpr
1851 redef fun expr(v)
1852 do
1853 var cond = v.expr(self.n_expr)
1854 if cond == null then return null
1855 if not cond.is_true then return v.true_instance
1856 return v.expr(self.n_expr2)
1857 end
1858 end
1859
1860 redef class AAndExpr
1861 redef fun expr(v)
1862 do
1863 var cond = v.expr(self.n_expr)
1864 if cond == null then return null
1865 if not cond.is_true then return cond
1866 return v.expr(self.n_expr2)
1867 end
1868 end
1869
1870 redef class ANotExpr
1871 redef fun expr(v)
1872 do
1873 var cond = v.expr(self.n_expr)
1874 if cond == null then return null
1875 return v.bool_instance(not cond.is_true)
1876 end
1877 end
1878
1879 redef class AOrElseExpr
1880 redef fun expr(v)
1881 do
1882 var i = v.expr(self.n_expr)
1883 if i == null then return null
1884 if i != v.null_instance then return i
1885 return v.expr(self.n_expr2)
1886 end
1887 end
1888
1889 redef class AIntegerExpr
1890 redef fun expr(v)
1891 do
1892 if value isa Int then return v.int_instance(value.as(Int))
1893 if value isa Byte then return v.byte_instance(value.as(Byte))
1894 if value isa Int8 then return v.int8_instance(value.as(Int8))
1895 if value isa Int16 then return v.int16_instance(value.as(Int16))
1896 if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
1897 if value isa Int32 then return v.int32_instance(value.as(Int32))
1898 if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
1899 return null
1900 end
1901 end
1902
1903 redef class AFloatExpr
1904 redef fun expr(v)
1905 do
1906 return v.float_instance(self.value.as(not null))
1907 end
1908 end
1909
1910 redef class ACharExpr
1911 redef fun expr(v)
1912 do
1913 return v.char_instance(self.value.as(not null))
1914 end
1915 end
1916
1917 redef class AArrayExpr
1918 redef fun expr(v)
1919 do
1920 var val = new Array[Instance]
1921 var old_comprehension = v.frame.comprehension
1922 v.frame.comprehension = val
1923 for nexpr in self.n_exprs do
1924 if nexpr isa AForExpr then
1925 v.stmt(nexpr)
1926 else
1927 var i = v.expr(nexpr)
1928 if i == null then return null
1929 val.add(i)
1930 end
1931 end
1932 v.frame.comprehension = old_comprehension
1933 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1934 var elttype = mtype.arguments.first
1935 return v.array_instance(val, elttype)
1936 end
1937 end
1938
1939 redef class AStringFormExpr
1940 redef fun expr(v)
1941 do
1942 var txt = self.value.as(not null)
1943 return v.string_instance(txt)
1944 end
1945 end
1946
1947 redef class ASuperstringExpr
1948 redef fun expr(v)
1949 do
1950 var array = new Array[Instance]
1951 for nexpr in n_exprs do
1952 var i = v.expr(nexpr)
1953 if i == null then return null
1954 array.add(i)
1955 end
1956 var i = v.array_instance(array, v.mainmodule.object_type)
1957 var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i])
1958 assert res != null
1959 return res
1960 end
1961 end
1962
1963 redef class ACrangeExpr
1964 redef fun expr(v)
1965 do
1966 var e1 = v.expr(self.n_expr)
1967 if e1 == null then return null
1968 var e2 = v.expr(self.n_expr2)
1969 if e2 == null then return null
1970 var mtype = v.unanchor_type(self.mtype.as(not null))
1971 var res = new MutableInstance(mtype)
1972 v.init_instance(res)
1973 v.callsite(init_callsite, [res, e1, e2])
1974 return res
1975 end
1976 end
1977
1978 redef class AOrangeExpr
1979 redef fun expr(v)
1980 do
1981 var e1 = v.expr(self.n_expr)
1982 if e1 == null then return null
1983 var e2 = v.expr(self.n_expr2)
1984 if e2 == null then return null
1985 var mtype = v.unanchor_type(self.mtype.as(not null))
1986 var res = new MutableInstance(mtype)
1987 v.init_instance(res)
1988 v.callsite(init_callsite, [res, e1, e2])
1989 return res
1990 end
1991 end
1992
1993 redef class ATrueExpr
1994 redef fun expr(v)
1995 do
1996 return v.bool_instance(true)
1997 end
1998 end
1999
2000 redef class AFalseExpr
2001 redef fun expr(v)
2002 do
2003 return v.bool_instance(false)
2004 end
2005 end
2006
2007 redef class ANullExpr
2008 redef fun expr(v)
2009 do
2010 return v.null_instance
2011 end
2012 end
2013
2014 redef class AIsaExpr
2015 redef fun expr(v)
2016 do
2017 var i = v.expr(self.n_expr)
2018 if i == null then return null
2019 var mtype = v.unanchor_type(self.cast_type.as(not null))
2020 return v.bool_instance(v.is_subtype(i.mtype, mtype))
2021 end
2022 end
2023
2024 redef class AAsCastExpr
2025 redef fun expr(v)
2026 do
2027 var i = v.expr(self.n_expr)
2028 if i == null then return null
2029 var mtype = self.mtype.as(not null)
2030 var amtype = v.unanchor_type(mtype)
2031 if not v.is_subtype(i.mtype, amtype) then
2032 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
2033 end
2034 return i
2035 end
2036 end
2037
2038 redef class AAsNotnullExpr
2039 redef fun expr(v)
2040 do
2041 var i = v.expr(self.n_expr)
2042 if i == null then return null
2043 if i.mtype isa MNullType then
2044 fatal(v, "Cast failed")
2045 end
2046 return i
2047 end
2048 end
2049
2050 redef class AParExpr
2051 redef fun expr(v)
2052 do
2053 return v.expr(self.n_expr)
2054 end
2055 end
2056
2057 redef class AOnceExpr
2058 redef fun expr(v)
2059 do
2060 if v.onces.has_key(self) then
2061 return v.onces[self]
2062 else
2063 var res = v.expr(self.n_expr)
2064 if res == null then return null
2065 v.onces[self] = res
2066 return res
2067 end
2068 end
2069 end
2070
2071 redef class ASendExpr
2072 redef fun expr(v)
2073 do
2074 var recv = v.expr(self.n_expr)
2075 if recv == null then return null
2076 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2077 if args == null then return null
2078
2079 var res = v.callsite(callsite, args)
2080 return res
2081 end
2082 end
2083
2084 redef class ASendReassignFormExpr
2085 redef fun stmt(v)
2086 do
2087 var recv = v.expr(self.n_expr)
2088 if recv == null then return
2089 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2090 if args == null then return
2091 var value = v.expr(self.n_value)
2092 if value == null then return
2093
2094 var read = v.callsite(callsite, args)
2095 assert read != null
2096
2097 var write = v.callsite(reassign_callsite, [read, value])
2098 assert write != null
2099
2100 args.add(write)
2101
2102 v.callsite(write_callsite, args)
2103 end
2104 end
2105
2106 redef class ASuperExpr
2107 redef fun expr(v)
2108 do
2109 var recv = v.frame.arguments.first
2110
2111 var callsite = self.callsite
2112 if callsite != null then
2113 var args
2114 if self.n_args.n_exprs.is_empty then
2115 # Add automatic arguments for the super init call
2116 args = [recv]
2117 for i in [0..callsite.msignature.arity[ do
2118 args.add(v.frame.arguments[i+1])
2119 end
2120 else
2121 args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2122 if args == null then return null
2123 end
2124
2125 # Super init call
2126 var res = v.callsite(callsite, args)
2127 return res
2128 end
2129
2130 # Standard call-next-method
2131 var mpropdef = self.mpropdef
2132 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
2133
2134 var args
2135 if self.n_args.n_exprs.is_empty then
2136 args = v.frame.arguments
2137 else
2138 args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
2139 if args == null then return null
2140 end
2141
2142 var res = v.call(mpropdef, args)
2143 return res
2144 end
2145 end
2146
2147 redef class ANewExpr
2148 redef fun expr(v)
2149 do
2150 var mtype = v.unanchor_type(self.recvtype.as(not null))
2151 var recv: Instance = new MutableInstance(mtype)
2152 v.init_instance(recv)
2153 var callsite = self.callsite
2154 if callsite == null then return recv
2155
2156 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2157 if args == null then return null
2158 var res2 = v.callsite(callsite, args)
2159 if res2 != null then
2160 #self.debug("got {res2} from {mproperty}. drop {recv}")
2161 return res2
2162 end
2163 return recv
2164 end
2165 end
2166
2167 redef class AAttrExpr
2168 redef fun expr(v)
2169 do
2170 var recv = v.expr(self.n_expr)
2171 if recv == null then return null
2172 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2173 var mproperty = self.mproperty.as(not null)
2174 return v.read_attribute(mproperty, recv)
2175 end
2176 end
2177
2178 redef class AAttrAssignExpr
2179 redef fun stmt(v)
2180 do
2181 var recv = v.expr(self.n_expr)
2182 if recv == null then return
2183 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2184 var i = v.expr(self.n_value)
2185 if i == null then return
2186 var mproperty = self.mproperty.as(not null)
2187 v.write_attribute(mproperty, recv, i)
2188 end
2189 end
2190
2191 redef class AAttrReassignExpr
2192 redef fun stmt(v)
2193 do
2194 var recv = v.expr(self.n_expr)
2195 if recv == null then return
2196 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2197 var value = v.expr(self.n_value)
2198 if value == null then return
2199 var mproperty = self.mproperty.as(not null)
2200 var attr = v.read_attribute(mproperty, recv)
2201 var res = v.callsite(reassign_callsite, [attr, value])
2202 assert res != null
2203 v.write_attribute(mproperty, recv, res)
2204 end
2205 end
2206
2207 redef class AIssetAttrExpr
2208 redef fun expr(v)
2209 do
2210 var recv = v.expr(self.n_expr)
2211 if recv == null then return null
2212 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2213 var mproperty = self.mproperty.as(not null)
2214 return v.bool_instance(v.isset_attribute(mproperty, recv))
2215 end
2216 end
2217
2218 redef class AVarargExpr
2219 redef fun expr(v)
2220 do
2221 return v.expr(self.n_expr)
2222 end
2223 end
2224
2225 redef class ANamedargExpr
2226 redef fun expr(v)
2227 do
2228 return v.expr(self.n_expr)
2229 end
2230 end
2231
2232 redef class ADebugTypeExpr
2233 redef fun stmt(v)
2234 do
2235 # do nothing
2236 end
2237 end