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