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