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