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