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