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