nitx: modifiers ARE accessible via the model
[nit.git] / src / naive_interpreter.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Interpretation of a Nit program directly on the AST
18 module naive_interpreter
19
20 import literal
21 import typing
22 import auto_super_init
23 import frontend
24 import common_ffi
25
26 redef class ToolContext
27 # --discover-call-trace
28 var opt_discover_call_trace: OptionBool = new OptionBool("Trace calls of the first invocation of a method", "--discover-call-trace")
29
30 redef init
31 do
32 super
33 self.option_context.add_option(self.opt_discover_call_trace)
34 end
35 end
36
37 redef class ModelBuilder
38 # Execute the program from the entry point (`Sys::main`) of the `mainmodule`
39 # `arguments` are the command-line arguments in order
40 # REQUIRE that:
41 # 1. the AST is fully loaded.
42 # 2. the model is fully built.
43 # 3. the instructions are fully analysed.
44 fun run_naive_interpreter(mainmodule: MModule, arguments: Array[String])
45 do
46 var time0 = get_time
47 self.toolcontext.info("*** START INTERPRETING ***", 1)
48
49 var interpreter = new NaiveInterpreter(self, mainmodule, arguments)
50 init_naive_interpreter(interpreter, mainmodule)
51
52 var time1 = get_time
53 self.toolcontext.info("*** END INTERPRETING: {time1-time0} ***", 2)
54 end
55
56 private fun init_naive_interpreter(interpreter: NaiveInterpreter, mainmodule: MModule) do
57 var sys_type = mainmodule.sys_type
58 if sys_type == null then return # no class Sys
59 var mainobj = new MutableInstance(sys_type)
60 interpreter.mainobj = mainobj
61 interpreter.init_instance(mainobj)
62 var initprop = mainmodule.try_get_primitive_method("init", sys_type.mclass)
63 if initprop != null then
64 interpreter.send(initprop, [mainobj])
65 end
66 var mainprop = mainmodule.try_get_primitive_method("main", sys_type.mclass)
67 if mainprop != null then
68 interpreter.send(mainprop, [mainobj])
69 end
70 end
71 end
72
73 # The visitor that interprets the Nit Program by walking on the AST
74 private class NaiveInterpreter
75 # The modelbuilder that know the AST and its associations with the model
76 var modelbuilder: ModelBuilder
77
78 # The main moduleof the program (used to lookup methoda
79 var mainmodule: MModule
80
81 # The command line arguments of the interpreted program
82 # arguments.first is the program name
83 # arguments[1] is the first argument
84 var arguments: Array[String]
85
86 var mainobj: nullable Instance
87
88 init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])
89 do
90 self.modelbuilder = modelbuilder
91 self.mainmodule = mainmodule
92 self.arguments = arguments
93 self.true_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, true)
94 self.false_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, false)
95 self.null_instance = new MutableInstance(mainmodule.model.null_type)
96 end
97
98 # Subtype test in the context of the mainmodule
99 fun is_subtype(sub, sup: MType): Bool
100 do
101 return sub.is_subtype(self.mainmodule, self.frame.arguments.first.mtype.as(MClassType), sup)
102 end
103
104 fun force_get_primitive_method(name: String, recv: MType): MMethod
105 do
106 assert recv isa MClassType
107 return self.modelbuilder.force_get_primitive_method(self.frame.current_node, name, recv.mclass, self.mainmodule)
108 end
109
110 # Is a return executed?
111 # Set this mark to skip the evaluation until the end of the specified method frame
112 var returnmark: nullable Frame = null
113
114 # Is a break executed?
115 # Set this mark to skip the evaluation until a labeled statement catch it with `is_break`
116 var breakmark: nullable EscapeMark = null
117
118 # Is a continue executed?
119 # Set this mark to skip the evaluation until a labeled statement catch it with `is_continue`
120 var continuemark: nullable EscapeMark = null
121
122 # Is a return or a break or a continue executed?
123 # Use this function to know if you must skip the evaluation of statements
124 fun is_escaping: Bool do return returnmark != null or breakmark != null or continuemark != null
125
126 # The value associated with the current return/break/continue, if any.
127 # Set the value when you set a escapemark.
128 # Read the value when you catch a mark or reach the end of a method
129 var escapevalue: nullable Instance = null
130
131 # If there is a break and is associated with `escapemark`, then return true an clear the mark.
132 # If there is no break or if `escapemark` is null then return false.
133 # Use this function to catch a potential break.
134 fun is_break(escapemark: nullable EscapeMark): Bool
135 do
136 if escapemark != null and self.breakmark == escapemark then
137 self.breakmark = null
138 return true
139 else
140 return false
141 end
142 end
143
144 # If there is a continue and is associated with `escapemark`, then return true an clear the mark.
145 # If there is no continue or if `escapemark` is null then return false.
146 # Use this function to catch a potential continue.
147 fun is_continue(escapemark: nullable EscapeMark): Bool
148 do
149 if escapemark != null and self.continuemark == escapemark then
150 self.continuemark = null
151 return true
152 else
153 return false
154 end
155 end
156
157 # Evaluate `n` as an expression in the current context.
158 # Return the value of the expression.
159 # If `n` cannot be evaluated, then aborts.
160 fun expr(n: AExpr): nullable Instance
161 do
162 var frame = self.frame
163 var old = frame.current_node
164 frame.current_node = n
165 #n.debug("IN Execute expr")
166 var i = n.expr(self)
167 if i == null and not self.is_escaping then
168 n.debug("inconsitance: no value and not escaping.")
169 end
170 var implicit_cast_to = n.implicit_cast_to
171 if implicit_cast_to != null then
172 var mtype = self.unanchor_type(implicit_cast_to)
173 if not self.is_subtype(i.mtype, mtype) then n.fatal(self, "Cast failed. Expected `{implicit_cast_to}`, got `{i.mtype}`")
174 end
175
176 #n.debug("OUT Execute expr: value is {i}")
177 #if not is_subtype(i.mtype, n.mtype.as(not null)) then n.debug("Expected {n.mtype.as(not null)} got {i}")
178 frame.current_node = old
179 return i
180 end
181
182 # Evaluate `n` as a statement in the current context.
183 # Do nothing if `n` is null.
184 # If `n` cannot be evaluated, then aborts.
185 fun stmt(n: nullable AExpr)
186 do
187 if n != null then
188 var frame = self.frame
189 var old = frame.current_node
190 frame.current_node = n
191 #n.debug("Execute stmt")
192 n.stmt(self)
193 frame.current_node = old
194 end
195 end
196
197 # Map used to store values of nodes that must be evaluated once in the system (`AOnceExpr`)
198 var onces: Map[ANode, Instance] = new HashMap[ANode, Instance]
199
200 # Return the boolean instance associated with `val`.
201 fun bool_instance(val: Bool): Instance
202 do
203 if val then return self.true_instance else return self.false_instance
204 end
205
206 # Return the integer instance associated with `val`.
207 fun int_instance(val: Int): Instance
208 do
209 var ic = self.mainmodule.get_primitive_class("Int")
210 return new PrimitiveInstance[Int](ic.mclass_type, val)
211 end
212
213 # Return the char instance associated with `val`.
214 fun char_instance(val: Char): Instance
215 do
216 var ic = self.mainmodule.get_primitive_class("Char")
217 return new PrimitiveInstance[Char](ic.mclass_type, val)
218 end
219
220 # Return the float instance associated with `val`.
221 fun float_instance(val: Float): Instance
222 do
223 var ic = self.mainmodule.get_primitive_class("Float")
224 return new PrimitiveInstance[Float](ic.mclass_type, val)
225 end
226
227 # The unique intance of the `true` value.
228 var true_instance: Instance
229
230 # The unique intance of the `false` value.
231 var false_instance: Instance
232
233 # The unique intance of the `null` value.
234 var null_instance: Instance
235
236 # Return a new array made of `values`.
237 # The dynamic type of the result is Array[elttype].
238 fun array_instance(values: Array[Instance], elttype: MType): Instance
239 do
240 assert not elttype.need_anchor
241 var nat = new PrimitiveInstance[Array[Instance]](self.mainmodule.get_primitive_class("NativeArray").get_mtype([elttype]), values)
242 var mtype = self.mainmodule.get_primitive_class("Array").get_mtype([elttype])
243 var res = new MutableInstance(mtype)
244 self.init_instance(res)
245 self.send(self.force_get_primitive_method("with_native", mtype), [res, nat, self.int_instance(values.length)])
246 return res
247 end
248
249 # Return a new native string initialized with `txt`
250 fun native_string_instance(txt: String): Instance
251 do
252 var val = new FlatBuffer.from(txt)
253 val.add('\0')
254 var ic = self.mainmodule.get_primitive_class("NativeString")
255 return new PrimitiveInstance[Buffer](ic.mclass_type, val)
256 end
257
258 # The current frame used to store local variables of the current method executed
259 fun frame: Frame do return frames.first
260
261 # The stack of all frames. The first one is the current one.
262 var frames: List[Frame] = new List[Frame]
263
264 # Return a stack stace. One line per function
265 fun stack_trace: String
266 do
267 var b = new FlatBuffer
268 b.append(",---- Stack trace -- - - -\n")
269 for f in frames do
270 b.append("| {f.mpropdef} ({f.current_node.location})\n")
271 end
272 b.append("`------------------- - - -")
273 return b.to_s
274 end
275
276 # Exit the program with a message
277 fun fatal(message: String)
278 do
279 if frames.is_empty then
280 print message
281 else
282 self.frame.current_node.fatal(self, message)
283 end
284 exit(1)
285 end
286
287 # Debug on the current node
288 fun debug(message: String)
289 do
290 if frames.is_empty then
291 print message
292 else
293 self.frame.current_node.debug(message)
294 end
295 end
296
297 # Store known method, used to trace methods as thez are reached
298 var discover_call_trace: Set[MMethodDef] = new HashSet[MMethodDef]
299
300 # Common code for calls to injected methods and normal methods
301 fun call_commons(mpropdef: MMethodDef, args: Array[Instance]): Array[Instance]
302 do
303 var vararg_rank = mpropdef.msignature.vararg_rank
304 if vararg_rank >= 0 then
305 assert args.length >= mpropdef.msignature.arity + 1 # because of self
306 var rawargs = args
307 args = new Array[Instance]
308
309 args.add(rawargs.first) # recv
310
311 for i in [0..vararg_rank[ do
312 args.add(rawargs[i+1])
313 end
314
315 var vararg_lastrank = vararg_rank + rawargs.length-1-mpropdef.msignature.arity
316 var vararg = new Array[Instance]
317 for i in [vararg_rank..vararg_lastrank] do
318 vararg.add(rawargs[i+1])
319 end
320 # FIXME: its it to late to determine the vararg type, this should have been done during a previous analysis
321 var elttype = mpropdef.msignature.mparameters[vararg_rank].mtype.anchor_to(self.mainmodule, args.first.mtype.as(MClassType))
322 args.add(self.array_instance(vararg, elttype))
323
324 for i in [vararg_lastrank+1..rawargs.length-1[ do
325 args.add(rawargs[i+1])
326 end
327 end
328 return args
329 end
330
331 # Execute `mpropdef` for a `args` (where `args[0]` is the receiver).
332 # Return a falue if `mpropdef` is a function, or null if it is a procedure.
333 # The call is direct/static. There is no message-seding/late-binding.
334 fun call(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
335 do
336 args = call_commons(mpropdef, args)
337 return call_without_varargs(mpropdef, args)
338 end
339
340 # Common code to call and this function
341 #
342 # Call only executes the variadic part, this avoids
343 # double encapsulation of variadic parameters into an Array
344 fun call_without_varargs(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
345 do
346 if self.modelbuilder.toolcontext.opt_discover_call_trace.value and not self.discover_call_trace.has(mpropdef) then
347 self.discover_call_trace.add mpropdef
348 self.debug("Discovered {mpropdef}")
349 end
350 assert args.length == mpropdef.msignature.arity + 1 else debug("Invalid arity for {mpropdef}. {args.length} arguments given.")
351
352 # Look for the AST node that implements the property
353 var mproperty = mpropdef.mproperty
354 if self.modelbuilder.mpropdef2npropdef.has_key(mpropdef) then
355 var npropdef = self.modelbuilder.mpropdef2npropdef[mpropdef]
356 self.parameter_check(npropdef, mpropdef, args)
357 return npropdef.call(self, mpropdef, args)
358 else if mproperty.name == "init" then
359 var nclassdef = self.modelbuilder.mclassdef2nclassdef[mpropdef.mclassdef]
360 self.parameter_check(nclassdef, mpropdef, args)
361 return nclassdef.call(self, mpropdef, args)
362 else
363 fatal("Fatal Error: method {mpropdef} not found in the AST")
364 abort
365 end
366 end
367
368 # Generate type checks in the C code to check covariant parameters
369 fun parameter_check(node: ANode, mpropdef: MMethodDef, args: Array[Instance])
370 do
371 var msignature = mpropdef.msignature
372 for i in [0..msignature.arity[ do
373 # skip test for vararg since the array is instantiated with the correct polymorphic type
374 if msignature.vararg_rank == i then continue
375
376 # skip if the cast is not required
377 var origmtype = mpropdef.mproperty.intro.msignature.mparameters[i].mtype
378 if not origmtype.need_anchor then continue
379
380 # get the parameter type
381 var mtype = msignature.mparameters[i].mtype
382 var anchor = args.first.mtype.as(MClassType)
383 var amtype = mtype.anchor_to(self.mainmodule, anchor)
384 if not args[i+1].mtype.is_subtype(self.mainmodule, anchor, amtype) then
385 node.fatal(self, "Cast failed. Expected `{mtype}`, got `{args[i+1].mtype}`")
386 end
387 end
388 end
389
390 # Common code for runtime injected calls and normal calls
391 fun send_commons(mproperty: MMethod, args: Array[Instance], mtype: MType): nullable Instance
392 do
393 if mtype isa MNullType then
394 if mproperty.name == "==" then
395 return self.bool_instance(args[0] == args[1])
396 else if mproperty.name == "!=" then
397 return self.bool_instance(args[0] != args[1])
398 end
399 #fatal("Receiver is null. {mproperty}. {args.join(" ")} {self.frame.current_node.class_name}")
400 fatal("Receiver is null")
401 end
402 return null
403 end
404
405 # Execute a full `callsite` for given `args`
406 # Use this method, instead of `send` to execute and control the aditionnal behavior of the call-sites
407 fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
408 do
409 return send(callsite.mproperty, arguments)
410 end
411
412 # Execute `mproperty` for a `args` (where `args[0]` is the receiver).
413 # Return a falue if `mproperty` is a function, or null if it is a procedure.
414 # The call is polimotphic. There is a message-seding/late-bindng according to te receiver (args[0]).
415 fun send(mproperty: MMethod, args: Array[Instance]): nullable Instance
416 do
417 var recv = args.first
418 var mtype = recv.mtype
419 var ret = send_commons(mproperty, args, mtype)
420 if ret != null then return ret
421 var propdef = mproperty.lookup_first_definition(self.mainmodule, mtype)
422 return self.call(propdef, args)
423 end
424
425 # Read the attribute `mproperty` of an instance `recv` and return its value.
426 # If the attribute in not yet initialized, then aborts with an error message.
427 fun read_attribute(mproperty: MAttribute, recv: Instance): Instance
428 do
429 assert recv isa MutableInstance
430 if not recv.attributes.has_key(mproperty) then
431 fatal("Uninitialized attribute {mproperty.name}")
432 abort
433 end
434 return recv.attributes[mproperty]
435 end
436
437 # Collect attributes of a type in the order of their init
438 fun collect_attr_propdef(mtype: MType): Array[AAttrPropdef]
439 do
440 var cache = self.collect_attr_propdef_cache
441 if cache.has_key(mtype) then return cache[mtype]
442
443 var res = new Array[AAttrPropdef]
444 var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
445 self.mainmodule.linearize_mclassdefs(cds)
446 for cd in cds do
447 var n = self.modelbuilder.mclassdef2nclassdef[cd]
448 for npropdef in n.n_propdefs do
449 if npropdef isa AAttrPropdef then
450 res.add(npropdef)
451 end
452 end
453 end
454
455 cache[mtype] = res
456 return res
457 end
458
459 var collect_attr_propdef_cache = new HashMap[MType, Array[AAttrPropdef]]
460
461 # Fill the initial values of the newly created instance `recv`.
462 # `recv.mtype` is used to know what must be filled.
463 fun init_instance(recv: Instance)
464 do
465 for npropdef in collect_attr_propdef(recv.mtype) do
466 npropdef.init_expr(self, recv)
467 end
468 end
469
470 # This function determine the correct type according the reciever of the current definition (self).
471 fun unanchor_type(mtype: MType): MType
472 do
473 return mtype.anchor_to(self.mainmodule, self.frame.arguments.first.mtype.as(MClassType))
474 end
475 end
476
477 # An instance represents a value of the executed program.
478 abstract class Instance
479 # The dynamic type of the instance
480 # ASSERT: not self.mtype.is_anchored
481 var mtype: MType
482
483 # return true if the instance is the true value.
484 # return false if the instance is the true value.
485 # else aborts
486 fun is_true: Bool do abort
487
488 # Return true if `self` IS `o` (using the Nit semantic of is)
489 fun eq_is(o: Instance): Bool do return self.is_same_instance(o)
490
491 # Human readable object identity "Type#number"
492 redef fun to_s do return "{mtype}"
493
494 # Return the integer value if the instance is an integer.
495 # else aborts
496 fun to_i: Int do abort
497
498 # Return the integer value if the instance is a float.
499 # else aborts
500 fun to_f: Float do abort
501
502 # The real value encapsulated if the instance is primitive.
503 # Else aborts.
504 fun val: Object do abort
505 end
506
507 # A instance with attribute (standards objects)
508 class MutableInstance
509 super Instance
510
511 # The values of the attributes
512 var attributes: Map[MAttribute, Instance] = new HashMap[MAttribute, Instance]
513 end
514
515 # Special instance to handle primitives values (int, bool, etc.)
516 # The trick it just to encapsulate the <<real>> value
517 class PrimitiveInstance[E: Object]
518 super Instance
519
520 # The real value encapsulated
521 redef var val: E
522
523 init(mtype: MType, val: E)
524 do
525 super(mtype)
526 self.val = val
527 end
528
529 redef fun is_true
530 do
531 if val == true then return true
532 if val == false then return false
533 abort
534 end
535
536 redef fun ==(o)
537 do
538 if not o isa PrimitiveInstance[Object] then return false
539 return self.val == o.val
540 end
541
542 redef fun eq_is(o)
543 do
544 if not o isa PrimitiveInstance[Object] then return false
545 return self.val.is_same_instance(o.val)
546 end
547
548 redef fun to_s do return "{mtype}#{val.object_id}({val})"
549
550 redef fun to_i do return val.as(Int)
551
552 redef fun to_f do return val.as(Float)
553 end
554
555 # Information about local variables in a running method
556 private class Frame
557 # The current visited node
558 # The node is stored by frame to keep a stack trace
559 var current_node: ANode
560 # The executed property.
561 # A Method in case of a call, an attribute in case of a default initialization.
562 var mpropdef: MPropDef
563 # Arguments of the method (the first is te receiver
564 var arguments: Array[Instance]
565 # Mapping betwen a variable an the current value
566 var map: Map[Variable, Instance] = new HashMap[Variable, Instance]
567 end
568
569 redef class ANode
570 # Aborts the program with a message
571 # `v` is used to know if a colored message is displayed or not
572 private fun fatal(v: NaiveInterpreter, message: String)
573 do
574 if v.modelbuilder.toolcontext.opt_no_color.value == true then
575 stderr.write("Runtime error: {message} ({location.file.filename}:{location.line_start})\n")
576 else
577 stderr.write("{location}: Runtime error: {message}\n{location.colored_line("0;31")}\n")
578 stderr.write(v.stack_trace)
579 stderr.write("\n")
580 end
581 exit(1)
582 end
583 end
584
585 redef class APropdef
586 # Execute a `mpropdef` associated with the current node.
587 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
588 do
589 fatal(v, "NOT YET IMPLEMENTED method kind {class_name}. {mpropdef}")
590 abort
591 end
592 end
593
594 redef class AConcreteMethPropdef
595
596 redef fun call(v, mpropdef, args)
597 do
598 var f = new Frame(self, self.mpropdef.as(not null), args)
599 call_commons(v, mpropdef, args, f)
600 v.frames.shift
601 if v.returnmark == f then
602 v.returnmark = null
603 var res = v.escapevalue
604 v.escapevalue = null
605 return res
606 end
607 return null
608 end
609
610 private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame)
611 do
612 for i in [0..mpropdef.msignature.arity[ do
613 var variable = self.n_signature.n_params[i].variable
614 assert variable != null
615 f.map[variable] = arguments[i+1]
616 end
617
618 v.frames.unshift(f)
619
620 # Call the implicit super-init
621 var auto_super_inits = self.auto_super_inits
622 if auto_super_inits != null then
623 var args = [arguments.first]
624 for auto_super_init in auto_super_inits do
625 args.clear
626 for i in [0..auto_super_init.msignature.arity+1[ do
627 args.add(arguments[i])
628 end
629 v.callsite(auto_super_init, args)
630 end
631 end
632
633 v.stmt(self.n_block)
634 end
635 end
636
637 redef class AInternMethPropdef
638 redef fun call(v, mpropdef, args)
639 do
640 var pname = mpropdef.mproperty.name
641 var cname = mpropdef.mclassdef.mclass.name
642 if pname == "output" then
643 var recv = args.first
644 recv.val.output
645 return null
646 else if pname == "object_id" then
647 var recv = args.first
648 if recv isa PrimitiveInstance[Object] then
649 return v.int_instance(recv.val.object_id)
650 else
651 return v.int_instance(recv.object_id)
652 end
653 else if pname == "output_class_name" then
654 var recv = args.first
655 print recv.mtype
656 return null
657 else if pname == "native_class_name" then
658 var recv = args.first
659 var txt = recv.mtype.to_s
660 return v.native_string_instance(txt)
661 else if pname == "==" then
662 # == is correclt redefined for instances
663 return v.bool_instance(args[0] == args[1])
664 else if pname == "!=" then
665 return v.bool_instance(args[0] != args[1])
666 else if pname == "is_same_type" then
667 return v.bool_instance(args[0].mtype == args[1].mtype)
668 else if pname == "is_same_instance" then
669 return v.bool_instance(args[1] != null and args[0].eq_is(args[1]))
670 else if pname == "exit" then
671 exit(args[1].to_i)
672 abort
673 else if pname == "sys" then
674 return v.mainobj
675 else if cname == "Int" then
676 if pname == "unary -" then
677 return v.int_instance(-args[0].to_i)
678 else if pname == "+" then
679 return v.int_instance(args[0].to_i + args[1].to_i)
680 else if pname == "-" then
681 return v.int_instance(args[0].to_i - args[1].to_i)
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.bool_instance(args[0].to_i < args[1].to_i)
690 else if pname == ">" then
691 return v.bool_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.int_instance(args[0].to_i <=> args[1].to_i)
698 else if pname == "ascii" then
699 return v.char_instance(args[0].to_i.ascii)
700 else if pname == "to_f" then
701 return v.float_instance(args[0].to_i.to_f)
702 else if pname == "lshift" then
703 return v.int_instance(args[0].to_i.lshift(args[1].to_i))
704 else if pname == "rshift" then
705 return v.int_instance(args[0].to_i.rshift(args[1].to_i))
706 end
707 else if cname == "Char" then
708 var recv = args[0].val.as(Char)
709 if pname == "ascii" then
710 return v.int_instance(recv.ascii)
711 else if pname == "successor" then
712 return v.char_instance(recv.successor(args[1].to_i))
713 else if pname == "predecessor" then
714 return v.char_instance(recv.predecessor(args[1].to_i))
715 else if pname == "<" then
716 return v.bool_instance(recv < args[1].val.as(Char))
717 else if pname == ">" then
718 return v.bool_instance(recv > args[1].val.as(Char))
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.int_instance(recv <=> args[1].val.as(Char))
725 end
726 else if cname == "Float" then
727 var recv = args[0].to_f
728 if pname == "unary -" then
729 return v.float_instance(-recv)
730 else if pname == "+" then
731 return v.float_instance(recv + args[1].to_f)
732 else if pname == "-" then
733 return v.float_instance(recv - args[1].to_f)
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.bool_instance(recv < args[1].to_f)
740 else if pname == ">" then
741 return v.bool_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 == "to_i" then
747 return v.int_instance(recv.to_i)
748 end
749 else if cname == "NativeString" then
750 var recvval = args.first.val.as(Buffer)
751 if pname == "[]" then
752 var arg1 = args[1].to_i
753 if arg1 >= recvval.length or arg1 < 0 then
754 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
755 end
756 return v.char_instance(recvval.chars[arg1])
757 else if pname == "[]=" then
758 var arg1 = args[1].to_i
759 if arg1 >= recvval.length or arg1 < 0 then
760 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
761 end
762 recvval.chars[arg1] = args[2].val.as(Char)
763 return null
764 else if pname == "copy_to" then
765 # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
766 var destval = args[1].val.as(FlatBuffer)
767 var lenval = args[2].to_i
768 var fromval = args[3].to_i
769 var toval = args[4].to_i
770 if fromval < 0 then
771 debug("Illegal access on {recvval} for element {fromval}/{recvval.length}")
772 end
773 if fromval + lenval >= recvval.length then
774 debug("Illegal access on {recvval} for element {fromval}+{lenval}/{recvval.length}")
775 end
776 if toval < 0 then
777 debug("Illegal access on {destval} for element {toval}/{destval.length}")
778 end
779 if toval + lenval >= destval.length then
780 debug("Illegal access on {destval} for element {toval}+{lenval}/{destval.length}")
781 end
782 recvval.as(FlatBuffer).copy(fromval, lenval, destval, toval)
783 return null
784 else if pname == "atoi" then
785 return v.int_instance(recvval.to_i)
786 end
787 else if pname == "calloc_string" then
788 return v.native_string_instance("!" * args[1].to_i)
789 else if cname == "NativeArray" then
790 var recvval = args.first.val.as(Array[Instance])
791 if pname == "[]" then
792 if args[1].to_i >= recvval.length or args[1].to_i < 0 then
793 debug("Illegal access on {recvval} for element {args[1].to_i}/{recvval.length}")
794 end
795 return recvval[args[1].to_i]
796 else if pname == "[]=" then
797 recvval[args[1].to_i] = args[2]
798 return null
799 else if pname == "length" then
800 return v.int_instance(recvval.length)
801 else if pname == "copy_to" then
802 recvval.copy(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
803 return null
804 end
805 else if pname == "calloc_array" then
806 var recvtype = args.first.mtype.as(MClassType)
807 var mtype: MType
808 mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.mainmodule.get_primitive_class("ArrayCapable"))
809 mtype = mtype.arguments.first
810 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
811 return new PrimitiveInstance[Array[Instance]](v.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype]), val)
812 else if pname == "native_argc" then
813 return v.int_instance(v.arguments.length)
814 else if pname == "native_argv" then
815 var txt = v.arguments[args[1].to_i]
816 return v.native_string_instance(txt)
817 end
818 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
819 abort
820 end
821 end
822
823 redef class AbstractArray[E]
824 fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
825 do
826 self.copy_to(start, len, dest, new_start)
827 end
828 end
829
830 redef class AExternInitPropdef
831 redef fun call(v, mpropdef, args)
832 do
833 var pname = mpropdef.mproperty.name
834 var cname = mpropdef.mclassdef.mclass.name
835 if pname == "native_stdout" then
836 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stdout)
837 else if pname == "native_stdin" then
838 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, stdin)
839 else if pname == "native_stderr" then
840 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stderr)
841 else if pname == "io_open_read" then
842 var a1 = args[1].val.as(Buffer)
843 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
844 else if pname == "io_open_write" then
845 var a1 = args[1].val.as(Buffer)
846 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
847 end
848 fatal(v, "NOT YET IMPLEMENTED extern init {mpropdef}")
849 abort
850 end
851 end
852
853 redef class AExternMethPropdef
854 super TablesCapable
855 redef fun call(v, mpropdef, args)
856 do
857 var pname = mpropdef.mproperty.name
858 var cname = mpropdef.mclassdef.mclass.name
859 if cname == "Int" then
860 var recvval = args.first.val.as(Int)
861 if pname == "rand" then
862 var res = recvval.rand
863 return v.int_instance(res)
864 else if pname == "native_int_to_s" then
865 return v.native_string_instance(recvval.to_s)
866 else if pname == "strerror_ext" then
867 return v.native_string_instance(recvval.strerror)
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).to_s)
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 FlatBuffer.from(str).copy(0, str.length, a1.as(FlatBuffer), 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 else if pname == "address_is_null" then
884 return v.false_instance
885 end
886 else if cname == "NativeString" then
887 var recvval = args.first.val.as(Buffer)
888 if pname == "file_exists" then
889 return v.bool_instance(recvval.to_s.file_exists)
890 else if pname == "file_mkdir" then
891 recvval.to_s.mkdir
892 return null
893 else if pname == "file_chdir" then
894 recvval.to_s.chdir
895 return null
896 else if pname == "file_realpath" then
897 return v.native_string_instance(recvval.to_s.realpath)
898 else if pname == "get_environ" then
899 var txt = recvval.to_s.environ
900 return v.native_string_instance(txt)
901 else if pname == "system" then
902 var res = sys.system(recvval.to_s)
903 return v.int_instance(res)
904 else if pname == "atof" then
905 return v.float_instance(recvval.to_f)
906 end
907 else if cname == "Float" then
908 if pname == "cos" then
909 return v.float_instance(args[0].to_f.cos)
910 else if pname == "sin" then
911 return v.float_instance(args[0].to_f.sin)
912 else if pname == "tan" then
913 return v.float_instance(args[0].to_f.tan)
914 else if pname == "acos" then
915 return v.float_instance(args[0].to_f.acos)
916 else if pname == "asin" then
917 return v.float_instance(args[0].to_f.asin)
918 else if pname == "atan" then
919 return v.float_instance(args[0].to_f.atan)
920 else if pname == "sqrt" then
921 return v.float_instance(args[0].to_f.sqrt)
922 else if pname == "exp" then
923 return v.float_instance(args[0].to_f.exp)
924 else if pname == "log" then
925 return v.float_instance(args[0].to_f.log)
926 else if pname == "pow" then
927 return v.float_instance(args[0].to_f.pow(args[1].to_f))
928 else if pname == "rand" then
929 return v.float_instance(args[0].to_f.rand)
930 else if pname == "abs" then
931 return v.float_instance(args[0].to_f.abs)
932 else if pname == "hypot_with" then
933 return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
934 else if pname == "is_nan" then
935 return v.bool_instance(args[0].to_f.is_nan)
936 else if pname == "is_inf_extern" then
937 return v.bool_instance(args[0].to_f.is_inf != 0)
938 end
939 else if pname == "native_argc" then
940 return v.int_instance(v.arguments.length)
941 else if pname == "native_argv" then
942 var txt = v.arguments[args[1].to_i]
943 return v.native_string_instance(txt)
944 else if pname == "get_time" then
945 return v.int_instance(get_time)
946 else if pname == "srand_from" then
947 srand_from(args[1].to_i)
948 return null
949 else if pname == "atan2" then
950 return v.float_instance(atan2(args[1].to_f, args[2].to_f))
951 else if pname == "pi" then
952 return v.float_instance(pi)
953 else if pname == "lexer_goto" then
954 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
955 else if pname == "lexer_accept" then
956 return v.int_instance(lexer_accept(args[1].to_i))
957 else if pname == "parser_goto" then
958 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
959 else if pname == "parser_action" then
960 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
961 else if pname == "file_getcwd" then
962 return v.native_string_instance(getcwd)
963 else if pname == "errno" then
964 return v.int_instance(sys.errno)
965 else if pname == "address_is_null" then
966 return v.false_instance
967 end
968 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
969 abort
970 end
971 end
972
973 redef class AAttrPropdef
974 redef fun call(v, mpropdef, args)
975 do
976 var recv = args.first
977 assert recv isa MutableInstance
978 var attr = self.mpropdef.mproperty
979 if args.length == 1 then
980 return v.read_attribute(attr, recv)
981 else
982 assert args.length == 2
983 recv.attributes[attr] = args[1]
984 return null
985 end
986 end
987
988 # Evaluate and set the default value of the attribute in `recv`
989 private fun init_expr(v: NaiveInterpreter, recv: Instance)
990 do
991 assert recv isa MutableInstance
992 var nexpr = self.n_expr
993 if nexpr != null then
994 var f = new Frame(self, self.mpropdef.as(not null), [recv])
995 v.frames.unshift(f)
996 var val = v.expr(nexpr)
997 assert val != null
998 v.frames.shift
999 assert not v.is_escaping
1000 recv.attributes[self.mpropdef.mproperty] = val
1001 return
1002 end
1003 var mtype = self.mpropdef.static_mtype.as(not null)
1004 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1005 if mtype isa MNullableType then
1006 recv.attributes[self.mpropdef.mproperty] = v.null_instance
1007 end
1008 end
1009 end
1010
1011 redef class ADeferredMethPropdef
1012 redef fun call(v, mpropdef, args)
1013 do
1014 fatal(v, "Abstract method `{mpropdef.mproperty.name}` called on `{args.first.mtype}`")
1015 abort
1016 end
1017 end
1018
1019 redef class AClassdef
1020 # Execute an implicit `mpropdef` associated with the current node.
1021 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
1022 do
1023 var super_inits = self.super_inits
1024 if super_inits != null then
1025 assert args.length == 1
1026 for su in super_inits do
1027 v.send(su, args)
1028 end
1029 return null
1030 end
1031 var recv = args.first
1032 assert recv isa MutableInstance
1033 var i = 1
1034 # Collect undefined attributes
1035 for npropdef in self.n_propdefs do
1036 if npropdef isa AAttrPropdef and npropdef.n_expr == null then
1037 recv.attributes[npropdef.mpropdef.mproperty] = args[i]
1038 i += 1
1039 end
1040 end
1041 return null
1042 end
1043 end
1044
1045 redef class AExpr
1046 # Evaluate the node as a possible expression.
1047 # Return a possible value
1048 # NOTE: Do not call this method directly, but use `v.expr`
1049 # This method is here to be implemented by subclasses.
1050 private fun expr(v: NaiveInterpreter): nullable Instance
1051 do
1052 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1053 abort
1054 end
1055
1056 # Evaluate the node as a statement.
1057 # NOTE: Do not call this method directly, but use `v.stmt`
1058 # This method is here to be implemented by subclasses (no need to return something).
1059 private fun stmt(v: NaiveInterpreter)
1060 do
1061 expr(v)
1062 end
1063
1064 end
1065
1066 redef class ABlockExpr
1067 redef fun expr(v)
1068 do
1069 var last = self.n_expr.last
1070 for e in self.n_expr do
1071 if e == last then break
1072 v.stmt(e)
1073 if v.is_escaping then return null
1074 end
1075 return last.expr(v)
1076 end
1077
1078 redef fun stmt(v)
1079 do
1080 for e in self.n_expr do
1081 v.stmt(e)
1082 if v.is_escaping then return
1083 end
1084 end
1085 end
1086
1087 redef class AVardeclExpr
1088 redef fun stmt(v)
1089 do
1090 var ne = self.n_expr
1091 if ne != null then
1092 var i = v.expr(ne)
1093 if i == null then return
1094 v.frame.map[self.variable.as(not null)] = i
1095 end
1096 end
1097 end
1098
1099 redef class AVarExpr
1100 redef fun expr(v)
1101 do
1102 return v.frame.map[self.variable.as(not null)]
1103 end
1104 end
1105
1106 redef class AVarAssignExpr
1107 redef fun expr(v)
1108 do
1109 var i = v.expr(self.n_value)
1110 if i == null then return null
1111 v.frame.map[self.variable.as(not null)] = i
1112 return i
1113 end
1114 end
1115
1116 redef class AVarReassignExpr
1117 redef fun stmt(v)
1118 do
1119 var vari = v.frame.map[self.variable.as(not null)]
1120 var value = v.expr(self.n_value)
1121 if value == null then return
1122 var res = v.callsite(reassign_callsite, [vari, value])
1123 assert res != null
1124 v.frame.map[self.variable.as(not null)] = res
1125 end
1126 end
1127
1128 redef class ASelfExpr
1129 redef fun expr(v)
1130 do
1131 return v.frame.arguments.first
1132 end
1133 end
1134
1135 redef class AContinueExpr
1136 redef fun stmt(v)
1137 do
1138 var ne = self.n_expr
1139 if ne != null then
1140 var i = v.expr(ne)
1141 if i == null then return
1142 v.escapevalue = i
1143 end
1144 v.continuemark = self.escapemark
1145 end
1146 end
1147
1148 redef class ABreakExpr
1149 redef fun stmt(v)
1150 do
1151 var ne = self.n_expr
1152 if ne != null then
1153 var i = v.expr(ne)
1154 if i == null then return
1155 v.escapevalue = i
1156 end
1157 v.breakmark = self.escapemark
1158 end
1159 end
1160
1161 redef class AReturnExpr
1162 redef fun stmt(v)
1163 do
1164 var ne = self.n_expr
1165 if ne != null then
1166 var i = v.expr(ne)
1167 if i == null then return
1168 v.escapevalue = i
1169 end
1170 v.returnmark = v.frame
1171 end
1172 end
1173
1174 redef class AAbortExpr
1175 redef fun stmt(v)
1176 do
1177 fatal(v, "Aborted")
1178 exit(1)
1179 end
1180 end
1181
1182 redef class AIfExpr
1183 redef fun expr(v)
1184 do
1185 var cond = v.expr(self.n_expr)
1186 if cond == null then return null
1187 if cond.is_true then
1188 return v.expr(self.n_then.as(not null))
1189 else
1190 return v.expr(self.n_else.as(not null))
1191 end
1192 end
1193
1194 redef fun stmt(v)
1195 do
1196 var cond = v.expr(self.n_expr)
1197 if cond == null then return
1198 if cond.is_true then
1199 v.stmt(self.n_then)
1200 else
1201 v.stmt(self.n_else)
1202 end
1203 end
1204 end
1205
1206 redef class AIfexprExpr
1207 redef fun expr(v)
1208 do
1209 var cond = v.expr(self.n_expr)
1210 if cond == null then return null
1211 if cond.is_true then
1212 return v.expr(self.n_then)
1213 else
1214 return v.expr(self.n_else)
1215 end
1216 end
1217 end
1218
1219 redef class ADoExpr
1220 redef fun stmt(v)
1221 do
1222 v.stmt(self.n_block)
1223 v.is_break(self.escapemark) # Clear the break (if any)
1224 end
1225 end
1226
1227 redef class AWhileExpr
1228 redef fun stmt(v)
1229 do
1230 loop
1231 var cond = v.expr(self.n_expr)
1232 if cond == null then return
1233 if not cond.is_true then return
1234 v.stmt(self.n_block)
1235 if v.is_break(self.escapemark) then return
1236 v.is_continue(self.escapemark) # Clear the break
1237 if v.is_escaping then return
1238 end
1239 end
1240 end
1241
1242 redef class ALoopExpr
1243 redef fun stmt(v)
1244 do
1245 loop
1246 v.stmt(self.n_block)
1247 if v.is_break(self.escapemark) then return
1248 v.is_continue(self.escapemark) # Clear the break
1249 if v.is_escaping then return
1250 end
1251 end
1252 end
1253
1254 redef class AForExpr
1255 redef fun stmt(v)
1256 do
1257 var col = v.expr(self.n_expr)
1258 if col == null then return
1259 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1260
1261 #self.debug("col {col}")
1262 var iter = v.callsite(method_iterator, [col]).as(not null)
1263 #self.debug("iter {iter}")
1264 loop
1265 var isok = v.callsite(method_is_ok, [iter]).as(not null)
1266 if not isok.is_true then return
1267 if self.variables.length == 1 then
1268 var item = v.callsite(method_item, [iter]).as(not null)
1269 #self.debug("item {item}")
1270 v.frame.map[self.variables.first] = item
1271 else if self.variables.length == 2 then
1272 var key = v.callsite(method_key, [iter]).as(not null)
1273 v.frame.map[self.variables[0]] = key
1274 var item = v.callsite(method_item, [iter]).as(not null)
1275 v.frame.map[self.variables[1]] = item
1276 else
1277 abort
1278 end
1279 v.stmt(self.n_block)
1280 if v.is_break(self.escapemark) then return
1281 v.is_continue(self.escapemark) # Clear the break
1282 if v.is_escaping then return
1283 v.callsite(method_next, [iter])
1284 end
1285 end
1286 end
1287
1288 redef class AAssertExpr
1289 redef fun stmt(v)
1290 do
1291 var cond = v.expr(self.n_expr)
1292 if cond == null then return
1293 if not cond.is_true then
1294 v.stmt(self.n_else)
1295 if v.is_escaping then return
1296 var nid = self.n_id
1297 if nid != null then
1298 fatal(v, "Assert '{nid.text}' failed")
1299 else
1300 fatal(v, "Assert failed")
1301 end
1302 exit(1)
1303 end
1304 end
1305 end
1306
1307 redef class AOrExpr
1308 redef fun expr(v)
1309 do
1310 var cond = v.expr(self.n_expr)
1311 if cond == null then return null
1312 if cond.is_true then return cond
1313 return v.expr(self.n_expr2)
1314 end
1315 end
1316
1317 redef class AImpliesExpr
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 v.true_instance
1323 return v.expr(self.n_expr2)
1324 end
1325 end
1326
1327 redef class AAndExpr
1328 redef fun expr(v)
1329 do
1330 var cond = v.expr(self.n_expr)
1331 if cond == null then return null
1332 if not cond.is_true then return cond
1333 return v.expr(self.n_expr2)
1334 end
1335 end
1336
1337 redef class ANotExpr
1338 redef fun expr(v)
1339 do
1340 var cond = v.expr(self.n_expr)
1341 if cond == null then return null
1342 return v.bool_instance(not cond.is_true)
1343 end
1344 end
1345
1346 redef class AOrElseExpr
1347 redef fun expr(v)
1348 do
1349 var i = v.expr(self.n_expr)
1350 if i == null then return null
1351 if i != v.null_instance then return i
1352 return v.expr(self.n_expr2)
1353 end
1354 end
1355
1356 redef class AIntExpr
1357 redef fun expr(v)
1358 do
1359 return v.int_instance(self.value.as(not null))
1360 end
1361 end
1362
1363 redef class AFloatExpr
1364 redef fun expr(v)
1365 do
1366 return v.float_instance(self.value.as(not null))
1367 end
1368 end
1369
1370 redef class ACharExpr
1371 redef fun expr(v)
1372 do
1373 return v.char_instance(self.value.as(not null))
1374 end
1375 end
1376
1377 redef class AArrayExpr
1378 redef fun expr(v)
1379 do
1380 var val = new Array[Instance]
1381 for nexpr in self.n_exprs.n_exprs do
1382 var i = v.expr(nexpr)
1383 if i == null then return null
1384 val.add(i)
1385 end
1386 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1387 var elttype = mtype.arguments.first
1388 return v.array_instance(val, elttype)
1389 end
1390 end
1391
1392 redef class AStringFormExpr
1393 redef fun expr(v)
1394 do
1395 var txt = self.value.as(not null)
1396 var nat = v.native_string_instance(txt)
1397 var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null)
1398 return res
1399 end
1400 end
1401
1402 redef class ASuperstringExpr
1403 redef fun expr(v)
1404 do
1405 var array = new Array[Instance]
1406 for nexpr in n_exprs do
1407 var i = v.expr(nexpr)
1408 if i == null then return null
1409 array.add(i)
1410 end
1411 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1412 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1413 assert res != null
1414 return res
1415 end
1416 end
1417
1418 redef class ACrangeExpr
1419 redef fun expr(v)
1420 do
1421 var e1 = v.expr(self.n_expr)
1422 if e1 == null then return null
1423 var e2 = v.expr(self.n_expr2)
1424 if e2 == null then return null
1425 var mtype = v.unanchor_type(self.mtype.as(not null))
1426 var res = new MutableInstance(mtype)
1427 v.init_instance(res)
1428 v.callsite(init_callsite, [res, e1, e2])
1429 return res
1430 end
1431 end
1432
1433 redef class AOrangeExpr
1434 redef fun expr(v)
1435 do
1436 var e1 = v.expr(self.n_expr)
1437 if e1 == null then return null
1438 var e2 = v.expr(self.n_expr2)
1439 if e2 == null then return null
1440 var mtype = v.unanchor_type(self.mtype.as(not null))
1441 var res = new MutableInstance(mtype)
1442 v.init_instance(res)
1443 v.callsite(init_callsite, [res, e1, e2])
1444 return res
1445 end
1446 end
1447
1448 redef class ATrueExpr
1449 redef fun expr(v)
1450 do
1451 return v.bool_instance(true)
1452 end
1453 end
1454
1455 redef class AFalseExpr
1456 redef fun expr(v)
1457 do
1458 return v.bool_instance(false)
1459 end
1460 end
1461
1462 redef class ANullExpr
1463 redef fun expr(v)
1464 do
1465 return v.null_instance
1466 end
1467 end
1468
1469 redef class AIsaExpr
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 = v.unanchor_type(self.cast_type.as(not null))
1475 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1476 end
1477 end
1478
1479 redef class AAsCastExpr
1480 redef fun expr(v)
1481 do
1482 var i = v.expr(self.n_expr)
1483 if i == null then return null
1484 var mtype = self.mtype.as(not null)
1485 var amtype = v.unanchor_type(mtype)
1486 if not v.is_subtype(i.mtype, amtype) then
1487 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1488 end
1489 return i
1490 end
1491 end
1492
1493 redef class AAsNotnullExpr
1494 redef fun expr(v)
1495 do
1496 var i = v.expr(self.n_expr)
1497 if i == null then return null
1498 var mtype = v.unanchor_type(self.mtype.as(not null))
1499 if i.mtype isa MNullType then
1500 fatal(v, "Cast failed")
1501 end
1502 return i
1503 end
1504 end
1505
1506 redef class AParExpr
1507 redef fun expr(v)
1508 do
1509 return v.expr(self.n_expr)
1510 end
1511 end
1512
1513 redef class AOnceExpr
1514 redef fun expr(v)
1515 do
1516 if v.onces.has_key(self) then
1517 return v.onces[self]
1518 else
1519 var res = v.expr(self.n_expr)
1520 if res == null then return null
1521 v.onces[self] = res
1522 return res
1523 end
1524 end
1525 end
1526
1527 redef class ASendExpr
1528 redef fun expr(v)
1529 do
1530 var recv = v.expr(self.n_expr)
1531 if recv == null then return null
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 null
1536 args.add(i)
1537 end
1538
1539 var res = v.callsite(callsite, args)
1540 return res
1541 end
1542 end
1543
1544 redef class ASendReassignFormExpr
1545 redef fun stmt(v)
1546 do
1547 var recv = v.expr(self.n_expr)
1548 if recv == null then return
1549 var args = [recv]
1550 for a in self.raw_arguments.as(not null) do
1551 var i = v.expr(a)
1552 if i == null then return
1553 args.add(i)
1554 end
1555 var value = v.expr(self.n_value)
1556 if value == null then return
1557
1558 var read = v.callsite(callsite, args)
1559 assert read != null
1560
1561 var write = v.callsite(reassign_callsite, [read, value])
1562 assert write != null
1563
1564 args.add(write)
1565
1566 v.callsite(write_callsite, args)
1567 end
1568 end
1569
1570 redef class ASuperExpr
1571 redef fun expr(v)
1572 do
1573 var recv = v.frame.arguments.first
1574 var args = [recv]
1575 for a in self.n_args.n_exprs do
1576 var i = v.expr(a)
1577 if i == null then return null
1578 args.add(i)
1579 end
1580
1581 var callsite = self.callsite
1582 if callsite != null then
1583 # Add additionnals arguments for the super init call
1584 if args.length == 1 then
1585 for i in [0..callsite.mproperty.intro.msignature.arity[ do
1586 args.add(v.frame.arguments[i+1])
1587 end
1588 end
1589 # Super init call
1590 var res = v.callsite(callsite, args)
1591 return res
1592 end
1593
1594 if args.length == 1 then
1595 args = v.frame.arguments
1596 end
1597
1598 # stantard call-next-method
1599 var mpropdef = self.mpropdef
1600 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1601 var res = v.call_without_varargs(mpropdef, args)
1602 return res
1603 end
1604 end
1605
1606 redef class ANewExpr
1607 redef fun expr(v)
1608 do
1609 var mtype = v.unanchor_type(self.mtype.as(not null))
1610 var recv: Instance = new MutableInstance(mtype)
1611 v.init_instance(recv)
1612 var args = [recv]
1613 for a in self.n_args.n_exprs do
1614 var i = v.expr(a)
1615 if i == null then return null
1616 args.add(i)
1617 end
1618 var res2 = v.callsite(callsite, args)
1619 if res2 != null then
1620 #self.debug("got {res2} from {mproperty}. drop {recv}")
1621 return res2
1622 end
1623 return recv
1624 end
1625 end
1626
1627 redef class AAttrExpr
1628 redef fun expr(v)
1629 do
1630 var recv = v.expr(self.n_expr)
1631 if recv == null then return null
1632 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1633 var mproperty = self.mproperty.as(not null)
1634 return v.read_attribute(mproperty, recv)
1635 end
1636 end
1637
1638 redef class AAttrAssignExpr
1639 redef fun stmt(v)
1640 do
1641 var recv = v.expr(self.n_expr)
1642 if recv == null then return
1643 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1644 var i = v.expr(self.n_value)
1645 if i == null then return
1646 var mproperty = self.mproperty.as(not null)
1647 assert recv isa MutableInstance
1648 recv.attributes[mproperty] = i
1649 end
1650 end
1651
1652 redef class AAttrReassignExpr
1653 redef fun stmt(v)
1654 do
1655 var recv = v.expr(self.n_expr)
1656 if recv == null then return
1657 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1658 var value = v.expr(self.n_value)
1659 if value == null then return
1660 var mproperty = self.mproperty.as(not null)
1661 var attr = v.read_attribute(mproperty, recv)
1662 var res = v.callsite(reassign_callsite, [attr, value])
1663 assert res != null
1664 assert recv isa MutableInstance
1665 recv.attributes[mproperty] = res
1666 end
1667 end
1668
1669 redef class AIssetAttrExpr
1670 redef fun expr(v)
1671 do
1672 var recv = v.expr(self.n_expr)
1673 if recv == null then return null
1674 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1675 var mproperty = self.mproperty.as(not null)
1676 assert recv isa MutableInstance
1677 return v.bool_instance(recv.attributes.has_key(mproperty))
1678 end
1679 end
1680
1681 redef class ADebugTypeExpr
1682 redef fun stmt(v)
1683 do
1684 # do nothing
1685 end
1686 end