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