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