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