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