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