Merge remote-tracking branch 'origin/master' into init_auto
[nit.git] / src / interpreter / naive_interpreter.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Interpretation of a Nit program directly on the AST
18 module naive_interpreter
19
20 import literal
21 import semantize
22 private import parser::tables
23 import mixin
24 import primitive_types
25
26 redef class ToolContext
27 # --discover-call-trace
28 var opt_discover_call_trace = new OptionBool("Trace calls of the first invocation of methods", "--discover-call-trace")
29
30 redef init
31 do
32 super
33 self.option_context.add_option(self.opt_discover_call_trace)
34 end
35 end
36
37 redef class ModelBuilder
38 # Execute the program from the entry point (`Sys::main`) of the `mainmodule`
39 # `arguments` are the command-line arguments in order
40 # REQUIRE that:
41 # 1. the AST is fully loaded.
42 # 2. the model is fully built.
43 # 3. the instructions are fully analysed.
44 fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])
45 do
46 var time0 = get_time
47 self.toolcontext.info("*** START INTERPRETING ***", 1)
48
49 var interpreter = new NaiveInterpreter(self, mainmodule, arguments)
50 interpreter.start(mainmodule)
51
52 var time1 = get_time
53 self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
54 end
55 end
56
57 # The visitor that interprets the Nit Program by walking on the AST
58 class NaiveInterpreter
59 # The modelbuilder that know the AST and its associations with the model
60 var modelbuilder: ModelBuilder
61
62 # The main module of the program (used to lookup method)
63 var mainmodule: MModule
64
65 # The command line arguments of the interpreted program
66 # arguments.first is the program name
67 # arguments[1] is the first argument
68 var arguments: Array[String]
69
70 # The main Sys instance
71 var mainobj: nullable Instance is noinit
72
73 init
74 do
75 if mainmodule.model.get_mclasses_by_name("Bool") != null then
76 self.true_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, true)
77 init_instance_primitive(self.true_instance)
78 self.false_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, false)
79 init_instance_primitive(self.false_instance)
80 end
81 self.null_instance = new PrimitiveInstance[nullable Object](mainmodule.model.null_type, null)
82 end
83
84 # Starts the interpreter on the main module of a program
85 fun start(mainmodule: MModule) do
86 var interpreter = self
87 var sys_type = mainmodule.sys_type
88 if sys_type == null then return # no class Sys
89 var mainobj = new MutableInstance(sys_type)
90 interpreter.mainobj = mainobj
91 interpreter.init_instance(mainobj)
92 var initprop = mainmodule.try_get_primitive_method("init", sys_type.mclass)
93 if initprop != null then
94 interpreter.send(initprop, [mainobj])
95 end
96 var mainprop = mainmodule.try_get_primitive_method("run", sys_type.mclass) or else
97 mainmodule.try_get_primitive_method("main", sys_type.mclass)
98 if mainprop != null then
99 interpreter.send(mainprop, [mainobj])
100 end
101 end
102
103 # Subtype test in the context of the mainmodule
104 fun is_subtype(sub, sup: MType): Bool
105 do
106 return sub.is_subtype(self.mainmodule, current_receiver_class, sup)
107 end
108
109 # Get a primitive method in the context of the main module
110 fun force_get_primitive_method(name: String, recv: MType): MMethod
111 do
112 assert recv isa MClassType
113 return self.modelbuilder.force_get_primitive_method(current_node, name, recv.mclass, self.mainmodule)
114 end
115
116 # Is a return, a break or a continue executed?
117 # Set this mark to skip the evaluation until a labeled statement catch it with `is_escape`
118 var escapemark: nullable EscapeMark = null
119
120 # 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.byte_length+1)
323 var val = instance.val
324 val[txt.byte_length] = 0u8
325 txt.to_cstring.copy_to(val, txt.byte_length, 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.byte_length), 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.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 return send(callsite.mproperty, arguments)
582 end
583
584 # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
585 # Return a value if `mproperty` is a function, or null if it is a procedure.
586 # The call is polymorphic. There is a message-sending/late-binding according to the receiver (args[0]).
587 fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
588 do
589 var recv = args.first
590 var mtype = recv.mtype
591 var ret = send_commons(mproperty, args, mtype)
592 if ret != null then return ret
593 var propdef = mproperty.lookup_first_definition(self.mainmodule, mtype)
594 return self.call(propdef, args)
595 end
596
597 # Read the attribute `mproperty` of an instance `recv` and return its value.
598 # If the attribute in not yet initialized, then aborts with an error message.
599 fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
600 do
601 assert recv isa MutableInstance
602 if not recv.attributes.has_key(mproperty) then
603 fatal("Uninitialized attribute {mproperty.name}")
604 abort
605 end
606 return recv.attributes[mproperty]
607 end
608
609 # Replace in `recv` the value of the attribute `mproperty` by `value`
610 fun write_attribute(mproperty: MAttribute, recv: Instance, value: Instance)
611 do
612 assert recv isa MutableInstance
613 recv.attributes[mproperty] = value
614 end
615
616 # Is the attribute `mproperty` initialized the instance `recv`?
617 fun isset_attribute(mproperty: MAttribute, recv: Instance): Bool
618 do
619 assert recv isa MutableInstance
620 return recv.attributes.has_key(mproperty)
621 end
622
623 # Collect attributes of a type in the order of their init
624 fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]
625 do
626 var cache = self.collect_attr_propdef_cache
627 if cache.has_key(mtype) then return cache[mtype]
628
629 var res = new Array[AAttrPropdef]
630 var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
631 self.mainmodule.linearize_mclassdefs(cds)
632 for cd in cds do
633 res.add_all(modelbuilder.collect_attr_propdef(cd))
634 end
635
636 cache[mtype] = res
637 return res
638 end
639
640 private var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
641
642 # Fill the initial values of the newly created instance `recv`.
643 # `recv.mtype` is used to know what must be filled.
644 fun init_instance(recv: Instance)
645 do
646 for npropdef in collect_attr_propdef(recv.mtype) do
647 npropdef.init_expr(self, recv)
648 end
649 end
650
651 # A hook to initialize a `PrimitiveInstance`
652 fun init_instance_primitive(recv: Instance) do end
653
654 # This function determines the correct type according to the receiver of the current propdef (self).
655 fun unanchor_type(mtype: MType): MType
656 do
657 return mtype.anchor_to(self.mainmodule, current_receiver_class)
658 end
659
660 # Placebo instance used to mark internal error result when `null` already have a meaning.
661 # TODO: replace with multiple return or something better
662 var error_instance = new MutableInstance(modelbuilder.model.null_type) is lazy
663 end
664
665 # An instance represents a value of the executed program.
666 abstract class Instance
667 # The dynamic type of the instance
668 # ASSERT: not self.mtype.is_anchored
669 var mtype: MType
670
671 # return true if the instance is the true value.
672 # return false if the instance is the true value.
673 # else aborts
674 fun is_true: Bool do abort
675
676 # Return true if `self` IS `o` (using the Nit semantic of is)
677 fun eq_is(o: Instance): Bool do return self.is_same_instance(o)
678
679 # Human readable object identity "Type#number"
680 redef fun to_s do return "{mtype}"
681
682 # Return the integer value if the instance is an integer.
683 # else aborts
684 fun to_i: Int do abort
685
686 # Return the integer value if the instance is a float.
687 # else aborts
688 fun to_f: Float do abort
689
690 # Return the integer value if the instance is a byte.
691 # else aborts
692 fun to_b: Byte do abort
693
694 # Return the integer value if the instance is a int8.
695 # else aborts
696 fun to_i8: Int8 do abort
697
698 # Return the integer value if the instance is a int16.
699 # else aborts
700 fun to_i16: Int16 do abort
701
702 # Return the integer value if the instance is a uint16.
703 # else aborts
704 fun to_u16: UInt16 do abort
705
706 # Return the integer value if the instance is a int32.
707 # else aborts
708 fun to_i32: Int32 do abort
709
710 # Return the integer value if the instance is a uint32.
711 # else aborts
712 fun to_u32: UInt32 do abort
713
714 # The real value encapsulated if the instance is primitive.
715 # Else aborts.
716 fun val: nullable Object do abort
717 end
718
719 # A instance with attribute (standards objects)
720 class MutableInstance
721 super Instance
722
723 # The values of the attributes
724 var attributes: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
725 end
726
727 # Special instance to handle primitives values (int, bool, etc.)
728 # The trick it just to encapsulate the <<real>> value
729 class PrimitiveInstance[E]
730 super Instance
731
732 # The real value encapsulated
733 redef var val: E
734
735 redef fun is_true
736 do
737 if val == true then return true
738 if val == false then return false
739 abort
740 end
741
742 redef fun ==(o)
743 do
744 if not o isa PrimitiveInstance[nullable Object] then return false
745 return self.val == o.val
746 end
747
748 redef fun eq_is(o)
749 do
750 if not o isa PrimitiveInstance[nullable Object] then return false
751 return self.val.is_same_instance(o.val)
752 end
753
754 redef fun to_s do return "{mtype}#{val.object_id}({val or else "null"})"
755
756 redef fun to_i do return val.as(Int)
757
758 redef fun to_f do return val.as(Float)
759
760 redef fun to_b do return val.as(Byte)
761
762 redef fun to_i8 do return val.as(Int8)
763
764 redef fun to_i16 do return val.as(Int16)
765
766 redef fun to_u16 do return val.as(UInt16)
767
768 redef fun to_i32 do return val.as(Int32)
769
770 redef fun to_u32 do return val.as(UInt32)
771 end
772
773 # Information about local variables in a running method
774 abstract class Frame
775 # The current visited node
776 # The node is stored by frame to keep a stack trace
777 var current_node: ANode
778 # The executed property.
779 # A Method in case of a call, an attribute in case of a default initialization.
780 var mpropdef: MPropDef
781 # Arguments of the method (the first is the receiver)
782 var arguments: Array[Instance]
783 # Indicate if the expression has an array comprehension form
784 var comprehension: nullable Array[Instance] = null
785 end
786
787 # Implementation of a Frame with a Hashmap to store local variables
788 class InterpreterFrame
789 super Frame
790
791 # Mapping between a variable and the current value
792 private var map: Map[Variable, Instance] = new HashMap[Variable, Instance]
793 end
794
795 redef class ANode
796 # Aborts the program with a message
797 # `v` is used to know if a colored message is displayed or not
798 fun fatal(v: NaiveInterpreter, message: String)
799 do
800 if v.modelbuilder.toolcontext.opt_no_color.value == true then
801 sys.stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
802 else
803 sys.stderr.write("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
804 sys.stderr.write(v.stack_trace)
805 sys.stderr.write("\n")
806 end
807 exit(1)
808 end
809 end
810
811 redef class APropdef
812 # Execute a `mpropdef` associated with the current node.
813 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
814 do
815 fatal(v, "NOT YET IMPLEMENTED method kind {class_name}. {mpropdef}")
816 abort
817 end
818 end
819
820 redef class AMethPropdef
821 super TablesCapable
822
823 redef fun call(v, mpropdef, args)
824 do
825 var f = v.new_frame(self, mpropdef, args)
826 var res = call_commons(v, mpropdef, args, f)
827 v.frames.shift
828 if v.is_escape(self.return_mark) then
829 res = v.escapevalue
830 return res
831 end
832 return res
833 end
834
835 private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
836 do
837 v.frames.unshift(f)
838
839 for i in [0..mpropdef.msignature.arity[ do
840 var variable = self.n_signature.n_params[i].variable
841 assert variable != null
842 v.write_variable(variable, arguments[i+1])
843 end
844
845 # Call the implicit super-init
846 var auto_super_inits = self.auto_super_inits
847 if auto_super_inits != null then
848 var args = [arguments.first]
849 for auto_super_init in auto_super_inits do
850 args.clear
851 for i in [0..auto_super_init.msignature.arity+1[ do
852 args.add(arguments[i])
853 end
854 assert auto_super_init.mproperty != mpropdef.mproperty
855 v.callsite(auto_super_init, args)
856 end
857 end
858 if auto_super_call then
859 # standard call-next-method
860 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
861 v.call(superpd, arguments)
862 end
863
864 # First, try intern
865 if mpropdef.is_intern or mpropdef.is_extern then
866 var res = intern_call(v, mpropdef, arguments)
867 if res != v.error_instance then return res
868 end
869 # Then, try extern
870 if mpropdef.is_extern then
871 var res = call_extern(v, mpropdef, arguments, f)
872 if res != v.error_instance then return res
873 end
874 # Else try block
875 if n_block != null then
876 v.stmt(self.n_block)
877 return null
878 end
879
880 # Fail if nothing succeed
881 if mpropdef.is_intern then
882 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
883 else if mpropdef.is_extern then
884 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
885 else
886 fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
887 end
888 abort
889 end
890
891 # Call this extern method
892 protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
893 do
894 return v.error_instance
895 end
896
897 # Interprets a intern or a shortcut extern method.
898 # Returns the result for a function, `null` for a procedure, or `error_instance` if the method is unknown.
899 private fun intern_call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
900 do
901 var pname = mpropdef.mproperty.name
902 var cname = mpropdef.mclassdef.mclass.name
903 if pname == "output" then
904 var recv = args.first
905 recv.val.output
906 return null
907 else if pname == "object_id" then
908 var recv = args.first
909 if recv isa PrimitiveInstance[Object] then
910 return v.int_instance(recv.val.object_id)
911 else
912 return v.int_instance(recv.object_id)
913 end
914 else if pname == "output_class_name" then
915 var recv = args.first
916 print recv.mtype
917 return null
918 else if pname == "native_class_name" then
919 var recv = args.first
920 var txt = recv.mtype.to_s
921 return v.native_string_instance(txt)
922 else if pname == "==" then
923 # == is correctly redefined for instances
924 return v.bool_instance(args[0] == args[1])
925 else if pname == "!=" then
926 return v.bool_instance(args[0] != args[1])
927 else if pname == "is_same_type" then
928 return v.bool_instance(args[0].mtype == args[1].mtype)
929 else if pname == "is_same_instance" then
930 return v.bool_instance(args[0].eq_is(args[1]))
931 else if pname == "exit" then
932 exit(args[1].to_i)
933 abort
934 else if pname == "buffer_mode_full" then
935 return v.int_instance(sys.buffer_mode_full)
936 else if pname == "buffer_mode_line" then
937 return v.int_instance(sys.buffer_mode_line)
938 else if pname == "buffer_mode_none" then
939 return v.int_instance(sys.buffer_mode_none)
940 else if pname == "sys" then
941 return v.mainobj
942 else if cname == "Int" then
943 var recvval = args[0].to_i
944 if pname == "unary -" then
945 return v.int_instance(-recvval)
946 else if pname == "unary +" then
947 return args[0]
948 else if pname == "+" then
949 return v.int_instance(recvval + args[1].to_i)
950 else if pname == "-" then
951 return v.int_instance(recvval - args[1].to_i)
952 else if pname == "*" then
953 return v.int_instance(recvval * args[1].to_i)
954 else if pname == "%" then
955 return v.int_instance(recvval % args[1].to_i)
956 else if pname == "/" then
957 return v.int_instance(recvval / args[1].to_i)
958 else if pname == "<" then
959 return v.bool_instance(recvval < args[1].to_i)
960 else if pname == ">" then
961 return v.bool_instance(recvval > args[1].to_i)
962 else if pname == "<=" then
963 return v.bool_instance(recvval <= args[1].to_i)
964 else if pname == ">=" then
965 return v.bool_instance(recvval >= args[1].to_i)
966 else if pname == "<=>" then
967 return v.int_instance(recvval <=> args[1].to_i)
968 else if pname == "&" then
969 return v.int_instance(recvval & args[1].to_i)
970 else if pname == "|" then
971 return v.int_instance(recvval | args[1].to_i)
972 else if pname == "to_f" then
973 return v.float_instance(recvval.to_f)
974 else if pname == "to_b" then
975 return v.byte_instance(recvval.to_b)
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 == "to_i8" then
981 return v.int8_instance(recvval.to_i8)
982 else if pname == "to_i16" then
983 return v.int16_instance(recvval.to_i16)
984 else if pname == "to_u16" then
985 return v.uint16_instance(recvval.to_u16)
986 else if pname == "to_i32" then
987 return v.int32_instance(recvval.to_i32)
988 else if pname == "to_u32" then
989 return v.uint32_instance(recvval.to_u32)
990 end
991 else if cname == "Byte" then
992 var recvval = args[0].to_b
993 if pname == "unary -" then
994 return v.byte_instance(-recvval)
995 else if pname == "unary +" then
996 return args[0]
997 else if pname == "+" then
998 return v.byte_instance(recvval + args[1].to_b)
999 else if pname == "-" then
1000 return v.byte_instance(recvval - args[1].to_b)
1001 else if pname == "*" then
1002 return v.byte_instance(recvval * args[1].to_b)
1003 else if pname == "%" then
1004 return v.byte_instance(recvval % args[1].to_b)
1005 else if pname == "/" then
1006 return v.byte_instance(recvval / args[1].to_b)
1007 else if pname == "<" then
1008 return v.bool_instance(recvval < args[1].to_b)
1009 else if pname == ">" then
1010 return v.bool_instance(recvval > args[1].to_b)
1011 else if pname == "<=" then
1012 return v.bool_instance(recvval <= args[1].to_b)
1013 else if pname == ">=" then
1014 return v.bool_instance(recvval >= args[1].to_b)
1015 else if pname == "<=>" then
1016 return v.int_instance(recvval <=> args[1].to_b)
1017 else if pname == "&" then
1018 return v.byte_instance(recvval & args[1].to_b)
1019 else if pname == "|" then
1020 return v.byte_instance(recvval | args[1].to_b)
1021 else if pname == "to_f" then
1022 return v.float_instance(recvval.to_f)
1023 else if pname == "to_i" then
1024 return v.int_instance(recvval.to_i)
1025 else if pname == "<<" then
1026 return v.byte_instance(recvval << args[1].to_i)
1027 else if pname == ">>" then
1028 return v.byte_instance(recvval >> args[1].to_i)
1029 else if pname == "to_i8" then
1030 return v.int8_instance(recvval.to_i8)
1031 else if pname == "to_i16" then
1032 return v.int16_instance(recvval.to_i16)
1033 else if pname == "to_u16" then
1034 return v.uint16_instance(recvval.to_u16)
1035 else if pname == "to_i32" then
1036 return v.int32_instance(recvval.to_i32)
1037 else if pname == "to_u32" then
1038 return v.uint32_instance(recvval.to_u32)
1039 else if pname == "byte_to_s_len" then
1040 return v.int_instance(recvval.to_s.length)
1041 end
1042 else if cname == "Char" then
1043 var recv = args[0].val.as(Char)
1044 if pname == "successor" then
1045 return v.char_instance(recv.successor(args[1].to_i))
1046 else if pname == "predecessor" then
1047 return v.char_instance(recv.predecessor(args[1].to_i))
1048 else if pname == "<" then
1049 return v.bool_instance(recv < args[1].val.as(Char))
1050 else if pname == ">" then
1051 return v.bool_instance(recv > args[1].val.as(Char))
1052 else if pname == "<=" then
1053 return v.bool_instance(recv <= args[1].val.as(Char))
1054 else if pname == ">=" then
1055 return v.bool_instance(recv >= args[1].val.as(Char))
1056 else if pname == "<=>" then
1057 return v.int_instance(recv <=> args[1].val.as(Char))
1058 end
1059 else if cname == "Float" then
1060 var recv = args[0].to_f
1061 if pname == "unary -" then
1062 return v.float_instance(-recv)
1063 else if pname == "unary +" then
1064 return args[0]
1065 else if pname == "+" then
1066 return v.float_instance(recv + args[1].to_f)
1067 else if pname == "-" then
1068 return v.float_instance(recv - args[1].to_f)
1069 else if pname == "*" then
1070 return v.float_instance(recv * args[1].to_f)
1071 else if pname == "/" then
1072 return v.float_instance(recv / args[1].to_f)
1073 else if pname == "<" then
1074 return v.bool_instance(recv < args[1].to_f)
1075 else if pname == ">" then
1076 return v.bool_instance(recv > args[1].to_f)
1077 else if pname == "<=" then
1078 return v.bool_instance(recv <= args[1].to_f)
1079 else if pname == ">=" then
1080 return v.bool_instance(recv >= args[1].to_f)
1081 else if pname == "to_i" then
1082 return v.int_instance(recv.to_i)
1083 else if pname == "to_b" then
1084 return v.byte_instance(recv.to_b)
1085 else if pname == "to_i8" then
1086 return v.int8_instance(recv.to_i8)
1087 else if pname == "to_i16" then
1088 return v.int16_instance(recv.to_i16)
1089 else if pname == "to_u16" then
1090 return v.uint16_instance(recv.to_u16)
1091 else if pname == "to_i32" then
1092 return v.int32_instance(recv.to_i32)
1093 else if pname == "to_u32" then
1094 return v.uint32_instance(recv.to_u32)
1095 else if pname == "cos" then
1096 return v.float_instance(args[0].to_f.cos)
1097 else if pname == "sin" then
1098 return v.float_instance(args[0].to_f.sin)
1099 else if pname == "tan" then
1100 return v.float_instance(args[0].to_f.tan)
1101 else if pname == "acos" then
1102 return v.float_instance(args[0].to_f.acos)
1103 else if pname == "asin" then
1104 return v.float_instance(args[0].to_f.asin)
1105 else if pname == "atan" then
1106 return v.float_instance(args[0].to_f.atan)
1107 else if pname == "sqrt" then
1108 return v.float_instance(args[0].to_f.sqrt)
1109 else if pname == "exp" then
1110 return v.float_instance(args[0].to_f.exp)
1111 else if pname == "log" then
1112 return v.float_instance(args[0].to_f.log)
1113 else if pname == "pow" then
1114 return v.float_instance(args[0].to_f.pow(args[1].to_f))
1115 else if pname == "abs" then
1116 return v.float_instance(args[0].to_f.abs)
1117 else if pname == "hypot_with" then
1118 return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
1119 else if pname == "is_nan" then
1120 return v.bool_instance(args[0].to_f.is_nan)
1121 else if pname == "is_inf_extern" then
1122 return v.bool_instance(args[0].to_f.is_inf != 0)
1123 else if pname == "round" then
1124 return v.float_instance(args[0].to_f.round)
1125 end
1126 else if cname == "NativeString" then
1127 if pname == "new" then
1128 return v.native_string_instance_len(args[1].to_i)
1129 end
1130 var recvval = args.first.val.as(NativeString)
1131 if pname == "[]" then
1132 var arg1 = args[1].to_i
1133 return v.byte_instance(recvval[arg1])
1134 else if pname == "[]=" then
1135 var arg1 = args[1].to_i
1136 recvval[arg1] = args[2].val.as(Byte)
1137 return null
1138 else if pname == "copy_to" then
1139 # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
1140 var destval = args[1].val.as(NativeString)
1141 var lenval = args[2].to_i
1142 var fromval = args[3].to_i
1143 var toval = args[4].to_i
1144 recvval.copy_to(destval, lenval, fromval, toval)
1145 return null
1146 else if pname == "atoi" then
1147 return v.int_instance(recvval.atoi)
1148 else if pname == "fast_cstring" then
1149 var ns = recvval.fast_cstring(args[1].to_i)
1150 return v.native_string_instance(ns.to_s)
1151 else if pname == "fetch_4_chars" then
1152 return v.int_instance(args[0].val.as(NativeString).fetch_4_chars(args[1].to_i))
1153 else if pname == "fetch_4_hchars" then
1154 return v.int_instance(args[0].val.as(NativeString).fetch_4_hchars(args[1].to_i))
1155 else if pname == "utf8_length" then
1156 return v.int_instance(args[0].val.as(NativeString).utf8_length(args[1].to_i, args[2].to_i))
1157 end
1158 else if cname == "NativeArray" then
1159 if pname == "new" then
1160 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
1161 var instance = new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
1162 v.init_instance_primitive(instance)
1163 return instance
1164 end
1165 var recvval = args.first.val.as(Array[Instance])
1166 if pname == "[]" then
1167 return recvval[args[1].to_i]
1168 else if pname == "[]=" then
1169 recvval[args[1].to_i] = args[2]
1170 return null
1171 else if pname == "length" then
1172 return v.int_instance(recvval.length)
1173 else if pname == "copy_to" then
1174 recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
1175 return null
1176 end
1177 else if cname == "Int8" then
1178 var recvval = args[0].to_i8
1179 if pname == "unary -" then
1180 return v.int8_instance(-recvval)
1181 else if pname == "unary +" then
1182 return args[0]
1183 else if pname == "+" then
1184 return v.int8_instance(recvval + args[1].to_i8)
1185 else if pname == "-" then
1186 return v.int8_instance(recvval - args[1].to_i8)
1187 else if pname == "*" then
1188 return v.int8_instance(recvval * args[1].to_i8)
1189 else if pname == "%" then
1190 return v.int8_instance(recvval % args[1].to_i8)
1191 else if pname == "/" then
1192 return v.int8_instance(recvval / args[1].to_i8)
1193 else if pname == "<" then
1194 return v.bool_instance(recvval < args[1].to_i8)
1195 else if pname == ">" then
1196 return v.bool_instance(recvval > args[1].to_i8)
1197 else if pname == "<=" then
1198 return v.bool_instance(recvval <= args[1].to_i8)
1199 else if pname == ">=" then
1200 return v.bool_instance(recvval >= args[1].to_i8)
1201 else if pname == "<=>" then
1202 return v.int_instance(recvval <=> args[1].to_i8)
1203 else if pname == "to_f" then
1204 return v.float_instance(recvval.to_f)
1205 else if pname == "to_i" then
1206 return v.int_instance(recvval.to_i)
1207 else if pname == "to_b" then
1208 return v.byte_instance(recvval.to_b)
1209 else if pname == "to_i16" then
1210 return v.int16_instance(recvval.to_i16)
1211 else if pname == "to_u16" then
1212 return v.uint16_instance(recvval.to_u16)
1213 else if pname == "to_i32" then
1214 return v.int32_instance(recvval.to_i32)
1215 else if pname == "to_u32" then
1216 return v.uint32_instance(recvval.to_u32)
1217 else if pname == "<<" then
1218 return v.int8_instance(recvval << (args[1].to_i))
1219 else if pname == ">>" then
1220 return v.int8_instance(recvval >> (args[1].to_i))
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.int8_instance(recvval ^ args[1].to_i8)
1227 else if pname == "unary ~" then
1228 return v.int8_instance(~recvval)
1229 end
1230 else if cname == "Int16" then
1231 var recvval = args[0].to_i16
1232 if pname == "unary -" then
1233 return v.int16_instance(-recvval)
1234 else if pname == "unary +" then
1235 return args[0]
1236 else if pname == "+" then
1237 return v.int16_instance(recvval + args[1].to_i16)
1238 else if pname == "-" then
1239 return v.int16_instance(recvval - args[1].to_i16)
1240 else if pname == "*" then
1241 return v.int16_instance(recvval * args[1].to_i16)
1242 else if pname == "%" then
1243 return v.int16_instance(recvval % args[1].to_i16)
1244 else if pname == "/" then
1245 return v.int16_instance(recvval / args[1].to_i16)
1246 else if pname == "<" then
1247 return v.bool_instance(recvval < args[1].to_i16)
1248 else if pname == ">" then
1249 return v.bool_instance(recvval > args[1].to_i16)
1250 else if pname == "<=" then
1251 return v.bool_instance(recvval <= args[1].to_i16)
1252 else if pname == ">=" then
1253 return v.bool_instance(recvval >= args[1].to_i16)
1254 else if pname == "<=>" then
1255 return v.int_instance(recvval <=> args[1].to_i16)
1256 else if pname == "to_f" then
1257 return v.float_instance(recvval.to_f)
1258 else if pname == "to_i" then
1259 return v.int_instance(recvval.to_i)
1260 else if pname == "to_b" then
1261 return v.byte_instance(recvval.to_b)
1262 else if pname == "to_i8" then
1263 return v.int8_instance(recvval.to_i8)
1264 else if pname == "to_u16" then
1265 return v.uint16_instance(recvval.to_u16)
1266 else if pname == "to_i32" then
1267 return v.int32_instance(recvval.to_i32)
1268 else if pname == "to_u32" then
1269 return v.uint32_instance(recvval.to_u32)
1270 else if pname == "<<" then
1271 return v.int16_instance(recvval << (args[1].to_i))
1272 else if pname == ">>" then
1273 return v.int16_instance(recvval >> (args[1].to_i))
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.int16_instance(recvval ^ args[1].to_i16)
1280 else if pname == "unary ~" then
1281 return v.int16_instance(~recvval)
1282 end
1283 else if cname == "UInt16" then
1284 var recvval = args[0].to_u16
1285 if pname == "unary -" then
1286 return v.uint16_instance(-recvval)
1287 else if pname == "unary +" then
1288 return args[0]
1289 else if pname == "+" then
1290 return v.uint16_instance(recvval + args[1].to_u16)
1291 else if pname == "-" then
1292 return v.uint16_instance(recvval - args[1].to_u16)
1293 else if pname == "*" then
1294 return v.uint16_instance(recvval * args[1].to_u16)
1295 else if pname == "%" then
1296 return v.uint16_instance(recvval % args[1].to_u16)
1297 else if pname == "/" then
1298 return v.uint16_instance(recvval / args[1].to_u16)
1299 else if pname == "<" then
1300 return v.bool_instance(recvval < args[1].to_u16)
1301 else if pname == ">" then
1302 return v.bool_instance(recvval > args[1].to_u16)
1303 else if pname == "<=" then
1304 return v.bool_instance(recvval <= args[1].to_u16)
1305 else if pname == ">=" then
1306 return v.bool_instance(recvval >= args[1].to_u16)
1307 else if pname == "<=>" then
1308 return v.int_instance(recvval <=> args[1].to_u16)
1309 else if pname == "to_f" then
1310 return v.float_instance(recvval.to_f)
1311 else if pname == "to_i" then
1312 return v.int_instance(recvval.to_i)
1313 else if pname == "to_b" then
1314 return v.byte_instance(recvval.to_b)
1315 else if pname == "to_i8" then
1316 return v.int8_instance(recvval.to_i8)
1317 else if pname == "to_i16" then
1318 return v.int16_instance(recvval.to_i16)
1319 else if pname == "to_i32" then
1320 return v.int32_instance(recvval.to_i32)
1321 else if pname == "to_u32" then
1322 return v.uint32_instance(recvval.to_u32)
1323 else if pname == "<<" then
1324 return v.uint16_instance(recvval << (args[1].to_i))
1325 else if pname == ">>" then
1326 return v.uint16_instance(recvval >> (args[1].to_i))
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.uint16_instance(recvval ^ args[1].to_u16)
1333 else if pname == "unary ~" then
1334 return v.uint16_instance(~recvval)
1335 end
1336 else if cname == "Int32" then
1337 var recvval = args[0].to_i32
1338 if pname == "unary -" then
1339 return v.int32_instance(-recvval)
1340 else if pname == "unary +" then
1341 return args[0]
1342 else if pname == "+" then
1343 return v.int32_instance(recvval + args[1].to_i32)
1344 else if pname == "-" then
1345 return v.int32_instance(recvval - args[1].to_i32)
1346 else if pname == "*" then
1347 return v.int32_instance(recvval * args[1].to_i32)
1348 else if pname == "%" then
1349 return v.int32_instance(recvval % args[1].to_i32)
1350 else if pname == "/" then
1351 return v.int32_instance(recvval / args[1].to_i32)
1352 else if pname == "<" then
1353 return v.bool_instance(recvval < args[1].to_i32)
1354 else if pname == ">" then
1355 return v.bool_instance(recvval > args[1].to_i32)
1356 else if pname == "<=" then
1357 return v.bool_instance(recvval <= args[1].to_i32)
1358 else if pname == ">=" then
1359 return v.bool_instance(recvval >= args[1].to_i32)
1360 else if pname == "<=>" then
1361 return v.int_instance(recvval <=> args[1].to_i32)
1362 else if pname == "to_f" then
1363 return v.float_instance(recvval.to_f)
1364 else if pname == "to_i" then
1365 return v.int_instance(recvval.to_i)
1366 else if pname == "to_b" then
1367 return v.byte_instance(recvval.to_b)
1368 else if pname == "to_i8" then
1369 return v.int8_instance(recvval.to_i8)
1370 else if pname == "to_i16" then
1371 return v.int16_instance(recvval.to_i16)
1372 else if pname == "to_u16" then
1373 return v.uint16_instance(recvval.to_u16)
1374 else if pname == "to_u32" then
1375 return v.uint32_instance(recvval.to_u32)
1376 else if pname == "<<" then
1377 return v.int32_instance(recvval << (args[1].to_i))
1378 else if pname == ">>" then
1379 return v.int32_instance(recvval >> (args[1].to_i))
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.int32_instance(recvval ^ args[1].to_i32)
1386 else if pname == "unary ~" then
1387 return v.int32_instance(~recvval)
1388 end
1389 else if cname == "UInt32" then
1390 var recvval = args[0].to_u32
1391 if pname == "unary -" then
1392 return v.uint32_instance(-recvval)
1393 else if pname == "unary +" then
1394 return args[0]
1395 else if pname == "+" then
1396 return v.uint32_instance(recvval + args[1].to_u32)
1397 else if pname == "-" then
1398 return v.uint32_instance(recvval - args[1].to_u32)
1399 else if pname == "*" then
1400 return v.uint32_instance(recvval * args[1].to_u32)
1401 else if pname == "%" then
1402 return v.uint32_instance(recvval % args[1].to_u32)
1403 else if pname == "/" then
1404 return v.uint32_instance(recvval / args[1].to_u32)
1405 else if pname == "<" then
1406 return v.bool_instance(recvval < args[1].to_u32)
1407 else if pname == ">" then
1408 return v.bool_instance(recvval > args[1].to_u32)
1409 else if pname == "<=" then
1410 return v.bool_instance(recvval <= args[1].to_u32)
1411 else if pname == ">=" then
1412 return v.bool_instance(recvval >= args[1].to_u32)
1413 else if pname == "<=>" then
1414 return v.int_instance(recvval <=> args[1].to_u32)
1415 else if pname == "to_f" then
1416 return v.float_instance(recvval.to_f)
1417 else if pname == "to_i" then
1418 return v.int_instance(recvval.to_i)
1419 else if pname == "to_b" then
1420 return v.byte_instance(recvval.to_b)
1421 else if pname == "to_i8" then
1422 return v.int8_instance(recvval.to_i8)
1423 else if pname == "to_i16" then
1424 return v.int16_instance(recvval.to_i16)
1425 else if pname == "to_u16" then
1426 return v.uint16_instance(recvval.to_u16)
1427 else if pname == "to_i32" then
1428 return v.int32_instance(recvval.to_i32)
1429 else if pname == "<<" then
1430 return v.uint32_instance(recvval << (args[1].to_i))
1431 else if pname == ">>" then
1432 return v.uint32_instance(recvval >> (args[1].to_i))
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.uint32_instance(recvval ^ args[1].to_u32)
1439 else if pname == "unary ~" then
1440 return v.uint32_instance(~recvval)
1441 end
1442 else if pname == "native_argc" then
1443 return v.int_instance(v.arguments.length)
1444 else if pname == "native_argv" then
1445 var txt = v.arguments[args[1].to_i]
1446 return v.native_string_instance(txt)
1447 else if pname == "native_argc" then
1448 return v.int_instance(v.arguments.length)
1449 else if pname == "native_argv" then
1450 var txt = v.arguments[args[1].to_i]
1451 return v.native_string_instance(txt)
1452 else if pname == "lexer_goto" then
1453 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
1454 else if pname == "lexer_accept" then
1455 return v.int_instance(lexer_accept(args[1].to_i))
1456 else if pname == "parser_goto" then
1457 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
1458 else if pname == "parser_action" then
1459 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
1460 end
1461 return v.error_instance
1462 end
1463 end
1464
1465 redef class AAttrPropdef
1466 redef fun call(v, mpropdef, args)
1467 do
1468 var recv = args.first
1469 assert recv isa MutableInstance
1470 var attr = self.mpropdef.mproperty
1471 if mpropdef == mreadpropdef then
1472 assert args.length == 1
1473 if not is_lazy or v.isset_attribute(attr, recv) then return v.read_attribute(attr, recv)
1474 var f = v.new_frame(self, mpropdef, args)
1475 return evaluate_expr(v, recv, f)
1476 else if mpropdef == mwritepropdef then
1477 assert args.length == 2
1478 var arg = args[1]
1479 if is_optional and arg.mtype isa MNullType then
1480 var f = v.new_frame(self, mpropdef, args)
1481 arg = evaluate_expr(v, recv, f)
1482 end
1483 v.write_attribute(attr, recv, arg)
1484 return null
1485 else
1486 abort
1487 end
1488 end
1489
1490 # Evaluate and set the default value of the attribute in `recv`
1491 private fun init_expr(v: NaiveInterpreter, recv: Instance)
1492 do
1493 if is_lazy or is_optional then return
1494 if has_value then
1495 var f = v.new_frame(self, mreadpropdef.as(not null), [recv])
1496 evaluate_expr(v, recv, f)
1497 return
1498 end
1499 var mpropdef = self.mpropdef
1500 if mpropdef == null then return
1501 var mtype = self.mtype.as(not null)
1502 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1503 if mtype isa MNullableType then
1504 v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
1505 end
1506 end
1507
1508 private fun evaluate_expr(v: NaiveInterpreter, recv: Instance, f: Frame): Instance
1509 do
1510 assert recv isa MutableInstance
1511 v.frames.unshift(f)
1512
1513 var val
1514
1515 var nexpr = self.n_expr
1516 var nblock = self.n_block
1517 if nexpr != null then
1518 val = v.expr(nexpr)
1519 else if nblock != null then
1520 v.stmt(nblock)
1521 assert v.escapemark == return_mark
1522 val = v.escapevalue
1523 v.escapemark = null
1524 else
1525 abort
1526 end
1527 assert val != null
1528
1529 v.frames.shift
1530 assert not v.is_escaping
1531 v.write_attribute(self.mpropdef.mproperty, recv, val)
1532 return val
1533 end
1534 end
1535
1536 redef class AClassdef
1537 # Execute an implicit `mpropdef` associated with the current node.
1538 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance]): nullable Instance
1539 do
1540 if mpropdef.mproperty.is_root_init then
1541 assert arguments.length == 1
1542 if not mpropdef.is_intro then
1543 # standard call-next-method
1544 var superpd = mpropdef.lookup_next_definition(v.mainmodule, arguments.first.mtype)
1545 v.call(superpd, arguments)
1546 end
1547 return null
1548 else if mclassdef.auto_init == mpropdef then
1549 var recv = arguments.first
1550 var initializers = mpropdef.initializers
1551 var no_init = false
1552 if not initializers.is_empty then
1553 var i = 1
1554 for p in initializers do
1555 if p isa MMethod then
1556 var args = [recv]
1557 for x in p.intro.msignature.mparameters do
1558 args.add arguments[i]
1559 i += 1
1560 end
1561 v.send(p, args)
1562 if p.intro.is_calling_init then no_init = true
1563 else if p isa MAttribute then
1564 assert recv isa MutableInstance
1565 v.write_attribute(p, recv, arguments[i])
1566 i += 1
1567 else abort
1568 end
1569 assert i == arguments.length
1570 end
1571 if not no_init then v.send(mclass.the_root_init_mmethod.as(not null), [recv])
1572 return null
1573 else
1574 abort
1575 end
1576 end
1577 end
1578
1579 redef class AExpr
1580 # Evaluate the node as a possible expression.
1581 # Return a possible value
1582 # NOTE: Do not call this method directly, but use `v.expr`
1583 # This method is here to be implemented by subclasses.
1584 protected fun expr(v: NaiveInterpreter): nullable Instance
1585 do
1586 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1587 abort
1588 end
1589
1590 # Evaluate the node as a statement.
1591 # NOTE: Do not call this method directly, but use `v.stmt`
1592 # This method is here to be implemented by subclasses (no need to return something).
1593 protected fun stmt(v: NaiveInterpreter)
1594 do
1595 expr(v)
1596 end
1597
1598 end
1599
1600 redef class ABlockExpr
1601 redef fun expr(v)
1602 do
1603 var last = self.n_expr.last
1604 for e in self.n_expr do
1605 if e == last then break
1606 v.stmt(e)
1607 if v.is_escaping then return null
1608 end
1609 return last.expr(v)
1610 end
1611
1612 redef fun stmt(v)
1613 do
1614 for e in self.n_expr do
1615 v.stmt(e)
1616 if v.is_escaping then return
1617 end
1618 end
1619 end
1620
1621 redef class AVardeclExpr
1622 redef fun expr(v)
1623 do
1624 var ne = self.n_expr
1625 if ne != null then
1626 var i = v.expr(ne)
1627 if i == null then return null
1628 v.write_variable(self.variable.as(not null), i)
1629 return i
1630 end
1631 return null
1632 end
1633 end
1634
1635 redef class AVarExpr
1636 redef fun expr(v)
1637 do
1638 return v.read_variable(self.variable.as(not null))
1639 end
1640 end
1641
1642 redef class AVarAssignExpr
1643 redef fun expr(v)
1644 do
1645 var i = v.expr(self.n_value)
1646 if i == null then return null
1647 v.write_variable(self.variable.as(not null), i)
1648 return i
1649 end
1650 end
1651
1652 redef class AVarReassignExpr
1653 redef fun stmt(v)
1654 do
1655 var variable = self.variable.as(not null)
1656 var vari = v.read_variable(variable)
1657 var value = v.expr(self.n_value)
1658 if value == null then return
1659 var res = v.callsite(reassign_callsite, [vari, value])
1660 assert res != null
1661 v.write_variable(variable, res)
1662 end
1663 end
1664
1665 redef class ASelfExpr
1666 redef fun expr(v)
1667 do
1668 return v.frame.arguments.first
1669 end
1670 end
1671
1672 redef class AImplicitSelfExpr
1673 redef fun expr(v)
1674 do
1675 if not is_sys then return super
1676 return v.mainobj
1677 end
1678 end
1679
1680 redef class AEscapeExpr
1681 redef fun stmt(v)
1682 do
1683 var ne = self.n_expr
1684 if ne != null then
1685 var i = v.expr(ne)
1686 if i == null then return
1687 v.escapevalue = i
1688 end
1689 v.escapemark = self.escapemark
1690 end
1691 end
1692
1693 redef class AAbortExpr
1694 redef fun stmt(v)
1695 do
1696 # Abort as asked if there is no `catch` bloc
1697 if v.catch_count <= 0 then
1698 fatal(v, "Aborted")
1699 exit(1)
1700 else
1701 abort
1702 end
1703 end
1704 end
1705
1706 redef class AIfExpr
1707 redef fun expr(v)
1708 do
1709 var cond = v.expr(self.n_expr)
1710 if cond == null then return null
1711 if cond.is_true then
1712 return v.expr(self.n_then.as(not null))
1713 else
1714 return v.expr(self.n_else.as(not null))
1715 end
1716 end
1717
1718 redef fun stmt(v)
1719 do
1720 var cond = v.expr(self.n_expr)
1721 if cond == null then return
1722 if cond.is_true then
1723 v.stmt(self.n_then)
1724 else
1725 v.stmt(self.n_else)
1726 end
1727 end
1728 end
1729
1730 redef class AIfexprExpr
1731 redef fun expr(v)
1732 do
1733 var cond = v.expr(self.n_expr)
1734 if cond == null then return null
1735 if cond.is_true then
1736 return v.expr(self.n_then)
1737 else
1738 return v.expr(self.n_else)
1739 end
1740 end
1741 end
1742
1743 redef class ADoExpr
1744 redef fun stmt(v)
1745 do
1746 # If this bloc has a catch, handle it with a do ... catch ... end
1747 if self.n_catch != null then
1748 var frame = v.frame
1749 v.catch_count += 1
1750 do
1751 v.stmt(self.n_block)
1752 v.is_escape(self.break_mark) # Clear the break (if any)
1753 v.catch_count -= 1
1754 catch
1755 # Restore the current frame if needed
1756 while v.frame != frame do v.frames.shift
1757 v.catch_count -= 1
1758 v.stmt(self.n_catch)
1759 end
1760 else
1761 v.stmt(self.n_block)
1762 v.is_escape(self.break_mark)
1763 end
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
1852 # Execute the finally without an escape
1853 var old_mark = v.escapemark
1854 v.escapemark = null
1855 v.callsite(method_finish, [expr])
1856 # Restore the escape unless another escape was provided
1857 if v.escapemark == null then v.escapemark = old_mark
1858 end
1859 end
1860
1861 redef class AAssertExpr
1862 redef fun stmt(v)
1863 do
1864 var cond = v.expr(self.n_expr)
1865 if cond == null then return
1866 if not cond.is_true then
1867 v.stmt(self.n_else)
1868 if v.is_escaping then return
1869 var nid = self.n_id
1870 if nid != null then
1871 fatal(v, "Assert '{nid.text}' failed")
1872 else
1873 fatal(v, "Assert failed")
1874 end
1875 exit(1)
1876 end
1877 end
1878 end
1879
1880 redef class AOrExpr
1881 redef fun expr(v)
1882 do
1883 var cond = v.expr(self.n_expr)
1884 if cond == null then return null
1885 if cond.is_true then return cond
1886 return v.expr(self.n_expr2)
1887 end
1888 end
1889
1890 redef class AImpliesExpr
1891 redef fun expr(v)
1892 do
1893 var cond = v.expr(self.n_expr)
1894 if cond == null then return null
1895 if not cond.is_true then return v.true_instance
1896 return v.expr(self.n_expr2)
1897 end
1898 end
1899
1900 redef class AAndExpr
1901 redef fun expr(v)
1902 do
1903 var cond = v.expr(self.n_expr)
1904 if cond == null then return null
1905 if not cond.is_true then return cond
1906 return v.expr(self.n_expr2)
1907 end
1908 end
1909
1910 redef class ANotExpr
1911 redef fun expr(v)
1912 do
1913 var cond = v.expr(self.n_expr)
1914 if cond == null then return null
1915 return v.bool_instance(not cond.is_true)
1916 end
1917 end
1918
1919 redef class AOrElseExpr
1920 redef fun expr(v)
1921 do
1922 var i = v.expr(self.n_expr)
1923 if i == null then return null
1924 if i != v.null_instance then return i
1925 return v.expr(self.n_expr2)
1926 end
1927 end
1928
1929 redef class AIntegerExpr
1930 redef fun expr(v)
1931 do
1932 if value isa Int then return v.int_instance(value.as(Int))
1933 if value isa Byte then return v.byte_instance(value.as(Byte))
1934 if value isa Int8 then return v.int8_instance(value.as(Int8))
1935 if value isa Int16 then return v.int16_instance(value.as(Int16))
1936 if value isa UInt16 then return v.uint16_instance(value.as(UInt16))
1937 if value isa Int32 then return v.int32_instance(value.as(Int32))
1938 if value isa UInt32 then return v.uint32_instance(value.as(UInt32))
1939 return null
1940 end
1941 end
1942
1943 redef class AFloatExpr
1944 redef fun expr(v)
1945 do
1946 return v.float_instance(self.value.as(not null))
1947 end
1948 end
1949
1950 redef class ACharExpr
1951 redef fun expr(v)
1952 do
1953 if is_ascii then return v.byte_instance(self.value.as(not null).ascii)
1954 if is_code_point then return v.int_instance(self.value.as(not null).code_point)
1955 return v.char_instance(self.value.as(not null))
1956 end
1957 end
1958
1959 redef class AArrayExpr
1960 redef fun expr(v)
1961 do
1962 var val = new Array[Instance]
1963 var old_comprehension = v.frame.comprehension
1964 v.frame.comprehension = val
1965 for nexpr in self.n_exprs do
1966 if nexpr isa AForExpr then
1967 v.stmt(nexpr)
1968 else
1969 var i = v.expr(nexpr)
1970 if i == null then return null
1971 val.add(i)
1972 end
1973 end
1974 v.frame.comprehension = old_comprehension
1975 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1976 var elttype = mtype.arguments.first
1977 return v.array_instance(val, elttype)
1978 end
1979 end
1980
1981 redef class AugmentedStringFormExpr
1982 # Factorize the making of a `Regex` object from a literal prefixed string
1983 fun make_re(v: NaiveInterpreter, rs: Instance): nullable Instance do
1984 var tore = to_re
1985 assert tore != null
1986 var res = v.callsite(tore, [rs])
1987 if res == null then
1988 print "Cannot call property `to_re` on {self}"
1989 abort
1990 end
1991 for j in suffix.chars do
1992 if j == 'i' then
1993 var prop = ignore_case
1994 assert prop != null
1995 v.callsite(prop, [res, v.bool_instance(true)])
1996 continue
1997 end
1998 if j == 'm' then
1999 var prop = newline
2000 assert prop != null
2001 v.callsite(prop, [res, v.bool_instance(true)])
2002 continue
2003 end
2004 if j == 'b' then
2005 var prop = extended
2006 assert prop != null
2007 v.callsite(prop, [res, v.bool_instance(false)])
2008 continue
2009 end
2010 # Should not happen, this needs to be updated
2011 # along with the addition of new suffixes
2012 abort
2013 end
2014 return res
2015 end
2016 end
2017
2018 redef class AStringFormExpr
2019 redef fun expr(v) do return v.string_instance(value)
2020 end
2021
2022 redef class AStringExpr
2023 redef fun expr(v) do
2024 var s = v.string_instance(value)
2025 if is_string then return s
2026 if is_bytestring then
2027 var ns = v.native_string_instance_from_ns(bytes.items, bytes.length)
2028 var ln = v.int_instance(bytes.length)
2029 var prop = to_bytes_with_copy
2030 assert prop != null
2031 var res = v.callsite(prop, [ns, ln])
2032 if res == null then
2033 print "Cannot call property `to_bytes` on {self}"
2034 abort
2035 end
2036 s = res
2037 else if is_re then
2038 var res = make_re(v, s)
2039 assert res != null
2040 s = res
2041 else
2042 print "Unimplemented prefix or suffix for {self}"
2043 abort
2044 end
2045 return s
2046 end
2047 end
2048
2049 redef class ASuperstringExpr
2050 redef fun expr(v)
2051 do
2052 var array = new Array[Instance]
2053 for nexpr in n_exprs do
2054 var i = v.expr(nexpr)
2055 if i == null then return null
2056 array.add(i)
2057 end
2058 var i = v.array_instance(array, v.mainmodule.object_type)
2059 var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i])
2060 assert res != null
2061 if is_re then res = make_re(v, res)
2062 return res
2063 end
2064 end
2065
2066 redef class ACrangeExpr
2067 redef fun expr(v)
2068 do
2069 var e1 = v.expr(self.n_expr)
2070 if e1 == null then return null
2071 var e2 = v.expr(self.n_expr2)
2072 if e2 == null then return null
2073 var mtype = v.unanchor_type(self.mtype.as(not null))
2074 var res = new MutableInstance(mtype)
2075 v.init_instance(res)
2076 v.callsite(init_callsite, [res, e1, e2])
2077 return res
2078 end
2079 end
2080
2081 redef class AOrangeExpr
2082 redef fun expr(v)
2083 do
2084 var e1 = v.expr(self.n_expr)
2085 if e1 == null then return null
2086 var e2 = v.expr(self.n_expr2)
2087 if e2 == null then return null
2088 var mtype = v.unanchor_type(self.mtype.as(not null))
2089 var res = new MutableInstance(mtype)
2090 v.init_instance(res)
2091 v.callsite(init_callsite, [res, e1, e2])
2092 return res
2093 end
2094 end
2095
2096 redef class ATrueExpr
2097 redef fun expr(v)
2098 do
2099 return v.bool_instance(true)
2100 end
2101 end
2102
2103 redef class AFalseExpr
2104 redef fun expr(v)
2105 do
2106 return v.bool_instance(false)
2107 end
2108 end
2109
2110 redef class ANullExpr
2111 redef fun expr(v)
2112 do
2113 return v.null_instance
2114 end
2115 end
2116
2117 redef class AIsaExpr
2118 redef fun expr(v)
2119 do
2120 var i = v.expr(self.n_expr)
2121 if i == null then return null
2122 var mtype = v.unanchor_type(self.cast_type.as(not null))
2123 return v.bool_instance(v.is_subtype(i.mtype, mtype))
2124 end
2125 end
2126
2127 redef class AAsCastExpr
2128 redef fun expr(v)
2129 do
2130 var i = v.expr(self.n_expr)
2131 if i == null then return null
2132 var mtype = self.mtype.as(not null)
2133 var amtype = v.unanchor_type(mtype)
2134 if not v.is_subtype(i.mtype, amtype) then
2135 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
2136 end
2137 return i
2138 end
2139 end
2140
2141 redef class AAsNotnullExpr
2142 redef fun expr(v)
2143 do
2144 var i = v.expr(self.n_expr)
2145 if i == null then return null
2146 if i.mtype isa MNullType then
2147 fatal(v, "Cast failed")
2148 end
2149 return i
2150 end
2151 end
2152
2153 redef class AParExpr
2154 redef fun expr(v)
2155 do
2156 return v.expr(self.n_expr)
2157 end
2158 end
2159
2160 redef class AOnceExpr
2161 redef fun expr(v)
2162 do
2163 if v.onces.has_key(self) then
2164 return v.onces[self]
2165 else
2166 var res = v.expr(self.n_expr)
2167 if res == null then return null
2168 v.onces[self] = res
2169 return res
2170 end
2171 end
2172 end
2173
2174 redef class ASendExpr
2175 redef fun expr(v)
2176 do
2177 var recv = v.expr(self.n_expr)
2178 if recv == null then return null
2179 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2180 if args == null then return null
2181
2182 var res = v.callsite(callsite, args)
2183 return res
2184 end
2185 end
2186
2187 redef class ASendReassignFormExpr
2188 redef fun stmt(v)
2189 do
2190 var recv = v.expr(self.n_expr)
2191 if recv == null then return
2192 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
2193 if args == null then return
2194 var value = v.expr(self.n_value)
2195 if value == null then return
2196
2197 var read = v.callsite(callsite, args)
2198 assert read != null
2199
2200 var write = v.callsite(reassign_callsite, [read, value])
2201 assert write != null
2202
2203 args.add(write)
2204
2205 v.callsite(write_callsite, args)
2206 end
2207 end
2208
2209 redef class ASuperExpr
2210 redef fun expr(v)
2211 do
2212 var recv = v.frame.arguments.first
2213
2214 var callsite = self.callsite
2215 if callsite != null then
2216 var args
2217 if self.n_args.n_exprs.is_empty then
2218 # Add automatic arguments for the super init call
2219 args = [recv]
2220 for i in [0..callsite.msignature.arity[ do
2221 args.add(v.frame.arguments[i+1])
2222 end
2223 else
2224 args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2225 if args == null then return null
2226 end
2227
2228 # Super init call
2229 var res = v.callsite(callsite, args)
2230 return res
2231 end
2232
2233 # Standard call-next-method
2234 var mpropdef = self.mpropdef
2235 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
2236
2237 var args
2238 if self.n_args.n_exprs.is_empty then
2239 args = v.frame.arguments
2240 else
2241 args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
2242 if args == null then return null
2243 end
2244
2245 var res = v.call(mpropdef, args)
2246 return res
2247 end
2248 end
2249
2250 redef class ANewExpr
2251 redef fun expr(v)
2252 do
2253 var mtype = v.unanchor_type(self.recvtype.as(not null))
2254 var recv: Instance = new MutableInstance(mtype)
2255 v.init_instance(recv)
2256 var callsite = self.callsite
2257 if callsite == null then return recv
2258
2259 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
2260 if args == null then return null
2261 var res2 = v.callsite(callsite, args)
2262 if res2 != null then
2263 #self.debug("got {res2} from {mproperty}. drop {recv}")
2264 return res2
2265 end
2266 return recv
2267 end
2268 end
2269
2270 redef class AAttrExpr
2271 redef fun expr(v)
2272 do
2273 var recv = v.expr(self.n_expr)
2274 if recv == null then return null
2275 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2276 var mproperty = self.mproperty.as(not null)
2277 return v.read_attribute(mproperty, recv)
2278 end
2279 end
2280
2281 redef class AAttrAssignExpr
2282 redef fun stmt(v)
2283 do
2284 var recv = v.expr(self.n_expr)
2285 if recv == null then return
2286 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2287 var i = v.expr(self.n_value)
2288 if i == null then return
2289 var mproperty = self.mproperty.as(not null)
2290 v.write_attribute(mproperty, recv, i)
2291 end
2292 end
2293
2294 redef class AAttrReassignExpr
2295 redef fun stmt(v)
2296 do
2297 var recv = v.expr(self.n_expr)
2298 if recv == null then return
2299 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2300 var value = v.expr(self.n_value)
2301 if value == null then return
2302 var mproperty = self.mproperty.as(not null)
2303 var attr = v.read_attribute(mproperty, recv)
2304 var res = v.callsite(reassign_callsite, [attr, value])
2305 assert res != null
2306 v.write_attribute(mproperty, recv, res)
2307 end
2308 end
2309
2310 redef class AIssetAttrExpr
2311 redef fun expr(v)
2312 do
2313 var recv = v.expr(self.n_expr)
2314 if recv == null then return null
2315 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
2316 var mproperty = self.mproperty.as(not null)
2317 return v.bool_instance(v.isset_attribute(mproperty, recv))
2318 end
2319 end
2320
2321 redef class AVarargExpr
2322 redef fun expr(v)
2323 do
2324 return v.expr(self.n_expr)
2325 end
2326 end
2327
2328 redef class ANamedargExpr
2329 redef fun expr(v)
2330 do
2331 return v.expr(self.n_expr)
2332 end
2333 end
2334
2335 redef class ADebugTypeExpr
2336 redef fun stmt(v)
2337 do
2338 # do nothing
2339 end
2340 end