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