Merge: CallSite on AFor and ARange
[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 # Collect attributes of a type in the order of their init
438 fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]
439 do
440 var cache = self.collect_attr_propdef_cache
441 if cache.has_key(mtype) then return cache[mtype]
442
443 var res = new Array[AAttrPropdef]
444 var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
445 self.mainmodule.linearize_mclassdefs(cds)
446 for cd in cds do
447 var n = self.modelbuilder.mclassdef2nclassdef[cd]
448 for npropdef in n.n_propdefs do
449 if npropdef isa AAttrPropdef then
450 res.add(npropdef)
451 end
452 end
453 end
454
455 cache[mtype] = res
456 return res
457 end
458
459 var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
460
461 # Fill the initial values of the newly created instance `recv`.
462 # `recv.mtype` is used to know what must be filled.
463 fun init_instance(recv: Instance)
464 do
465 for npropdef in collect_attr_propdef(recv.mtype) do
466 npropdef.init_expr(self, recv)
467 end
468 end
469
470 # This function determine the correct type according the reciever of the current definition (self).
471 fun unanchor_type(mtype: MType): MType
472 do
473 return mtype.anchor_to(self.mainmodule, self.frame.arguments.first.mtype.as(MClassType))
474 end
475 end
476
477 # An instance represents a value of the executed program.
478 abstract class Instance
479 # The dynamic type of the instance
480 # ASSERT: not self.mtype.is_anchored
481 var mtype: MType
482
483 # return true if the instance is the true value.
484 # return false if the instance is the true value.
485 # else aborts
486 fun is_true: Bool do abort
487
488 # Return true if `self` IS `o` (using the Nit semantic of is)
489 fun eq_is(o: Instance): Bool do return self.is_same_instance(o)
490
491 # Human readable object identity "Type#number"
492 redef fun to_s do return "{mtype}"
493
494 # Return the integer value if the instance is an integer.
495 # else aborts
496 fun to_i: Int do abort
497
498 # Return the integer value if the instance is a float.
499 # else aborts
500 fun to_f: Float do abort
501
502 # The real value encapsulated if the instance is primitive.
503 # Else aborts.
504 fun val: Object do abort
505 end
506
507 # A instance with attribute (standards objects)
508 class MutableInstance
509 super Instance
510
511 # The values of the attributes
512 var attributes: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
513 end
514
515 # Special instance to handle primitives values (int, bool, etc.)
516 # The trick it just to encapsulate the <<real>> value
517 class PrimitiveInstance[E: Object]
518 super Instance
519
520 # The real value encapsulated
521 redef var val: E
522
523 init(mtype: MType, val: E)
524 do
525 super(mtype)
526 self.val = val
527 end
528
529 redef fun is_true
530 do
531 if val == true then return true
532 if val == false then return false
533 abort
534 end
535
536 redef fun ==(o)
537 do
538 if not o isa PrimitiveInstance[Object] then return false
539 return self.val == o.val
540 end
541
542 redef fun eq_is(o)
543 do
544 if not o isa PrimitiveInstance[Object] then return false
545 return self.val.is_same_instance(o.val)
546 end
547
548 redef fun to_s do return "{mtype}#{val.object_id}({val})"
549
550 redef fun to_i do return val.as(Int)
551
552 redef fun to_f do return val.as(Float)
553 end
554
555 # Information about local variables in a running method
556 private class Frame
557 # The current visited node
558 # The node is stored by frame to keep a stack trace
559 var current_node: ANode
560 # The executed property.
561 # A Method in case of a call, an attribute in case of a default initialization.
562 var mpropdef: MPropDef
563 # Arguments of the method (the first is te receiver
564 var arguments: Array[Instance]
565 # Mapping betwen a variable an the current value
566 var map: Map[Variable, Instance] = new HashMap[Variable, Instance]
567 end
568
569 redef class ANode
570 # Aborts the program with a message
571 # `v` is used to know if a colored message is displayed or not
572 private fun fatal(v: NaiveInterpreter, message: String)
573 do
574 if v.modelbuilder.toolcontext.opt_no_color.value == true then
575 stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
576 else
577 stderr.write("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
578 stderr.write(v.stack_trace)
579 stderr.write("\n")
580 end
581 exit(1)
582 end
583 end
584
585 redef class APropdef
586 # Execute a `mpropdef` associated with the current node.
587 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
588 do
589 fatal(v, "NOT YET IMPLEMENTED method kind {class_name}. {mpropdef}")
590 abort
591 end
592 end
593
594 redef class AConcreteMethPropdef
595
596 redef fun call(v, mpropdef, args)
597 do
598 var f = new Frame(self, self.mpropdef.as(not null), args)
599 call_commons(v, mpropdef, args, f)
600 v.frames.shift
601 if v.returnmark == f then
602 v.returnmark = null
603 var res = v.escapevalue
604 v.escapevalue = null
605 return res
606 end
607 return null
608 end
609
610 private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame)
611 do
612 for i in [0..mpropdef.msignature.arity[ do
613 var variable = self.n_signature.n_params[i].variable
614 assert variable != null
615 f.map[variable] = arguments[i+1]
616 end
617
618 v.frames.unshift(f)
619
620 # Call the implicit super-init
621 var auto_super_inits = self.auto_super_inits
622 if auto_super_inits != null then
623 var args = [arguments.first]
624 for auto_super_init in auto_super_inits do
625 args.clear
626 for i in [0..auto_super_init.msignature.arity+1[ do
627 args.add(arguments[i])
628 end
629 v.callsite(auto_super_init, args)
630 end
631 end
632
633 v.stmt(self.n_block)
634 end
635 end
636
637 redef class AInternMethPropdef
638 redef fun call(v, mpropdef, args)
639 do
640 var pname = mpropdef.mproperty.name
641 var cname = mpropdef.mclassdef.mclass.name
642 if pname == "output" then
643 var recv = args.first
644 recv.val.output
645 return null
646 else if pname == "object_id" then
647 var recv = args.first
648 if recv isa PrimitiveInstance[Object] then
649 return v.int_instance(recv.val.object_id)
650 else
651 return v.int_instance(recv.object_id)
652 end
653 else if pname == "output_class_name" then
654 var recv = args.first
655 print recv.mtype
656 return null
657 else if pname == "native_class_name" then
658 var recv = args.first
659 var txt = recv.mtype.to_s
660 return v.native_string_instance(txt)
661 else if pname == "==" then
662 # == is correclt redefined for instances
663 return v.bool_instance(args[0] == args[1])
664 else if pname == "!=" then
665 return v.bool_instance(args[0] != args[1])
666 else if pname == "is_same_type" then
667 return v.bool_instance(args[0].mtype == args[1].mtype)
668 else if pname == "is_same_instance" then
669 return v.bool_instance(args[1] != null and args[0].eq_is(args[1]))
670 else if pname == "exit" then
671 exit(args[1].to_i)
672 abort
673 else if pname == "sys" then
674 return v.mainobj
675 else if cname == "Int" then
676 if pname == "unary -" then
677 return v.int_instance(-args[0].to_i)
678 else if pname == "succ" then
679 return v.int_instance(args[0].to_i + 1)
680 else if pname == "prec" then
681 return v.int_instance(args[0].to_i - 1)
682 else if pname == "+" then
683 return v.int_instance(args[0].to_i + args[1].to_i)
684 else if pname == "-" then
685 return v.int_instance(args[0].to_i - args[1].to_i)
686 else if pname == "*" then
687 return v.int_instance(args[0].to_i * args[1].to_i)
688 else if pname == "%" then
689 return v.int_instance(args[0].to_i % args[1].to_i)
690 else if pname == "/" then
691 return v.int_instance(args[0].to_i / args[1].to_i)
692 else if pname == "<" then
693 return v.bool_instance(args[0].to_i < args[1].to_i)
694 else if pname == ">" then
695 return v.bool_instance(args[0].to_i > args[1].to_i)
696 else if pname == "<=" then
697 return v.bool_instance(args[0].to_i <= args[1].to_i)
698 else if pname == ">=" then
699 return v.bool_instance(args[0].to_i >= args[1].to_i)
700 else if pname == "<=>" then
701 return v.int_instance(args[0].to_i <=> args[1].to_i)
702 else if pname == "ascii" then
703 return v.char_instance(args[0].to_i.ascii)
704 else if pname == "to_f" then
705 return v.float_instance(args[0].to_i.to_f)
706 else if pname == "lshift" then
707 return v.int_instance(args[0].to_i.lshift(args[1].to_i))
708 else if pname == "rshift" then
709 return v.int_instance(args[0].to_i.rshift(args[1].to_i))
710 end
711 else if cname == "Char" then
712 var recv = args[0].val.as(Char)
713 if pname == "ascii" then
714 return v.int_instance(recv.ascii)
715 else if pname == "succ" then
716 return v.char_instance(recv.succ)
717 else if pname == "prec" then
718 return v.char_instance(recv.prec)
719 else if pname == "+" then
720 return v.char_instance(recv + args[1].to_i)
721 else if pname == "-" then
722 return v.char_instance(recv - args[1].to_i)
723 else if pname == "<" then
724 return v.bool_instance(recv < args[1].val.as(Char))
725 else if pname == ">" then
726 return v.bool_instance(recv > args[1].val.as(Char))
727 else if pname == "<=" then
728 return v.bool_instance(recv <= args[1].val.as(Char))
729 else if pname == ">=" then
730 return v.bool_instance(recv >= args[1].val.as(Char))
731 else if pname == "<=>" then
732 return v.int_instance(recv <=> args[1].val.as(Char))
733 end
734 else if cname == "Float" then
735 var recv = args[0].to_f
736 if pname == "unary -" then
737 return v.float_instance(-recv)
738 else if pname == "+" then
739 return v.float_instance(recv + args[1].to_f)
740 else if pname == "-" then
741 return v.float_instance(recv - args[1].to_f)
742 else if pname == "*" then
743 return v.float_instance(recv * args[1].to_f)
744 else if pname == "/" then
745 return v.float_instance(recv / args[1].to_f)
746 else if pname == "<" then
747 return v.bool_instance(recv < args[1].to_f)
748 else if pname == ">" then
749 return v.bool_instance(recv > args[1].to_f)
750 else if pname == "<=" then
751 return v.bool_instance(recv <= args[1].to_f)
752 else if pname == ">=" then
753 return v.bool_instance(recv >= args[1].to_f)
754 else if pname == "to_i" then
755 return v.int_instance(recv.to_i)
756 end
757 else if cname == "NativeString" then
758 var recvval = args.first.val.as(Buffer)
759 if pname == "[]" then
760 var arg1 = args[1].to_i
761 if arg1 >= recvval.length or arg1 < 0 then
762 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
763 end
764 return v.char_instance(recvval.chars[arg1])
765 else if pname == "[]=" then
766 var arg1 = args[1].to_i
767 if arg1 >= recvval.length or arg1 < 0 then
768 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
769 end
770 recvval.chars[arg1] = args[2].val.as(Char)
771 return null
772 else if pname == "copy_to" then
773 # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
774 var destval = args[1].val.as(FlatBuffer)
775 var lenval = args[2].to_i
776 var fromval = args[3].to_i
777 var toval = args[4].to_i
778 if fromval < 0 then
779 debug("Illegal access on {recvval} for element {fromval}/{recvval.length}")
780 end
781 if fromval + lenval >= recvval.length then
782 debug("Illegal access on {recvval} for element {fromval}+{lenval}/{recvval.length}")
783 end
784 if toval < 0 then
785 debug("Illegal access on {destval} for element {toval}/{destval.length}")
786 end
787 if toval + lenval >= destval.length then
788 debug("Illegal access on {destval} for element {toval}+{lenval}/{destval.length}")
789 end
790 recvval.as(FlatBuffer).copy(fromval, lenval, destval, toval)
791 return null
792 else if pname == "atoi" then
793 return v.int_instance(recvval.to_i)
794 end
795 else if pname == "calloc_string" then
796 return v.native_string_instance("!" * args[1].to_i)
797 else if cname == "NativeArray" then
798 var recvval = args.first.val.as(Array[Instance])
799 if pname == "[]" then
800 if args[1].to_i >= recvval.length or args[1].to_i < 0 then
801 debug("Illegal access on {recvval} for element {args[1].to_i}/{recvval.length}")
802 end
803 return recvval[args[1].to_i]
804 else if pname == "[]=" then
805 recvval[args[1].to_i] = args[2]
806 return null
807 else if pname == "copy_to" then
808 recvval.copy(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
809 return null
810 end
811 else if pname == "calloc_array" then
812 var recvtype = args.first.mtype.as(MClassType)
813 var mtype: MType
814 mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.mainmodule.get_primitive_class("ArrayCapable"))
815 mtype = mtype.arguments.first
816 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
817 return new PrimitiveInstance[Array[Instance]](v.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype]), val)
818 else if pname == "native_argc" then
819 return v.int_instance(v.arguments.length)
820 else if pname == "native_argv" then
821 var txt = v.arguments[args[1].to_i]
822 return v.native_string_instance(txt)
823 end
824 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
825 abort
826 end
827 end
828
829 redef class AbstractArray[E]
830 fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
831 do
832 self.copy_to(start, len, dest, new_start)
833 end
834 end
835
836 redef class AExternInitPropdef
837 redef fun call(v, mpropdef, args)
838 do
839 var pname = mpropdef.mproperty.name
840 var cname = mpropdef.mclassdef.mclass.name
841 if pname == "native_stdout" then
842 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stdout)
843 else if pname == "native_stdin" then
844 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, stdin)
845 else if pname == "native_stderr" then
846 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stderr)
847 else if pname == "io_open_read" then
848 var a1 = args[1].val.as(Buffer)
849 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
850 else if pname == "io_open_write" then
851 var a1 = args[1].val.as(Buffer)
852 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
853 end
854 fatal(v, "NOT YET IMPLEMENTED extern init {mpropdef}")
855 abort
856 end
857 end
858
859 redef class AExternMethPropdef
860 super TablesCapable
861 redef fun call(v, mpropdef, args)
862 do
863 var pname = mpropdef.mproperty.name
864 var cname = mpropdef.mclassdef.mclass.name
865 if cname == "Int" then
866 var recvval = args.first.val.as(Int)
867 if pname == "rand" then
868 var res = recvval.rand
869 return v.int_instance(res)
870 else if pname == "native_int_to_s" then
871 return v.native_string_instance(recvval.to_s)
872 end
873 else if cname == "NativeFile" then
874 var recvval = args.first.val
875 if pname == "io_write" then
876 var a1 = args[1].val.as(Buffer)
877 recvval.as(OStream).write(a1.substring(0, args[2].to_i).to_s)
878 return args[2]
879 else if pname == "io_read" then
880 var str = recvval.as(IStream).read(args[2].to_i)
881 var a1 = args[1].val.as(Buffer)
882 new FlatBuffer.from(str).copy(0, str.length, a1.as(FlatBuffer), 0)
883 return v.int_instance(str.length)
884 else if pname == "io_close" then
885 recvval.as(IOS).close
886 return v.int_instance(0)
887 end
888 else if cname == "NativeString" then
889 var recvval = args.first.val.as(Buffer)
890 if pname == "file_exists" then
891 return v.bool_instance(recvval.to_s.file_exists)
892 else if pname == "file_mkdir" then
893 recvval.to_s.mkdir
894 return null
895 else if pname == "file_chdir" then
896 recvval.to_s.chdir
897 return null
898 else if pname == "file_realpath" then
899 return v.native_string_instance(recvval.to_s.realpath)
900 else if pname == "get_environ" then
901 var txt = recvval.to_s.environ
902 return v.native_string_instance(txt)
903 else if pname == "system" then
904 var res = sys.system(recvval.to_s)
905 return v.int_instance(res)
906 else if pname == "atof" then
907 return v.float_instance(recvval.to_f)
908 end
909 else if cname == "Int" then
910 if pname == "rand" then
911 return v.int_instance(args[0].to_i.rand)
912 end
913 else if cname == "Float" then
914 if pname == "cos" then
915 return v.float_instance(args[0].to_f.cos)
916 else if pname == "sin" then
917 return v.float_instance(args[0].to_f.sin)
918 else if pname == "tan" then
919 return v.float_instance(args[0].to_f.tan)
920 else if pname == "acos" then
921 return v.float_instance(args[0].to_f.acos)
922 else if pname == "asin" then
923 return v.float_instance(args[0].to_f.asin)
924 else if pname == "atan" then
925 return v.float_instance(args[0].to_f.atan)
926 else if pname == "sqrt" then
927 return v.float_instance(args[0].to_f.sqrt)
928 else if pname == "exp" then
929 return v.float_instance(args[0].to_f.exp)
930 else if pname == "log" then
931 return v.float_instance(args[0].to_f.log)
932 else if pname == "pow" then
933 return v.float_instance(args[0].to_f.pow(args[1].to_f))
934 else if pname == "rand" then
935 return v.float_instance(args[0].to_f.rand)
936 else if pname == "abs" then
937 return v.float_instance(args[0].to_f.abs)
938 else if pname == "hypot_with" then
939 return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
940 else if pname == "is_nan" then
941 return v.bool_instance(args[0].to_f.is_nan)
942 else if pname == "is_inf_extern" then
943 return v.bool_instance(args[0].to_f.is_inf != 0)
944 end
945 else if pname == "native_argc" then
946 return v.int_instance(v.arguments.length)
947 else if pname == "native_argv" then
948 var txt = v.arguments[args[1].to_i]
949 return v.native_string_instance(txt)
950 else if pname == "get_time" then
951 return v.int_instance(get_time)
952 else if pname == "srand_from" then
953 srand_from(args[1].to_i)
954 return null
955 else if pname == "atan2" then
956 return v.float_instance(atan2(args[1].to_f, args[2].to_f))
957 else if pname == "pi" then
958 return v.float_instance(pi)
959 else if pname == "lexer_goto" then
960 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
961 else if pname == "lexer_accept" then
962 return v.int_instance(lexer_accept(args[1].to_i))
963 else if pname == "parser_goto" then
964 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
965 else if pname == "parser_action" then
966 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
967 else if pname == "file_getcwd" then
968 return v.native_string_instance(getcwd)
969 end
970 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
971 abort
972 end
973 end
974
975 redef class AAttrPropdef
976 redef fun call(v, mpropdef, args)
977 do
978 var recv = args.first
979 assert recv isa MutableInstance
980 var attr = self.mpropdef.mproperty
981 if args.length == 1 then
982 return v.read_attribute(attr, recv)
983 else
984 assert args.length == 2
985 recv.attributes[attr] = args[1]
986 return null
987 end
988 end
989
990 # Evaluate and set the default value of the attribute in `recv`
991 private fun init_expr(v: NaiveInterpreter, recv: Instance)
992 do
993 assert recv isa MutableInstance
994 var nexpr = self.n_expr
995 if nexpr != null then
996 var f = new Frame(self, self.mpropdef.as(not null), [recv])
997 v.frames.unshift(f)
998 var val = v.expr(nexpr)
999 assert val != null
1000 v.frames.shift
1001 assert not v.is_escaping
1002 recv.attributes[self.mpropdef.mproperty] = val
1003 return
1004 end
1005 var mtype = self.mpropdef.static_mtype.as(not null)
1006 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1007 if mtype isa MNullableType then
1008 recv.attributes[self.mpropdef.mproperty] = v.null_instance
1009 end
1010 end
1011 end
1012
1013 redef class ADeferredMethPropdef
1014 redef fun call(v, mpropdef, args)
1015 do
1016 fatal(v, "Abstract method `{mpropdef.mproperty.name}` called on `{args.first.mtype}`")
1017 abort
1018 end
1019 end
1020
1021 redef class AClassdef
1022 # Execute an implicit `mpropdef` associated with the current node.
1023 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
1024 do
1025 var super_inits = self.super_inits
1026 if super_inits != null then
1027 assert args.length == 1
1028 for su in super_inits do
1029 v.send(su, args)
1030 end
1031 return null
1032 end
1033 var recv = args.first
1034 assert recv isa MutableInstance
1035 var i = 1
1036 # Collect undefined attributes
1037 for npropdef in self.n_propdefs do
1038 if npropdef isa AAttrPropdef and npropdef.n_expr == null then
1039 recv.attributes[npropdef.mpropdef.mproperty] = args[i]
1040 i += 1
1041 end
1042 end
1043 return null
1044 end
1045 end
1046
1047 redef class AExpr
1048 # Evaluate the node as a possible expression.
1049 # Return a possible value
1050 # NOTE: Do not call this method directly, but use `v.expr`
1051 # This method is here to be implemented by subclasses.
1052 private fun expr(v: NaiveInterpreter): nullable Instance
1053 do
1054 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1055 abort
1056 end
1057
1058 # Evaluate the node as a statement.
1059 # NOTE: Do not call this method directly, but use `v.stmt`
1060 # This method is here to be implemented by subclasses (no need to return something).
1061 private fun stmt(v: NaiveInterpreter)
1062 do
1063 expr(v)
1064 end
1065
1066 end
1067
1068 redef class ABlockExpr
1069 redef fun expr(v)
1070 do
1071 var last = self.n_expr.last
1072 for e in self.n_expr do
1073 if e == last then break
1074 v.stmt(e)
1075 if v.is_escaping then return null
1076 end
1077 return last.expr(v)
1078 end
1079
1080 redef fun stmt(v)
1081 do
1082 for e in self.n_expr do
1083 v.stmt(e)
1084 if v.is_escaping then return
1085 end
1086 end
1087 end
1088
1089 redef class AVardeclExpr
1090 redef fun stmt(v)
1091 do
1092 var ne = self.n_expr
1093 if ne != null then
1094 var i = v.expr(ne)
1095 if i == null then return
1096 v.frame.map[self.variable.as(not null)] = i
1097 end
1098 end
1099 end
1100
1101 redef class AVarExpr
1102 redef fun expr(v)
1103 do
1104 return v.frame.map[self.variable.as(not null)]
1105 end
1106 end
1107
1108 redef class AVarAssignExpr
1109 redef fun expr(v)
1110 do
1111 var i = v.expr(self.n_value)
1112 if i == null then return null
1113 v.frame.map[self.variable.as(not null)] = i
1114 return i
1115 end
1116 end
1117
1118 redef class AVarReassignExpr
1119 redef fun stmt(v)
1120 do
1121 var vari = v.frame.map[self.variable.as(not null)]
1122 var value = v.expr(self.n_value)
1123 if value == null then return
1124 var res = v.callsite(reassign_callsite, [vari, value])
1125 assert res != null
1126 v.frame.map[self.variable.as(not null)] = res
1127 end
1128 end
1129
1130 redef class ASelfExpr
1131 redef fun expr(v)
1132 do
1133 return v.frame.arguments.first
1134 end
1135 end
1136
1137 redef class AContinueExpr
1138 redef fun stmt(v)
1139 do
1140 var ne = self.n_expr
1141 if ne != null then
1142 var i = v.expr(ne)
1143 if i == null then return
1144 v.escapevalue = i
1145 end
1146 v.continuemark = self.escapemark
1147 end
1148 end
1149
1150 redef class ABreakExpr
1151 redef fun stmt(v)
1152 do
1153 var ne = self.n_expr
1154 if ne != null then
1155 var i = v.expr(ne)
1156 if i == null then return
1157 v.escapevalue = i
1158 end
1159 v.breakmark = self.escapemark
1160 end
1161 end
1162
1163 redef class AReturnExpr
1164 redef fun stmt(v)
1165 do
1166 var ne = self.n_expr
1167 if ne != null then
1168 var i = v.expr(ne)
1169 if i == null then return
1170 v.escapevalue = i
1171 end
1172 v.returnmark = v.frame
1173 end
1174 end
1175
1176 redef class AAbortExpr
1177 redef fun stmt(v)
1178 do
1179 fatal(v, "Aborted")
1180 exit(1)
1181 end
1182 end
1183
1184 redef class AIfExpr
1185 redef fun expr(v)
1186 do
1187 var cond = v.expr(self.n_expr)
1188 if cond == null then return null
1189 if cond.is_true then
1190 return v.expr(self.n_then.as(not null))
1191 else
1192 return v.expr(self.n_else.as(not null))
1193 end
1194 end
1195
1196 redef fun stmt(v)
1197 do
1198 var cond = v.expr(self.n_expr)
1199 if cond == null then return
1200 if cond.is_true then
1201 v.stmt(self.n_then)
1202 else
1203 v.stmt(self.n_else)
1204 end
1205 end
1206 end
1207
1208 redef class AIfexprExpr
1209 redef fun expr(v)
1210 do
1211 var cond = v.expr(self.n_expr)
1212 if cond == null then return null
1213 if cond.is_true then
1214 return v.expr(self.n_then)
1215 else
1216 return v.expr(self.n_else)
1217 end
1218 end
1219 end
1220
1221 redef class ADoExpr
1222 redef fun stmt(v)
1223 do
1224 v.stmt(self.n_block)
1225 v.is_break(self.escapemark) # Clear the break (if any)
1226 end
1227 end
1228
1229 redef class AWhileExpr
1230 redef fun stmt(v)
1231 do
1232 loop
1233 var cond = v.expr(self.n_expr)
1234 if cond == null then return
1235 if not cond.is_true then return
1236 v.stmt(self.n_block)
1237 if v.is_break(self.escapemark) then return
1238 v.is_continue(self.escapemark) # Clear the break
1239 if v.is_escaping then return
1240 end
1241 end
1242 end
1243
1244 redef class ALoopExpr
1245 redef fun stmt(v)
1246 do
1247 loop
1248 v.stmt(self.n_block)
1249 if v.is_break(self.escapemark) then return
1250 v.is_continue(self.escapemark) # Clear the break
1251 if v.is_escaping then return
1252 end
1253 end
1254 end
1255
1256 redef class AForExpr
1257 redef fun stmt(v)
1258 do
1259 var col = v.expr(self.n_expr)
1260 if col == null then return
1261 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1262
1263 #self.debug("col {col}")
1264 var iter = v.callsite(method_iterator, [col]).as(not null)
1265 #self.debug("iter {iter}")
1266 loop
1267 var isok = v.callsite(method_is_ok, [iter]).as(not null)
1268 if not isok.is_true then return
1269 if self.variables.length == 1 then
1270 var item = v.callsite(method_item, [iter]).as(not null)
1271 #self.debug("item {item}")
1272 v.frame.map[self.variables.first] = item
1273 else if self.variables.length == 2 then
1274 var key = v.callsite(method_key, [iter]).as(not null)
1275 v.frame.map[self.variables[0]] = key
1276 var item = v.callsite(method_item, [iter]).as(not null)
1277 v.frame.map[self.variables[1]] = item
1278 else
1279 abort
1280 end
1281 v.stmt(self.n_block)
1282 if v.is_break(self.escapemark) then return
1283 v.is_continue(self.escapemark) # Clear the break
1284 if v.is_escaping then return
1285 v.callsite(method_next, [iter])
1286 end
1287 end
1288 end
1289
1290 redef class AAssertExpr
1291 redef fun stmt(v)
1292 do
1293 var cond = v.expr(self.n_expr)
1294 if cond == null then return
1295 if not cond.is_true then
1296 v.stmt(self.n_else)
1297 if v.is_escaping then return
1298 var nid = self.n_id
1299 if nid != null then
1300 fatal(v, "Assert '{nid.text}' failed")
1301 else
1302 fatal(v, "Assert failed")
1303 end
1304 exit(1)
1305 end
1306 end
1307 end
1308
1309 redef class AOrExpr
1310 redef fun expr(v)
1311 do
1312 var cond = v.expr(self.n_expr)
1313 if cond == null then return null
1314 if cond.is_true then return cond
1315 return v.expr(self.n_expr2)
1316 end
1317 end
1318
1319 redef class AImpliesExpr
1320 redef fun expr(v)
1321 do
1322 var cond = v.expr(self.n_expr)
1323 if cond == null then return null
1324 if not cond.is_true then return v.true_instance
1325 return v.expr(self.n_expr2)
1326 end
1327 end
1328
1329 redef class AAndExpr
1330 redef fun expr(v)
1331 do
1332 var cond = v.expr(self.n_expr)
1333 if cond == null then return null
1334 if not cond.is_true then return cond
1335 return v.expr(self.n_expr2)
1336 end
1337 end
1338
1339 redef class ANotExpr
1340 redef fun expr(v)
1341 do
1342 var cond = v.expr(self.n_expr)
1343 if cond == null then return null
1344 return v.bool_instance(not cond.is_true)
1345 end
1346 end
1347
1348 redef class AOrElseExpr
1349 redef fun expr(v)
1350 do
1351 var i = v.expr(self.n_expr)
1352 if i == null then return null
1353 if i != v.null_instance then return i
1354 return v.expr(self.n_expr2)
1355 end
1356 end
1357
1358 redef class AIntExpr
1359 redef fun expr(v)
1360 do
1361 return v.int_instance(self.value.as(not null))
1362 end
1363 end
1364
1365 redef class AFloatExpr
1366 redef fun expr(v)
1367 do
1368 return v.float_instance(self.value.as(not null))
1369 end
1370 end
1371
1372 redef class ACharExpr
1373 redef fun expr(v)
1374 do
1375 return v.char_instance(self.value.as(not null))
1376 end
1377 end
1378
1379 redef class AArrayExpr
1380 redef fun expr(v)
1381 do
1382 var val = new Array[Instance]
1383 for nexpr in self.n_exprs.n_exprs do
1384 var i = v.expr(nexpr)
1385 if i == null then return null
1386 val.add(i)
1387 end
1388 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1389 var elttype = mtype.arguments.first
1390 return v.array_instance(val, elttype)
1391 end
1392 end
1393
1394 redef class AStringFormExpr
1395 redef fun expr(v)
1396 do
1397 var txt = self.value.as(not null)
1398 var nat = v.native_string_instance(txt)
1399 var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null)
1400 return res
1401 end
1402 end
1403
1404 redef class ASuperstringExpr
1405 redef fun expr(v)
1406 do
1407 var array = new Array[Instance]
1408 for nexpr in n_exprs do
1409 var i = v.expr(nexpr)
1410 if i == null then return null
1411 array.add(i)
1412 end
1413 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1414 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1415 assert res != null
1416 return res
1417 end
1418 end
1419
1420 redef class ACrangeExpr
1421 redef fun expr(v)
1422 do
1423 var e1 = v.expr(self.n_expr)
1424 if e1 == null then return null
1425 var e2 = v.expr(self.n_expr2)
1426 if e2 == null then return null
1427 var mtype = v.unanchor_type(self.mtype.as(not null))
1428 var res = new MutableInstance(mtype)
1429 v.init_instance(res)
1430 v.callsite(init_callsite, [res, e1, e2])
1431 return res
1432 end
1433 end
1434
1435 redef class AOrangeExpr
1436 redef fun expr(v)
1437 do
1438 var e1 = v.expr(self.n_expr)
1439 if e1 == null then return null
1440 var e2 = v.expr(self.n_expr2)
1441 if e2 == null then return null
1442 var mtype = v.unanchor_type(self.mtype.as(not null))
1443 var res = new MutableInstance(mtype)
1444 v.init_instance(res)
1445 v.callsite(init_callsite, [res, e1, e2])
1446 return res
1447 end
1448 end
1449
1450 redef class ATrueExpr
1451 redef fun expr(v)
1452 do
1453 return v.bool_instance(true)
1454 end
1455 end
1456
1457 redef class AFalseExpr
1458 redef fun expr(v)
1459 do
1460 return v.bool_instance(false)
1461 end
1462 end
1463
1464 redef class ANullExpr
1465 redef fun expr(v)
1466 do
1467 return v.null_instance
1468 end
1469 end
1470
1471 redef class AIsaExpr
1472 redef fun expr(v)
1473 do
1474 var i = v.expr(self.n_expr)
1475 if i == null then return null
1476 var mtype = v.unanchor_type(self.cast_type.as(not null))
1477 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1478 end
1479 end
1480
1481 redef class AAsCastExpr
1482 redef fun expr(v)
1483 do
1484 var i = v.expr(self.n_expr)
1485 if i == null then return null
1486 var mtype = self.mtype.as(not null)
1487 var amtype = v.unanchor_type(mtype)
1488 if not v.is_subtype(i.mtype, amtype) then
1489 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1490 end
1491 return i
1492 end
1493 end
1494
1495 redef class AAsNotnullExpr
1496 redef fun expr(v)
1497 do
1498 var i = v.expr(self.n_expr)
1499 if i == null then return null
1500 var mtype = v.unanchor_type(self.mtype.as(not null))
1501 if i.mtype isa MNullType then
1502 fatal(v, "Cast failed")
1503 end
1504 return i
1505 end
1506 end
1507
1508 redef class AParExpr
1509 redef fun expr(v)
1510 do
1511 return v.expr(self.n_expr)
1512 end
1513 end
1514
1515 redef class AOnceExpr
1516 redef fun expr(v)
1517 do
1518 if v.onces.has_key(self) then
1519 return v.onces[self]
1520 else
1521 var res = v.expr(self.n_expr)
1522 if res == null then return null
1523 v.onces[self] = res
1524 return res
1525 end
1526 end
1527 end
1528
1529 redef class ASendExpr
1530 redef fun expr(v)
1531 do
1532 var recv = v.expr(self.n_expr)
1533 if recv == null then return null
1534 var args = [recv]
1535 for a in self.raw_arguments.as(not null) do
1536 var i = v.expr(a)
1537 if i == null then return null
1538 args.add(i)
1539 end
1540
1541 var res = v.callsite(callsite, args)
1542 return res
1543 end
1544 end
1545
1546 redef class ASendReassignFormExpr
1547 redef fun stmt(v)
1548 do
1549 var recv = v.expr(self.n_expr)
1550 if recv == null then return
1551 var args = [recv]
1552 for a in self.raw_arguments.as(not null) do
1553 var i = v.expr(a)
1554 if i == null then return
1555 args.add(i)
1556 end
1557 var value = v.expr(self.n_value)
1558 if value == null then return
1559
1560 var read = v.callsite(callsite, args)
1561 assert read != null
1562
1563 var write = v.callsite(reassign_callsite, [read, value])
1564 assert write != null
1565
1566 args.add(write)
1567
1568 v.callsite(write_callsite, args)
1569 end
1570 end
1571
1572 redef class ASuperExpr
1573 redef fun expr(v)
1574 do
1575 var recv = v.frame.arguments.first
1576 var args = [recv]
1577 for a in self.n_args.n_exprs do
1578 var i = v.expr(a)
1579 if i == null then return null
1580 args.add(i)
1581 end
1582
1583 var callsite = self.callsite
1584 if callsite != null then
1585 # Add additionnals arguments for the super init call
1586 if args.length == 1 then
1587 for i in [0..callsite.mproperty.intro.msignature.arity[ do
1588 args.add(v.frame.arguments[i+1])
1589 end
1590 end
1591 # Super init call
1592 var res = v.callsite(callsite, args)
1593 return res
1594 end
1595
1596 if args.length == 1 then
1597 args = v.frame.arguments
1598 end
1599
1600 # stantard call-next-method
1601 var mpropdef = self.mpropdef
1602 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1603 var res = v.call_without_varargs(mpropdef, args)
1604 return res
1605 end
1606 end
1607
1608 redef class ANewExpr
1609 redef fun expr(v)
1610 do
1611 var mtype = v.unanchor_type(self.mtype.as(not null))
1612 var recv: Instance = new MutableInstance(mtype)
1613 v.init_instance(recv)
1614 var args = [recv]
1615 for a in self.n_args.n_exprs do
1616 var i = v.expr(a)
1617 if i == null then return null
1618 args.add(i)
1619 end
1620 var res2 = v.callsite(callsite, args)
1621 if res2 != null then
1622 #self.debug("got {res2} from {mproperty}. drop {recv}")
1623 return res2
1624 end
1625 return recv
1626 end
1627 end
1628
1629 redef class AAttrExpr
1630 redef fun expr(v)
1631 do
1632 var recv = v.expr(self.n_expr)
1633 if recv == null then return null
1634 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1635 var mproperty = self.mproperty.as(not null)
1636 return v.read_attribute(mproperty, recv)
1637 end
1638 end
1639
1640 redef class AAttrAssignExpr
1641 redef fun stmt(v)
1642 do
1643 var recv = v.expr(self.n_expr)
1644 if recv == null then return
1645 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1646 var i = v.expr(self.n_value)
1647 if i == null then return
1648 var mproperty = self.mproperty.as(not null)
1649 assert recv isa MutableInstance
1650 recv.attributes[mproperty] = i
1651 end
1652 end
1653
1654 redef class AAttrReassignExpr
1655 redef fun stmt(v)
1656 do
1657 var recv = v.expr(self.n_expr)
1658 if recv == null then return
1659 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1660 var value = v.expr(self.n_value)
1661 if value == null then return
1662 var mproperty = self.mproperty.as(not null)
1663 var attr = v.read_attribute(mproperty, recv)
1664 var res = v.callsite(reassign_callsite, [attr, value])
1665 assert res != null
1666 assert recv isa MutableInstance
1667 recv.attributes[mproperty] = res
1668 end
1669 end
1670
1671 redef class AIssetAttrExpr
1672 redef fun expr(v)
1673 do
1674 var recv = v.expr(self.n_expr)
1675 if recv == null then return null
1676 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1677 var mproperty = self.mproperty.as(not null)
1678 assert recv isa MutableInstance
1679 return v.bool_instance(recv.attributes.has_key(mproperty))
1680 end
1681 end
1682
1683 redef class ADebugTypeExpr
1684 redef fun stmt(v)
1685 do
1686 # do nothing
1687 end
1688 end