Merge branch 'explain-assert' into master
[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 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 # Execution of the body of the method
879 #
880 # It handle the common special cases: super, intern, extern
881 fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
882 do
883 v.frames.unshift(f)
884
885 for i in [0..mpropdef.msignature.arity[ do
886 var variable = self.n_signature.n_params[i].variable
887 assert variable != null
888 v.write_variable(variable, arguments[i+1])
889 end
890
891 # Call the implicit super-init
892 var auto_super_inits = self.auto_super_inits
893 if auto_super_inits != null then
894 var args = [arguments.first]
895 for auto_super_init in auto_super_inits do
896 args.clear
897 for i in [0..auto_super_init.msignature.arity+1[ do
898 args.add(arguments[i])
899 end
900 assert auto_super_init.mproperty != mpropdef.mproperty
901 v.callsite(auto_super_init, args)
902 end
903 end
904 if auto_super_call then
905 # standard call-next-method
906 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
907 v.call(superpd, arguments)
908 end
909
910 # First, try intern
911 if mpropdef.is_intern or mpropdef.is_extern then
912 var res = intern_call(v, mpropdef, arguments)
913 if res != v.error_instance then return res
914 end
915 # Then, try extern
916 if mpropdef.is_extern then
917 var res = call_extern(v, mpropdef, arguments, f)
918 if res != v.error_instance then return res
919 end
920 # Else try block
921 if n_block != null then
922 v.stmt(self.n_block)
923 return null
924 end
925
926 # Fail if nothing succeed
927 if mpropdef.is_intern then
928 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
929 else if mpropdef.is_extern then
930 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
931 else
932 fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
933 end
934 abort
935 end
936
937 # Call this extern method
938 protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
939 do
940 return v.error_instance
941 end
942
943 # Interprets a intern or a shortcut extern method.
944 # Returns the result for a function, `null` for a procedure, or `error_instance` if the method is unknown.
945 private fun intern_call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
946 do
947 var pname = mpropdef.mproperty.name
948 var cname = mpropdef.mclassdef.mclass.name
949 if pname == "output" then
950 var recv = args.first
951 recv.val.output
952 return null
953 else if pname == "object_id" then
954 var recv = args.first
955 if recv isa PrimitiveInstance[Object] then
956 return v.int_instance(recv.val.object_id)
957 else
958 return v.int_instance(recv.object_id)
959 end
960 else if pname == "output_class_name" then
961 var recv = args.first
962 print recv.mtype
963 return null
964 else if pname == "native_class_name" then
965 var recv = args.first
966 var txt = recv.mtype.to_s
967 return v.c_string_instance(txt)
968 else if pname == "==" then
969 # == is correctly redefined for instances
970 return v.bool_instance(args[0] == args[1])
971 else if pname == "!=" then
972 return v.bool_instance(args[0] != args[1])
973 else if pname == "is_same_type" then
974 return v.bool_instance(args[0].mtype == args[1].mtype)
975 else if pname == "is_same_instance" then
976 return v.bool_instance(args[0].eq_is(args[1]))
977 else if pname == "class_inheritance_metamodel_json" then
978 return v.c_string_instance(v.mainmodule.flatten_mclass_hierarchy.to_thin_json)
979 else if pname == "exit" then
980 exit(args[1].to_i)
981 abort
982 else if pname == "buffer_mode_full" then
983 return v.int_instance(sys.buffer_mode_full)
984 else if pname == "buffer_mode_line" then
985 return v.int_instance(sys.buffer_mode_line)
986 else if pname == "buffer_mode_none" then
987 return v.int_instance(sys.buffer_mode_none)
988 else if pname == "sys" then
989 return v.mainobj
990 else if cname == "Int" then
991 var recvval = args[0].to_i
992 if pname == "unary -" then
993 return v.int_instance(-recvval)
994 else if pname == "unary +" then
995 return args[0]
996 else if pname == "+" then
997 return v.int_instance(recvval + args[1].to_i)
998 else if pname == "-" then
999 return v.int_instance(recvval - args[1].to_i)
1000 else if pname == "*" then
1001 return v.int_instance(recvval * args[1].to_i)
1002 else if pname == "%" then
1003 return v.int_instance(recvval % args[1].to_i)
1004 else if pname == "/" then
1005 return v.int_instance(recvval / args[1].to_i)
1006 else if pname == "<" then
1007 return v.bool_instance(recvval < args[1].to_i)
1008 else if pname == ">" then
1009 return v.bool_instance(recvval > args[1].to_i)
1010 else if pname == "<=" then
1011 return v.bool_instance(recvval <= args[1].to_i)
1012 else if pname == ">=" then
1013 return v.bool_instance(recvval >= args[1].to_i)
1014 else if pname == "<=>" then
1015 return v.int_instance(recvval <=> args[1].to_i)
1016 else if pname == "&" then
1017 return v.int_instance(recvval & args[1].to_i)
1018 else if pname == "|" then
1019 return v.int_instance(recvval | args[1].to_i)
1020 else if pname == "to_f" then
1021 return v.float_instance(recvval.to_f)
1022 else if pname == "to_b" then
1023 return v.byte_instance(recvval.to_b)
1024 else if pname == "<<" then
1025 return v.int_instance(recvval << args[1].to_i)
1026 else if pname == ">>" then
1027 return v.int_instance(recvval >> args[1].to_i)
1028 else if pname == "to_i8" then
1029 return v.int8_instance(recvval.to_i8)
1030 else if pname == "to_i16" then
1031 return v.int16_instance(recvval.to_i16)
1032 else if pname == "to_u16" then
1033 return v.uint16_instance(recvval.to_u16)
1034 else if pname == "to_i32" then
1035 return v.int32_instance(recvval.to_i32)
1036 else if pname == "to_u32" then
1037 return v.uint32_instance(recvval.to_u32)
1038 end
1039 else if cname == "Byte" then
1040 var recvval = args[0].to_b
1041 if pname == "unary -" then
1042 return v.byte_instance(-recvval)
1043 else if pname == "unary +" then
1044 return args[0]
1045 else if pname == "+" then
1046 return v.byte_instance(recvval + args[1].to_b)
1047 else if pname == "-" then
1048 return v.byte_instance(recvval - args[1].to_b)
1049 else if pname == "*" then
1050 return v.byte_instance(recvval * args[1].to_b)
1051 else if pname == "%" then
1052 return v.byte_instance(recvval % args[1].to_b)
1053 else if pname == "/" then
1054 return v.byte_instance(recvval / args[1].to_b)
1055 else if pname == "<" then
1056 return v.bool_instance(recvval < args[1].to_b)
1057 else if pname == ">" then
1058 return v.bool_instance(recvval > args[1].to_b)
1059 else if pname == "<=" then
1060 return v.bool_instance(recvval <= args[1].to_b)
1061 else if pname == ">=" then
1062 return v.bool_instance(recvval >= args[1].to_b)
1063 else if pname == "<=>" then
1064 return v.int_instance(recvval <=> args[1].to_b)
1065 else if pname == "&" then
1066 return v.byte_instance(recvval & args[1].to_b)
1067 else if pname == "|" then
1068 return v.byte_instance(recvval | args[1].to_b)
1069 else if pname == "to_f" then
1070 return v.float_instance(recvval.to_f)
1071 else if pname == "to_i" then
1072 return v.int_instance(recvval.to_i)
1073 else if pname == "<<" then
1074 return v.byte_instance(recvval << args[1].to_i)
1075 else if pname == ">>" then
1076 return v.byte_instance(recvval >> args[1].to_i)
1077 else if pname == "to_i8" then
1078 return v.int8_instance(recvval.to_i8)
1079 else if pname == "to_i16" then
1080 return v.int16_instance(recvval.to_i16)
1081 else if pname == "to_u16" then
1082 return v.uint16_instance(recvval.to_u16)
1083 else if pname == "to_i32" then
1084 return v.int32_instance(recvval.to_i32)
1085 else if pname == "to_u32" then
1086 return v.uint32_instance(recvval.to_u32)
1087 else if pname == "byte_to_s_len" then
1088 return v.int_instance(recvval.to_s.length)
1089 end
1090 else if cname == "Char" then
1091 var recv = args[0].val.as(Char)
1092 if pname == "successor" then
1093 return v.char_instance(recv.successor(args[1].to_i))
1094 else if pname == "predecessor" then
1095 return v.char_instance(recv.predecessor(args[1].to_i))
1096 else if pname == "<" then
1097 return v.bool_instance(recv < args[1].val.as(Char))
1098 else if pname == ">" then
1099 return v.bool_instance(recv > args[1].val.as(Char))
1100 else if pname == "<=" then
1101 return v.bool_instance(recv <= args[1].val.as(Char))
1102 else if pname == ">=" then
1103 return v.bool_instance(recv >= args[1].val.as(Char))
1104 else if pname == "<=>" then
1105 return v.int_instance(recv <=> args[1].val.as(Char))
1106 end
1107 else if cname == "Float" then
1108 var recv = args[0].to_f
1109 if pname == "unary -" then
1110 return v.float_instance(-recv)
1111 else if pname == "unary +" then
1112 return args[0]
1113 else if pname == "+" then
1114 return v.float_instance(recv + args[1].to_f)
1115 else if pname == "-" then
1116 return v.float_instance(recv - args[1].to_f)
1117 else if pname == "*" then
1118 return v.float_instance(recv * args[1].to_f)
1119 else if pname == "/" then
1120 return v.float_instance(recv / args[1].to_f)
1121 else if pname == "<" then
1122 return v.bool_instance(recv < args[1].to_f)
1123 else if pname == ">" then
1124 return v.bool_instance(recv > args[1].to_f)
1125 else if pname == "<=" then
1126 return v.bool_instance(recv <= args[1].to_f)
1127 else if pname == ">=" then
1128 return v.bool_instance(recv >= args[1].to_f)
1129 else if pname == "to_i" then
1130 return v.int_instance(recv.to_i)
1131 else if pname == "to_b" then
1132 return v.byte_instance(recv.to_b)
1133 else if pname == "to_i8" then
1134 return v.int8_instance(recv.to_i8)
1135 else if pname == "to_i16" then
1136 return v.int16_instance(recv.to_i16)
1137 else if pname == "to_u16" then
1138 return v.uint16_instance(recv.to_u16)
1139 else if pname == "to_i32" then
1140 return v.int32_instance(recv.to_i32)
1141 else if pname == "to_u32" then
1142 return v.uint32_instance(recv.to_u32)
1143 else if pname == "cos" then
1144 return v.float_instance(args[0].to_f.cos)
1145 else if pname == "sin" then
1146 return v.float_instance(args[0].to_f.sin)
1147 else if pname == "tan" then
1148 return v.float_instance(args[0].to_f.tan)
1149 else if pname == "acos" then
1150 return v.float_instance(args[0].to_f.acos)
1151 else if pname == "asin" then
1152 return v.float_instance(args[0].to_f.asin)
1153 else if pname == "atan" then
1154 return v.float_instance(args[0].to_f.atan)
1155 else if pname == "sqrt" then
1156 return v.float_instance(args[0].to_f.sqrt)
1157 else if pname == "exp" then
1158 return v.float_instance(args[0].to_f.exp)
1159 else if pname == "log" then
1160 return v.float_instance(args[0].to_f.log)
1161 else if pname == "pow" then
1162 return v.float_instance(args[0].to_f.pow(args[1].to_f))
1163 else if pname == "abs" then
1164 return v.float_instance(args[0].to_f.abs)
1165 else if pname == "hypot_with" then
1166 return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
1167 else if pname == "is_nan" then
1168 return v.bool_instance(args[0].to_f.is_nan)
1169 else if pname == "is_inf_extern" then
1170 return v.bool_instance(args[0].to_f.is_inf != 0)
1171 else if pname == "round" then
1172 return v.float_instance(args[0].to_f.round)
1173 end
1174 else if cname == "CString" then
1175 if pname == "new" then
1176 return v.c_string_instance_len(args[1].to_i)
1177 end
1178 var recvval = args.first.val.as(CString)
1179 if pname == "[]" then
1180 var arg1 = args[1].to_i
1181 return v.byte_instance(recvval[arg1])
1182 else if pname == "[]=" then
1183 var arg1 = args[1].to_i
1184 recvval[arg1] = args[2].val.as(Byte)
1185 return null
1186 else if pname == "copy_to" then
1187 # sig= copy_to(dest: CString, length: Int, from: Int, to: Int)
1188 var destval = args[1].val.as(CString)
1189 var lenval = args[2].to_i
1190 var fromval = args[3].to_i
1191 var toval = args[4].to_i
1192 recvval.copy_to(destval, lenval, fromval, toval)
1193 return null
1194 else if pname == "atoi" then
1195 return v.int_instance(recvval.atoi)
1196 else if pname == "fast_cstring" then
1197 var ns = recvval.fast_cstring(args[1].to_i)
1198 return v.c_string_instance(ns.to_s)
1199 else if pname == "fetch_4_chars" then
1200 return v.uint32_instance(args[0].val.as(CString).fetch_4_chars(args[1].to_i))
1201 else if pname == "fetch_4_hchars" then
1202 return v.uint32_instance(args[0].val.as(CString).fetch_4_hchars(args[1].to_i))
1203 else if pname == "utf8_length" then
1204 return v.int_instance(args[0].val.as(CString).utf8_length(args[1].to_i, args[2].to_i))
1205 end
1206 else if cname == "NativeArray" then
1207 if pname == "new" then
1208 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
1209 var instance = new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
1210 v.init_instance_primitive(instance)
1211 return instance
1212 end
1213 var recvval = args.first.val.as(Array[Instance])
1214 if pname == "[]" then
1215 return recvval[args[1].to_i]
1216 else if pname == "[]=" then
1217 recvval[args[1].to_i] = args[2]
1218 return null
1219 else if pname == "length" then
1220 return v.int_instance(recvval.length)
1221 else if pname == "copy_to" then
1222 recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
1223 return null
1224 end
1225 else if cname == "Int8" then
1226 var recvval = args[0].to_i8
1227 if pname == "unary -" then
1228 return v.int8_instance(-recvval)
1229 else if pname == "unary +" then
1230 return args[0]
1231 else if pname == "+" then
1232 return v.int8_instance(recvval + args[1].to_i8)
1233 else if pname == "-" then
1234 return v.int8_instance(recvval - args[1].to_i8)
1235 else if pname == "*" then
1236 return v.int8_instance(recvval * args[1].to_i8)
1237 else if pname == "%" then
1238 return v.int8_instance(recvval % args[1].to_i8)
1239 else if pname == "/" then
1240 return v.int8_instance(recvval / args[1].to_i8)
1241 else if pname == "<" then
1242 return v.bool_instance(recvval < args[1].to_i8)
1243 else if pname == ">" then
1244 return v.bool_instance(recvval > args[1].to_i8)
1245 else if pname == "<=" then
1246 return v.bool_instance(recvval <= args[1].to_i8)
1247 else if pname == ">=" then
1248 return v.bool_instance(recvval >= args[1].to_i8)
1249 else if pname == "<=>" then
1250 return v.int_instance(recvval <=> args[1].to_i8)
1251 else if pname == "to_f" then
1252 return v.float_instance(recvval.to_f)
1253 else if pname == "to_i" then
1254 return v.int_instance(recvval.to_i)
1255 else if pname == "to_b" then
1256 return v.byte_instance(recvval.to_b)
1257 else if pname == "to_i16" then
1258 return v.int16_instance(recvval.to_i16)
1259 else if pname == "to_u16" then
1260 return v.uint16_instance(recvval.to_u16)
1261 else if pname == "to_i32" then
1262 return v.int32_instance(recvval.to_i32)
1263 else if pname == "to_u32" then
1264 return v.uint32_instance(recvval.to_u32)
1265 else if pname == "<<" then
1266 return v.int8_instance(recvval << (args[1].to_i))
1267 else if pname == ">>" then
1268 return v.int8_instance(recvval >> (args[1].to_i))
1269 else if pname == "&" then
1270 return v.int8_instance(recvval & args[1].to_i8)
1271 else if pname == "|" then
1272 return v.int8_instance(recvval | args[1].to_i8)
1273 else if pname == "^" then
1274 return v.int8_instance(recvval ^ args[1].to_i8)
1275 else if pname == "unary ~" then
1276 return v.int8_instance(~recvval)
1277 end
1278 else if cname == "Int16" then
1279 var recvval = args[0].to_i16
1280 if pname == "unary -" then
1281 return v.int16_instance(-recvval)
1282 else if pname == "unary +" then
1283 return args[0]
1284 else if pname == "+" then
1285 return v.int16_instance(recvval + args[1].to_i16)
1286 else if pname == "-" then
1287 return v.int16_instance(recvval - args[1].to_i16)
1288 else if pname == "*" then
1289 return v.int16_instance(recvval * args[1].to_i16)
1290 else if pname == "%" then
1291 return v.int16_instance(recvval % args[1].to_i16)
1292 else if pname == "/" then
1293 return v.int16_instance(recvval / args[1].to_i16)
1294 else if pname == "<" then
1295 return v.bool_instance(recvval < args[1].to_i16)
1296 else if pname == ">" then
1297 return v.bool_instance(recvval > args[1].to_i16)
1298 else if pname == "<=" then
1299 return v.bool_instance(recvval <= args[1].to_i16)
1300 else if pname == ">=" then
1301 return v.bool_instance(recvval >= args[1].to_i16)
1302 else if pname == "<=>" then
1303 return v.int_instance(recvval <=> args[1].to_i16)
1304 else if pname == "to_f" then
1305 return v.float_instance(recvval.to_f)
1306 else if pname == "to_i" then
1307 return v.int_instance(recvval.to_i)
1308 else if pname == "to_b" then
1309 return v.byte_instance(recvval.to_b)
1310 else if pname == "to_i8" then
1311 return v.int8_instance(recvval.to_i8)
1312 else if pname == "to_u16" then
1313 return v.uint16_instance(recvval.to_u16)
1314 else if pname == "to_i32" then
1315 return v.int32_instance(recvval.to_i32)
1316 else if pname == "to_u32" then
1317 return v.uint32_instance(recvval.to_u32)
1318 else if pname == "<<" then
1319 return v.int16_instance(recvval << (args[1].to_i))
1320 else if pname == ">>" then
1321 return v.int16_instance(recvval >> (args[1].to_i))
1322 else if pname == "&" then
1323 return v.int16_instance(recvval & args[1].to_i16)
1324 else if pname == "|" then
1325 return v.int16_instance(recvval | args[1].to_i16)
1326 else if pname == "^" then
1327 return v.int16_instance(recvval ^ args[1].to_i16)
1328 else if pname == "unary ~" then
1329 return v.int16_instance(~recvval)
1330 end
1331 else if cname == "UInt16" then
1332 var recvval = args[0].to_u16
1333 if pname == "unary -" then
1334 return v.uint16_instance(-recvval)
1335 else if pname == "unary +" then
1336 return args[0]
1337 else if pname == "+" then
1338 return v.uint16_instance(recvval + args[1].to_u16)
1339 else if pname == "-" then
1340 return v.uint16_instance(recvval - args[1].to_u16)
1341 else if pname == "*" then
1342 return v.uint16_instance(recvval * args[1].to_u16)
1343 else if pname == "%" then
1344 return v.uint16_instance(recvval % args[1].to_u16)
1345 else if pname == "/" then
1346 return v.uint16_instance(recvval / args[1].to_u16)
1347 else if pname == "<" then
1348 return v.bool_instance(recvval < args[1].to_u16)
1349 else if pname == ">" then
1350 return v.bool_instance(recvval > args[1].to_u16)
1351 else if pname == "<=" then
1352 return v.bool_instance(recvval <= args[1].to_u16)
1353 else if pname == ">=" then
1354 return v.bool_instance(recvval >= args[1].to_u16)
1355 else if pname == "<=>" then
1356 return v.int_instance(recvval <=> args[1].to_u16)
1357 else if pname == "to_f" then
1358 return v.float_instance(recvval.to_f)
1359 else if pname == "to_i" then
1360 return v.int_instance(recvval.to_i)
1361 else if pname == "to_b" then
1362 return v.byte_instance(recvval.to_b)
1363 else if pname == "to_i8" then
1364 return v.int8_instance(recvval.to_i8)
1365 else if pname == "to_i16" then
1366 return v.int16_instance(recvval.to_i16)
1367 else if pname == "to_i32" then
1368 return v.int32_instance(recvval.to_i32)
1369 else if pname == "to_u32" then
1370 return v.uint32_instance(recvval.to_u32)
1371 else if pname == "<<" then
1372 return v.uint16_instance(recvval << (args[1].to_i))
1373 else if pname == ">>" then
1374 return v.uint16_instance(recvval >> (args[1].to_i))
1375 else if pname == "&" then
1376 return v.uint16_instance(recvval & args[1].to_u16)
1377 else if pname == "|" then
1378 return v.uint16_instance(recvval | args[1].to_u16)
1379 else if pname == "^" then
1380 return v.uint16_instance(recvval ^ args[1].to_u16)
1381 else if pname == "unary ~" then
1382 return v.uint16_instance(~recvval)
1383 end
1384 else if cname == "Int32" then
1385 var recvval = args[0].to_i32
1386 if pname == "unary -" then
1387 return v.int32_instance(-recvval)
1388 else if pname == "unary +" then
1389 return args[0]
1390 else if pname == "+" then
1391 return v.int32_instance(recvval + args[1].to_i32)
1392 else if pname == "-" then
1393 return v.int32_instance(recvval - args[1].to_i32)
1394 else if pname == "*" then
1395 return v.int32_instance(recvval * args[1].to_i32)
1396 else if pname == "%" then
1397 return v.int32_instance(recvval % args[1].to_i32)
1398 else if pname == "/" then
1399 return v.int32_instance(recvval / args[1].to_i32)
1400 else if pname == "<" then
1401 return v.bool_instance(recvval < args[1].to_i32)
1402 else if pname == ">" then
1403 return v.bool_instance(recvval > args[1].to_i32)
1404 else if pname == "<=" then
1405 return v.bool_instance(recvval <= args[1].to_i32)
1406 else if pname == ">=" then
1407 return v.bool_instance(recvval >= args[1].to_i32)
1408 else if pname == "<=>" then
1409 return v.int_instance(recvval <=> args[1].to_i32)
1410 else if pname == "to_f" then
1411 return v.float_instance(recvval.to_f)
1412 else if pname == "to_i" then
1413 return v.int_instance(recvval.to_i)
1414 else if pname == "to_b" then
1415 return v.byte_instance(recvval.to_b)
1416 else if pname == "to_i8" then
1417 return v.int8_instance(recvval.to_i8)
1418 else if pname == "to_i16" then
1419 return v.int16_instance(recvval.to_i16)
1420 else if pname == "to_u16" then
1421 return v.uint16_instance(recvval.to_u16)
1422 else if pname == "to_u32" then
1423 return v.uint32_instance(recvval.to_u32)
1424 else if pname == "<<" then
1425 return v.int32_instance(recvval << (args[1].to_i))
1426 else if pname == ">>" then
1427 return v.int32_instance(recvval >> (args[1].to_i))
1428 else if pname == "&" then
1429 return v.int32_instance(recvval & args[1].to_i32)
1430 else if pname == "|" then
1431 return v.int32_instance(recvval | args[1].to_i32)
1432 else if pname == "^" then
1433 return v.int32_instance(recvval ^ args[1].to_i32)
1434 else if pname == "unary ~" then
1435 return v.int32_instance(~recvval)
1436 end
1437 else if cname == "UInt32" then
1438 var recvval = args[0].to_u32
1439 if pname == "unary -" then
1440 return v.uint32_instance(-recvval)
1441 else if pname == "unary +" then
1442 return args[0]
1443 else if pname == "+" then
1444 return v.uint32_instance(recvval + args[1].to_u32)
1445 else if pname == "-" then
1446 return v.uint32_instance(recvval - args[1].to_u32)
1447 else if pname == "*" then
1448 return v.uint32_instance(recvval * args[1].to_u32)
1449 else if pname == "%" then
1450 return v.uint32_instance(recvval % args[1].to_u32)
1451 else if pname == "/" then
1452 return v.uint32_instance(recvval / args[1].to_u32)
1453 else if pname == "<" then
1454 return v.bool_instance(recvval < args[1].to_u32)
1455 else if pname == ">" then
1456 return v.bool_instance(recvval > args[1].to_u32)
1457 else if pname == "<=" then
1458 return v.bool_instance(recvval <= args[1].to_u32)
1459 else if pname == ">=" then
1460 return v.bool_instance(recvval >= args[1].to_u32)
1461 else if pname == "<=>" then
1462 return v.int_instance(recvval <=> args[1].to_u32)
1463 else if pname == "to_f" then
1464 return v.float_instance(recvval.to_f)
1465 else if pname == "to_i" then
1466 return v.int_instance(recvval.to_i)
1467 else if pname == "to_b" then
1468 return v.byte_instance(recvval.to_b)
1469 else if pname == "to_i8" then
1470 return v.int8_instance(recvval.to_i8)
1471 else if pname == "to_i16" then
1472 return v.int16_instance(recvval.to_i16)
1473 else if pname == "to_u16" then
1474 return v.uint16_instance(recvval.to_u16)
1475 else if pname == "to_i32" then
1476 return v.int32_instance(recvval.to_i32)
1477 else if pname == "<<" then
1478 return v.uint32_instance(recvval << (args[1].to_i))
1479 else if pname == ">>" then
1480 return v.uint32_instance(recvval >> (args[1].to_i))
1481 else if pname == "&" then
1482 return v.uint32_instance(recvval & args[1].to_u32)
1483 else if pname == "|" then
1484 return v.uint32_instance(recvval | args[1].to_u32)
1485 else if pname == "^" then
1486 return v.uint32_instance(recvval ^ args[1].to_u32)
1487 else if pname == "unary ~" then
1488 return v.uint32_instance(~recvval)
1489 end
1490 else if pname == "native_argc" then
1491 return v.int_instance(v.arguments.length)
1492 else if pname == "native_argv" then
1493 var txt = v.arguments[args[1].to_i]
1494 return v.c_string_instance(txt)
1495 else if pname == "lexer_goto" then
1496 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
1497 else if pname == "lexer_accept" then
1498 return v.int_instance(lexer_accept(args[1].to_i))
1499 else if pname == "parser_goto" then
1500 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
1501 else if pname == "parser_action" then
1502 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
1503 end
1504 return v.error_instance
1505 end
1506 end
1507
1508 redef class AAttrPropdef
1509 redef fun call(v, mpropdef, args)
1510 do
1511 var recv = args.first
1512 assert recv isa MutableInstance
1513 var attr = self.mpropdef.mproperty
1514 if mpropdef == mreadpropdef then
1515 assert args.length == 1
1516 if not is_lazy or v.isset_attribute(attr, recv) then return v.read_attribute(attr, recv)
1517 var f = v.new_frame(self, mpropdef, args)
1518 return evaluate_expr(v, recv, f)
1519 else if mpropdef == mwritepropdef then
1520 assert args.length == 2
1521 var arg = args[1]
1522 if is_optional and arg.mtype isa MNullType then
1523 var f = v.new_frame(self, mpropdef, args)
1524 arg = evaluate_expr(v, recv, f)
1525 end
1526 v.write_attribute(attr, recv, arg)
1527 return null
1528 else
1529 abort
1530 end
1531 end
1532
1533 # Evaluate and set the default value of the attribute in `recv`
1534 private fun init_expr(v: NaiveInterpreter, recv: Instance)
1535 do
1536 if is_lazy or is_optional then return
1537 if has_value then
1538 var f = v.new_frame(self, mreadpropdef.as(not null), [recv])
1539 evaluate_expr(v, recv, f)
1540 return
1541 end
1542 var mpropdef = self.mpropdef
1543 if mpropdef == null then return
1544 var mtype = self.mtype.as(not null)
1545 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1546 if mtype isa MNullableType then
1547 v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
1548 end
1549 end
1550
1551 private fun evaluate_expr(v: NaiveInterpreter, recv: Instance, f: Frame): Instance
1552 do
1553 assert recv isa MutableInstance
1554 v.frames.unshift(f)
1555
1556 var val
1557
1558 var nexpr = self.n_expr
1559 var nblock = self.n_block
1560 if nexpr != null then
1561 val = v.expr(nexpr)
1562 else if nblock != null then
1563 v.stmt(nblock)
1564 assert v.escapemark == return_mark
1565 val = v.escapevalue
1566 v.escapemark = null
1567 else
1568 abort
1569 end
1570 assert val != null
1571
1572 v.frames.shift
1573 assert not v.is_escaping
1574 v.write_attribute(self.mpropdef.mproperty, recv, val)
1575 return val
1576 end
1577 end
1578
1579 redef class AClassdef
1580 # Execute an implicit `mpropdef` associated with the current node.
1581 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance]): nullable Instance
1582 do
1583 if mpropdef.mproperty.is_root_init then
1584 assert arguments.length == 1
1585 if not mpropdef.is_intro then
1586 # standard call-next-method
1587 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
1588 v.call(superpd, arguments)
1589 end
1590 return null
1591 else
1592 abort
1593 end
1594 end
1595 end
1596
1597 redef class AExpr
1598 # Evaluate the node as a possible expression.
1599 # Return a possible value
1600 # NOTE: Do not call this method directly, but use `v.expr`
1601 # This method is here to be implemented by subclasses.
1602 protected fun expr(v: NaiveInterpreter): nullable Instance
1603 do
1604 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1605 abort
1606 end
1607
1608 # Evaluate the node as a statement.
1609 # NOTE: Do not call this method directly, but use `v.stmt`
1610 # This method is here to be implemented by subclasses (no need to return something).
1611 protected fun stmt(v: NaiveInterpreter)
1612 do
1613 expr(v)
1614 end
1615
1616 end
1617
1618 redef class ABlockExpr
1619 redef fun expr(v)
1620 do
1621 var last = self.n_expr.last
1622 for e in self.n_expr do
1623 if e == last then break
1624 v.stmt(e)
1625 if v.is_escaping then return null
1626 end
1627 return last.expr(v)
1628 end
1629
1630 redef fun stmt(v)
1631 do
1632 for e in self.n_expr do
1633 v.stmt(e)
1634 if v.is_escaping then return
1635 end
1636 end
1637 end
1638
1639 redef class AVardeclExpr
1640 redef fun expr(v)
1641 do
1642 var ne = self.n_expr
1643 if ne != null then
1644 var i = v.expr(ne)
1645 if i == null then return null
1646 v.write_variable(self.variable.as(not null), i)
1647 return i
1648 end
1649 return null
1650 end
1651 end
1652
1653 redef class AVarExpr
1654 redef fun expr(v)
1655 do
1656 return v.read_variable(self.variable.as(not null))
1657 end
1658 end
1659
1660 redef class AVarAssignExpr
1661 redef fun expr(v)
1662 do
1663 var i = v.expr(self.n_value)
1664 if i == null then return null
1665 v.write_variable(self.variable.as(not null), i)
1666 return i
1667 end
1668 end
1669
1670 redef class AVarReassignExpr
1671 redef fun stmt(v)
1672 do
1673 var variable = self.variable.as(not null)
1674 var vari = v.read_variable(variable)
1675 var value = v.expr(self.n_value)
1676 if value == null then return
1677 var res = v.callsite(reassign_callsite, [vari, value])
1678 assert res != null
1679 v.write_variable(variable, res)
1680 end
1681 end
1682
1683 redef class ASelfExpr
1684 redef fun expr(v)
1685 do
1686 return v.frame.arguments.first
1687 end
1688 end
1689
1690 redef class AImplicitSelfExpr
1691 redef fun expr(v)
1692 do
1693 if not is_sys then return super
1694 return v.mainobj
1695 end
1696 end
1697
1698 redef class AEscapeExpr
1699 redef fun stmt(v)
1700 do
1701 var ne = self.n_expr
1702 if ne != null then
1703 var i = v.expr(ne)
1704 if i == null then return
1705 v.escapevalue = i
1706 else
1707 v.escapevalue = null
1708 end
1709 v.escapemark = self.escapemark
1710 end
1711 end
1712
1713 redef class AAbortExpr
1714 redef fun stmt(v)
1715 do
1716 fatal(v, "Aborted")
1717 exit(1)
1718 end
1719 end
1720
1721 redef class AIfExpr
1722 redef fun expr(v)
1723 do
1724 var cond = v.expr(self.n_expr)
1725 if cond == null then return null
1726 if cond.is_true then
1727 return v.expr(self.n_then.as(not null))
1728 else
1729 return v.expr(self.n_else.as(not null))
1730 end
1731 end
1732
1733 redef fun stmt(v)
1734 do
1735 var cond = v.expr(self.n_expr)
1736 if cond == null then return
1737 if cond.is_true then
1738 v.stmt(self.n_then)
1739 else
1740 v.stmt(self.n_else)
1741 end
1742 end
1743 end
1744
1745 redef class AIfexprExpr
1746 redef fun expr(v)
1747 do
1748 var cond = v.expr(self.n_expr)
1749 if cond == null then return null
1750 if cond.is_true then
1751 return v.expr(self.n_then)
1752 else
1753 return v.expr(self.n_else)
1754 end
1755 end
1756 end
1757
1758 redef class ADoExpr
1759 redef fun stmt(v)
1760 do
1761 # If this bloc has a catch, handle it with a do ... catch ... end
1762 if self.n_catch != null then
1763 var frame = v.frame
1764 v.catch_count += 1
1765 do
1766 v.stmt(self.n_block)
1767 v.is_escape(self.break_mark) # Clear the break (if any)
1768 v.catch_count -= 1
1769 catch
1770 # Restore the current frame if needed
1771 while v.frame != frame do v.frames.shift
1772 v.catch_count -= 1
1773 v.stmt(self.n_catch)
1774 end
1775 else
1776 v.stmt(self.n_block)
1777 v.is_escape(self.break_mark)
1778 end
1779 end
1780 end
1781
1782 redef class AWhileExpr
1783 redef fun stmt(v)
1784 do
1785 loop
1786 var cond = v.expr(self.n_expr)
1787 if cond == null then return
1788 if not cond.is_true then return
1789 v.stmt(self.n_block)
1790 if v.is_escape(self.break_mark) then return
1791 v.is_escape(self.continue_mark) # Clear the break
1792 if v.is_escaping then return
1793 end
1794 end
1795 end
1796
1797 redef class ALoopExpr
1798 redef fun stmt(v)
1799 do
1800 loop
1801 v.stmt(self.n_block)
1802 if v.is_escape(self.break_mark) then return
1803 v.is_escape(self.continue_mark) # Clear the break
1804 if v.is_escaping then return
1805 end
1806 end
1807 end
1808
1809 redef class AForExpr
1810 redef fun stmt(v)
1811 do
1812 var iters = new Array[Instance]
1813
1814 for g in n_groups do
1815 var col = v.expr(g.n_expr)
1816 if col == null then return
1817 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1818
1819 var iter = v.callsite(g.method_iterator, [col]).as(not null)
1820 iters.add iter
1821 end
1822
1823 loop
1824 for g in n_groups, iter in iters do
1825 var isok = v.callsite(g.method_is_ok, [iter]).as(not null)
1826 if not isok.is_true then break label
1827 if g.variables.length == 1 then
1828 var item = v.callsite(g.method_item, [iter]).as(not null)
1829 #self.debug("item {item}")
1830 v.write_variable(g.variables.first, item)
1831 else if g.variables.length == 2 then
1832 var key = v.callsite(g.method_key, [iter]).as(not null)
1833 v.write_variable(g.variables[0], key)
1834 var item = v.callsite(g.method_item, [iter]).as(not null)
1835 v.write_variable(g.variables[1], item)
1836 else
1837 abort
1838 end
1839 end
1840 v.stmt(self.n_block)
1841 if v.is_escape(self.break_mark) then break
1842 v.is_escape(self.continue_mark) # Clear the break
1843 if v.is_escaping then break
1844 for g in n_groups, iter in iters do
1845 v.callsite(g.method_next, [iter])
1846 end
1847 end label
1848 for g in n_groups, iter in iters do
1849 var method_finish = g.method_finish
1850 if method_finish != null then
1851 v.callsite(method_finish, [iter])
1852 end
1853 end
1854 end
1855 end
1856
1857 redef class AWithExpr
1858 redef fun stmt(v)
1859 do
1860 var expr = v.expr(self.n_expr)
1861 if expr == null then return
1862
1863 v.callsite(method_start, [expr])
1864 v.stmt(self.n_block)
1865 v.is_escape(self.break_mark) # Clear the break
1866
1867 # Execute the finally without an escape
1868 var old_mark = v.escapemark
1869 v.escapemark = null
1870 v.callsite(method_finish, [expr])
1871 # Restore the escape unless another escape was provided
1872 if v.escapemark == null then v.escapemark = old_mark
1873 end
1874 end
1875
1876 redef class AAssertExpr
1877 redef fun stmt(v)
1878 do
1879 var cond = v.expr(self.n_expr)
1880 if cond == null then return
1881 if not cond.is_true then
1882 v.stmt(self.n_else)
1883 if v.is_escaping then return
1884
1885 # Explain assert if it fails
1886 var explain_assert_str = explain_assert_str
1887 if explain_assert_str != null then
1888 var i = v.expr(explain_assert_str)
1889 if i isa MutableInstance then
1890 var res = v.send(v.force_get_primitive_method("to_cstring", i.mtype), [i])
1891 if res != null then
1892 var val = res.val
1893 if val != null then
1894 print_error "Runtime assert: {val.to_s}"
1895 end
1896 end
1897 end
1898 end
1899
1900 var nid = self.n_id
1901 if nid != null then
1902 fatal(v, "Assert '{nid.text}' failed")
1903 else
1904 fatal(v, "Assert failed")
1905 end
1906 exit(1)
1907 end
1908 end
1909 end
1910
1911 redef class AOrExpr
1912 redef fun expr(v)
1913 do
1914 var cond = v.expr(self.n_expr)
1915 if cond == null then return null
1916 if cond.is_true then return cond
1917 return v.expr(self.n_expr2)
1918 end
1919 end
1920
1921 redef class AImpliesExpr
1922 redef fun expr(v)
1923 do
1924 var cond = v.expr(self.n_expr)
1925 if cond == null then return null
1926 if not cond.is_true then return v.true_instance
1927 return v.expr(self.n_expr2)
1928 end
1929 end
1930
1931 redef class AAndExpr
1932 redef fun expr(v)
1933 do
1934 var cond = v.expr(self.n_expr)
1935 if cond == null then return null
1936 if not cond.is_true then return cond
1937 return v.expr(self.n_expr2)
1938 end
1939 end
1940
1941 redef class ANotExpr
1942 redef fun expr(v)
1943 do
1944 var cond = v.expr(self.n_expr)
1945 if cond == null then return null
1946 return v.bool_instance(not cond.is_true)
1947 end
1948 end
1949
1950 redef class AOrElseExpr
1951 redef fun expr(v)
1952 do
1953 var i = v.expr(self.n_expr)
1954 if i == null then return null
1955 if i != v.null_instance then return i
1956 return v.expr(self.n_expr2)
1957 end
1958 end
1959
1960 redef class AIntegerExpr
1961 redef fun expr(v)
1962 do
1963 if value isa Int then return v.int_instance(value.as(Int))
1964 if value isa Byte then return v.byte_instance(value.as(Byte))
1965 if value isa Int8 then return v.int8_instance(value.as(Int8))
1966 if value isa Int16 then return v.int16_instance(value.as(Int16))
1967 if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
1968 if value isa Int32 then return v.int32_instance(value.as(Int32))
1969 if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
1970 return null
1971 end
1972 end
1973
1974 redef class AFloatExpr
1975 redef fun expr(v)
1976 do
1977 return v.float_instance(self.value.as(not null))
1978 end
1979 end
1980
1981 redef class ACharExpr
1982 redef fun expr(v)
1983 do
1984 if is_ascii then return v.byte_instance(self.value.as(not null).ascii)
1985 if is_code_point then return v.int_instance(self.value.as(not null).code_point)
1986 return v.char_instance(self.value.as(not null))
1987 end
1988 end
1989
1990 redef class AArrayExpr
1991 redef fun expr(v)
1992 do
1993 var val = new Array[Instance]
1994 var old_comprehension = v.frame.comprehension
1995 v.frame.comprehension = val
1996 for nexpr in self.n_exprs do
1997 if nexpr isa AForExpr then
1998 v.stmt(nexpr)
1999 else
2000 var i = v.expr(nexpr)
2001 if i == null then return null
2002 val.add(i)
2003 end
2004 end
2005 v.frame.comprehension = old_comprehension
2006 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
2007 var elttype = mtype.arguments.first
2008 return v.array_instance(val, elttype)
2009 end
2010 end
2011
2012 redef class AugmentedStringFormExpr
2013 # Factorize the making of a `Regex` object from a literal prefixed string
2014 fun make_re(v: NaiveInterpreter, rs: Instance): nullable Instance do
2015 var tore = to_re
2016 assert tore != null
2017 var res = v.callsite(tore, [rs])
2018 if res == null then
2019 print "Cannot call property `to_re` on {self}"
2020 abort
2021 end
2022 for j in suffix.chars do
2023 if j == 'i' then
2024 var prop = ignore_case
2025 assert prop != null
2026 v.callsite(prop, [res, v.bool_instance(true)])
2027 continue
2028 end
2029 if j == 'm' then
2030 var prop = newline
2031 assert prop != null
2032 v.callsite(prop, [res, v.bool_instance(true)])
2033 continue
2034 end
2035 if j == 'b' then
2036 var prop = extended
2037 assert prop != null
2038 v.callsite(prop, [res, v.bool_instance(false)])
2039 continue
2040 end
2041 # Should not happen, this needs to be updated
2042 # along with the addition of new suffixes
2043 abort
2044 end
2045 return res
2046 end
2047 end
2048
2049 redef class AStringFormExpr
2050 redef fun expr(v) do return v.string_instance(value)
2051 end
2052
2053 redef class AStringExpr
2054 redef fun expr(v) do
2055 var s = v.string_instance(value)
2056 if is_string then return s
2057 if is_bytestring then
2058 var ns = v.c_string_instance_from_ns(bytes.items, bytes.length)
2059 var ln = v.int_instance(bytes.length)
2060 var prop = to_bytes_with_copy
2061 assert prop != null
2062 var res = v.callsite(prop, [ns, ln])
2063 if res == null then
2064 print "Cannot call property `to_bytes` on {self}"
2065 abort
2066 end
2067 s = res
2068 else if is_re then
2069 var res = make_re(v, s)
2070 assert res != null
2071 s = res
2072 else
2073 print "Unimplemented prefix or suffix for {self}"
2074 abort
2075 end
2076 return s
2077 end
2078 end
2079
2080 redef class ASuperstringExpr
2081 redef fun expr(v)
2082 do
2083 var array = new Array[Instance]
2084 for nexpr in n_exprs do
2085 var i = v.expr(nexpr)
2086 if i == null then return null
2087 array.add(i)
2088 end
2089 var i = v.array_instance(array, v.mainmodule.object_type)
2090 var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i])
2091 assert res != null
2092 if is_re then res = make_re(v, res)
2093 return res
2094 end
2095 end
2096
2097 redef class ACrangeExpr
2098 redef fun expr(v)
2099 do
2100 var e1 = v.expr(self.n_expr)
2101 if e1 == null then return null
2102 var e2 = v.expr(self.n_expr2)
2103 if e2 == null then return null
2104 var mtype = v.unanchor_type(self.mtype.as(not null))
2105 var res = new MutableInstance(mtype)
2106 v.init_instance(res)
2107 v.callsite(init_callsite, [res, e1, e2])
2108 return res
2109 end
2110 end
2111
2112 redef class AOrangeExpr
2113 redef fun expr(v)
2114 do
2115 var e1 = v.expr(self.n_expr)
2116 if e1 == null then return null
2117 var e2 = v.expr(self.n_expr2)
2118 if e2 == null then return null
2119 var mtype = v.unanchor_type(self.mtype.as(not null))
2120 var res = new MutableInstance(mtype)
2121 v.init_instance(res)
2122 v.callsite(init_callsite, [res, e1, e2])
2123 return res
2124 end
2125 end
2126
2127 redef class ATrueExpr
2128 redef fun expr(v)
2129 do
2130 return v.bool_instance(true)
2131 end
2132 end
2133
2134 redef class AFalseExpr
2135 redef fun expr(v)
2136 do
2137 return v.bool_instance(false)
2138 end
2139 end
2140
2141 redef class ANullExpr
2142 redef fun expr(v)
2143 do
2144 return v.null_instance
2145 end
2146 end
2147
2148 redef class AIsaExpr
2149 redef fun expr(v)
2150 do
2151 var i = v.expr(self.n_expr)
2152 if i == null then return null
2153 var mtype = v.unanchor_type(self.cast_type.as(not null))
2154 return v.bool_instance(v.is_subtype(i.mtype, mtype))
2155 end
2156 end
2157
2158 redef class AAsCastExpr
2159 redef fun expr(v)
2160 do
2161 var i = v.expr(self.n_expr)
2162 if i == null then return null
2163 var mtype = self.mtype.as(not null)
2164 var amtype = v.unanchor_type(mtype)
2165 if not v.is_subtype(i.mtype, amtype) then
2166 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
2167 end
2168 return i
2169 end
2170 end
2171
2172 redef class AAsNotnullExpr
2173 redef fun expr(v)
2174 do
2175 var i = v.expr(self.n_expr)
2176 if i == null then return null
2177 if i.mtype isa MNullType then
2178 fatal(v, "Cast failed")
2179 end
2180 return i
2181 end
2182 end
2183
2184 redef class AParExpr
2185 redef fun expr(v)
2186 do
2187 return v.expr(self.n_expr)
2188 end
2189 end
2190
2191 redef class AOnceExpr
2192 redef fun expr(v)
2193 do
2194 if v.onces.has_key(self) then
2195 return v.onces[self]
2196 else
2197 var res = v.expr(self.n_expr)
2198 if res == null then return null
2199 v.onces[self] = res
2200 return res
2201 end
2202 end
2203 end
2204
2205 redef class ASendExpr
2206 redef fun expr(v)
2207 do
2208 var recv = v.expr(self.n_expr)
2209 if recv == null then return null
2210 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2211 if args == null then return null
2212
2213 var res = v.callsite(callsite, args)
2214 return res
2215 end
2216 end
2217
2218 redef class ASendReassignFormExpr
2219 redef fun stmt(v)
2220 do
2221 var recv = v.expr(self.n_expr)
2222 if recv == null then return
2223 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2224 if args == null then return
2225 var value = v.expr(self.n_value)
2226 if value == null then return
2227
2228 var read = v.callsite(callsite, args)
2229 assert read != null
2230
2231 var write = v.callsite(reassign_callsite, [read, value])
2232 assert write != null
2233
2234 args.add(write)
2235
2236 v.callsite(write_callsite, args)
2237 end
2238 end
2239
2240 redef class ASuperExpr
2241 redef fun expr(v)
2242 do
2243 var recv = v.frame.arguments.first
2244
2245 var callsite = self.callsite
2246 if callsite != null then
2247 var args
2248 if self.n_args.n_exprs.is_empty then
2249 # Add automatic arguments for the super init call
2250 args = [recv]
2251 for i in [0..callsite.msignature.arity[ do
2252 args.add(v.frame.arguments[i+1])
2253 end
2254 else
2255 args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2256 if args == null then return null
2257 end
2258
2259 # Super init call
2260 var res = v.callsite(callsite, args)
2261 return res
2262 end
2263
2264 # Standard call-next-method
2265 var mpropdef = self.mpropdef
2266 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
2267
2268 var args
2269 if self.n_args.n_exprs.is_empty then
2270 args = v.frame.arguments
2271 else
2272 args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
2273 if args == null then return null
2274 end
2275
2276 var res = v.call(mpropdef, args)
2277 return res
2278 end
2279 end
2280
2281 redef class ANewExpr
2282 redef fun expr(v)
2283 do
2284 var mtype = v.unanchor_type(self.recvtype.as(not null))
2285 var recv: Instance = new MutableInstance(mtype)
2286 v.init_instance(recv)
2287 var callsite = self.callsite
2288 if callsite == null then return recv
2289
2290 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2291 if args == null then return null
2292 var res2 = v.callsite(callsite, args)
2293 if res2 != null then
2294 #self.debug("got {res2} from {mproperty}. drop {recv}")
2295 return res2
2296 end
2297 return recv
2298 end
2299 end
2300
2301 redef class AAttrExpr
2302 redef fun expr(v)
2303 do
2304 var recv = v.expr(self.n_expr)
2305 if recv == null then return null
2306 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2307 var mproperty = self.mproperty.as(not null)
2308 return v.read_attribute(mproperty, recv)
2309 end
2310 end
2311
2312 redef class AAttrAssignExpr
2313 redef fun stmt(v)
2314 do
2315 var recv = v.expr(self.n_expr)
2316 if recv == null then return
2317 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2318 var i = v.expr(self.n_value)
2319 if i == null then return
2320 var mproperty = self.mproperty.as(not null)
2321 v.write_attribute(mproperty, recv, i)
2322 end
2323 end
2324
2325 redef class AAttrReassignExpr
2326 redef fun stmt(v)
2327 do
2328 var recv = v.expr(self.n_expr)
2329 if recv == null then return
2330 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2331 var value = v.expr(self.n_value)
2332 if value == null then return
2333 var mproperty = self.mproperty.as(not null)
2334 var attr = v.read_attribute(mproperty, recv)
2335 var res = v.callsite(reassign_callsite, [attr, value])
2336 assert res != null
2337 v.write_attribute(mproperty, recv, res)
2338 end
2339 end
2340
2341 redef class AIssetAttrExpr
2342 redef fun expr(v)
2343 do
2344 var recv = v.expr(self.n_expr)
2345 if recv == null then return null
2346 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2347 var mproperty = self.mproperty.as(not null)
2348 return v.bool_instance(v.isset_attribute(mproperty, recv))
2349 end
2350 end
2351
2352 redef class AVarargExpr
2353 redef fun expr(v)
2354 do
2355 return v.expr(self.n_expr)
2356 end
2357 end
2358
2359 redef class ANamedargExpr
2360 redef fun expr(v)
2361 do
2362 return v.expr(self.n_expr)
2363 end
2364 end
2365
2366 redef class ADebugTypeExpr
2367 redef fun stmt(v)
2368 do
2369 # do nothing
2370 end
2371 end