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