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