rta: store real types in live_cast_type
[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 if args.length < mpropdef.msignature.arity + 1 or args.length > mpropdef.msignature.arity + 1 then
351 fatal("NOT YET IMPLEMENTED: Invalid arity for {mpropdef}. {args.length} arguments given.")
352 end
353
354 # Look for the AST node that implements the property
355 var mproperty = mpropdef.mproperty
356 if self.modelbuilder.mpropdef2npropdef.has_key(mpropdef) then
357 var npropdef = self.modelbuilder.mpropdef2npropdef[mpropdef]
358 self.parameter_check(npropdef, mpropdef, args)
359 return npropdef.call(self, mpropdef, args)
360 else if mproperty.name == "init" then
361 var nclassdef = self.modelbuilder.mclassdef2nclassdef[mpropdef.mclassdef]
362 self.parameter_check(nclassdef, mpropdef, args)
363 return nclassdef.call(self, mpropdef, args)
364 else
365 fatal("Fatal Error: method {mpropdef} not found in the AST")
366 abort
367 end
368 end
369
370 # Generate type checks in the C code to check covariant parameters
371 fun parameter_check(node: ANode, mpropdef: MMethodDef, args: Array[Instance])
372 do
373 var msignature = mpropdef.msignature
374 for i in [0..msignature.arity[ do
375 # skip test for vararg since the array is instantiated with the correct polymorphic type
376 if msignature.vararg_rank == i then continue
377
378 # skip if the cast is not required
379 var origmtype = mpropdef.mproperty.intro.msignature.mparameters[i].mtype
380 if not origmtype.need_anchor then continue
381
382 # get the parameter type
383 var mtype = msignature.mparameters[i].mtype
384 var anchor = args.first.mtype.as(MClassType)
385 var amtype = mtype.anchor_to(self.mainmodule, anchor)
386 if not args[i+1].mtype.is_subtype(self.mainmodule, anchor, amtype) then
387 node.fatal(self, "Cast failed. Expected `{mtype}`, got `{args[i+1].mtype}`")
388 end
389 end
390 end
391
392 # Common code for runtime injected calls and normal calls
393 fun send_commons(mproperty: MMethod, args: Array[Instance], mtype: MType): nullable Instance
394 do
395 if mtype isa MNullType then
396 if mproperty.name == "==" then
397 return self.bool_instance(args[0] == args[1])
398 else if mproperty.name == "!=" then
399 return self.bool_instance(args[0] != args[1])
400 end
401 #fatal("Reciever is null. {mproperty}. {args.join(" ")} {self.frame.current_node.class_name}")
402 fatal("Reciever is null")
403 end
404 return null
405 end
406
407 # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
408 # Return a falue if `mproperty` is a function, or null if it is a procedure.
409 # The call is polimotphic. There is a message-seding/late-bindng according to te receiver (args[0]).
410 fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
411 do
412 var recv = args.first
413 var mtype = recv.mtype
414 var ret = send_commons(mproperty, args, mtype)
415 if ret != null then return ret
416 var propdef = mproperty.lookup_first_definition(self.mainmodule, mtype)
417 return self.call(propdef, args)
418 end
419
420 # Read the attribute `mproperty` of an instance `recv` and return its value.
421 # If the attribute in not yet initialized, then aborts with an error message.
422 fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
423 do
424 assert recv isa MutableInstance
425 if not recv.attributes.has_key(mproperty) then
426 fatal("Uninitialized attribute {mproperty.name}")
427 abort
428 end
429 return recv.attributes[mproperty]
430 end
431
432 # Collect attributes of a type in the order of their init
433 fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]
434 do
435 var cache = self.collect_attr_propdef_cache
436 if cache.has_key(mtype) then return cache[mtype]
437
438 var res = new Array[AAttrPropdef]
439 var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
440 self.mainmodule.linearize_mclassdefs(cds)
441 for cd in cds do
442 var n = self.modelbuilder.mclassdef2nclassdef[cd]
443 for npropdef in n.n_propdefs do
444 if npropdef isa AAttrPropdef then
445 res.add(npropdef)
446 end
447 end
448 end
449
450 cache[mtype] = res
451 return res
452 end
453
454 var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
455
456 # Fill the initial values of the newly created instance `recv`.
457 # `recv.mtype` is used to know what must be filled.
458 fun init_instance(recv: Instance)
459 do
460 for npropdef in collect_attr_propdef(recv.mtype) do
461 npropdef.init_expr(self, recv)
462 end
463 end
464
465 # This function determine the correct type according the reciever of the current definition (self).
466 fun unanchor_type(mtype: MType): MType
467 do
468 return mtype.anchor_to(self.mainmodule, self.frame.arguments.first.mtype.as(MClassType))
469 end
470 end
471
472 # An instance represents a value of the executed program.
473 abstract class Instance
474 # The dynamic type of the instance
475 # ASSERT: not self.mtype.is_anchored
476 var mtype: MType
477
478 # return true if the instance is the true value.
479 # return false if the instance is the true value.
480 # else aborts
481 fun is_true: Bool do abort
482
483 # Return true if `self` IS `o` (using the Nit semantic of is)
484 fun eq_is(o: Instance): Bool do return self.is_same_instance(o)
485
486 # Human readable object identity "Type#number"
487 redef fun to_s do return "{mtype}"
488
489 # Return the integer value if the instance is an integer.
490 # else aborts
491 fun to_i: Int do abort
492
493 # Return the integer value if the instance is a float.
494 # else aborts
495 fun to_f: Float do abort
496
497 # The real value encapsulated if the instance is primitive.
498 # Else aborts.
499 fun val: Object do abort
500 end
501
502 # A instance with attribute (standards objects)
503 class MutableInstance
504 super Instance
505
506 # The values of the attributes
507 var attributes: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
508 end
509
510 # Special instance to handle primitives values (int, bool, etc.)
511 # The trick it just to encapsulate the <<real>> value
512 class PrimitiveInstance[E: Object]
513 super Instance
514
515 # The real value encapsulated
516 redef var val: E
517
518 init(mtype: MType, val: E)
519 do
520 super(mtype)
521 self.val = val
522 end
523
524 redef fun is_true
525 do
526 if val == true then return true
527 if val == false then return false
528 abort
529 end
530
531 redef fun ==(o)
532 do
533 if not o isa PrimitiveInstance[Object] then return false
534 return self.val == o.val
535 end
536
537 redef fun eq_is(o)
538 do
539 if not o isa PrimitiveInstance[Object] then return false
540 return self.val.is_same_instance(o.val)
541 end
542
543 redef fun to_s do return "{mtype}#{val.object_id}({val})"
544
545 redef fun to_i do return val.as(Int)
546
547 redef fun to_f do return val.as(Float)
548 end
549
550 # Information about local variables in a running method
551 private class Frame
552 # The current visited node
553 # The node is stored by frame to keep a stack trace
554 var current_node: ANode
555 # The executed property.
556 # A Method in case of a call, an attribute in case of a default initialization.
557 var mpropdef: MPropDef
558 # Arguments of the method (the first is te receiver
559 var arguments: Array[Instance]
560 # Mapping betwen a variable an the current value
561 var map: Map[Variable, Instance] = new HashMap[Variable, Instance]
562 end
563
564 redef class ANode
565 # Aborts the program with a message
566 # `v` is used to know if a colored message is displayed or not
567 private fun fatal(v: NaiveInterpreter, message: String)
568 do
569 if v.modelbuilder.toolcontext.opt_no_color.value == true then
570 stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
571 else
572 stderr.write("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
573 stderr.write(v.stack_trace)
574 stderr.write("\n")
575 end
576 exit(1)
577 end
578 end
579
580 redef class APropdef
581 # Execute a `mpropdef` associated with the current node.
582 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
583 do
584 fatal(v, "NOT YET IMPLEMENTED method kind {class_name}. {mpropdef}")
585 abort
586 end
587 end
588
589 redef class AConcreteMethPropdef
590
591 redef fun call(v, mpropdef, args)
592 do
593 var f = new Frame(self, self.mpropdef.as(not null), args)
594 call_commons(v, mpropdef, args, f)
595 v.frames.shift
596 if v.returnmark == f then
597 v.returnmark = null
598 var res = v.escapevalue
599 v.escapevalue = null
600 return res
601 end
602 return null
603 end
604
605 private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance], f: Frame)
606 do
607 for i in [0..mpropdef.msignature.arity[ do
608 var variable = self.n_signature.n_params[i].variable
609 assert variable != null
610 f.map[variable] = args[i+1]
611 end
612
613 v.frames.unshift(f)
614
615 # Call the implicit super-init
616 var auto_super_inits = self.auto_super_inits
617 if auto_super_inits != null then
618 var selfarg = [args.first]
619 for auto_super_init in auto_super_inits do
620 if auto_super_init.intro.msignature.arity == 0 then
621 v.send(auto_super_init, selfarg)
622 else
623 v.send(auto_super_init, args)
624 end
625 end
626 end
627
628 v.stmt(self.n_block)
629 end
630 end
631
632 redef class AInternMethPropdef
633 redef fun call(v, mpropdef, args)
634 do
635 var pname = mpropdef.mproperty.name
636 var cname = mpropdef.mclassdef.mclass.name
637 if pname == "output" then
638 var recv = args.first
639 recv.val.output
640 return null
641 else if pname == "object_id" then
642 var recv = args.first
643 if recv isa PrimitiveInstance[Object] then
644 return v.int_instance(recv.val.object_id)
645 else
646 return v.int_instance(recv.object_id)
647 end
648 else if pname == "output_class_name" then
649 var recv = args.first
650 print recv.mtype
651 return null
652 else if pname == "native_class_name" then
653 var recv = args.first
654 var txt = recv.mtype.to_s
655 return v.native_string_instance(txt)
656 else if pname == "==" then
657 # == is correclt redefined for instances
658 return v.bool_instance(args[0] == args[1])
659 else if pname == "!=" then
660 return v.bool_instance(args[0] != args[1])
661 else if pname == "is_same_type" then
662 return v.bool_instance(args[0].mtype == args[1].mtype)
663 else if pname == "is_same_instance" then
664 return v.bool_instance(args[1] != null and args[0].eq_is(args[1]))
665 else if pname == "exit" then
666 exit(args[1].to_i)
667 abort
668 else if pname == "sys" then
669 return v.mainobj
670 else if cname == "Int" then
671 if pname == "unary -" then
672 return v.int_instance(-args[0].to_i)
673 else if pname == "succ" then
674 return v.int_instance(args[0].to_i + 1)
675 else if pname == "prec" then
676 return v.int_instance(args[0].to_i - 1)
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.int_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.bool_instance(args[0].to_i >= args[1].to_i)
695 else if pname == "<=>" then
696 return v.int_instance(args[0].to_i <=> args[1].to_i)
697 else if pname == "ascii" then
698 return v.char_instance(args[0].to_i.ascii)
699 else if pname == "to_f" then
700 return v.float_instance(args[0].to_i.to_f)
701 else if pname == "lshift" then
702 return v.int_instance(args[0].to_i.lshift(args[1].to_i))
703 else if pname == "rshift" then
704 return v.int_instance(args[0].to_i.rshift(args[1].to_i))
705 end
706 else if cname == "Char" then
707 var recv = args[0].val.as(Char)
708 if pname == "ascii" then
709 return v.int_instance(recv.ascii)
710 else if pname == "succ" then
711 return v.char_instance(recv.succ)
712 else if pname == "prec" then
713 return v.char_instance(recv.prec)
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.bool_instance(recv >= args[1].val.as(Char))
722 else if pname == "<=>" then
723 return v.int_instance(recv <=> args[1].val.as(Char))
724 end
725 else if cname == "Float" then
726 var recv = args[0].to_f
727 if pname == "unary -" then
728 return v.float_instance(-recv)
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.float_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 == ">=" then
744 return v.bool_instance(recv >= args[1].to_f)
745 else if pname == "to_i" then
746 return v.int_instance(recv.to_i)
747 end
748 else if cname == "NativeString" then
749 var recvval = args.first.val.as(Buffer)
750 if pname == "[]" then
751 var arg1 = args[1].to_i
752 if arg1 >= recvval.length or arg1 < 0 then
753 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
754 end
755 return v.char_instance(recvval.chars[arg1])
756 else if pname == "[]=" then
757 var arg1 = args[1].to_i
758 if arg1 >= recvval.length or arg1 < 0 then
759 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
760 end
761 recvval.chars[arg1] = args[2].val.as(Char)
762 return null
763 else if pname == "copy_to" then
764 # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
765 var destval = args[1].val.as(Buffer)
766 var lenval = args[2].to_i
767 var fromval = args[3].to_i
768 var toval = args[4].to_i
769 if fromval < 0 then
770 debug("Illegal access on {recvval} for element {fromval}/{recvval.length}")
771 end
772 if fromval + lenval >= recvval.length then
773 debug("Illegal access on {recvval} for element {fromval}+{lenval}/{recvval.length}")
774 end
775 if toval < 0 then
776 debug("Illegal access on {destval} for element {toval}/{destval.length}")
777 end
778 if toval + lenval >= destval.length then
779 debug("Illegal access on {destval} for element {toval}+{lenval}/{destval.length}")
780 end
781 recvval.copy(fromval, lenval, destval, toval)
782 return null
783 else if pname == "atoi" then
784 return v.int_instance(recvval.to_i)
785 end
786 else if pname == "calloc_string" then
787 return v.native_string_instance("!" * args[1].to_i)
788 else if cname == "NativeArray" then
789 var recvval = args.first.val.as(Array[Instance])
790 if pname == "[]" then
791 if args[1].to_i >= recvval.length or args[1].to_i < 0 then
792 debug("Illegal access on {recvval} for element {args[1].to_i}/{recvval.length}")
793 end
794 return recvval[args[1].to_i]
795 else if pname == "[]=" then
796 recvval[args[1].to_i] = args[2]
797 return null
798 else if pname == "copy_to" then
799 recvval.copy(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
800 return null
801 end
802 else if pname == "calloc_array" then
803 var recvtype = args.first.mtype.as(MClassType)
804 var mtype: MType
805 mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.mainmodule.get_primitive_class("ArrayCapable"))
806 mtype = mtype.arguments.first
807 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
808 return new PrimitiveInstance[Array[Instance]](v.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype]), val)
809 else if pname == "native_argc" then
810 return v.int_instance(v.arguments.length)
811 else if pname == "native_argv" then
812 var txt = v.arguments[args[1].to_i]
813 return v.native_string_instance(txt)
814 end
815 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
816 abort
817 end
818 end
819
820 redef class AbstractArray[E]
821 fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
822 do
823 self.copy_to(start, len, dest, new_start)
824 end
825 end
826
827 redef class AExternInitPropdef
828 redef fun call(v, mpropdef, args)
829 do
830 var pname = mpropdef.mproperty.name
831 var cname = mpropdef.mclassdef.mclass.name
832 if pname == "native_stdout" then
833 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stdout)
834 else if pname == "native_stdin" then
835 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, stdin)
836 else if pname == "native_stderr" then
837 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stderr)
838 else if pname == "io_open_read" then
839 var a1 = args[1].val.as(Buffer)
840 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
841 else if pname == "io_open_write" then
842 var a1 = args[1].val.as(Buffer)
843 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
844 end
845 fatal(v, "NOT YET IMPLEMENTED extern init {mpropdef}")
846 abort
847 end
848 end
849
850 redef class AExternMethPropdef
851 super TablesCapable
852 redef fun call(v, mpropdef, args)
853 do
854 var pname = mpropdef.mproperty.name
855 var cname = mpropdef.mclassdef.mclass.name
856 if cname == "Int" then
857 var recvval = args.first.val.as(Int)
858 if pname == "rand" then
859 var res = recvval.rand
860 return v.int_instance(res)
861 else if pname == "native_int_to_s" then
862 return v.native_string_instance(recvval.to_s)
863 end
864 else if cname == "NativeFile" then
865 var recvval = args.first.val
866 if pname == "io_write" then
867 var a1 = args[1].val.as(Buffer)
868 recvval.as(OStream).write(a1.substring(0, args[2].to_i))
869 return args[2]
870 else if pname == "io_read" then
871 var str = recvval.as(IStream).read(args[2].to_i)
872 var a1 = args[1].val.as(Buffer)
873 new Buffer.from(str).copy(0, str.length, a1, 0)
874 return v.int_instance(str.length)
875 else if pname == "io_close" then
876 recvval.as(IOS).close
877 return v.int_instance(0)
878 end
879 else if cname == "NativeString" then
880 var recvval = args.first.val.as(Buffer)
881 if pname == "file_exists" then
882 return v.bool_instance(recvval.to_s.file_exists)
883 else if pname == "file_mkdir" then
884 recvval.to_s.mkdir
885 return null
886 else if pname == "file_chdir" then
887 recvval.to_s.chdir
888 return null
889 else if pname == "file_realpath" then
890 return v.native_string_instance(recvval.to_s.realpath)
891 else if pname == "get_environ" then
892 var txt = recvval.to_s.environ
893 return v.native_string_instance(txt)
894 else if pname == "system" then
895 var res = sys.system(recvval.to_s)
896 return v.int_instance(res)
897 else if pname == "atof" then
898 return v.float_instance(recvval.to_f)
899 end
900 else if cname == "Int" then
901 if pname == "rand" then
902 return v.int_instance(args[0].to_i.rand)
903 end
904 else if cname == "Float" then
905 if pname == "cos" then
906 return v.float_instance(args[0].to_f.cos)
907 else if pname == "sin" then
908 return v.float_instance(args[0].to_f.sin)
909 else if pname == "tan" then
910 return v.float_instance(args[0].to_f.tan)
911 else if pname == "acos" then
912 return v.float_instance(args[0].to_f.acos)
913 else if pname == "asin" then
914 return v.float_instance(args[0].to_f.asin)
915 else if pname == "atan" then
916 return v.float_instance(args[0].to_f.atan)
917 else if pname == "sqrt" then
918 return v.float_instance(args[0].to_f.sqrt)
919 else if pname == "exp" then
920 return v.float_instance(args[0].to_f.exp)
921 else if pname == "log" then
922 return v.float_instance(args[0].to_f.log)
923 else if pname == "pow" then
924 return v.float_instance(args[0].to_f.pow(args[1].to_f))
925 else if pname == "rand" then
926 return v.float_instance(args[0].to_f.rand)
927 end
928 else if pname == "native_argc" then
929 return v.int_instance(v.arguments.length)
930 else if pname == "native_argv" then
931 var txt = v.arguments[args[1].to_i]
932 return v.native_string_instance(txt)
933 else if pname == "get_time" then
934 return v.int_instance(get_time)
935 else if pname == "srand_from" then
936 srand_from(args[1].to_i)
937 return null
938 else if pname == "atan2" then
939 return v.float_instance(atan2(args[1].to_f, args[2].to_f))
940 else if pname == "pi" then
941 return v.float_instance(pi)
942 else if pname == "lexer_goto" then
943 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
944 else if pname == "lexer_accept" then
945 return v.int_instance(lexer_accept(args[1].to_i))
946 else if pname == "parser_goto" then
947 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
948 else if pname == "parser_action" then
949 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
950 else if pname == "file_getcwd" then
951 return v.native_string_instance(getcwd)
952 end
953 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
954 abort
955 end
956 end
957
958 redef class AAttrPropdef
959 redef fun call(v, mpropdef, args)
960 do
961 var recv = args.first
962 assert recv isa MutableInstance
963 var attr = self.mpropdef.mproperty
964 if args.length == 1 then
965 return v.read_attribute(attr, recv)
966 else
967 assert args.length == 2
968 recv.attributes[attr] = args[1]
969 return null
970 end
971 end
972
973 # Evaluate and set the default value of the attribute in `recv`
974 private fun init_expr(v: NaiveInterpreter, recv: Instance)
975 do
976 assert recv isa MutableInstance
977 var nexpr = self.n_expr
978 if nexpr != null then
979 var f = new Frame(self, self.mpropdef.as(not null), [recv])
980 v.frames.unshift(f)
981 var val = v.expr(nexpr)
982 assert val != null
983 v.frames.shift
984 assert not v.is_escaping
985 recv.attributes[self.mpropdef.mproperty] = val
986 return
987 end
988 var mtype = self.mpropdef.static_mtype.as(not null)
989 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
990 if mtype isa MNullableType then
991 recv.attributes[self.mpropdef.mproperty] = v.null_instance
992 end
993 end
994 end
995
996 redef class ADeferredMethPropdef
997 redef fun call(v, mpropdef, args)
998 do
999 fatal(v, "Abstract method `{mpropdef.mproperty.name}` called on `{args.first.mtype}`")
1000 abort
1001 end
1002 end
1003
1004 redef class AClassdef
1005 # Execute an implicit `mpropdef` associated with the current node.
1006 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
1007 do
1008 var super_inits = self.super_inits
1009 if super_inits != null then
1010 assert args.length == 1
1011 for su in super_inits do
1012 v.send(su, args)
1013 end
1014 return null
1015 end
1016 var recv = args.first
1017 assert recv isa MutableInstance
1018 var i = 1
1019 # Collect undefined attributes
1020 for npropdef in self.n_propdefs do
1021 if npropdef isa AAttrPropdef and npropdef.n_expr == null then
1022 recv.attributes[npropdef.mpropdef.mproperty] = args[i]
1023 i += 1
1024 end
1025 end
1026 return null
1027 end
1028 end
1029
1030 redef class AExpr
1031 # Evaluate the node as a possible expression.
1032 # Return a possible value
1033 # NOTE: Do not call this method directly, but use `v.expr`
1034 # This method is here to be implemented by subclasses.
1035 private fun expr(v: NaiveInterpreter): nullable Instance
1036 do
1037 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1038 abort
1039 end
1040
1041 # Evaluate the node as a statement.
1042 # NOTE: Do not call this method directly, but use `v.stmt`
1043 # This method is here to be implemented by subclasses (no need to return something).
1044 private fun stmt(v: NaiveInterpreter)
1045 do
1046 expr(v)
1047 end
1048
1049 end
1050
1051 redef class ABlockExpr
1052 redef fun expr(v)
1053 do
1054 var last = self.n_expr.last
1055 for e in self.n_expr do
1056 if e == last then break
1057 v.stmt(e)
1058 if v.is_escaping then return null
1059 end
1060 return last.expr(v)
1061 end
1062
1063 redef fun stmt(v)
1064 do
1065 for e in self.n_expr do
1066 v.stmt(e)
1067 if v.is_escaping then return
1068 end
1069 end
1070 end
1071
1072 redef class AVardeclExpr
1073 redef fun stmt(v)
1074 do
1075 var ne = self.n_expr
1076 if ne != null then
1077 var i = v.expr(ne)
1078 if i == null then return
1079 v.frame.map[self.variable.as(not null)] = i
1080 end
1081 end
1082 end
1083
1084 redef class AVarExpr
1085 redef fun expr(v)
1086 do
1087 return v.frame.map[self.variable.as(not null)]
1088 end
1089 end
1090
1091 redef class AVarAssignExpr
1092 redef fun expr(v)
1093 do
1094 var i = v.expr(self.n_value)
1095 if i == null then return null
1096 v.frame.map[self.variable.as(not null)] = i
1097 return i
1098 end
1099 end
1100
1101 redef class AVarReassignExpr
1102 redef fun stmt(v)
1103 do
1104 var vari = v.frame.map[self.variable.as(not null)]
1105 var value = v.expr(self.n_value)
1106 if value == null then return
1107 var res = v.send(reassign_callsite.mproperty, [vari, value])
1108 assert res != null
1109 v.frame.map[self.variable.as(not null)] = res
1110 end
1111 end
1112
1113 redef class ASelfExpr
1114 redef fun expr(v)
1115 do
1116 return v.frame.arguments.first
1117 end
1118 end
1119
1120 redef class AContinueExpr
1121 redef fun stmt(v)
1122 do
1123 var ne = self.n_expr
1124 if ne != null then
1125 var i = v.expr(ne)
1126 if i == null then return
1127 v.escapevalue = i
1128 end
1129 v.continuemark = self.escapemark
1130 end
1131 end
1132
1133 redef class ABreakExpr
1134 redef fun stmt(v)
1135 do
1136 var ne = self.n_expr
1137 if ne != null then
1138 var i = v.expr(ne)
1139 if i == null then return
1140 v.escapevalue = i
1141 end
1142 v.breakmark = self.escapemark
1143 end
1144 end
1145
1146 redef class AReturnExpr
1147 redef fun stmt(v)
1148 do
1149 var ne = self.n_expr
1150 if ne != null then
1151 var i = v.expr(ne)
1152 if i == null then return
1153 v.escapevalue = i
1154 end
1155 v.returnmark = v.frame
1156 end
1157 end
1158
1159 redef class AAbortExpr
1160 redef fun stmt(v)
1161 do
1162 fatal(v, "Aborted")
1163 exit(1)
1164 end
1165 end
1166
1167 redef class AIfExpr
1168 redef fun expr(v)
1169 do
1170 var cond = v.expr(self.n_expr)
1171 if cond == null then return null
1172 if cond.is_true then
1173 return v.expr(self.n_then.as(not null))
1174 else
1175 return v.expr(self.n_else.as(not null))
1176 end
1177 end
1178
1179 redef fun stmt(v)
1180 do
1181 var cond = v.expr(self.n_expr)
1182 if cond == null then return
1183 if cond.is_true then
1184 v.stmt(self.n_then)
1185 else
1186 v.stmt(self.n_else)
1187 end
1188 end
1189 end
1190
1191 redef class AIfexprExpr
1192 redef fun expr(v)
1193 do
1194 var cond = v.expr(self.n_expr)
1195 if cond == null then return null
1196 if cond.is_true then
1197 return v.expr(self.n_then)
1198 else
1199 return v.expr(self.n_else)
1200 end
1201 end
1202 end
1203
1204 redef class ADoExpr
1205 redef fun stmt(v)
1206 do
1207 v.stmt(self.n_block)
1208 v.is_break(self.escapemark) # Clear the break (if any)
1209 end
1210 end
1211
1212 redef class AWhileExpr
1213 redef fun stmt(v)
1214 do
1215 loop
1216 var cond = v.expr(self.n_expr)
1217 if cond == null then return
1218 if not cond.is_true then return
1219 v.stmt(self.n_block)
1220 if v.is_break(self.escapemark) then return
1221 v.is_continue(self.escapemark) # Clear the break
1222 if v.is_escaping then return
1223 end
1224 end
1225 end
1226
1227 redef class ALoopExpr
1228 redef fun stmt(v)
1229 do
1230 loop
1231 v.stmt(self.n_block)
1232 if v.is_break(self.escapemark) then return
1233 v.is_continue(self.escapemark) # Clear the break
1234 if v.is_escaping then return
1235 end
1236 end
1237 end
1238
1239 redef class AForExpr
1240 redef fun stmt(v)
1241 do
1242 var col = v.expr(self.n_expr)
1243 if col == null then return
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 if args.length == 1 then
1564 args = v.frame.arguments
1565 end
1566
1567 var callsite = self.callsite
1568 if callsite != null then
1569 if callsite.mproperty.intro.msignature.arity == 0 then
1570 args = [recv]
1571 end
1572 # Super init call
1573 var res = v.send(callsite.mproperty, args)
1574 return res
1575 end
1576
1577 # stantard call-next-method
1578 var mpropdef = v.frame.mpropdef
1579 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1580 assert mpropdef isa MMethodDef
1581 var res = v.call_without_varargs(mpropdef, args)
1582 return res
1583 end
1584 end
1585
1586 redef class ANewExpr
1587 redef fun expr(v)
1588 do
1589 var mtype = v.unanchor_type(self.mtype.as(not null))
1590 var recv: Instance = new MutableInstance(mtype)
1591 v.init_instance(recv)
1592 var args = [recv]
1593 for a in self.n_args.n_exprs do
1594 var i = v.expr(a)
1595 if i == null then return null
1596 args.add(i)
1597 end
1598 var res2 = v.send(callsite.mproperty, args)
1599 if res2 != null then
1600 #self.debug("got {res2} from {mproperty}. drop {recv}")
1601 return res2
1602 end
1603 return recv
1604 end
1605 end
1606
1607 redef class AAttrExpr
1608 redef fun expr(v)
1609 do
1610 var recv = v.expr(self.n_expr)
1611 if recv == null then return null
1612 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1613 var mproperty = self.mproperty.as(not null)
1614 return v.read_attribute(mproperty, recv)
1615 end
1616 end
1617
1618 redef class AAttrAssignExpr
1619 redef fun stmt(v)
1620 do
1621 var recv = v.expr(self.n_expr)
1622 if recv == null then return
1623 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1624 var i = v.expr(self.n_value)
1625 if i == null then return
1626 var mproperty = self.mproperty.as(not null)
1627 assert recv isa MutableInstance
1628 recv.attributes[mproperty] = i
1629 end
1630 end
1631
1632 redef class AAttrReassignExpr
1633 redef fun stmt(v)
1634 do
1635 var recv = v.expr(self.n_expr)
1636 if recv == null then return
1637 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1638 var value = v.expr(self.n_value)
1639 if value == null then return
1640 var mproperty = self.mproperty.as(not null)
1641 var attr = v.read_attribute(mproperty, recv)
1642 var res = v.send(reassign_callsite.mproperty, [attr, value])
1643 assert res != null
1644 assert recv isa MutableInstance
1645 recv.attributes[mproperty] = res
1646 end
1647 end
1648
1649 redef class AIssetAttrExpr
1650 redef fun expr(v)
1651 do
1652 var recv = v.expr(self.n_expr)
1653 if recv == null then return null
1654 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1655 var mproperty = self.mproperty.as(not null)
1656 assert recv isa MutableInstance
1657 return v.bool_instance(recv.attributes.has_key(mproperty))
1658 end
1659 end
1660
1661 redef class ADebugTypeExpr
1662 redef fun stmt(v)
1663 do
1664 # do nothing
1665 end
1666 end