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