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