src/nit: remove unused primitive_types module
[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 private import model::serialize_model
25 private import frontend::explain_assert_api
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 else
1706 v.escapevalue = null
1707 end
1708 v.escapemark = self.escapemark
1709 end
1710 end
1711
1712 redef class AAbortExpr
1713 redef fun stmt(v)
1714 do
1715 fatal(v, "Aborted")
1716 exit(1)
1717 end
1718 end
1719
1720 redef class AIfExpr
1721 redef fun expr(v)
1722 do
1723 var cond = v.expr(self.n_expr)
1724 if cond == null then return null
1725 if cond.is_true then
1726 return v.expr(self.n_then.as(not null))
1727 else
1728 return v.expr(self.n_else.as(not null))
1729 end
1730 end
1731
1732 redef fun stmt(v)
1733 do
1734 var cond = v.expr(self.n_expr)
1735 if cond == null then return
1736 if cond.is_true then
1737 v.stmt(self.n_then)
1738 else
1739 v.stmt(self.n_else)
1740 end
1741 end
1742 end
1743
1744 redef class AIfexprExpr
1745 redef fun expr(v)
1746 do
1747 var cond = v.expr(self.n_expr)
1748 if cond == null then return null
1749 if cond.is_true then
1750 return v.expr(self.n_then)
1751 else
1752 return v.expr(self.n_else)
1753 end
1754 end
1755 end
1756
1757 redef class ADoExpr
1758 redef fun stmt(v)
1759 do
1760 # If this bloc has a catch, handle it with a do ... catch ... end
1761 if self.n_catch != null then
1762 var frame = v.frame
1763 v.catch_count += 1
1764 do
1765 v.stmt(self.n_block)
1766 v.is_escape(self.break_mark) # Clear the break (if any)
1767 v.catch_count -= 1
1768 catch
1769 # Restore the current frame if needed
1770 while v.frame != frame do v.frames.shift
1771 v.catch_count -= 1
1772 v.stmt(self.n_catch)
1773 end
1774 else
1775 v.stmt(self.n_block)
1776 v.is_escape(self.break_mark)
1777 end
1778 end
1779 end
1780
1781 redef class AWhileExpr
1782 redef fun stmt(v)
1783 do
1784 loop
1785 var cond = v.expr(self.n_expr)
1786 if cond == null then return
1787 if not cond.is_true then return
1788 v.stmt(self.n_block)
1789 if v.is_escape(self.break_mark) then return
1790 v.is_escape(self.continue_mark) # Clear the break
1791 if v.is_escaping then return
1792 end
1793 end
1794 end
1795
1796 redef class ALoopExpr
1797 redef fun stmt(v)
1798 do
1799 loop
1800 v.stmt(self.n_block)
1801 if v.is_escape(self.break_mark) then return
1802 v.is_escape(self.continue_mark) # Clear the break
1803 if v.is_escaping then return
1804 end
1805 end
1806 end
1807
1808 redef class AForExpr
1809 redef fun stmt(v)
1810 do
1811 var iters = new Array[Instance]
1812
1813 for g in n_groups do
1814 var col = v.expr(g.n_expr)
1815 if col == null then return
1816 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1817
1818 var iter = v.callsite(g.method_iterator, [col]).as(not null)
1819 iters.add iter
1820 end
1821
1822 loop
1823 for g in n_groups, iter in iters do
1824 var isok = v.callsite(g.method_is_ok, [iter]).as(not null)
1825 if not isok.is_true then break label
1826 if g.variables.length == 1 then
1827 var item = v.callsite(g.method_item, [iter]).as(not null)
1828 #self.debug("item {item}")
1829 v.write_variable(g.variables.first, item)
1830 else if g.variables.length == 2 then
1831 var key = v.callsite(g.method_key, [iter]).as(not null)
1832 v.write_variable(g.variables[0], key)
1833 var item = v.callsite(g.method_item, [iter]).as(not null)
1834 v.write_variable(g.variables[1], item)
1835 else
1836 abort
1837 end
1838 end
1839 v.stmt(self.n_block)
1840 if v.is_escape(self.break_mark) then break
1841 v.is_escape(self.continue_mark) # Clear the break
1842 if v.is_escaping then break
1843 for g in n_groups, iter in iters do
1844 v.callsite(g.method_next, [iter])
1845 end
1846 end label
1847 for g in n_groups, iter in iters do
1848 var method_finish = g.method_finish
1849 if method_finish != null then
1850 v.callsite(method_finish, [iter])
1851 end
1852 end
1853 end
1854 end
1855
1856 redef class AWithExpr
1857 redef fun stmt(v)
1858 do
1859 var expr = v.expr(self.n_expr)
1860 if expr == null then return
1861
1862 v.callsite(method_start, [expr])
1863 v.stmt(self.n_block)
1864 v.is_escape(self.break_mark) # Clear the break
1865
1866 # Execute the finally without an escape
1867 var old_mark = v.escapemark
1868 v.escapemark = null
1869 v.callsite(method_finish, [expr])
1870 # Restore the escape unless another escape was provided
1871 if v.escapemark == null then v.escapemark = old_mark
1872 end
1873 end
1874
1875 redef class AAssertExpr
1876 redef fun stmt(v)
1877 do
1878 var cond = v.expr(self.n_expr)
1879 if cond == null then return
1880 if not cond.is_true then
1881 v.stmt(self.n_else)
1882 if v.is_escaping then return
1883
1884 # Explain assert if it fails
1885 var explain_assert_str = explain_assert_str
1886 if explain_assert_str != null then
1887 var i = v.expr(explain_assert_str)
1888 if i isa MutableInstance then
1889 var res = v.send(v.force_get_primitive_method("to_cstring", i.mtype), [i])
1890 if res != null then
1891 var val = res.val
1892 if val != null then
1893 print_error "Runtime assert: {val.to_s}"
1894 end
1895 end
1896 end
1897 end
1898
1899 var nid = self.n_id
1900 if nid != null then
1901 fatal(v, "Assert '{nid.text}' failed")
1902 else
1903 fatal(v, "Assert failed")
1904 end
1905 exit(1)
1906 end
1907 end
1908 end
1909
1910 redef class AOrExpr
1911 redef fun expr(v)
1912 do
1913 var cond = v.expr(self.n_expr)
1914 if cond == null then return null
1915 if cond.is_true then return cond
1916 return v.expr(self.n_expr2)
1917 end
1918 end
1919
1920 redef class AImpliesExpr
1921 redef fun expr(v)
1922 do
1923 var cond = v.expr(self.n_expr)
1924 if cond == null then return null
1925 if not cond.is_true then return v.true_instance
1926 return v.expr(self.n_expr2)
1927 end
1928 end
1929
1930 redef class AAndExpr
1931 redef fun expr(v)
1932 do
1933 var cond = v.expr(self.n_expr)
1934 if cond == null then return null
1935 if not cond.is_true then return cond
1936 return v.expr(self.n_expr2)
1937 end
1938 end
1939
1940 redef class ANotExpr
1941 redef fun expr(v)
1942 do
1943 var cond = v.expr(self.n_expr)
1944 if cond == null then return null
1945 return v.bool_instance(not cond.is_true)
1946 end
1947 end
1948
1949 redef class AOrElseExpr
1950 redef fun expr(v)
1951 do
1952 var i = v.expr(self.n_expr)
1953 if i == null then return null
1954 if i != v.null_instance then return i
1955 return v.expr(self.n_expr2)
1956 end
1957 end
1958
1959 redef class AIntegerExpr
1960 redef fun expr(v)
1961 do
1962 if value isa Int then return v.int_instance(value.as(Int))
1963 if value isa Byte then return v.byte_instance(value.as(Byte))
1964 if value isa Int8 then return v.int8_instance(value.as(Int8))
1965 if value isa Int16 then return v.int16_instance(value.as(Int16))
1966 if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
1967 if value isa Int32 then return v.int32_instance(value.as(Int32))
1968 if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
1969 return null
1970 end
1971 end
1972
1973 redef class AFloatExpr
1974 redef fun expr(v)
1975 do
1976 return v.float_instance(self.value.as(not null))
1977 end
1978 end
1979
1980 redef class ACharExpr
1981 redef fun expr(v)
1982 do
1983 if is_ascii then return v.byte_instance(self.value.as(not null).ascii)
1984 if is_code_point then return v.int_instance(self.value.as(not null).code_point)
1985 return v.char_instance(self.value.as(not null))
1986 end
1987 end
1988
1989 redef class AArrayExpr
1990 redef fun expr(v)
1991 do
1992 var val = new Array[Instance]
1993 var old_comprehension = v.frame.comprehension
1994 v.frame.comprehension = val
1995 for nexpr in self.n_exprs do
1996 if nexpr isa AForExpr then
1997 v.stmt(nexpr)
1998 else
1999 var i = v.expr(nexpr)
2000 if i == null then return null
2001 val.add(i)
2002 end
2003 end
2004 v.frame.comprehension = old_comprehension
2005 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
2006 var elttype = mtype.arguments.first
2007 return v.array_instance(val, elttype)
2008 end
2009 end
2010
2011 redef class AugmentedStringFormExpr
2012 # Factorize the making of a `Regex` object from a literal prefixed string
2013 fun make_re(v: NaiveInterpreter, rs: Instance): nullable Instance do
2014 var tore = to_re
2015 assert tore != null
2016 var res = v.callsite(tore, [rs])
2017 if res == null then
2018 print "Cannot call property `to_re` on {self}"
2019 abort
2020 end
2021 for j in suffix.chars do
2022 if j == 'i' then
2023 var prop = ignore_case
2024 assert prop != null
2025 v.callsite(prop, [res, v.bool_instance(true)])
2026 continue
2027 end
2028 if j == 'm' then
2029 var prop = newline
2030 assert prop != null
2031 v.callsite(prop, [res, v.bool_instance(true)])
2032 continue
2033 end
2034 if j == 'b' then
2035 var prop = extended
2036 assert prop != null
2037 v.callsite(prop, [res, v.bool_instance(false)])
2038 continue
2039 end
2040 # Should not happen, this needs to be updated
2041 # along with the addition of new suffixes
2042 abort
2043 end
2044 return res
2045 end
2046 end
2047
2048 redef class AStringFormExpr
2049 redef fun expr(v) do return v.string_instance(value)
2050 end
2051
2052 redef class AStringExpr
2053 redef fun expr(v) do
2054 var s = v.string_instance(value)
2055 if is_string then return s
2056 if is_bytestring then
2057 var ns = v.c_string_instance_from_ns(bytes.items, bytes.length)
2058 var ln = v.int_instance(bytes.length)
2059 var prop = to_bytes_with_copy
2060 assert prop != null
2061 var res = v.callsite(prop, [ns, ln])
2062 if res == null then
2063 print "Cannot call property `to_bytes` on {self}"
2064 abort
2065 end
2066 s = res
2067 else if is_re then
2068 var res = make_re(v, s)
2069 assert res != null
2070 s = res
2071 else
2072 print "Unimplemented prefix or suffix for {self}"
2073 abort
2074 end
2075 return s
2076 end
2077 end
2078
2079 redef class ASuperstringExpr
2080 redef fun expr(v)
2081 do
2082 var array = new Array[Instance]
2083 for nexpr in n_exprs do
2084 var i = v.expr(nexpr)
2085 if i == null then return null
2086 array.add(i)
2087 end
2088 var i = v.array_instance(array, v.mainmodule.object_type)
2089 var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i])
2090 assert res != null
2091 if is_re then res = make_re(v, res)
2092 return res
2093 end
2094 end
2095
2096 redef class ACrangeExpr
2097 redef fun expr(v)
2098 do
2099 var e1 = v.expr(self.n_expr)
2100 if e1 == null then return null
2101 var e2 = v.expr(self.n_expr2)
2102 if e2 == null then return null
2103 var mtype = v.unanchor_type(self.mtype.as(not null))
2104 var res = new MutableInstance(mtype)
2105 v.init_instance(res)
2106 v.callsite(init_callsite, [res, e1, e2])
2107 return res
2108 end
2109 end
2110
2111 redef class AOrangeExpr
2112 redef fun expr(v)
2113 do
2114 var e1 = v.expr(self.n_expr)
2115 if e1 == null then return null
2116 var e2 = v.expr(self.n_expr2)
2117 if e2 == null then return null
2118 var mtype = v.unanchor_type(self.mtype.as(not null))
2119 var res = new MutableInstance(mtype)
2120 v.init_instance(res)
2121 v.callsite(init_callsite, [res, e1, e2])
2122 return res
2123 end
2124 end
2125
2126 redef class ATrueExpr
2127 redef fun expr(v)
2128 do
2129 return v.bool_instance(true)
2130 end
2131 end
2132
2133 redef class AFalseExpr
2134 redef fun expr(v)
2135 do
2136 return v.bool_instance(false)
2137 end
2138 end
2139
2140 redef class ANullExpr
2141 redef fun expr(v)
2142 do
2143 return v.null_instance
2144 end
2145 end
2146
2147 redef class AIsaExpr
2148 redef fun expr(v)
2149 do
2150 var i = v.expr(self.n_expr)
2151 if i == null then return null
2152 var mtype = v.unanchor_type(self.cast_type.as(not null))
2153 return v.bool_instance(v.is_subtype(i.mtype, mtype))
2154 end
2155 end
2156
2157 redef class AAsCastExpr
2158 redef fun expr(v)
2159 do
2160 var i = v.expr(self.n_expr)
2161 if i == null then return null
2162 var mtype = self.mtype.as(not null)
2163 var amtype = v.unanchor_type(mtype)
2164 if not v.is_subtype(i.mtype, amtype) then
2165 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
2166 end
2167 return i
2168 end
2169 end
2170
2171 redef class AAsNotnullExpr
2172 redef fun expr(v)
2173 do
2174 var i = v.expr(self.n_expr)
2175 if i == null then return null
2176 if i.mtype isa MNullType then
2177 fatal(v, "Cast failed")
2178 end
2179 return i
2180 end
2181 end
2182
2183 redef class AParExpr
2184 redef fun expr(v)
2185 do
2186 return v.expr(self.n_expr)
2187 end
2188 end
2189
2190 redef class AOnceExpr
2191 redef fun expr(v)
2192 do
2193 if v.onces.has_key(self) then
2194 return v.onces[self]
2195 else
2196 var res = v.expr(self.n_expr)
2197 if res == null then return null
2198 v.onces[self] = res
2199 return res
2200 end
2201 end
2202 end
2203
2204 redef class ASendExpr
2205 redef fun expr(v)
2206 do
2207 var recv = v.expr(self.n_expr)
2208 if recv == null then return null
2209 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2210 if args == null then return null
2211
2212 var res = v.callsite(callsite, args)
2213 return res
2214 end
2215 end
2216
2217 redef class ASendReassignFormExpr
2218 redef fun stmt(v)
2219 do
2220 var recv = v.expr(self.n_expr)
2221 if recv == null then return
2222 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2223 if args == null then return
2224 var value = v.expr(self.n_value)
2225 if value == null then return
2226
2227 var read = v.callsite(callsite, args)
2228 assert read != null
2229
2230 var write = v.callsite(reassign_callsite, [read, value])
2231 assert write != null
2232
2233 args.add(write)
2234
2235 v.callsite(write_callsite, args)
2236 end
2237 end
2238
2239 redef class ASuperExpr
2240 redef fun expr(v)
2241 do
2242 var recv = v.frame.arguments.first
2243
2244 var callsite = self.callsite
2245 if callsite != null then
2246 var args
2247 if self.n_args.n_exprs.is_empty then
2248 # Add automatic arguments for the super init call
2249 args = [recv]
2250 for i in [0..callsite.msignature.arity[ do
2251 args.add(v.frame.arguments[i+1])
2252 end
2253 else
2254 args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2255 if args == null then return null
2256 end
2257
2258 # Super init call
2259 var res = v.callsite(callsite, args)
2260 return res
2261 end
2262
2263 # Standard call-next-method
2264 var mpropdef = self.mpropdef
2265 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
2266
2267 var args
2268 if self.n_args.n_exprs.is_empty then
2269 args = v.frame.arguments
2270 else
2271 args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
2272 if args == null then return null
2273 end
2274
2275 var res = v.call(mpropdef, args)
2276 return res
2277 end
2278 end
2279
2280 redef class ANewExpr
2281 redef fun expr(v)
2282 do
2283 var mtype = v.unanchor_type(self.recvtype.as(not null))
2284 var recv: Instance = new MutableInstance(mtype)
2285 v.init_instance(recv)
2286 var callsite = self.callsite
2287 if callsite == null then return recv
2288
2289 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2290 if args == null then return null
2291 var res2 = v.callsite(callsite, args)
2292 if res2 != null then
2293 #self.debug("got {res2} from {mproperty}. drop {recv}")
2294 return res2
2295 end
2296 return recv
2297 end
2298 end
2299
2300 redef class AAttrExpr
2301 redef fun expr(v)
2302 do
2303 var recv = v.expr(self.n_expr)
2304 if recv == null then return null
2305 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2306 var mproperty = self.mproperty.as(not null)
2307 return v.read_attribute(mproperty, recv)
2308 end
2309 end
2310
2311 redef class AAttrAssignExpr
2312 redef fun stmt(v)
2313 do
2314 var recv = v.expr(self.n_expr)
2315 if recv == null then return
2316 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2317 var i = v.expr(self.n_value)
2318 if i == null then return
2319 var mproperty = self.mproperty.as(not null)
2320 v.write_attribute(mproperty, recv, i)
2321 end
2322 end
2323
2324 redef class AAttrReassignExpr
2325 redef fun stmt(v)
2326 do
2327 var recv = v.expr(self.n_expr)
2328 if recv == null then return
2329 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2330 var value = v.expr(self.n_value)
2331 if value == null then return
2332 var mproperty = self.mproperty.as(not null)
2333 var attr = v.read_attribute(mproperty, recv)
2334 var res = v.callsite(reassign_callsite, [attr, value])
2335 assert res != null
2336 v.write_attribute(mproperty, recv, res)
2337 end
2338 end
2339
2340 redef class AIssetAttrExpr
2341 redef fun expr(v)
2342 do
2343 var recv = v.expr(self.n_expr)
2344 if recv == null then return null
2345 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2346 var mproperty = self.mproperty.as(not null)
2347 return v.bool_instance(v.isset_attribute(mproperty, recv))
2348 end
2349 end
2350
2351 redef class AVarargExpr
2352 redef fun expr(v)
2353 do
2354 return v.expr(self.n_expr)
2355 end
2356 end
2357
2358 redef class ANamedargExpr
2359 redef fun expr(v)
2360 do
2361 return v.expr(self.n_expr)
2362 end
2363 end
2364
2365 redef class ADebugTypeExpr
2366 redef fun stmt(v)
2367 do
2368 # do nothing
2369 end
2370 end