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