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