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