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