src: new module mixin to factorize the -m option
[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: OptionBool = 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 moduleof the program (used to lookup methoda
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 var mainobj: nullable Instance
70
71 init(modelbuilder: ModelBuilder, mainmodule: MModule, arguments: Array[String])
72 do
73 self.modelbuilder = modelbuilder
74 self.mainmodule = mainmodule
75 self.arguments = arguments
76 self.true_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, true)
77 self.false_instance = new PrimitiveInstance[Bool](mainmodule.bool_type, false)
78 self.null_instance = new MutableInstance(mainmodule.model.null_type)
79 end
80
81 # Starts the interpreter on the main module of a program
82 fun start(mainmodule: MModule) do
83 var interpreter = self
84 var sys_type = mainmodule.sys_type
85 if sys_type == null then return # no class Sys
86 var mainobj = new MutableInstance(sys_type)
87 interpreter.mainobj = mainobj
88 interpreter.init_instance(mainobj)
89 var initprop = mainmodule.try_get_primitive_method("init", sys_type.mclass)
90 if initprop != null then
91 interpreter.send(initprop, [mainobj])
92 end
93 var mainprop = mainmodule.try_get_primitive_method("run", sys_type.mclass) or else
94 mainmodule.try_get_primitive_method("main", sys_type.mclass)
95 if mainprop != null then
96 interpreter.send(mainprop, [mainobj])
97 end
98 end
99
100 # Subtype test in the context of the mainmodule
101 fun is_subtype(sub, sup: MType): Bool
102 do
103 return sub.is_subtype(self.mainmodule, self.frame.arguments.first.mtype.as(MClassType), sup)
104 end
105
106 fun force_get_primitive_method(name: String, recv: MType): MMethod
107 do
108 assert recv isa MClassType
109 return self.modelbuilder.force_get_primitive_method(self.frame.current_node, name, recv.mclass, self.mainmodule)
110 end
111
112 # Is a return executed?
113 # Set this mark to skip the evaluation until the end of the specified method frame
114 var returnmark: nullable Frame = null
115
116 # Is a break executed?
117 # Set this mark to skip the evaluation until a labeled statement catch it with `is_break`
118 var breakmark: nullable EscapeMark = null
119
120 # Is a continue executed?
121 # Set this mark to skip the evaluation until a labeled statement catch it with `is_continue`
122 var continuemark: nullable EscapeMark = null
123
124 # Is a return or a break or a continue executed?
125 # Use this function to know if you must skip the evaluation of statements
126 fun is_escaping: Bool do return returnmark != null or breakmark != null or continuemark != null
127
128 # The value associated with the current return/break/continue, if any.
129 # Set the value when you set a escapemark.
130 # Read the value when you catch a mark or reach the end of a method
131 var escapevalue: nullable Instance = null
132
133 # If there is a break and is associated with `escapemark`, then return true an clear the mark.
134 # If there is no break or if `escapemark` is null then return false.
135 # Use this function to catch a potential break.
136 fun is_break(escapemark: nullable EscapeMark): Bool
137 do
138 if escapemark != null and self.breakmark == escapemark then
139 self.breakmark = null
140 return true
141 else
142 return false
143 end
144 end
145
146 # If there is a continue and is associated with `escapemark`, then return true an clear the mark.
147 # If there is no continue or if `escapemark` is null then return false.
148 # Use this function to catch a potential continue.
149 fun is_continue(escapemark: nullable EscapeMark): Bool
150 do
151 if escapemark != null and self.continuemark == escapemark then
152 self.continuemark = null
153 return true
154 else
155 return false
156 end
157 end
158
159 # Evaluate `n` as an expression in the current context.
160 # Return the value of the expression.
161 # If `n` cannot be evaluated, then aborts.
162 fun expr(n: AExpr): nullable Instance
163 do
164 var frame = self.frame
165 var old = frame.current_node
166 frame.current_node = n
167 #n.debug("IN Execute expr")
168 var i = n.expr(self)
169 if i == null and not self.is_escaping then
170 n.debug("inconsitance: no value and not escaping.")
171 end
172 var implicit_cast_to = n.implicit_cast_to
173 if implicit_cast_to != null then
174 var mtype = self.unanchor_type(implicit_cast_to)
175 if not self.is_subtype(i.mtype, mtype) then n.fatal(self, "Cast failed. Expected `{implicit_cast_to}`, got `{i.mtype}`")
176 end
177
178 #n.debug("OUT Execute expr: value is {i}")
179 #if not is_subtype(i.mtype, n.mtype.as(not null)) then n.debug("Expected {n.mtype.as(not null)} got {i}")
180 frame.current_node = old
181 return i
182 end
183
184 # Evaluate `n` as a statement in the current context.
185 # Do nothing if `n` is null.
186 # If `n` cannot be evaluated, then aborts.
187 fun stmt(n: nullable AExpr)
188 do
189 if n != null then
190 var frame = self.frame
191 var old = frame.current_node
192 frame.current_node = n
193 #n.debug("Execute stmt")
194 n.stmt(self)
195 frame.current_node = old
196 end
197 end
198
199 # Map used to store values of nodes that must be evaluated once in the system (`AOnceExpr`)
200 var onces: Map[ANode, Instance] = new HashMap[ANode, Instance]
201
202 # Return the boolean instance associated with `val`.
203 fun bool_instance(val: Bool): Instance
204 do
205 if val then return self.true_instance else return self.false_instance
206 end
207
208 # Return the integer instance associated with `val`.
209 fun int_instance(val: Int): Instance
210 do
211 var ic = self.mainmodule.get_primitive_class("Int")
212 return new PrimitiveInstance[Int](ic.mclass_type, val)
213 end
214
215 # Return the char instance associated with `val`.
216 fun char_instance(val: Char): Instance
217 do
218 var ic = self.mainmodule.get_primitive_class("Char")
219 return new PrimitiveInstance[Char](ic.mclass_type, val)
220 end
221
222 # Return the float instance associated with `val`.
223 fun float_instance(val: Float): Instance
224 do
225 var ic = self.mainmodule.get_primitive_class("Float")
226 return new PrimitiveInstance[Float](ic.mclass_type, val)
227 end
228
229 # The unique intance of the `true` value.
230 var true_instance: Instance
231
232 # The unique intance of the `false` value.
233 var false_instance: Instance
234
235 # The unique intance of the `null` value.
236 var null_instance: Instance
237
238 # Return a new array made of `values`.
239 # The dynamic type of the result is Array[elttype].
240 fun array_instance(values: Array[Instance], elttype: MType): Instance
241 do
242 assert not elttype.need_anchor
243 var nat = new PrimitiveInstance[Array[Instance]](self.mainmodule.get_primitive_class("NativeArray").get_mtype([elttype]), values)
244 var mtype = self.mainmodule.get_primitive_class("Array").get_mtype([elttype])
245 var res = new MutableInstance(mtype)
246 self.init_instance(res)
247 self.send(self.force_get_primitive_method("with_native", mtype), [res, nat, self.int_instance(values.length)])
248 return res
249 end
250
251 # Return a new native string initialized with `txt`
252 fun native_string_instance(txt: String): Instance
253 do
254 var val = new FlatBuffer.from(txt)
255 val.add('\0')
256 var ic = self.mainmodule.get_primitive_class("NativeString")
257 return new PrimitiveInstance[Buffer](ic.mclass_type, val)
258 end
259
260 # Return a new String instance for `txt`
261 fun string_instance(txt: String): Instance
262 do
263 var nat = native_string_instance(txt)
264 var res = self.send(self.force_get_primitive_method("to_s_with_length", nat.mtype), [nat, self.int_instance(txt.length)])
265 assert res != null
266 return res
267 end
268
269 # The current frame used to store local variables of the current method executed
270 fun frame: Frame do return frames.first
271
272 # The stack of all frames. The first one is the current one.
273 var frames: List[Frame] = new List[Frame]
274
275 # Return a stack stace. One line per function
276 fun stack_trace: String
277 do
278 var b = new FlatBuffer
279 b.append(",---- Stack trace -- - - -\n")
280 for f in frames do
281 b.append("| {f.mpropdef} ({f.current_node.location})\n")
282 end
283 b.append("`------------------- - - -")
284 return b.to_s
285 end
286
287 # Exit the program with a message
288 fun fatal(message: String)
289 do
290 if frames.is_empty then
291 print message
292 else
293 self.frame.current_node.fatal(self, message)
294 end
295 exit(1)
296 end
297
298 # Debug on the current node
299 fun debug(message: String)
300 do
301 if frames.is_empty then
302 print message
303 else
304 self.frame.current_node.debug(message)
305 end
306 end
307
308 # Retrieve the value of the variable in the current frame
309 fun read_variable(v: Variable): Instance
310 do
311 var f = frames.first
312 return f.map[v]
313 end
314
315 # Assign the value of the variable in the current frame
316 fun write_variable(v: Variable, value: Instance)
317 do
318 var f = frames.first
319 f.map[v] = value
320 end
321
322 # Store known method, used to trace methods as thez are reached
323 var discover_call_trace: Set[MMethodDef] = new HashSet[MMethodDef]
324
325 # Common code for calls to injected methods and normal methods
326 fun call_commons(mpropdef: MMethodDef, args: Array[Instance]): Array[Instance]
327 do
328 var vararg_rank = mpropdef.msignature.vararg_rank
329 if vararg_rank >= 0 then
330 assert args.length >= mpropdef.msignature.arity + 1 # because of self
331 var rawargs = args
332 args = new Array[Instance]
333
334 args.add(rawargs.first) # recv
335
336 for i in [0..vararg_rank[ do
337 args.add(rawargs[i+1])
338 end
339
340 var vararg_lastrank = vararg_rank + rawargs.length-1-mpropdef.msignature.arity
341 var vararg = new Array[Instance]
342 for i in [vararg_rank..vararg_lastrank] do
343 vararg.add(rawargs[i+1])
344 end
345 # FIXME: its it to late to determine the vararg type, this should have been done during a previous analysis
346 var elttype = mpropdef.msignature.mparameters[vararg_rank].mtype.anchor_to(self.mainmodule, args.first.mtype.as(MClassType))
347 args.add(self.array_instance(vararg, elttype))
348
349 for i in [vararg_lastrank+1..rawargs.length-1[ do
350 args.add(rawargs[i+1])
351 end
352 end
353 return args
354 end
355
356 # Execute `mpropdef` for a `args` (where `args[0]` is the receiver).
357 # Return a falue if `mpropdef` is a function, or null if it is a procedure.
358 # The call is direct/static. There is no message-seding/late-binding.
359 fun call(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
360 do
361 args = call_commons(mpropdef, args)
362 return call_without_varargs(mpropdef, args)
363 end
364
365 # Common code to call and this function
366 #
367 # Call only executes the variadic part, this avoids
368 # double encapsulation of variadic parameters into an Array
369 fun call_without_varargs(mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
370 do
371 if self.modelbuilder.toolcontext.opt_discover_call_trace.value and not self.discover_call_trace.has(mpropdef) then
372 self.discover_call_trace.add mpropdef
373 self.debug("Discovered {mpropdef}")
374 end
375 assert args.length == mpropdef.msignature.arity + 1 else debug("Invalid arity for {mpropdef}. {args.length} arguments given.")
376
377 # Look for the AST node that implements the property
378 var mproperty = mpropdef.mproperty
379 if self.modelbuilder.mpropdef2npropdef.has_key(mpropdef) then
380 var npropdef = self.modelbuilder.mpropdef2npropdef[mpropdef]
381 self.parameter_check(npropdef, mpropdef, args)
382 return npropdef.call(self, mpropdef, args)
383 else if mproperty.name == "init" then
384 var nclassdef = self.modelbuilder.mclassdef2nclassdef[mpropdef.mclassdef]
385 self.parameter_check(nclassdef, mpropdef, args)
386 return nclassdef.call(self, mpropdef, args)
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 aditionnal 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 falue if `mproperty` is a function, or null if it is a procedure.
461 # The call is polimotphic. There is a message-seding/late-bindng according to te 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 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 correclt 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[1] != null and 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 AContinueExpr
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.continuemark = self.escapemark
1223 end
1224 end
1225
1226 redef class ABreakExpr
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.breakmark = self.escapemark
1236 end
1237 end
1238
1239 redef class AReturnExpr
1240 redef fun stmt(v)
1241 do
1242 var ne = self.n_expr
1243 if ne != null then
1244 var i = v.expr(ne)
1245 if i == null then return
1246 v.escapevalue = i
1247 end
1248 v.returnmark = v.frame
1249 end
1250 end
1251
1252 redef class AAbortExpr
1253 redef fun stmt(v)
1254 do
1255 fatal(v, "Aborted")
1256 exit(1)
1257 end
1258 end
1259
1260 redef class AIfExpr
1261 redef fun expr(v)
1262 do
1263 var cond = v.expr(self.n_expr)
1264 if cond == null then return null
1265 if cond.is_true then
1266 return v.expr(self.n_then.as(not null))
1267 else
1268 return v.expr(self.n_else.as(not null))
1269 end
1270 end
1271
1272 redef fun stmt(v)
1273 do
1274 var cond = v.expr(self.n_expr)
1275 if cond == null then return
1276 if cond.is_true then
1277 v.stmt(self.n_then)
1278 else
1279 v.stmt(self.n_else)
1280 end
1281 end
1282 end
1283
1284 redef class AIfexprExpr
1285 redef fun expr(v)
1286 do
1287 var cond = v.expr(self.n_expr)
1288 if cond == null then return null
1289 if cond.is_true then
1290 return v.expr(self.n_then)
1291 else
1292 return v.expr(self.n_else)
1293 end
1294 end
1295 end
1296
1297 redef class ADoExpr
1298 redef fun stmt(v)
1299 do
1300 v.stmt(self.n_block)
1301 v.is_break(self.escapemark) # Clear the break (if any)
1302 end
1303 end
1304
1305 redef class AWhileExpr
1306 redef fun stmt(v)
1307 do
1308 loop
1309 var cond = v.expr(self.n_expr)
1310 if cond == null then return
1311 if not cond.is_true then return
1312 v.stmt(self.n_block)
1313 if v.is_break(self.escapemark) then return
1314 v.is_continue(self.escapemark) # Clear the break
1315 if v.is_escaping then return
1316 end
1317 end
1318 end
1319
1320 redef class ALoopExpr
1321 redef fun stmt(v)
1322 do
1323 loop
1324 v.stmt(self.n_block)
1325 if v.is_break(self.escapemark) then return
1326 v.is_continue(self.escapemark) # Clear the break
1327 if v.is_escaping then return
1328 end
1329 end
1330 end
1331
1332 redef class AForExpr
1333 redef fun stmt(v)
1334 do
1335 var col = v.expr(self.n_expr)
1336 if col == null then return
1337 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1338
1339 #self.debug("col {col}")
1340 var iter = v.callsite(method_iterator, [col]).as(not null)
1341 #self.debug("iter {iter}")
1342 loop
1343 var isok = v.callsite(method_is_ok, [iter]).as(not null)
1344 if not isok.is_true then return
1345 if self.variables.length == 1 then
1346 var item = v.callsite(method_item, [iter]).as(not null)
1347 #self.debug("item {item}")
1348 v.write_variable(self.variables.first, item)
1349 else if self.variables.length == 2 then
1350 var key = v.callsite(method_key, [iter]).as(not null)
1351 v.write_variable(self.variables[0], key)
1352 var item = v.callsite(method_item, [iter]).as(not null)
1353 v.write_variable(self.variables[1], item)
1354 else
1355 abort
1356 end
1357 v.stmt(self.n_block)
1358 if v.is_break(self.escapemark) then return
1359 v.is_continue(self.escapemark) # Clear the break
1360 if v.is_escaping then return
1361 v.callsite(method_next, [iter])
1362 end
1363 end
1364 end
1365
1366 redef class AAssertExpr
1367 redef fun stmt(v)
1368 do
1369 var cond = v.expr(self.n_expr)
1370 if cond == null then return
1371 if not cond.is_true then
1372 v.stmt(self.n_else)
1373 if v.is_escaping then return
1374 var nid = self.n_id
1375 if nid != null then
1376 fatal(v, "Assert '{nid.text}' failed")
1377 else
1378 fatal(v, "Assert failed")
1379 end
1380 exit(1)
1381 end
1382 end
1383 end
1384
1385 redef class AOrExpr
1386 redef fun expr(v)
1387 do
1388 var cond = v.expr(self.n_expr)
1389 if cond == null then return null
1390 if cond.is_true then return cond
1391 return v.expr(self.n_expr2)
1392 end
1393 end
1394
1395 redef class AImpliesExpr
1396 redef fun expr(v)
1397 do
1398 var cond = v.expr(self.n_expr)
1399 if cond == null then return null
1400 if not cond.is_true then return v.true_instance
1401 return v.expr(self.n_expr2)
1402 end
1403 end
1404
1405 redef class AAndExpr
1406 redef fun expr(v)
1407 do
1408 var cond = v.expr(self.n_expr)
1409 if cond == null then return null
1410 if not cond.is_true then return cond
1411 return v.expr(self.n_expr2)
1412 end
1413 end
1414
1415 redef class ANotExpr
1416 redef fun expr(v)
1417 do
1418 var cond = v.expr(self.n_expr)
1419 if cond == null then return null
1420 return v.bool_instance(not cond.is_true)
1421 end
1422 end
1423
1424 redef class AOrElseExpr
1425 redef fun expr(v)
1426 do
1427 var i = v.expr(self.n_expr)
1428 if i == null then return null
1429 if i != v.null_instance then return i
1430 return v.expr(self.n_expr2)
1431 end
1432 end
1433
1434 redef class AIntExpr
1435 redef fun expr(v)
1436 do
1437 return v.int_instance(self.value.as(not null))
1438 end
1439 end
1440
1441 redef class AFloatExpr
1442 redef fun expr(v)
1443 do
1444 return v.float_instance(self.value.as(not null))
1445 end
1446 end
1447
1448 redef class ACharExpr
1449 redef fun expr(v)
1450 do
1451 return v.char_instance(self.value.as(not null))
1452 end
1453 end
1454
1455 redef class AArrayExpr
1456 redef fun expr(v)
1457 do
1458 var val = new Array[Instance]
1459 for nexpr in self.n_exprs.n_exprs do
1460 var i = v.expr(nexpr)
1461 if i == null then return null
1462 val.add(i)
1463 end
1464 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1465 var elttype = mtype.arguments.first
1466 return v.array_instance(val, elttype)
1467 end
1468 end
1469
1470 redef class AStringFormExpr
1471 redef fun expr(v)
1472 do
1473 var txt = self.value.as(not null)
1474 return v.string_instance(txt)
1475 end
1476 end
1477
1478 redef class ASuperstringExpr
1479 redef fun expr(v)
1480 do
1481 var array = new Array[Instance]
1482 for nexpr in n_exprs do
1483 var i = v.expr(nexpr)
1484 if i == null then return null
1485 array.add(i)
1486 end
1487 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1488 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1489 assert res != null
1490 return res
1491 end
1492 end
1493
1494 redef class ACrangeExpr
1495 redef fun expr(v)
1496 do
1497 var e1 = v.expr(self.n_expr)
1498 if e1 == null then return null
1499 var e2 = v.expr(self.n_expr2)
1500 if e2 == null then return null
1501 var mtype = v.unanchor_type(self.mtype.as(not null))
1502 var res = new MutableInstance(mtype)
1503 v.init_instance(res)
1504 v.callsite(init_callsite, [res, e1, e2])
1505 return res
1506 end
1507 end
1508
1509 redef class AOrangeExpr
1510 redef fun expr(v)
1511 do
1512 var e1 = v.expr(self.n_expr)
1513 if e1 == null then return null
1514 var e2 = v.expr(self.n_expr2)
1515 if e2 == null then return null
1516 var mtype = v.unanchor_type(self.mtype.as(not null))
1517 var res = new MutableInstance(mtype)
1518 v.init_instance(res)
1519 v.callsite(init_callsite, [res, e1, e2])
1520 return res
1521 end
1522 end
1523
1524 redef class ATrueExpr
1525 redef fun expr(v)
1526 do
1527 return v.bool_instance(true)
1528 end
1529 end
1530
1531 redef class AFalseExpr
1532 redef fun expr(v)
1533 do
1534 return v.bool_instance(false)
1535 end
1536 end
1537
1538 redef class ANullExpr
1539 redef fun expr(v)
1540 do
1541 return v.null_instance
1542 end
1543 end
1544
1545 redef class AIsaExpr
1546 redef fun expr(v)
1547 do
1548 var i = v.expr(self.n_expr)
1549 if i == null then return null
1550 var mtype = v.unanchor_type(self.cast_type.as(not null))
1551 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1552 end
1553 end
1554
1555 redef class AAsCastExpr
1556 redef fun expr(v)
1557 do
1558 var i = v.expr(self.n_expr)
1559 if i == null then return null
1560 var mtype = self.mtype.as(not null)
1561 var amtype = v.unanchor_type(mtype)
1562 if not v.is_subtype(i.mtype, amtype) then
1563 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1564 end
1565 return i
1566 end
1567 end
1568
1569 redef class AAsNotnullExpr
1570 redef fun expr(v)
1571 do
1572 var i = v.expr(self.n_expr)
1573 if i == null then return null
1574 var mtype = v.unanchor_type(self.mtype.as(not null))
1575 if i.mtype isa MNullType then
1576 fatal(v, "Cast failed")
1577 end
1578 return i
1579 end
1580 end
1581
1582 redef class AParExpr
1583 redef fun expr(v)
1584 do
1585 return v.expr(self.n_expr)
1586 end
1587 end
1588
1589 redef class AOnceExpr
1590 redef fun expr(v)
1591 do
1592 if v.onces.has_key(self) then
1593 return v.onces[self]
1594 else
1595 var res = v.expr(self.n_expr)
1596 if res == null then return null
1597 v.onces[self] = res
1598 return res
1599 end
1600 end
1601 end
1602
1603 redef class ASendExpr
1604 redef fun expr(v)
1605 do
1606 var recv = v.expr(self.n_expr)
1607 if recv == null then return null
1608 var args = [recv]
1609 for a in self.raw_arguments do
1610 var i = v.expr(a)
1611 if i == null then return null
1612 args.add(i)
1613 end
1614
1615 var res = v.callsite(callsite, args)
1616 return res
1617 end
1618 end
1619
1620 redef class ASendReassignFormExpr
1621 redef fun stmt(v)
1622 do
1623 var recv = v.expr(self.n_expr)
1624 if recv == null then return
1625 var args = [recv]
1626 for a in self.raw_arguments do
1627 var i = v.expr(a)
1628 if i == null then return
1629 args.add(i)
1630 end
1631 var value = v.expr(self.n_value)
1632 if value == null then return
1633
1634 var read = v.callsite(callsite, args)
1635 assert read != null
1636
1637 var write = v.callsite(reassign_callsite, [read, value])
1638 assert write != null
1639
1640 args.add(write)
1641
1642 v.callsite(write_callsite, args)
1643 end
1644 end
1645
1646 redef class ASuperExpr
1647 redef fun expr(v)
1648 do
1649 var recv = v.frame.arguments.first
1650 var args = [recv]
1651 for a in self.n_args.n_exprs do
1652 var i = v.expr(a)
1653 if i == null then return null
1654 args.add(i)
1655 end
1656
1657 var callsite = self.callsite
1658 if callsite != null then
1659 # Add additionnals arguments for the super init call
1660 if args.length == 1 then
1661 for i in [0..callsite.msignature.arity[ do
1662 args.add(v.frame.arguments[i+1])
1663 end
1664 end
1665 # Super init call
1666 var res = v.callsite(callsite, args)
1667 return res
1668 end
1669
1670 if args.length == 1 then
1671 args = v.frame.arguments
1672 end
1673
1674 # stantard call-next-method
1675 var mpropdef = self.mpropdef
1676 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1677 var res = v.call_without_varargs(mpropdef, args)
1678 return res
1679 end
1680 end
1681
1682 redef class ANewExpr
1683 redef fun expr(v)
1684 do
1685 var mtype = v.unanchor_type(self.mtype.as(not null))
1686 var recv: Instance = new MutableInstance(mtype)
1687 v.init_instance(recv)
1688 var args = [recv]
1689 for a in self.n_args.n_exprs do
1690 var i = v.expr(a)
1691 if i == null then return null
1692 args.add(i)
1693 end
1694 var res2 = v.callsite(callsite, args)
1695 if res2 != null then
1696 #self.debug("got {res2} from {mproperty}. drop {recv}")
1697 return res2
1698 end
1699 return recv
1700 end
1701 end
1702
1703 redef class AAttrExpr
1704 redef fun expr(v)
1705 do
1706 var recv = v.expr(self.n_expr)
1707 if recv == null then return null
1708 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1709 var mproperty = self.mproperty.as(not null)
1710 return v.read_attribute(mproperty, recv)
1711 end
1712 end
1713
1714 redef class AAttrAssignExpr
1715 redef fun stmt(v)
1716 do
1717 var recv = v.expr(self.n_expr)
1718 if recv == null then return
1719 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1720 var i = v.expr(self.n_value)
1721 if i == null then return
1722 var mproperty = self.mproperty.as(not null)
1723 v.write_attribute(mproperty, recv, i)
1724 end
1725 end
1726
1727 redef class AAttrReassignExpr
1728 redef fun stmt(v)
1729 do
1730 var recv = v.expr(self.n_expr)
1731 if recv == null then return
1732 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1733 var value = v.expr(self.n_value)
1734 if value == null then return
1735 var mproperty = self.mproperty.as(not null)
1736 var attr = v.read_attribute(mproperty, recv)
1737 var res = v.callsite(reassign_callsite, [attr, value])
1738 assert res != null
1739 v.write_attribute(mproperty, recv, res)
1740 end
1741 end
1742
1743 redef class AIssetAttrExpr
1744 redef fun expr(v)
1745 do
1746 var recv = v.expr(self.n_expr)
1747 if recv == null then return null
1748 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1749 var mproperty = self.mproperty.as(not null)
1750 return v.bool_instance(v.isset_attribute(mproperty, recv))
1751 end
1752 end
1753
1754 redef class ADebugTypeExpr
1755 redef fun stmt(v)
1756 do
1757 # do nothing
1758 end
1759 end