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