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