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