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