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