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