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