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