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