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