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