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