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