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