Merge: Introducing the do ... catch ... end structure
[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.new_msignature or else 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 var initializers = callsite.mpropdef.initializers
586 if not initializers.is_empty then
587 var recv = arguments.first
588 var i = 1
589 for p in initializers do
590 if p isa MMethod then
591 var args = [recv]
592 for x in p.intro.msignature.mparameters do
593 args.add arguments[i]
594 i += 1
595 end
596 self.send(p, args)
597 else if p isa MAttribute then
598 assert recv isa MutableInstance
599 write_attribute(p, recv, arguments[i])
600 i += 1
601 else abort
602 end
603 assert i == arguments.length
604
605 return send(callsite.mproperty, [recv])
606 end
607 return send(callsite.mproperty, arguments)
608 end
609
610 # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
611 # Return a value if `mproperty` is a function, or null if it is a procedure.
612 # The call is polymorphic. There is a message-sending/late-binding according to the receiver (args[0]).
613 fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
614 do
615 var recv = args.first
616 var mtype = recv.mtype
617 var ret = send_commons(mproperty, args, mtype)
618 if ret != null then return ret
619 var propdef = mproperty.lookup_first_definition(self.mainmodule, mtype)
620 return self.call(propdef, args)
621 end
622
623 # Read the attribute `mproperty` of an instance `recv` and return its value.
624 # If the attribute in not yet initialized, then aborts with an error message.
625 fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
626 do
627 assert recv isa MutableInstance
628 if not recv.attributes.has_key(mproperty) then
629 fatal("Uninitialized attribute {mproperty.name}")
630 abort
631 end
632 return recv.attributes[mproperty]
633 end
634
635 # Replace in `recv` the value of the attribute `mproperty` by `value`
636 fun write_attribute(mproperty: MAttribute, recv: Instance, value: Instance)
637 do
638 assert recv isa MutableInstance
639 recv.attributes[mproperty] = value
640 end
641
642 # Is the attribute `mproperty` initialized the instance `recv`?
643 fun isset_attribute(mproperty: MAttribute, recv: Instance): Bool
644 do
645 assert recv isa MutableInstance
646 return recv.attributes.has_key(mproperty)
647 end
648
649 # Collect attributes of a type in the order of their init
650 fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]
651 do
652 var cache = self.collect_attr_propdef_cache
653 if cache.has_key(mtype) then return cache[mtype]
654
655 var res = new Array[AAttrPropdef]
656 var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
657 self.mainmodule.linearize_mclassdefs(cds)
658 for cd in cds do
659 res.add_all(modelbuilder.collect_attr_propdef(cd))
660 end
661
662 cache[mtype] = res
663 return res
664 end
665
666 private var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
667
668 # Fill the initial values of the newly created instance `recv`.
669 # `recv.mtype` is used to know what must be filled.
670 fun init_instance(recv: Instance)
671 do
672 for npropdef in collect_attr_propdef(recv.mtype) do
673 npropdef.init_expr(self, recv)
674 end
675 end
676
677 # A hook to initialize a `PrimitiveInstance`
678 fun init_instance_primitive(recv: Instance) do end
679
680 # This function determines the correct type according to the receiver of the current propdef (self).
681 fun unanchor_type(mtype: MType): MType
682 do
683 return mtype.anchor_to(self.mainmodule, current_receiver_class)
684 end
685
686 # Placebo instance used to mark internal error result when `null` already have a meaning.
687 # TODO: replace with multiple return or something better
688 var error_instance = new MutableInstance(modelbuilder.model.null_type) is lazy
689 end
690
691 # An instance represents a value of the executed program.
692 abstract class Instance
693 # The dynamic type of the instance
694 # ASSERT: not self.mtype.is_anchored
695 var mtype: MType
696
697 # return true if the instance is the true value.
698 # return false if the instance is the true value.
699 # else aborts
700 fun is_true: Bool do abort
701
702 # Return true if `self` IS `o` (using the Nit semantic of is)
703 fun eq_is(o: Instance): Bool do return self.is_same_instance(o)
704
705 # Human readable object identity "Type#number"
706 redef fun to_s do return "{mtype}"
707
708 # Return the integer value if the instance is an integer.
709 # else aborts
710 fun to_i: Int do abort
711
712 # Return the integer value if the instance is a float.
713 # else aborts
714 fun to_f: Float do abort
715
716 # Return the integer value if the instance is a byte.
717 # else aborts
718 fun to_b: Byte do abort
719
720 # Return the integer value if the instance is a int8.
721 # else aborts
722 fun to_i8: Int8 do abort
723
724 # Return the integer value if the instance is a int16.
725 # else aborts
726 fun to_i16: Int16 do abort
727
728 # Return the integer value if the instance is a uint16.
729 # else aborts
730 fun to_u16: UInt16 do abort
731
732 # Return the integer value if the instance is a int32.
733 # else aborts
734 fun to_i32: Int32 do abort
735
736 # Return the integer value if the instance is a uint32.
737 # else aborts
738 fun to_u32: UInt32 do abort
739
740 # The real value encapsulated if the instance is primitive.
741 # Else aborts.
742 fun val: nullable Object do abort
743 end
744
745 # A instance with attribute (standards objects)
746 class MutableInstance
747 super Instance
748
749 # The values of the attributes
750 var attributes: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
751 end
752
753 # Special instance to handle primitives values (int, bool, etc.)
754 # The trick it just to encapsulate the <<real>> value
755 class PrimitiveInstance[E]
756 super Instance
757
758 # The real value encapsulated
759 redef var val: E
760
761 redef fun is_true
762 do
763 if val == true then return true
764 if val == false then return false
765 abort
766 end
767
768 redef fun ==(o)
769 do
770 if not o isa PrimitiveInstance[nullable Object] then return false
771 return self.val == o.val
772 end
773
774 redef fun eq_is(o)
775 do
776 if not o isa PrimitiveInstance[nullable Object] then return false
777 return self.val.is_same_instance(o.val)
778 end
779
780 redef fun to_s do return "{mtype}#{val.object_id}({val or else "null"})"
781
782 redef fun to_i do return val.as(Int)
783
784 redef fun to_f do return val.as(Float)
785
786 redef fun to_b do return val.as(Byte)
787
788 redef fun to_i8 do return val.as(Int8)
789
790 redef fun to_i16 do return val.as(Int16)
791
792 redef fun to_u16 do return val.as(UInt16)
793
794 redef fun to_i32 do return val.as(Int32)
795
796 redef fun to_u32 do return val.as(UInt32)
797 end
798
799 # Information about local variables in a running method
800 abstract class Frame
801 # The current visited node
802 # The node is stored by frame to keep a stack trace
803 var current_node: ANode
804 # The executed property.
805 # A Method in case of a call, an attribute in case of a default initialization.
806 var mpropdef: MPropDef
807 # Arguments of the method (the first is the receiver)
808 var arguments: Array[Instance]
809 # Indicate if the expression has an array comprehension form
810 var comprehension: nullable Array[Instance] = null
811 end
812
813 # Implementation of a Frame with a Hashmap to store local variables
814 class InterpreterFrame
815 super Frame
816
817 # Mapping between a variable and the current value
818 private var map: Map[Variable, Instance] = new HashMap[Variable, Instance]
819 end
820
821 redef class ANode
822 # Aborts the program with a message
823 # `v` is used to know if a colored message is displayed or not
824 fun fatal(v: NaiveInterpreter, message: String)
825 do
826 if v.modelbuilder.toolcontext.opt_no_color.value == true then
827 sys.stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
828 else
829 sys.stderr.write("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
830 sys.stderr.write(v.stack_trace)
831 sys.stderr.write("\n")
832 end
833 exit(1)
834 end
835 end
836
837 redef class APropdef
838 # Execute a `mpropdef` associated with the current node.
839 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
840 do
841 fatal(v, "NOT YET IMPLEMENTED method kind {class_name}. {mpropdef}")
842 abort
843 end
844 end
845
846 redef class AMethPropdef
847 super TablesCapable
848
849 redef fun call(v, mpropdef, args)
850 do
851 var f = v.new_frame(self, mpropdef, args)
852 var res = call_commons(v, mpropdef, args, f)
853 v.frames.shift
854 if v.is_escape(self.return_mark) then
855 res = v.escapevalue
856 return res
857 end
858 return res
859 end
860
861 private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
862 do
863 v.frames.unshift(f)
864
865 for i in [0..mpropdef.msignature.arity[ do
866 var variable = self.n_signature.n_params[i].variable
867 assert variable != null
868 v.write_variable(variable, arguments[i+1])
869 end
870
871 # Call the implicit super-init
872 var auto_super_inits = self.auto_super_inits
873 if auto_super_inits != null then
874 var args = [arguments.first]
875 for auto_super_init in auto_super_inits do
876 args.clear
877 for i in [0..auto_super_init.msignature.arity+1[ do
878 args.add(arguments[i])
879 end
880 assert auto_super_init.mproperty != mpropdef.mproperty
881 v.callsite(auto_super_init, args)
882 end
883 end
884 if auto_super_call then
885 # standard call-next-method
886 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
887 v.call(superpd, arguments)
888 end
889
890 # First, try intern
891 if mpropdef.is_intern or mpropdef.is_extern then
892 var res = intern_call(v, mpropdef, arguments)
893 if res != v.error_instance then return res
894 end
895 # Then, try extern
896 if mpropdef.is_extern then
897 var res = call_extern(v, mpropdef, arguments, f)
898 if res != v.error_instance then return res
899 end
900 # Else try block
901 if n_block != null then
902 v.stmt(self.n_block)
903 return null
904 end
905
906 # Fail if nothing succeed
907 if mpropdef.is_intern then
908 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
909 else if mpropdef.is_extern then
910 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
911 else
912 fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
913 end
914 abort
915 end
916
917 # Call this extern method
918 protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
919 do
920 return v.error_instance
921 end
922
923 # Interprets a intern or a shortcut extern method.
924 # Returns the result for a function, `null` for a procedure, or `error_instance` if the method is unknown.
925 private fun intern_call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
926 do
927 var pname = mpropdef.mproperty.name
928 var cname = mpropdef.mclassdef.mclass.name
929 if pname == "output" then
930 var recv = args.first
931 recv.val.output
932 return null
933 else if pname == "object_id" then
934 var recv = args.first
935 if recv isa PrimitiveInstance[Object] then
936 return v.int_instance(recv.val.object_id)
937 else
938 return v.int_instance(recv.object_id)
939 end
940 else if pname == "output_class_name" then
941 var recv = args.first
942 print recv.mtype
943 return null
944 else if pname == "native_class_name" then
945 var recv = args.first
946 var txt = recv.mtype.to_s
947 return v.native_string_instance(txt)
948 else if pname == "==" then
949 # == is correctly redefined for instances
950 return v.bool_instance(args[0] == args[1])
951 else if pname == "!=" then
952 return v.bool_instance(args[0] != args[1])
953 else if pname == "is_same_type" then
954 return v.bool_instance(args[0].mtype == args[1].mtype)
955 else if pname == "is_same_instance" then
956 return v.bool_instance(args[0].eq_is(args[1]))
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 == "NativeString" then
1153 if pname == "new" then
1154 return v.native_string_instance_len(args[1].to_i)
1155 end
1156 var recvval = args.first.val.as(NativeString)
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: NativeString, length: Int, from: Int, to: Int)
1166 var destval = args[1].val.as(NativeString)
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.native_string_instance(ns.to_s)
1177 else if pname == "fetch_4_chars" then
1178 return v.int_instance(args[0].val.as(NativeString).fetch_4_chars(args[1].to_i))
1179 else if pname == "fetch_4_hchars" then
1180 return v.int_instance(args[0].val.as(NativeString).fetch_4_hchars(args[1].to_i))
1181 else if pname == "utf8_length" then
1182 return v.int_instance(args[0].val.as(NativeString).utf8_length(args[1].to_i, args[2].to_i))
1183 end
1184 else if pname == "calloc_string" then
1185 return v.native_string_instance_len(args[1].to_i)
1186 else if cname == "NativeArray" then
1187 if pname == "new" then
1188 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
1189 var instance = new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
1190 v.init_instance_primitive(instance)
1191 return instance
1192 end
1193 var recvval = args.first.val.as(Array[Instance])
1194 if pname == "[]" then
1195 return recvval[args[1].to_i]
1196 else if pname == "[]=" then
1197 recvval[args[1].to_i] = args[2]
1198 return null
1199 else if pname == "length" then
1200 return v.int_instance(recvval.length)
1201 else if pname == "copy_to" then
1202 recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
1203 return null
1204 end
1205 else if cname == "Int8" then
1206 var recvval = args[0].to_i8
1207 if pname == "unary -" then
1208 return v.int8_instance(-recvval)
1209 else if pname == "unary +" then
1210 return args[0]
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.int8_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.bool_instance(recvval >= args[1].to_i8)
1229 else if pname == "<=>" then
1230 return v.int_instance(recvval <=> args[1].to_i8)
1231 else if pname == "to_f" then
1232 return v.float_instance(recvval.to_f)
1233 else if pname == "to_i" then
1234 return v.int_instance(recvval.to_i)
1235 else if pname == "to_b" then
1236 return v.byte_instance(recvval.to_b)
1237 else if pname == "to_i16" then
1238 return v.int16_instance(recvval.to_i16)
1239 else if pname == "to_u16" then
1240 return v.uint16_instance(recvval.to_u16)
1241 else if pname == "to_i32" then
1242 return v.int32_instance(recvval.to_i32)
1243 else if pname == "to_u32" then
1244 return v.uint32_instance(recvval.to_u32)
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_i))
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 == "^" then
1254 return v.int8_instance(recvval ^ args[1].to_i8)
1255 else if pname == "unary ~" then
1256 return v.int8_instance(~recvval)
1257 end
1258 else if cname == "Int16" then
1259 var recvval = args[0].to_i16
1260 if pname == "unary -" then
1261 return v.int16_instance(-recvval)
1262 else if pname == "unary +" then
1263 return args[0]
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.int16_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.bool_instance(recvval >= args[1].to_i16)
1282 else if pname == "<=>" then
1283 return v.int_instance(recvval <=> args[1].to_i16)
1284 else if pname == "to_f" then
1285 return v.float_instance(recvval.to_f)
1286 else if pname == "to_i" then
1287 return v.int_instance(recvval.to_i)
1288 else if pname == "to_b" then
1289 return v.byte_instance(recvval.to_b)
1290 else if pname == "to_i8" then
1291 return v.int8_instance(recvval.to_i8)
1292 else if pname == "to_u16" then
1293 return v.uint16_instance(recvval.to_u16)
1294 else if pname == "to_i32" then
1295 return v.int32_instance(recvval.to_i32)
1296 else if pname == "to_u32" then
1297 return v.uint32_instance(recvval.to_u32)
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_i))
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 == "^" then
1307 return v.int16_instance(recvval ^ args[1].to_i16)
1308 else if pname == "unary ~" then
1309 return v.int16_instance(~recvval)
1310 end
1311 else if cname == "UInt16" then
1312 var recvval = args[0].to_u16
1313 if pname == "unary -" then
1314 return v.uint16_instance(-recvval)
1315 else if pname == "unary +" then
1316 return args[0]
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.uint16_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.bool_instance(recvval >= args[1].to_u16)
1335 else if pname == "<=>" then
1336 return v.int_instance(recvval <=> args[1].to_u16)
1337 else if pname == "to_f" then
1338 return v.float_instance(recvval.to_f)
1339 else if pname == "to_i" then
1340 return v.int_instance(recvval.to_i)
1341 else if pname == "to_b" then
1342 return v.byte_instance(recvval.to_b)
1343 else if pname == "to_i8" then
1344 return v.int8_instance(recvval.to_i8)
1345 else if pname == "to_i16" then
1346 return v.int16_instance(recvval.to_i16)
1347 else if pname == "to_i32" then
1348 return v.int32_instance(recvval.to_i32)
1349 else if pname == "to_u32" then
1350 return v.uint32_instance(recvval.to_u32)
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_i))
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 == "^" then
1360 return v.uint16_instance(recvval ^ args[1].to_u16)
1361 else if pname == "unary ~" then
1362 return v.uint16_instance(~recvval)
1363 end
1364 else if cname == "Int32" then
1365 var recvval = args[0].to_i32
1366 if pname == "unary -" then
1367 return v.int32_instance(-recvval)
1368 else if pname == "unary +" then
1369 return args[0]
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.int32_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.bool_instance(recvval >= args[1].to_i32)
1388 else if pname == "<=>" then
1389 return v.int_instance(recvval <=> args[1].to_i32)
1390 else if pname == "to_f" then
1391 return v.float_instance(recvval.to_f)
1392 else if pname == "to_i" then
1393 return v.int_instance(recvval.to_i)
1394 else if pname == "to_b" then
1395 return v.byte_instance(recvval.to_b)
1396 else if pname == "to_i8" then
1397 return v.int8_instance(recvval.to_i8)
1398 else if pname == "to_i16" then
1399 return v.int16_instance(recvval.to_i16)
1400 else if pname == "to_u16" then
1401 return v.uint16_instance(recvval.to_u16)
1402 else if pname == "to_u32" then
1403 return v.uint32_instance(recvval.to_u32)
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_i))
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 == "^" then
1413 return v.int32_instance(recvval ^ args[1].to_i32)
1414 else if pname == "unary ~" then
1415 return v.int32_instance(~recvval)
1416 end
1417 else if cname == "UInt32" then
1418 var recvval = args[0].to_u32
1419 if pname == "unary -" then
1420 return v.uint32_instance(-recvval)
1421 else if pname == "unary +" then
1422 return args[0]
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.uint32_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.bool_instance(recvval >= args[1].to_u32)
1441 else if pname == "<=>" then
1442 return v.int_instance(recvval <=> args[1].to_u32)
1443 else if pname == "to_f" then
1444 return v.float_instance(recvval.to_f)
1445 else if pname == "to_i" then
1446 return v.int_instance(recvval.to_i)
1447 else if pname == "to_b" then
1448 return v.byte_instance(recvval.to_b)
1449 else if pname == "to_i8" then
1450 return v.int8_instance(recvval.to_i8)
1451 else if pname == "to_i16" then
1452 return v.int16_instance(recvval.to_i16)
1453 else if pname == "to_u16" then
1454 return v.uint16_instance(recvval.to_u16)
1455 else if pname == "to_i32" then
1456 return v.int32_instance(recvval.to_i32)
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_i))
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 == "^" then
1466 return v.uint32_instance(recvval ^ args[1].to_u32)
1467 else if pname == "unary ~" then
1468 return v.uint32_instance(~recvval)
1469 end
1470 else if pname == "native_argc" then
1471 return v.int_instance(v.arguments.length)
1472 else if pname == "native_argv" then
1473 var txt = v.arguments[args[1].to_i]
1474 return v.native_string_instance(txt)
1475 else if pname == "native_argc" then
1476 return v.int_instance(v.arguments.length)
1477 else if pname == "native_argv" then
1478 var txt = v.arguments[args[1].to_i]
1479 return v.native_string_instance(txt)
1480 else if pname == "lexer_goto" then
1481 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
1482 else if pname == "lexer_accept" then
1483 return v.int_instance(lexer_accept(args[1].to_i))
1484 else if pname == "parser_goto" then
1485 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
1486 else if pname == "parser_action" then
1487 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
1488 end
1489 return v.error_instance
1490 end
1491 end
1492
1493 redef class AAttrPropdef
1494 redef fun call(v, mpropdef, args)
1495 do
1496 var recv = args.first
1497 assert recv isa MutableInstance
1498 var attr = self.mpropdef.mproperty
1499 if mpropdef == mreadpropdef then
1500 assert args.length == 1
1501 if not is_lazy or v.isset_attribute(attr, recv) then return v.read_attribute(attr, recv)
1502 var f = v.new_frame(self, mpropdef, args)
1503 return evaluate_expr(v, recv, f)
1504 else if mpropdef == mwritepropdef then
1505 assert args.length == 2
1506 var arg = args[1]
1507 if is_optional and arg.mtype isa MNullType then
1508 var f = v.new_frame(self, mpropdef, args)
1509 arg = evaluate_expr(v, recv, f)
1510 end
1511 v.write_attribute(attr, recv, arg)
1512 return null
1513 else
1514 abort
1515 end
1516 end
1517
1518 # Evaluate and set the default value of the attribute in `recv`
1519 private fun init_expr(v: NaiveInterpreter, recv: Instance)
1520 do
1521 if is_lazy then return
1522 if has_value then
1523 var f = v.new_frame(self, mreadpropdef.as(not null), [recv])
1524 evaluate_expr(v, recv, f)
1525 return
1526 end
1527 var mpropdef = self.mpropdef
1528 if mpropdef == null then return
1529 var mtype = self.mtype.as(not null)
1530 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1531 if mtype isa MNullableType then
1532 v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
1533 end
1534 end
1535
1536 private fun evaluate_expr(v: NaiveInterpreter, recv: Instance, f: Frame): Instance
1537 do
1538 assert recv isa MutableInstance
1539 v.frames.unshift(f)
1540
1541 var val
1542
1543 var nexpr = self.n_expr
1544 var nblock = self.n_block
1545 if nexpr != null then
1546 val = v.expr(nexpr)
1547 else if nblock != null then
1548 v.stmt(nblock)
1549 assert v.escapemark == return_mark
1550 val = v.escapevalue
1551 v.escapemark = null
1552 else
1553 abort
1554 end
1555 assert val != null
1556
1557 v.frames.shift
1558 assert not v.is_escaping
1559 v.write_attribute(self.mpropdef.mproperty, recv, val)
1560 return val
1561 end
1562 end
1563
1564 redef class AClassdef
1565 # Execute an implicit `mpropdef` associated with the current node.
1566 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance]): nullable Instance
1567 do
1568 if mpropdef.mproperty.is_root_init then
1569 assert arguments.length == 1
1570 if not mpropdef.is_intro then
1571 # standard call-next-method
1572 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
1573 v.call(superpd, arguments)
1574 end
1575 return null
1576 else
1577 abort
1578 end
1579 end
1580 end
1581
1582 redef class AExpr
1583 # Evaluate the node as a possible expression.
1584 # Return a possible value
1585 # NOTE: Do not call this method directly, but use `v.expr`
1586 # This method is here to be implemented by subclasses.
1587 protected fun expr(v: NaiveInterpreter): nullable Instance
1588 do
1589 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1590 abort
1591 end
1592
1593 # Evaluate the node as a statement.
1594 # NOTE: Do not call this method directly, but use `v.stmt`
1595 # This method is here to be implemented by subclasses (no need to return something).
1596 protected fun stmt(v: NaiveInterpreter)
1597 do
1598 expr(v)
1599 end
1600
1601 end
1602
1603 redef class ABlockExpr
1604 redef fun expr(v)
1605 do
1606 var last = self.n_expr.last
1607 for e in self.n_expr do
1608 if e == last then break
1609 v.stmt(e)
1610 if v.is_escaping then return null
1611 end
1612 return last.expr(v)
1613 end
1614
1615 redef fun stmt(v)
1616 do
1617 for e in self.n_expr do
1618 v.stmt(e)
1619 if v.is_escaping then return
1620 end
1621 end
1622 end
1623
1624 redef class AVardeclExpr
1625 redef fun expr(v)
1626 do
1627 var ne = self.n_expr
1628 if ne != null then
1629 var i = v.expr(ne)
1630 if i == null then return null
1631 v.write_variable(self.variable.as(not null), i)
1632 return i
1633 end
1634 return null
1635 end
1636 end
1637
1638 redef class AVarExpr
1639 redef fun expr(v)
1640 do
1641 return v.read_variable(self.variable.as(not null))
1642 end
1643 end
1644
1645 redef class AVarAssignExpr
1646 redef fun expr(v)
1647 do
1648 var i = v.expr(self.n_value)
1649 if i == null then return null
1650 v.write_variable(self.variable.as(not null), i)
1651 return i
1652 end
1653 end
1654
1655 redef class AVarReassignExpr
1656 redef fun stmt(v)
1657 do
1658 var variable = self.variable.as(not null)
1659 var vari = v.read_variable(variable)
1660 var value = v.expr(self.n_value)
1661 if value == null then return
1662 var res = v.callsite(reassign_callsite, [vari, value])
1663 assert res != null
1664 v.write_variable(variable, res)
1665 end
1666 end
1667
1668 redef class ASelfExpr
1669 redef fun expr(v)
1670 do
1671 return v.frame.arguments.first
1672 end
1673 end
1674
1675 redef class AImplicitSelfExpr
1676 redef fun expr(v)
1677 do
1678 if not is_sys then return super
1679 return v.mainobj
1680 end
1681 end
1682
1683 redef class AEscapeExpr
1684 redef fun stmt(v)
1685 do
1686 var ne = self.n_expr
1687 if ne != null then
1688 var i = v.expr(ne)
1689 if i == null then return
1690 v.escapevalue = i
1691 end
1692 v.escapemark = self.escapemark
1693 end
1694 end
1695
1696 redef class AAbortExpr
1697 redef fun stmt(v)
1698 do
1699 # Abort as asked if there is no `catch` bloc
1700 if v.catch_count <= 0 then
1701 fatal(v, "Aborted")
1702 exit(1)
1703 else
1704 # Abort mode, skipping everything until a `catch` bloc is reached
1705 v.escapemark = v.catch_mark
1706 end
1707 end
1708 end
1709
1710 redef class AIfExpr
1711 redef fun expr(v)
1712 do
1713 var cond = v.expr(self.n_expr)
1714 if cond == null then return null
1715 if cond.is_true then
1716 return v.expr(self.n_then.as(not null))
1717 else
1718 return v.expr(self.n_else.as(not null))
1719 end
1720 end
1721
1722 redef fun stmt(v)
1723 do
1724 var cond = v.expr(self.n_expr)
1725 if cond == null then return
1726 if cond.is_true then
1727 v.stmt(self.n_then)
1728 else
1729 v.stmt(self.n_else)
1730 end
1731 end
1732 end
1733
1734 redef class AIfexprExpr
1735 redef fun expr(v)
1736 do
1737 var cond = v.expr(self.n_expr)
1738 if cond == null then return null
1739 if cond.is_true then
1740 return v.expr(self.n_then)
1741 else
1742 return v.expr(self.n_else)
1743 end
1744 end
1745 end
1746
1747 redef class ADoExpr
1748 redef fun stmt(v)
1749 do
1750 # If this bloc has a catch, register it in the counter
1751 if self.n_catch != null then v.catch_count += 1
1752 v.stmt(self.n_block)
1753 v.is_escape(self.break_mark) # Clear the break (if any)
1754 if self.n_catch != null then
1755 v.catch_count -= 1
1756 # Are we in abort mode? then this catch is executing
1757 if v.is_escape(v.catch_mark) then v.stmt(self.n_catch)
1758 end
1759 end
1760 end
1761
1762 redef class AWhileExpr
1763 redef fun stmt(v)
1764 do
1765 loop
1766 var cond = v.expr(self.n_expr)
1767 if cond == null then return
1768 if not cond.is_true then return
1769 v.stmt(self.n_block)
1770 if v.is_escape(self.break_mark) then return
1771 v.is_escape(self.continue_mark) # Clear the break
1772 if v.is_escaping then return
1773 end
1774 end
1775 end
1776
1777 redef class ALoopExpr
1778 redef fun stmt(v)
1779 do
1780 loop
1781 v.stmt(self.n_block)
1782 if v.is_escape(self.break_mark) then return
1783 v.is_escape(self.continue_mark) # Clear the break
1784 if v.is_escaping then return
1785 end
1786 end
1787 end
1788
1789 redef class AForExpr
1790 redef fun stmt(v)
1791 do
1792 var iters = new Array[Instance]
1793
1794 for g in n_groups do
1795 var col = v.expr(g.n_expr)
1796 if col == null then return
1797 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1798
1799 var iter = v.callsite(g.method_iterator, [col]).as(not null)
1800 iters.add iter
1801 end
1802
1803 loop
1804 for g in n_groups, iter in iters do
1805 var isok = v.callsite(g.method_is_ok, [iter]).as(not null)
1806 if not isok.is_true then break label
1807 if g.variables.length == 1 then
1808 var item = v.callsite(g.method_item, [iter]).as(not null)
1809 #self.debug("item {item}")
1810 v.write_variable(g.variables.first, item)
1811 else if g.variables.length == 2 then
1812 var key = v.callsite(g.method_key, [iter]).as(not null)
1813 v.write_variable(g.variables[0], key)
1814 var item = v.callsite(g.method_item, [iter]).as(not null)
1815 v.write_variable(g.variables[1], item)
1816 else
1817 abort
1818 end
1819 end
1820 v.stmt(self.n_block)
1821 if v.is_escape(self.break_mark) then break
1822 v.is_escape(self.continue_mark) # Clear the break
1823 if v.is_escaping then break
1824 for g in n_groups, iter in iters do
1825 v.callsite(g.method_next, [iter])
1826 end
1827 end label
1828 for g in n_groups, iter in iters do
1829 var method_finish = g.method_finish
1830 if method_finish != null then
1831 v.callsite(method_finish, [iter])
1832 end
1833 end
1834 end
1835 end
1836
1837 redef class AWithExpr
1838 redef fun stmt(v)
1839 do
1840 var expr = v.expr(self.n_expr)
1841 if expr == null then return
1842
1843 v.callsite(method_start, [expr])
1844 v.stmt(self.n_block)
1845 v.is_escape(self.break_mark) # Clear the break
1846
1847 # Execute the finally without an escape
1848 var old_mark = v.escapemark
1849 v.escapemark = null
1850 v.callsite(method_finish, [expr])
1851 # Restore the escape unless another escape was provided
1852 if v.escapemark == null then v.escapemark = old_mark
1853 end
1854 end
1855
1856 redef class AAssertExpr
1857 redef fun stmt(v)
1858 do
1859 var cond = v.expr(self.n_expr)
1860 if cond == null then return
1861 if not cond.is_true then
1862 v.stmt(self.n_else)
1863 if v.is_escaping then return
1864 var nid = self.n_id
1865 if nid != null then
1866 fatal(v, "Assert '{nid.text}' failed")
1867 else
1868 fatal(v, "Assert failed")
1869 end
1870 exit(1)
1871 end
1872 end
1873 end
1874
1875 redef class AOrExpr
1876 redef fun expr(v)
1877 do
1878 var cond = v.expr(self.n_expr)
1879 if cond == null then return null
1880 if cond.is_true then return cond
1881 return v.expr(self.n_expr2)
1882 end
1883 end
1884
1885 redef class AImpliesExpr
1886 redef fun expr(v)
1887 do
1888 var cond = v.expr(self.n_expr)
1889 if cond == null then return null
1890 if not cond.is_true then return v.true_instance
1891 return v.expr(self.n_expr2)
1892 end
1893 end
1894
1895 redef class AAndExpr
1896 redef fun expr(v)
1897 do
1898 var cond = v.expr(self.n_expr)
1899 if cond == null then return null
1900 if not cond.is_true then return cond
1901 return v.expr(self.n_expr2)
1902 end
1903 end
1904
1905 redef class ANotExpr
1906 redef fun expr(v)
1907 do
1908 var cond = v.expr(self.n_expr)
1909 if cond == null then return null
1910 return v.bool_instance(not cond.is_true)
1911 end
1912 end
1913
1914 redef class AOrElseExpr
1915 redef fun expr(v)
1916 do
1917 var i = v.expr(self.n_expr)
1918 if i == null then return null
1919 if i != v.null_instance then return i
1920 return v.expr(self.n_expr2)
1921 end
1922 end
1923
1924 redef class AIntegerExpr
1925 redef fun expr(v)
1926 do
1927 if value isa Int then return v.int_instance(value.as(Int))
1928 if value isa Byte then return v.byte_instance(value.as(Byte))
1929 if value isa Int8 then return v.int8_instance(value.as(Int8))
1930 if value isa Int16 then return v.int16_instance(value.as(Int16))
1931 if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
1932 if value isa Int32 then return v.int32_instance(value.as(Int32))
1933 if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
1934 return null
1935 end
1936 end
1937
1938 redef class AFloatExpr
1939 redef fun expr(v)
1940 do
1941 return v.float_instance(self.value.as(not null))
1942 end
1943 end
1944
1945 redef class ACharExpr
1946 redef fun expr(v)
1947 do
1948 if is_ascii then return v.byte_instance(self.value.as(not null).ascii)
1949 if is_code_point then return v.int_instance(self.value.as(not null).code_point)
1950 return v.char_instance(self.value.as(not null))
1951 end
1952 end
1953
1954 redef class AArrayExpr
1955 redef fun expr(v)
1956 do
1957 var val = new Array[Instance]
1958 var old_comprehension = v.frame.comprehension
1959 v.frame.comprehension = val
1960 for nexpr in self.n_exprs do
1961 if nexpr isa AForExpr then
1962 v.stmt(nexpr)
1963 else
1964 var i = v.expr(nexpr)
1965 if i == null then return null
1966 val.add(i)
1967 end
1968 end
1969 v.frame.comprehension = old_comprehension
1970 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1971 var elttype = mtype.arguments.first
1972 return v.array_instance(val, elttype)
1973 end
1974 end
1975
1976 redef class AugmentedStringFormExpr
1977 # Factorize the making of a `Regex` object from a literal prefixed string
1978 fun make_re(v: NaiveInterpreter, rs: Instance): nullable Instance do
1979 var tore = to_re
1980 assert tore != null
1981 var res = v.callsite(tore, [rs])
1982 if res == null then
1983 print "Cannot call property `to_re` on {self}"
1984 abort
1985 end
1986 for j in suffix.chars do
1987 if j == 'i' then
1988 var prop = ignore_case
1989 assert prop != null
1990 v.callsite(prop, [res, v.bool_instance(true)])
1991 continue
1992 end
1993 if j == 'm' then
1994 var prop = newline
1995 assert prop != null
1996 v.callsite(prop, [res, v.bool_instance(true)])
1997 continue
1998 end
1999 if j == 'b' then
2000 var prop = extended
2001 assert prop != null
2002 v.callsite(prop, [res, v.bool_instance(false)])
2003 continue
2004 end
2005 # Should not happen, this needs to be updated
2006 # along with the addition of new suffixes
2007 abort
2008 end
2009 return res
2010 end
2011 end
2012
2013 redef class AStringFormExpr
2014 redef fun expr(v) do return v.string_instance(value)
2015 end
2016
2017 redef class AStringExpr
2018 redef fun expr(v) do
2019 var s = v.string_instance(value)
2020 if is_string then return s
2021 if is_bytestring then
2022 var ns = v.native_string_instance_from_ns(bytes.items, bytes.length)
2023 var ln = v.int_instance(bytes.length)
2024 var prop = to_bytes_with_copy
2025 assert prop != null
2026 var res = v.callsite(prop, [ns, ln])
2027 if res == null then
2028 print "Cannot call property `to_bytes` on {self}"
2029 abort
2030 end
2031 s = res
2032 else if is_re then
2033 var res = make_re(v, s)
2034 assert res != null
2035 s = res
2036 else
2037 print "Unimplemented prefix or suffix for {self}"
2038 abort
2039 end
2040 return s
2041 end
2042 end
2043
2044 redef class ASuperstringExpr
2045 redef fun expr(v)
2046 do
2047 var array = new Array[Instance]
2048 for nexpr in n_exprs do
2049 var i = v.expr(nexpr)
2050 if i == null then return null
2051 array.add(i)
2052 end
2053 var i = v.array_instance(array, v.mainmodule.object_type)
2054 var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i])
2055 assert res != null
2056 if is_re then res = make_re(v, res)
2057 return res
2058 end
2059 end
2060
2061 redef class ACrangeExpr
2062 redef fun expr(v)
2063 do
2064 var e1 = v.expr(self.n_expr)
2065 if e1 == null then return null
2066 var e2 = v.expr(self.n_expr2)
2067 if e2 == null then return null
2068 var mtype = v.unanchor_type(self.mtype.as(not null))
2069 var res = new MutableInstance(mtype)
2070 v.init_instance(res)
2071 v.callsite(init_callsite, [res, e1, e2])
2072 return res
2073 end
2074 end
2075
2076 redef class AOrangeExpr
2077 redef fun expr(v)
2078 do
2079 var e1 = v.expr(self.n_expr)
2080 if e1 == null then return null
2081 var e2 = v.expr(self.n_expr2)
2082 if e2 == null then return null
2083 var mtype = v.unanchor_type(self.mtype.as(not null))
2084 var res = new MutableInstance(mtype)
2085 v.init_instance(res)
2086 v.callsite(init_callsite, [res, e1, e2])
2087 return res
2088 end
2089 end
2090
2091 redef class ATrueExpr
2092 redef fun expr(v)
2093 do
2094 return v.bool_instance(true)
2095 end
2096 end
2097
2098 redef class AFalseExpr
2099 redef fun expr(v)
2100 do
2101 return v.bool_instance(false)
2102 end
2103 end
2104
2105 redef class ANullExpr
2106 redef fun expr(v)
2107 do
2108 return v.null_instance
2109 end
2110 end
2111
2112 redef class AIsaExpr
2113 redef fun expr(v)
2114 do
2115 var i = v.expr(self.n_expr)
2116 if i == null then return null
2117 var mtype = v.unanchor_type(self.cast_type.as(not null))
2118 return v.bool_instance(v.is_subtype(i.mtype, mtype))
2119 end
2120 end
2121
2122 redef class AAsCastExpr
2123 redef fun expr(v)
2124 do
2125 var i = v.expr(self.n_expr)
2126 if i == null then return null
2127 var mtype = self.mtype.as(not null)
2128 var amtype = v.unanchor_type(mtype)
2129 if not v.is_subtype(i.mtype, amtype) then
2130 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
2131 end
2132 return i
2133 end
2134 end
2135
2136 redef class AAsNotnullExpr
2137 redef fun expr(v)
2138 do
2139 var i = v.expr(self.n_expr)
2140 if i == null then return null
2141 if i.mtype isa MNullType then
2142 fatal(v, "Cast failed")
2143 end
2144 return i
2145 end
2146 end
2147
2148 redef class AParExpr
2149 redef fun expr(v)
2150 do
2151 return v.expr(self.n_expr)
2152 end
2153 end
2154
2155 redef class AOnceExpr
2156 redef fun expr(v)
2157 do
2158 if v.onces.has_key(self) then
2159 return v.onces[self]
2160 else
2161 var res = v.expr(self.n_expr)
2162 if res == null then return null
2163 v.onces[self] = res
2164 return res
2165 end
2166 end
2167 end
2168
2169 redef class ASendExpr
2170 redef fun expr(v)
2171 do
2172 var recv = v.expr(self.n_expr)
2173 if recv == null then return null
2174 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2175 if args == null then return null
2176
2177 var res = v.callsite(callsite, args)
2178 return res
2179 end
2180 end
2181
2182 redef class ASendReassignFormExpr
2183 redef fun stmt(v)
2184 do
2185 var recv = v.expr(self.n_expr)
2186 if recv == null then return
2187 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2188 if args == null then return
2189 var value = v.expr(self.n_value)
2190 if value == null then return
2191
2192 var read = v.callsite(callsite, args)
2193 assert read != null
2194
2195 var write = v.callsite(reassign_callsite, [read, value])
2196 assert write != null
2197
2198 args.add(write)
2199
2200 v.callsite(write_callsite, args)
2201 end
2202 end
2203
2204 redef class ASuperExpr
2205 redef fun expr(v)
2206 do
2207 var recv = v.frame.arguments.first
2208
2209 var callsite = self.callsite
2210 if callsite != null then
2211 var args
2212 if self.n_args.n_exprs.is_empty then
2213 # Add automatic arguments for the super init call
2214 args = [recv]
2215 for i in [0..callsite.msignature.arity[ do
2216 args.add(v.frame.arguments[i+1])
2217 end
2218 else
2219 args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2220 if args == null then return null
2221 end
2222
2223 # Super init call
2224 var res = v.callsite(callsite, args)
2225 return res
2226 end
2227
2228 # Standard call-next-method
2229 var mpropdef = self.mpropdef
2230 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
2231
2232 var args
2233 if self.n_args.n_exprs.is_empty then
2234 args = v.frame.arguments
2235 else
2236 args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
2237 if args == null then return null
2238 end
2239
2240 var res = v.call(mpropdef, args)
2241 return res
2242 end
2243 end
2244
2245 redef class ANewExpr
2246 redef fun expr(v)
2247 do
2248 var mtype = v.unanchor_type(self.recvtype.as(not null))
2249 var recv: Instance = new MutableInstance(mtype)
2250 v.init_instance(recv)
2251 var callsite = self.callsite
2252 if callsite == null then return recv
2253
2254 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2255 if args == null then return null
2256 var res2 = v.callsite(callsite, args)
2257 if res2 != null then
2258 #self.debug("got {res2} from {mproperty}. drop {recv}")
2259 return res2
2260 end
2261 return recv
2262 end
2263 end
2264
2265 redef class AAttrExpr
2266 redef fun expr(v)
2267 do
2268 var recv = v.expr(self.n_expr)
2269 if recv == null then return null
2270 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2271 var mproperty = self.mproperty.as(not null)
2272 return v.read_attribute(mproperty, recv)
2273 end
2274 end
2275
2276 redef class AAttrAssignExpr
2277 redef fun stmt(v)
2278 do
2279 var recv = v.expr(self.n_expr)
2280 if recv == null then return
2281 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2282 var i = v.expr(self.n_value)
2283 if i == null then return
2284 var mproperty = self.mproperty.as(not null)
2285 v.write_attribute(mproperty, recv, i)
2286 end
2287 end
2288
2289 redef class AAttrReassignExpr
2290 redef fun stmt(v)
2291 do
2292 var recv = v.expr(self.n_expr)
2293 if recv == null then return
2294 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2295 var value = v.expr(self.n_value)
2296 if value == null then return
2297 var mproperty = self.mproperty.as(not null)
2298 var attr = v.read_attribute(mproperty, recv)
2299 var res = v.callsite(reassign_callsite, [attr, value])
2300 assert res != null
2301 v.write_attribute(mproperty, recv, res)
2302 end
2303 end
2304
2305 redef class AIssetAttrExpr
2306 redef fun expr(v)
2307 do
2308 var recv = v.expr(self.n_expr)
2309 if recv == null then return null
2310 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2311 var mproperty = self.mproperty.as(not null)
2312 return v.bool_instance(v.isset_attribute(mproperty, recv))
2313 end
2314 end
2315
2316 redef class AVarargExpr
2317 redef fun expr(v)
2318 do
2319 return v.expr(self.n_expr)
2320 end
2321 end
2322
2323 redef class ANamedargExpr
2324 redef fun expr(v)
2325 do
2326 return v.expr(self.n_expr)
2327 end
2328 end
2329
2330 redef class ADebugTypeExpr
2331 redef fun stmt(v)
2332 do
2333 # do nothing
2334 end
2335 end