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