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