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