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