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