99dd950fcacd35b2bc461333832ea824ca15ca89
[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 mpropdef == mreadpropdef then
986 assert args.length == 1
987 return v.read_attribute(attr, recv)
988 else if mpropdef == mwritepropdef then
989 assert args.length == 2
990 v.write_attribute(attr, recv, args[1])
991 return null
992 else
993 abort
994 end
995 end
996
997 # Evaluate and set the default value of the attribute in `recv`
998 private fun init_expr(v: NaiveInterpreter, recv: Instance)
999 do
1000 assert recv isa MutableInstance
1001 var nexpr = self.n_expr
1002 if nexpr != null then
1003 var f = new Frame(self, self.mpropdef.as(not null), [recv])
1004 v.frames.unshift(f)
1005 var val = v.expr(nexpr)
1006 assert val != null
1007 v.frames.shift
1008 assert not v.is_escaping
1009 v.write_attribute(self.mpropdef.mproperty, recv, val)
1010 return
1011 end
1012 var mtype = self.mpropdef.static_mtype.as(not null)
1013 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1014 if mtype isa MNullableType then
1015 v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
1016 end
1017 end
1018 end
1019
1020 redef class AClassdef
1021 # Execute an implicit `mpropdef` associated with the current node.
1022 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
1023 do
1024 var super_inits = self.super_inits
1025 if super_inits != null then
1026 var args_of_super = args
1027 if args.length > 1 then args_of_super = [args.first]
1028 for su in super_inits do
1029 v.send(su, args_of_super)
1030 end
1031 end
1032 var recv = args.first
1033 assert recv isa MutableInstance
1034 var i = 1
1035 # Collect undefined attributes
1036 for npropdef in self.n_propdefs do
1037 if npropdef isa AAttrPropdef and not npropdef.noinit and npropdef.n_expr == null then
1038 v.write_attribute(npropdef.mpropdef.mproperty, recv, args[i])
1039 i += 1
1040 end
1041 end
1042 return null
1043 end
1044 end
1045
1046 redef class AExpr
1047 # Evaluate the node as a possible expression.
1048 # Return a possible value
1049 # NOTE: Do not call this method directly, but use `v.expr`
1050 # This method is here to be implemented by subclasses.
1051 private fun expr(v: NaiveInterpreter): nullable Instance
1052 do
1053 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1054 abort
1055 end
1056
1057 # Evaluate the node as a statement.
1058 # NOTE: Do not call this method directly, but use `v.stmt`
1059 # This method is here to be implemented by subclasses (no need to return something).
1060 private fun stmt(v: NaiveInterpreter)
1061 do
1062 expr(v)
1063 end
1064
1065 end
1066
1067 redef class ABlockExpr
1068 redef fun expr(v)
1069 do
1070 var last = self.n_expr.last
1071 for e in self.n_expr do
1072 if e == last then break
1073 v.stmt(e)
1074 if v.is_escaping then return null
1075 end
1076 return last.expr(v)
1077 end
1078
1079 redef fun stmt(v)
1080 do
1081 for e in self.n_expr do
1082 v.stmt(e)
1083 if v.is_escaping then return
1084 end
1085 end
1086 end
1087
1088 redef class AVardeclExpr
1089 redef fun stmt(v)
1090 do
1091 var ne = self.n_expr
1092 if ne != null then
1093 var i = v.expr(ne)
1094 if i == null then return
1095 v.frame.map[self.variable.as(not null)] = i
1096 end
1097 end
1098 end
1099
1100 redef class AVarExpr
1101 redef fun expr(v)
1102 do
1103 return v.frame.map[self.variable.as(not null)]
1104 end
1105 end
1106
1107 redef class AVarAssignExpr
1108 redef fun expr(v)
1109 do
1110 var i = v.expr(self.n_value)
1111 if i == null then return null
1112 v.frame.map[self.variable.as(not null)] = i
1113 return i
1114 end
1115 end
1116
1117 redef class AVarReassignExpr
1118 redef fun stmt(v)
1119 do
1120 var vari = v.frame.map[self.variable.as(not null)]
1121 var value = v.expr(self.n_value)
1122 if value == null then return
1123 var res = v.callsite(reassign_callsite, [vari, value])
1124 assert res != null
1125 v.frame.map[self.variable.as(not null)] = res
1126 end
1127 end
1128
1129 redef class ASelfExpr
1130 redef fun expr(v)
1131 do
1132 return v.frame.arguments.first
1133 end
1134 end
1135
1136 redef class AContinueExpr
1137 redef fun stmt(v)
1138 do
1139 var ne = self.n_expr
1140 if ne != null then
1141 var i = v.expr(ne)
1142 if i == null then return
1143 v.escapevalue = i
1144 end
1145 v.continuemark = self.escapemark
1146 end
1147 end
1148
1149 redef class ABreakExpr
1150 redef fun stmt(v)
1151 do
1152 var ne = self.n_expr
1153 if ne != null then
1154 var i = v.expr(ne)
1155 if i == null then return
1156 v.escapevalue = i
1157 end
1158 v.breakmark = self.escapemark
1159 end
1160 end
1161
1162 redef class AReturnExpr
1163 redef fun stmt(v)
1164 do
1165 var ne = self.n_expr
1166 if ne != null then
1167 var i = v.expr(ne)
1168 if i == null then return
1169 v.escapevalue = i
1170 end
1171 v.returnmark = v.frame
1172 end
1173 end
1174
1175 redef class AAbortExpr
1176 redef fun stmt(v)
1177 do
1178 fatal(v, "Aborted")
1179 exit(1)
1180 end
1181 end
1182
1183 redef class AIfExpr
1184 redef fun expr(v)
1185 do
1186 var cond = v.expr(self.n_expr)
1187 if cond == null then return null
1188 if cond.is_true then
1189 return v.expr(self.n_then.as(not null))
1190 else
1191 return v.expr(self.n_else.as(not null))
1192 end
1193 end
1194
1195 redef fun stmt(v)
1196 do
1197 var cond = v.expr(self.n_expr)
1198 if cond == null then return
1199 if cond.is_true then
1200 v.stmt(self.n_then)
1201 else
1202 v.stmt(self.n_else)
1203 end
1204 end
1205 end
1206
1207 redef class AIfexprExpr
1208 redef fun expr(v)
1209 do
1210 var cond = v.expr(self.n_expr)
1211 if cond == null then return null
1212 if cond.is_true then
1213 return v.expr(self.n_then)
1214 else
1215 return v.expr(self.n_else)
1216 end
1217 end
1218 end
1219
1220 redef class ADoExpr
1221 redef fun stmt(v)
1222 do
1223 v.stmt(self.n_block)
1224 v.is_break(self.escapemark) # Clear the break (if any)
1225 end
1226 end
1227
1228 redef class AWhileExpr
1229 redef fun stmt(v)
1230 do
1231 loop
1232 var cond = v.expr(self.n_expr)
1233 if cond == null then return
1234 if not cond.is_true then return
1235 v.stmt(self.n_block)
1236 if v.is_break(self.escapemark) then return
1237 v.is_continue(self.escapemark) # Clear the break
1238 if v.is_escaping then return
1239 end
1240 end
1241 end
1242
1243 redef class ALoopExpr
1244 redef fun stmt(v)
1245 do
1246 loop
1247 v.stmt(self.n_block)
1248 if v.is_break(self.escapemark) then return
1249 v.is_continue(self.escapemark) # Clear the break
1250 if v.is_escaping then return
1251 end
1252 end
1253 end
1254
1255 redef class AForExpr
1256 redef fun stmt(v)
1257 do
1258 var col = v.expr(self.n_expr)
1259 if col == null then return
1260 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1261
1262 #self.debug("col {col}")
1263 var iter = v.callsite(method_iterator, [col]).as(not null)
1264 #self.debug("iter {iter}")
1265 loop
1266 var isok = v.callsite(method_is_ok, [iter]).as(not null)
1267 if not isok.is_true then return
1268 if self.variables.length == 1 then
1269 var item = v.callsite(method_item, [iter]).as(not null)
1270 #self.debug("item {item}")
1271 v.frame.map[self.variables.first] = item
1272 else if self.variables.length == 2 then
1273 var key = v.callsite(method_key, [iter]).as(not null)
1274 v.frame.map[self.variables[0]] = key
1275 var item = v.callsite(method_item, [iter]).as(not null)
1276 v.frame.map[self.variables[1]] = item
1277 else
1278 abort
1279 end
1280 v.stmt(self.n_block)
1281 if v.is_break(self.escapemark) then return
1282 v.is_continue(self.escapemark) # Clear the break
1283 if v.is_escaping then return
1284 v.callsite(method_next, [iter])
1285 end
1286 end
1287 end
1288
1289 redef class AAssertExpr
1290 redef fun stmt(v)
1291 do
1292 var cond = v.expr(self.n_expr)
1293 if cond == null then return
1294 if not cond.is_true then
1295 v.stmt(self.n_else)
1296 if v.is_escaping then return
1297 var nid = self.n_id
1298 if nid != null then
1299 fatal(v, "Assert '{nid.text}' failed")
1300 else
1301 fatal(v, "Assert failed")
1302 end
1303 exit(1)
1304 end
1305 end
1306 end
1307
1308 redef class AOrExpr
1309 redef fun expr(v)
1310 do
1311 var cond = v.expr(self.n_expr)
1312 if cond == null then return null
1313 if cond.is_true then return cond
1314 return v.expr(self.n_expr2)
1315 end
1316 end
1317
1318 redef class AImpliesExpr
1319 redef fun expr(v)
1320 do
1321 var cond = v.expr(self.n_expr)
1322 if cond == null then return null
1323 if not cond.is_true then return v.true_instance
1324 return v.expr(self.n_expr2)
1325 end
1326 end
1327
1328 redef class AAndExpr
1329 redef fun expr(v)
1330 do
1331 var cond = v.expr(self.n_expr)
1332 if cond == null then return null
1333 if not cond.is_true then return cond
1334 return v.expr(self.n_expr2)
1335 end
1336 end
1337
1338 redef class ANotExpr
1339 redef fun expr(v)
1340 do
1341 var cond = v.expr(self.n_expr)
1342 if cond == null then return null
1343 return v.bool_instance(not cond.is_true)
1344 end
1345 end
1346
1347 redef class AOrElseExpr
1348 redef fun expr(v)
1349 do
1350 var i = v.expr(self.n_expr)
1351 if i == null then return null
1352 if i != v.null_instance then return i
1353 return v.expr(self.n_expr2)
1354 end
1355 end
1356
1357 redef class AIntExpr
1358 redef fun expr(v)
1359 do
1360 return v.int_instance(self.value.as(not null))
1361 end
1362 end
1363
1364 redef class AFloatExpr
1365 redef fun expr(v)
1366 do
1367 return v.float_instance(self.value.as(not null))
1368 end
1369 end
1370
1371 redef class ACharExpr
1372 redef fun expr(v)
1373 do
1374 return v.char_instance(self.value.as(not null))
1375 end
1376 end
1377
1378 redef class AArrayExpr
1379 redef fun expr(v)
1380 do
1381 var val = new Array[Instance]
1382 for nexpr in self.n_exprs.n_exprs do
1383 var i = v.expr(nexpr)
1384 if i == null then return null
1385 val.add(i)
1386 end
1387 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1388 var elttype = mtype.arguments.first
1389 return v.array_instance(val, elttype)
1390 end
1391 end
1392
1393 redef class AStringFormExpr
1394 redef fun expr(v)
1395 do
1396 var txt = self.value.as(not null)
1397 var nat = v.native_string_instance(txt)
1398 var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null)
1399 return res
1400 end
1401 end
1402
1403 redef class ASuperstringExpr
1404 redef fun expr(v)
1405 do
1406 var array = new Array[Instance]
1407 for nexpr in n_exprs do
1408 var i = v.expr(nexpr)
1409 if i == null then return null
1410 array.add(i)
1411 end
1412 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1413 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1414 assert res != null
1415 return res
1416 end
1417 end
1418
1419 redef class ACrangeExpr
1420 redef fun expr(v)
1421 do
1422 var e1 = v.expr(self.n_expr)
1423 if e1 == null then return null
1424 var e2 = v.expr(self.n_expr2)
1425 if e2 == null then return null
1426 var mtype = v.unanchor_type(self.mtype.as(not null))
1427 var res = new MutableInstance(mtype)
1428 v.init_instance(res)
1429 v.callsite(init_callsite, [res, e1, e2])
1430 return res
1431 end
1432 end
1433
1434 redef class AOrangeExpr
1435 redef fun expr(v)
1436 do
1437 var e1 = v.expr(self.n_expr)
1438 if e1 == null then return null
1439 var e2 = v.expr(self.n_expr2)
1440 if e2 == null then return null
1441 var mtype = v.unanchor_type(self.mtype.as(not null))
1442 var res = new MutableInstance(mtype)
1443 v.init_instance(res)
1444 v.callsite(init_callsite, [res, e1, e2])
1445 return res
1446 end
1447 end
1448
1449 redef class ATrueExpr
1450 redef fun expr(v)
1451 do
1452 return v.bool_instance(true)
1453 end
1454 end
1455
1456 redef class AFalseExpr
1457 redef fun expr(v)
1458 do
1459 return v.bool_instance(false)
1460 end
1461 end
1462
1463 redef class ANullExpr
1464 redef fun expr(v)
1465 do
1466 return v.null_instance
1467 end
1468 end
1469
1470 redef class AIsaExpr
1471 redef fun expr(v)
1472 do
1473 var i = v.expr(self.n_expr)
1474 if i == null then return null
1475 var mtype = v.unanchor_type(self.cast_type.as(not null))
1476 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1477 end
1478 end
1479
1480 redef class AAsCastExpr
1481 redef fun expr(v)
1482 do
1483 var i = v.expr(self.n_expr)
1484 if i == null then return null
1485 var mtype = self.mtype.as(not null)
1486 var amtype = v.unanchor_type(mtype)
1487 if not v.is_subtype(i.mtype, amtype) then
1488 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1489 end
1490 return i
1491 end
1492 end
1493
1494 redef class AAsNotnullExpr
1495 redef fun expr(v)
1496 do
1497 var i = v.expr(self.n_expr)
1498 if i == null then return null
1499 var mtype = v.unanchor_type(self.mtype.as(not null))
1500 if i.mtype isa MNullType then
1501 fatal(v, "Cast failed")
1502 end
1503 return i
1504 end
1505 end
1506
1507 redef class AParExpr
1508 redef fun expr(v)
1509 do
1510 return v.expr(self.n_expr)
1511 end
1512 end
1513
1514 redef class AOnceExpr
1515 redef fun expr(v)
1516 do
1517 if v.onces.has_key(self) then
1518 return v.onces[self]
1519 else
1520 var res = v.expr(self.n_expr)
1521 if res == null then return null
1522 v.onces[self] = res
1523 return res
1524 end
1525 end
1526 end
1527
1528 redef class ASendExpr
1529 redef fun expr(v)
1530 do
1531 var recv = v.expr(self.n_expr)
1532 if recv == null then return null
1533 var args = [recv]
1534 for a in self.raw_arguments do
1535 var i = v.expr(a)
1536 if i == null then return null
1537 args.add(i)
1538 end
1539
1540 var res = v.callsite(callsite, args)
1541 return res
1542 end
1543 end
1544
1545 redef class ASendReassignFormExpr
1546 redef fun stmt(v)
1547 do
1548 var recv = v.expr(self.n_expr)
1549 if recv == null then return
1550 var args = [recv]
1551 for a in self.raw_arguments do
1552 var i = v.expr(a)
1553 if i == null then return
1554 args.add(i)
1555 end
1556 var value = v.expr(self.n_value)
1557 if value == null then return
1558
1559 var read = v.callsite(callsite, args)
1560 assert read != null
1561
1562 var write = v.callsite(reassign_callsite, [read, value])
1563 assert write != null
1564
1565 args.add(write)
1566
1567 v.callsite(write_callsite, args)
1568 end
1569 end
1570
1571 redef class ASuperExpr
1572 redef fun expr(v)
1573 do
1574 var recv = v.frame.arguments.first
1575 var args = [recv]
1576 for a in self.n_args.n_exprs do
1577 var i = v.expr(a)
1578 if i == null then return null
1579 args.add(i)
1580 end
1581
1582 var callsite = self.callsite
1583 if callsite != null then
1584 # Add additionnals arguments for the super init call
1585 if args.length == 1 then
1586 for i in [0..callsite.msignature.arity[ do
1587 args.add(v.frame.arguments[i+1])
1588 end
1589 end
1590 # Super init call
1591 var res = v.callsite(callsite, args)
1592 return res
1593 end
1594
1595 if args.length == 1 then
1596 args = v.frame.arguments
1597 end
1598
1599 # stantard call-next-method
1600 var mpropdef = self.mpropdef
1601 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1602 var res = v.call_without_varargs(mpropdef, args)
1603 return res
1604 end
1605 end
1606
1607 redef class ANewExpr
1608 redef fun expr(v)
1609 do
1610 var mtype = v.unanchor_type(self.mtype.as(not null))
1611 var recv: Instance = new MutableInstance(mtype)
1612 v.init_instance(recv)
1613 var args = [recv]
1614 for a in self.n_args.n_exprs do
1615 var i = v.expr(a)
1616 if i == null then return null
1617 args.add(i)
1618 end
1619 var res2 = v.callsite(callsite, args)
1620 if res2 != null then
1621 #self.debug("got {res2} from {mproperty}. drop {recv}")
1622 return res2
1623 end
1624 return recv
1625 end
1626 end
1627
1628 redef class AAttrExpr
1629 redef fun expr(v)
1630 do
1631 var recv = v.expr(self.n_expr)
1632 if recv == null then return null
1633 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1634 var mproperty = self.mproperty.as(not null)
1635 return v.read_attribute(mproperty, recv)
1636 end
1637 end
1638
1639 redef class AAttrAssignExpr
1640 redef fun stmt(v)
1641 do
1642 var recv = v.expr(self.n_expr)
1643 if recv == null then return
1644 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1645 var i = v.expr(self.n_value)
1646 if i == null then return
1647 var mproperty = self.mproperty.as(not null)
1648 v.write_attribute(mproperty, recv, i)
1649 end
1650 end
1651
1652 redef class AAttrReassignExpr
1653 redef fun stmt(v)
1654 do
1655 var recv = v.expr(self.n_expr)
1656 if recv == null then return
1657 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1658 var value = v.expr(self.n_value)
1659 if value == null then return
1660 var mproperty = self.mproperty.as(not null)
1661 var attr = v.read_attribute(mproperty, recv)
1662 var res = v.callsite(reassign_callsite, [attr, value])
1663 assert res != null
1664 v.write_attribute(mproperty, recv, res)
1665 end
1666 end
1667
1668 redef class AIssetAttrExpr
1669 redef fun expr(v)
1670 do
1671 var recv = v.expr(self.n_expr)
1672 if recv == null then return null
1673 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1674 var mproperty = self.mproperty.as(not null)
1675 assert recv isa MutableInstance
1676 return v.bool_instance(recv.attributes.has_key(mproperty))
1677 end
1678 end
1679
1680 redef class ADebugTypeExpr
1681 redef fun stmt(v)
1682 do
1683 # do nothing
1684 end
1685 end