src/niti: remove intern implementations to extern methods
[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 var res = call_extern(v, mpropdef, arguments, f)
804 if res != v.error_instance then return res
805 else
806 fatal(v, "NOT YET IMPLEMENTED <wat?> {mpropdef}")
807 end
808 abort
809 end
810
811 # Call this extern method
812 protected fun call_extern(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame): nullable Instance
813 do
814 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
815 return v.error_instance
816 end
817
818 # Interprets a intern or a shortcut extern method.
819 # Returns the result for a function, `null` for a procedure, or `error_instance` if the method is unknown.
820 private fun intern_call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
821 do
822 var pname = mpropdef.mproperty.name
823 var cname = mpropdef.mclassdef.mclass.name
824 if pname == "output" then
825 var recv = args.first
826 recv.val.output
827 return null
828 else if pname == "object_id" then
829 var recv = args.first
830 if recv isa PrimitiveInstance[Object] then
831 return v.int_instance(recv.val.object_id)
832 else
833 return v.int_instance(recv.object_id)
834 end
835 else if pname == "output_class_name" then
836 var recv = args.first
837 print recv.mtype
838 return null
839 else if pname == "native_class_name" then
840 var recv = args.first
841 var txt = recv.mtype.to_s
842 return v.native_string_instance(txt)
843 else if pname == "==" then
844 # == is correctly redefined for instances
845 return v.bool_instance(args[0] == args[1])
846 else if pname == "!=" then
847 return v.bool_instance(args[0] != args[1])
848 else if pname == "is_same_type" then
849 return v.bool_instance(args[0].mtype == args[1].mtype)
850 else if pname == "is_same_instance" then
851 return v.bool_instance(args[0].eq_is(args[1]))
852 else if pname == "exit" then
853 exit(args[1].to_i)
854 abort
855 else if pname == "buffer_mode_full" then
856 return v.int_instance(sys.buffer_mode_full)
857 else if pname == "buffer_mode_line" then
858 return v.int_instance(sys.buffer_mode_line)
859 else if pname == "buffer_mode_none" then
860 return v.int_instance(sys.buffer_mode_none)
861 else if pname == "sys" then
862 return v.mainobj
863 else if cname == "Int" then
864 var recvval = args[0].to_i
865 if pname == "unary -" then
866 return v.int_instance(-args[0].to_i)
867 else if pname == "unary +" then
868 return args[0]
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.int_instance(args[0].to_i - args[1].to_i)
873 else if pname == "*" then
874 return v.int_instance(args[0].to_i * args[1].to_i)
875 else if pname == "%" then
876 return v.int_instance(args[0].to_i % args[1].to_i)
877 else if pname == "/" then
878 return v.int_instance(args[0].to_i / args[1].to_i)
879 else if pname == "<" then
880 return v.bool_instance(args[0].to_i < args[1].to_i)
881 else if pname == ">" then
882 return v.bool_instance(args[0].to_i > args[1].to_i)
883 else if pname == "<=" then
884 return v.bool_instance(args[0].to_i <= args[1].to_i)
885 else if pname == ">=" then
886 return v.bool_instance(args[0].to_i >= args[1].to_i)
887 else if pname == "<=>" then
888 return v.int_instance(args[0].to_i <=> args[1].to_i)
889 else if pname == "ascii" then
890 return v.char_instance(args[0].to_i.ascii)
891 else if pname == "to_f" then
892 return v.float_instance(args[0].to_i.to_f)
893 else if pname == "to_b" then
894 return v.byte_instance(args[0].to_i.to_b)
895 else if pname == "lshift" then
896 return v.int_instance(args[0].to_i.lshift(args[1].to_i))
897 else if pname == "rshift" then
898 return v.int_instance(args[0].to_i.rshift(args[1].to_i))
899 else if pname == "rand" then
900 var res = recvval.rand
901 return v.int_instance(res)
902 else if pname == "bin_and" then
903 return v.int_instance(args[0].to_i.bin_and(args[1].to_i))
904 else if pname == "bin_or" then
905 return v.int_instance(args[0].to_i.bin_or(args[1].to_i))
906 else if pname == "bin_xor" then
907 return v.int_instance(args[0].to_i.bin_xor(args[1].to_i))
908 else if pname == "bin_not" then
909 return v.int_instance(args[0].to_i.bin_not)
910 end
911 else if cname == "Byte" then
912 var recvval = args[0].to_b
913 if pname == "unary -" then
914 return v.byte_instance(-args[0].to_b)
915 else if pname == "unary +" then
916 return args[0]
917 else if pname == "+" then
918 return v.byte_instance(args[0].to_b + args[1].to_b)
919 else if pname == "-" then
920 return v.byte_instance(args[0].to_b - args[1].to_b)
921 else if pname == "*" then
922 return v.byte_instance(args[0].to_b * args[1].to_b)
923 else if pname == "%" then
924 return v.byte_instance(args[0].to_b % args[1].to_b)
925 else if pname == "/" then
926 return v.byte_instance(args[0].to_b / args[1].to_b)
927 else if pname == "<" then
928 return v.bool_instance(args[0].to_b < args[1].to_b)
929 else if pname == ">" then
930 return v.bool_instance(args[0].to_b > args[1].to_b)
931 else if pname == "<=" then
932 return v.bool_instance(args[0].to_b <= args[1].to_b)
933 else if pname == ">=" then
934 return v.bool_instance(args[0].to_b >= args[1].to_b)
935 else if pname == "<=>" then
936 return v.int_instance(args[0].to_b <=> args[1].to_b)
937 else if pname == "to_f" then
938 return v.float_instance(args[0].to_b.to_f)
939 else if pname == "to_i" then
940 return v.int_instance(args[0].to_b.to_i)
941 else if pname == "lshift" then
942 return v.byte_instance(args[0].to_b.lshift(args[1].to_i))
943 else if pname == "rshift" then
944 return v.byte_instance(args[0].to_b.rshift(args[1].to_i))
945 else if pname == "byte_to_s_len" then
946 return v.int_instance(recvval.to_s.length)
947 end
948 else if cname == "Char" then
949 var recv = args[0].val.as(Char)
950 if pname == "ascii" then
951 return v.int_instance(recv.ascii)
952 else if pname == "successor" then
953 return v.char_instance(recv.successor(args[1].to_i))
954 else if pname == "predecessor" then
955 return v.char_instance(recv.predecessor(args[1].to_i))
956 else if pname == "<" then
957 return v.bool_instance(recv < args[1].val.as(Char))
958 else if pname == ">" then
959 return v.bool_instance(recv > args[1].val.as(Char))
960 else if pname == "<=" then
961 return v.bool_instance(recv <= args[1].val.as(Char))
962 else if pname == ">=" then
963 return v.bool_instance(recv >= args[1].val.as(Char))
964 else if pname == "<=>" then
965 return v.int_instance(recv <=> args[1].val.as(Char))
966 end
967 else if cname == "Float" then
968 var recv = args[0].to_f
969 if pname == "unary -" then
970 return v.float_instance(-recv)
971 else if pname == "unary +" then
972 return args[0]
973 else if pname == "+" then
974 return v.float_instance(recv + args[1].to_f)
975 else if pname == "-" then
976 return v.float_instance(recv - args[1].to_f)
977 else if pname == "*" then
978 return v.float_instance(recv * args[1].to_f)
979 else if pname == "/" then
980 return v.float_instance(recv / args[1].to_f)
981 else if pname == "<" then
982 return v.bool_instance(recv < args[1].to_f)
983 else if pname == ">" then
984 return v.bool_instance(recv > args[1].to_f)
985 else if pname == "<=" then
986 return v.bool_instance(recv <= args[1].to_f)
987 else if pname == ">=" then
988 return v.bool_instance(recv >= args[1].to_f)
989 else if pname == "to_i" then
990 return v.int_instance(recv.to_i)
991 else if pname == "to_b" then
992 return v.byte_instance(recv.to_b)
993 else if pname == "cos" then
994 return v.float_instance(args[0].to_f.cos)
995 else if pname == "sin" then
996 return v.float_instance(args[0].to_f.sin)
997 else if pname == "tan" then
998 return v.float_instance(args[0].to_f.tan)
999 else if pname == "acos" then
1000 return v.float_instance(args[0].to_f.acos)
1001 else if pname == "asin" then
1002 return v.float_instance(args[0].to_f.asin)
1003 else if pname == "atan" then
1004 return v.float_instance(args[0].to_f.atan)
1005 else if pname == "sqrt" then
1006 return v.float_instance(args[0].to_f.sqrt)
1007 else if pname == "exp" then
1008 return v.float_instance(args[0].to_f.exp)
1009 else if pname == "log" then
1010 return v.float_instance(args[0].to_f.log)
1011 else if pname == "pow" then
1012 return v.float_instance(args[0].to_f.pow(args[1].to_f))
1013 else if pname == "rand" then
1014 return v.float_instance(args[0].to_f.rand)
1015 else if pname == "abs" then
1016 return v.float_instance(args[0].to_f.abs)
1017 else if pname == "hypot_with" then
1018 return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
1019 else if pname == "is_nan" then
1020 return v.bool_instance(args[0].to_f.is_nan)
1021 else if pname == "is_inf_extern" then
1022 return v.bool_instance(args[0].to_f.is_inf != 0)
1023 else if pname == "round" then
1024 return v.float_instance(args[0].to_f.round)
1025 end
1026 else if cname == "NativeString" then
1027 if pname == "new" then
1028 return v.native_string_instance("!" * args[1].to_i)
1029 end
1030 var recvval = args.first.val.as(Buffer)
1031 if pname == "[]" then
1032 var arg1 = args[1].to_i
1033 if arg1 >= recvval.length or arg1 < 0 then
1034 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
1035 end
1036 return v.char_instance(recvval.chars[arg1])
1037 else if pname == "[]=" then
1038 var arg1 = args[1].to_i
1039 if arg1 >= recvval.length or arg1 < 0 then
1040 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
1041 end
1042 recvval.chars[arg1] = args[2].val.as(Char)
1043 return null
1044 else if pname == "copy_to" then
1045 # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
1046 var destval = args[1].val.as(FlatBuffer)
1047 var lenval = args[2].to_i
1048 var fromval = args[3].to_i
1049 var toval = args[4].to_i
1050 if fromval < 0 then
1051 debug("Illegal access on {recvval} for element {fromval}/{recvval.length}")
1052 end
1053 if fromval + lenval > recvval.length then
1054 debug("Illegal access on {recvval} for element {fromval}+{lenval}/{recvval.length}")
1055 end
1056 if toval < 0 then
1057 debug("Illegal access on {destval} for element {toval}/{destval.length}")
1058 end
1059 if toval + lenval > destval.length then
1060 debug("Illegal access on {destval} for element {toval}+{lenval}/{destval.length}")
1061 end
1062 recvval.as(FlatBuffer).copy(fromval, lenval, destval, toval)
1063 return null
1064 else if pname == "atoi" then
1065 return v.int_instance(recvval.to_i)
1066 else if pname == "fast_cstring" then
1067 var ns = recvval.to_cstring.to_s.substring_from(args[1].to_i)
1068 return v.native_string_instance(ns)
1069 end
1070 else if pname == "calloc_string" then
1071 return v.native_string_instance("!" * args[1].to_i)
1072 else if cname == "NativeArray" then
1073 if pname == "new" then
1074 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
1075 var instance = new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
1076 v.init_instance_primitive(instance)
1077 return instance
1078 end
1079 var recvval = args.first.val.as(Array[Instance])
1080 if pname == "[]" then
1081 if args[1].to_i >= recvval.length or args[1].to_i < 0 then
1082 debug("Illegal access on {recvval} for element {args[1].to_i}/{recvval.length}")
1083 end
1084 return recvval[args[1].to_i]
1085 else if pname == "[]=" then
1086 recvval[args[1].to_i] = args[2]
1087 return null
1088 else if pname == "length" then
1089 return v.int_instance(recvval.length)
1090 else if pname == "copy_to" then
1091 recvval.copy_to(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
1092 return null
1093 end
1094 else if cname == "NativeFile" then
1095 if pname == "native_stdout" then
1096 var inst = new PrimitiveNativeFile.native_stdout
1097 var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst)
1098 v.init_instance_primitive(instance)
1099 return instance
1100 else if pname == "native_stdin" then
1101 var inst = new PrimitiveNativeFile.native_stdin
1102 var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst)
1103 v.init_instance_primitive(instance)
1104 return instance
1105 else if pname == "native_stderr" then
1106 var inst = new PrimitiveNativeFile.native_stderr
1107 var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst)
1108 v.init_instance_primitive(instance)
1109 return instance
1110 else if pname == "io_open_read" then
1111 var a1 = args[1].val.as(Buffer)
1112 var inst = new PrimitiveNativeFile.io_open_read(a1.to_s)
1113 var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst)
1114 v.init_instance_primitive(instance)
1115 return instance
1116 else if pname == "io_open_write" then
1117 var a1 = args[1].val.as(Buffer)
1118 var inst = new PrimitiveNativeFile.io_open_write(a1.to_s)
1119 var instance = new PrimitiveInstance[PrimitiveNativeFile](mpropdef.mclassdef.mclass.mclass_type, inst)
1120 v.init_instance_primitive(instance)
1121 return instance
1122 end
1123 var recvval = args.first.val
1124 if pname == "io_write" then
1125 var a1 = args[1].val.as(Buffer)
1126 return v.int_instance(recvval.as(PrimitiveNativeFile).io_write(a1.to_cstring, args[2].to_i))
1127 else if pname == "io_read" then
1128 var a1 = args[1].val.as(Buffer)
1129 var ns = new NativeString(a1.length)
1130 var len = recvval.as(PrimitiveNativeFile).io_read(ns, args[2].to_i)
1131 a1.clear
1132 a1.append(ns.to_s_with_length(len))
1133 return v.int_instance(len)
1134 else if pname == "flush" then
1135 recvval.as(PrimitiveNativeFile).flush
1136 return null
1137 else if pname == "io_close" then
1138 return v.int_instance(recvval.as(PrimitiveNativeFile).io_close)
1139 else if pname == "set_buffering_type" then
1140 return v.int_instance(recvval.as(PrimitiveNativeFile).set_buffering_type(args[1].to_i, args[2].to_i))
1141 end
1142 else if pname == "native_argc" then
1143 return v.int_instance(v.arguments.length)
1144 else if pname == "native_argv" then
1145 var txt = v.arguments[args[1].to_i]
1146 return v.native_string_instance(txt)
1147 else if pname == "native_argc" then
1148 return v.int_instance(v.arguments.length)
1149 else if pname == "native_argv" then
1150 var txt = v.arguments[args[1].to_i]
1151 return v.native_string_instance(txt)
1152 else if pname == "lexer_goto" then
1153 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
1154 else if pname == "lexer_accept" then
1155 return v.int_instance(lexer_accept(args[1].to_i))
1156 else if pname == "parser_goto" then
1157 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
1158 else if pname == "parser_action" then
1159 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
1160 end
1161 return v.error_instance
1162 end
1163 end
1164
1165 redef class AAttrPropdef
1166 redef fun call(v, mpropdef, args)
1167 do
1168 var recv = args.first
1169 assert recv isa MutableInstance
1170 var attr = self.mpropdef.mproperty
1171 if mpropdef == mreadpropdef then
1172 assert args.length == 1
1173 if not is_lazy or v.isset_attribute(attr, recv) then return v.read_attribute(attr, recv)
1174 var f = v.new_frame(self, mpropdef, args)
1175 return evaluate_expr(v, recv, f)
1176 else if mpropdef == mwritepropdef then
1177 assert args.length == 2
1178 v.write_attribute(attr, recv, args[1])
1179 return null
1180 else
1181 abort
1182 end
1183 end
1184
1185 # Evaluate and set the default value of the attribute in `recv`
1186 private fun init_expr(v: NaiveInterpreter, recv: Instance)
1187 do
1188 if is_lazy then return
1189 if has_value then
1190 var f = v.new_frame(self, mreadpropdef.as(not null), [recv])
1191 evaluate_expr(v, recv, f)
1192 return
1193 end
1194 var mpropdef = self.mpropdef
1195 if mpropdef == null then return
1196 var mtype = self.mtype.as(not null)
1197 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1198 if mtype isa MNullableType then
1199 v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
1200 end
1201 end
1202
1203 private fun evaluate_expr(v: NaiveInterpreter, recv: Instance, f: Frame): Instance
1204 do
1205 assert recv isa MutableInstance
1206 v.frames.unshift(f)
1207
1208 var val
1209
1210 var nexpr = self.n_expr
1211 var nblock = self.n_block
1212 if nexpr != null then
1213 val = v.expr(nexpr)
1214 else if nblock != null then
1215 v.stmt(nblock)
1216 assert v.returnmark == f
1217 val = v.escapevalue
1218 v.returnmark = null
1219 v.escapevalue = null
1220 else
1221 abort
1222 end
1223 assert val != null
1224
1225 v.frames.shift
1226 assert not v.is_escaping
1227 v.write_attribute(self.mpropdef.mproperty, recv, val)
1228 return val
1229 end
1230 end
1231
1232 redef class AClassdef
1233 # Execute an implicit `mpropdef` associated with the current node.
1234 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
1235 do
1236 if mpropdef.mproperty.is_root_init then
1237 assert args.length == 1
1238 if not mpropdef.is_intro then
1239 # standard call-next-method
1240 var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
1241 v.call(superpd, args)
1242 end
1243 return null
1244 else
1245 abort
1246 end
1247 end
1248 end
1249
1250 redef class AExpr
1251 # Evaluate the node as a possible expression.
1252 # Return a possible value
1253 # NOTE: Do not call this method directly, but use `v.expr`
1254 # This method is here to be implemented by subclasses.
1255 protected fun expr(v: NaiveInterpreter): nullable Instance
1256 do
1257 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1258 abort
1259 end
1260
1261 # Evaluate the node as a statement.
1262 # NOTE: Do not call this method directly, but use `v.stmt`
1263 # This method is here to be implemented by subclasses (no need to return something).
1264 protected fun stmt(v: NaiveInterpreter)
1265 do
1266 expr(v)
1267 end
1268
1269 end
1270
1271 redef class ABlockExpr
1272 redef fun expr(v)
1273 do
1274 var last = self.n_expr.last
1275 for e in self.n_expr do
1276 if e == last then break
1277 v.stmt(e)
1278 if v.is_escaping then return null
1279 end
1280 return last.expr(v)
1281 end
1282
1283 redef fun stmt(v)
1284 do
1285 for e in self.n_expr do
1286 v.stmt(e)
1287 if v.is_escaping then return
1288 end
1289 end
1290 end
1291
1292 redef class AVardeclExpr
1293 redef fun expr(v)
1294 do
1295 var ne = self.n_expr
1296 if ne != null then
1297 var i = v.expr(ne)
1298 if i == null then return null
1299 v.write_variable(self.variable.as(not null), i)
1300 return i
1301 end
1302 return null
1303 end
1304 end
1305
1306 redef class AVarExpr
1307 redef fun expr(v)
1308 do
1309 return v.read_variable(self.variable.as(not null))
1310 end
1311 end
1312
1313 redef class AVarAssignExpr
1314 redef fun expr(v)
1315 do
1316 var i = v.expr(self.n_value)
1317 if i == null then return null
1318 v.write_variable(self.variable.as(not null), i)
1319 return i
1320 end
1321 end
1322
1323 redef class AVarReassignExpr
1324 redef fun stmt(v)
1325 do
1326 var variable = self.variable.as(not null)
1327 var vari = v.read_variable(variable)
1328 var value = v.expr(self.n_value)
1329 if value == null then return
1330 var res = v.callsite(reassign_callsite, [vari, value])
1331 assert res != null
1332 v.write_variable(variable, res)
1333 end
1334 end
1335
1336 redef class ASelfExpr
1337 redef fun expr(v)
1338 do
1339 return v.frame.arguments.first
1340 end
1341 end
1342
1343 redef class AImplicitSelfExpr
1344 redef fun expr(v)
1345 do
1346 if not is_sys then return super
1347 return v.mainobj
1348 end
1349 end
1350
1351 redef class AEscapeExpr
1352 redef fun stmt(v)
1353 do
1354 var ne = self.n_expr
1355 if ne != null then
1356 var i = v.expr(ne)
1357 if i == null then return
1358 v.escapevalue = i
1359 end
1360 v.escapemark = self.escapemark
1361 end
1362 end
1363
1364 redef class AReturnExpr
1365 redef fun stmt(v)
1366 do
1367 var ne = self.n_expr
1368 if ne != null then
1369 var i = v.expr(ne)
1370 if i == null then return
1371 v.escapevalue = i
1372 end
1373 v.returnmark = v.frame
1374 end
1375 end
1376
1377 redef class AAbortExpr
1378 redef fun stmt(v)
1379 do
1380 fatal(v, "Aborted")
1381 exit(1)
1382 end
1383 end
1384
1385 redef class AIfExpr
1386 redef fun expr(v)
1387 do
1388 var cond = v.expr(self.n_expr)
1389 if cond == null then return null
1390 if cond.is_true then
1391 return v.expr(self.n_then.as(not null))
1392 else
1393 return v.expr(self.n_else.as(not null))
1394 end
1395 end
1396
1397 redef fun stmt(v)
1398 do
1399 var cond = v.expr(self.n_expr)
1400 if cond == null then return
1401 if cond.is_true then
1402 v.stmt(self.n_then)
1403 else
1404 v.stmt(self.n_else)
1405 end
1406 end
1407 end
1408
1409 redef class AIfexprExpr
1410 redef fun expr(v)
1411 do
1412 var cond = v.expr(self.n_expr)
1413 if cond == null then return null
1414 if cond.is_true then
1415 return v.expr(self.n_then)
1416 else
1417 return v.expr(self.n_else)
1418 end
1419 end
1420 end
1421
1422 redef class ADoExpr
1423 redef fun stmt(v)
1424 do
1425 v.stmt(self.n_block)
1426 v.is_escape(self.break_mark) # Clear the break (if any)
1427 end
1428 end
1429
1430 redef class AWhileExpr
1431 redef fun stmt(v)
1432 do
1433 loop
1434 var cond = v.expr(self.n_expr)
1435 if cond == null then return
1436 if not cond.is_true then return
1437 v.stmt(self.n_block)
1438 if v.is_escape(self.break_mark) then return
1439 v.is_escape(self.continue_mark) # Clear the break
1440 if v.is_escaping then return
1441 end
1442 end
1443 end
1444
1445 redef class ALoopExpr
1446 redef fun stmt(v)
1447 do
1448 loop
1449 v.stmt(self.n_block)
1450 if v.is_escape(self.break_mark) then return
1451 v.is_escape(self.continue_mark) # Clear the break
1452 if v.is_escaping then return
1453 end
1454 end
1455 end
1456
1457 redef class AForExpr
1458 redef fun stmt(v)
1459 do
1460 var col = v.expr(self.n_expr)
1461 if col == null then return
1462 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1463
1464 #self.debug("col {col}")
1465 var iter = v.callsite(method_iterator, [col]).as(not null)
1466 #self.debug("iter {iter}")
1467 loop
1468 var isok = v.callsite(method_is_ok, [iter]).as(not null)
1469 if not isok.is_true then break
1470 if self.variables.length == 1 then
1471 var item = v.callsite(method_item, [iter]).as(not null)
1472 #self.debug("item {item}")
1473 v.write_variable(self.variables.first, item)
1474 else if self.variables.length == 2 then
1475 var key = v.callsite(method_key, [iter]).as(not null)
1476 v.write_variable(self.variables[0], key)
1477 var item = v.callsite(method_item, [iter]).as(not null)
1478 v.write_variable(self.variables[1], item)
1479 else
1480 abort
1481 end
1482 v.stmt(self.n_block)
1483 if v.is_escape(self.break_mark) then break
1484 v.is_escape(self.continue_mark) # Clear the break
1485 if v.is_escaping then break
1486 v.callsite(method_next, [iter])
1487 end
1488 var method_finish = self.method_finish
1489 if method_finish != null then
1490 v.callsite(method_finish, [iter])
1491 end
1492 end
1493 end
1494
1495 redef class AWithExpr
1496 redef fun stmt(v)
1497 do
1498 var expr = v.expr(self.n_expr)
1499 if expr == null then return
1500
1501 v.callsite(method_start, [expr])
1502 v.stmt(self.n_block)
1503 v.is_escape(self.break_mark) # Clear the break
1504 v.callsite(method_finish, [expr])
1505 end
1506 end
1507
1508 redef class AAssertExpr
1509 redef fun stmt(v)
1510 do
1511 var cond = v.expr(self.n_expr)
1512 if cond == null then return
1513 if not cond.is_true then
1514 v.stmt(self.n_else)
1515 if v.is_escaping then return
1516 var nid = self.n_id
1517 if nid != null then
1518 fatal(v, "Assert '{nid.text}' failed")
1519 else
1520 fatal(v, "Assert failed")
1521 end
1522 exit(1)
1523 end
1524 end
1525 end
1526
1527 redef class AOrExpr
1528 redef fun expr(v)
1529 do
1530 var cond = v.expr(self.n_expr)
1531 if cond == null then return null
1532 if cond.is_true then return cond
1533 return v.expr(self.n_expr2)
1534 end
1535 end
1536
1537 redef class AImpliesExpr
1538 redef fun expr(v)
1539 do
1540 var cond = v.expr(self.n_expr)
1541 if cond == null then return null
1542 if not cond.is_true then return v.true_instance
1543 return v.expr(self.n_expr2)
1544 end
1545 end
1546
1547 redef class AAndExpr
1548 redef fun expr(v)
1549 do
1550 var cond = v.expr(self.n_expr)
1551 if cond == null then return null
1552 if not cond.is_true then return cond
1553 return v.expr(self.n_expr2)
1554 end
1555 end
1556
1557 redef class ANotExpr
1558 redef fun expr(v)
1559 do
1560 var cond = v.expr(self.n_expr)
1561 if cond == null then return null
1562 return v.bool_instance(not cond.is_true)
1563 end
1564 end
1565
1566 redef class AOrElseExpr
1567 redef fun expr(v)
1568 do
1569 var i = v.expr(self.n_expr)
1570 if i == null then return null
1571 if i != v.null_instance then return i
1572 return v.expr(self.n_expr2)
1573 end
1574 end
1575
1576 redef class AIntExpr
1577 redef fun expr(v)
1578 do
1579 return v.int_instance(self.value.as(not null))
1580 end
1581 end
1582
1583 redef class AByteExpr
1584 redef fun expr(v)
1585 do
1586 return v.byte_instance(self.value.as(not null))
1587 end
1588 end
1589
1590 redef class AFloatExpr
1591 redef fun expr(v)
1592 do
1593 return v.float_instance(self.value.as(not null))
1594 end
1595 end
1596
1597 redef class ACharExpr
1598 redef fun expr(v)
1599 do
1600 return v.char_instance(self.value.as(not null))
1601 end
1602 end
1603
1604 redef class AArrayExpr
1605 redef fun expr(v)
1606 do
1607 var val = new Array[Instance]
1608 var old_comprehension = v.frame.comprehension
1609 v.frame.comprehension = val
1610 for nexpr in self.n_exprs do
1611 if nexpr isa AForExpr then
1612 v.stmt(nexpr)
1613 else
1614 var i = v.expr(nexpr)
1615 if i == null then return null
1616 val.add(i)
1617 end
1618 end
1619 v.frame.comprehension = old_comprehension
1620 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1621 var elttype = mtype.arguments.first
1622 return v.array_instance(val, elttype)
1623 end
1624 end
1625
1626 redef class AStringFormExpr
1627 redef fun expr(v)
1628 do
1629 var txt = self.value.as(not null)
1630 return v.string_instance(txt)
1631 end
1632 end
1633
1634 redef class ASuperstringExpr
1635 redef fun expr(v)
1636 do
1637 var array = new Array[Instance]
1638 for nexpr in n_exprs do
1639 var i = v.expr(nexpr)
1640 if i == null then return null
1641 array.add(i)
1642 end
1643 var i = v.array_instance(array, v.mainmodule.object_type)
1644 var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i])
1645 assert res != null
1646 return res
1647 end
1648 end
1649
1650 redef class ACrangeExpr
1651 redef fun expr(v)
1652 do
1653 var e1 = v.expr(self.n_expr)
1654 if e1 == null then return null
1655 var e2 = v.expr(self.n_expr2)
1656 if e2 == null then return null
1657 var mtype = v.unanchor_type(self.mtype.as(not null))
1658 var res = new MutableInstance(mtype)
1659 v.init_instance(res)
1660 v.callsite(init_callsite, [res, e1, e2])
1661 return res
1662 end
1663 end
1664
1665 redef class AOrangeExpr
1666 redef fun expr(v)
1667 do
1668 var e1 = v.expr(self.n_expr)
1669 if e1 == null then return null
1670 var e2 = v.expr(self.n_expr2)
1671 if e2 == null then return null
1672 var mtype = v.unanchor_type(self.mtype.as(not null))
1673 var res = new MutableInstance(mtype)
1674 v.init_instance(res)
1675 v.callsite(init_callsite, [res, e1, e2])
1676 return res
1677 end
1678 end
1679
1680 redef class ATrueExpr
1681 redef fun expr(v)
1682 do
1683 return v.bool_instance(true)
1684 end
1685 end
1686
1687 redef class AFalseExpr
1688 redef fun expr(v)
1689 do
1690 return v.bool_instance(false)
1691 end
1692 end
1693
1694 redef class ANullExpr
1695 redef fun expr(v)
1696 do
1697 return v.null_instance
1698 end
1699 end
1700
1701 redef class AIsaExpr
1702 redef fun expr(v)
1703 do
1704 var i = v.expr(self.n_expr)
1705 if i == null then return null
1706 var mtype = v.unanchor_type(self.cast_type.as(not null))
1707 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1708 end
1709 end
1710
1711 redef class AAsCastExpr
1712 redef fun expr(v)
1713 do
1714 var i = v.expr(self.n_expr)
1715 if i == null then return null
1716 var mtype = self.mtype.as(not null)
1717 var amtype = v.unanchor_type(mtype)
1718 if not v.is_subtype(i.mtype, amtype) then
1719 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1720 end
1721 return i
1722 end
1723 end
1724
1725 redef class AAsNotnullExpr
1726 redef fun expr(v)
1727 do
1728 var i = v.expr(self.n_expr)
1729 if i == null then return null
1730 if i.mtype isa MNullType then
1731 fatal(v, "Cast failed")
1732 end
1733 return i
1734 end
1735 end
1736
1737 redef class AParExpr
1738 redef fun expr(v)
1739 do
1740 return v.expr(self.n_expr)
1741 end
1742 end
1743
1744 redef class AOnceExpr
1745 redef fun expr(v)
1746 do
1747 if v.onces.has_key(self) then
1748 return v.onces[self]
1749 else
1750 var res = v.expr(self.n_expr)
1751 if res == null then return null
1752 v.onces[self] = res
1753 return res
1754 end
1755 end
1756 end
1757
1758 redef class ASendExpr
1759 redef fun expr(v)
1760 do
1761 var recv = v.expr(self.n_expr)
1762 if recv == null then return null
1763 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
1764 if args == null then return null
1765
1766 var res = v.callsite(callsite, args)
1767 return res
1768 end
1769 end
1770
1771 redef class ASendReassignFormExpr
1772 redef fun stmt(v)
1773 do
1774 var recv = v.expr(self.n_expr)
1775 if recv == null then return
1776 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
1777 if args == null then return
1778 var value = v.expr(self.n_value)
1779 if value == null then return
1780
1781 var read = v.callsite(callsite, args)
1782 assert read != null
1783
1784 var write = v.callsite(reassign_callsite, [read, value])
1785 assert write != null
1786
1787 args.add(write)
1788
1789 v.callsite(write_callsite, args)
1790 end
1791 end
1792
1793 redef class ASuperExpr
1794 redef fun expr(v)
1795 do
1796 var recv = v.frame.arguments.first
1797
1798 var callsite = self.callsite
1799 if callsite != null then
1800 var args
1801 if self.n_args.n_exprs.is_empty then
1802 # Add automatic arguments for the super init call
1803 args = [recv]
1804 for i in [0..callsite.msignature.arity[ do
1805 args.add(v.frame.arguments[i+1])
1806 end
1807 else
1808 args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
1809 if args == null then return null
1810 end
1811
1812 # Super init call
1813 var res = v.callsite(callsite, args)
1814 return res
1815 end
1816
1817 # Standard call-next-method
1818 var mpropdef = self.mpropdef
1819 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1820
1821 var args
1822 if self.n_args.n_exprs.is_empty then
1823 args = v.frame.arguments
1824 else
1825 args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
1826 if args == null then return null
1827 end
1828
1829 var res = v.call(mpropdef, args)
1830 return res
1831 end
1832 end
1833
1834 redef class ANewExpr
1835 redef fun expr(v)
1836 do
1837 var mtype = v.unanchor_type(self.recvtype.as(not null))
1838 var recv: Instance = new MutableInstance(mtype)
1839 v.init_instance(recv)
1840 var callsite = self.callsite
1841 if callsite == null then return recv
1842
1843 var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
1844 if args == null then return null
1845 var res2 = v.callsite(callsite, args)
1846 if res2 != null then
1847 #self.debug("got {res2} from {mproperty}. drop {recv}")
1848 return res2
1849 end
1850 return recv
1851 end
1852 end
1853
1854 redef class AAttrExpr
1855 redef fun expr(v)
1856 do
1857 var recv = v.expr(self.n_expr)
1858 if recv == null then return null
1859 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1860 var mproperty = self.mproperty.as(not null)
1861 return v.read_attribute(mproperty, recv)
1862 end
1863 end
1864
1865 redef class AAttrAssignExpr
1866 redef fun stmt(v)
1867 do
1868 var recv = v.expr(self.n_expr)
1869 if recv == null then return
1870 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1871 var i = v.expr(self.n_value)
1872 if i == null then return
1873 var mproperty = self.mproperty.as(not null)
1874 v.write_attribute(mproperty, recv, i)
1875 end
1876 end
1877
1878 redef class AAttrReassignExpr
1879 redef fun stmt(v)
1880 do
1881 var recv = v.expr(self.n_expr)
1882 if recv == null then return
1883 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1884 var value = v.expr(self.n_value)
1885 if value == null then return
1886 var mproperty = self.mproperty.as(not null)
1887 var attr = v.read_attribute(mproperty, recv)
1888 var res = v.callsite(reassign_callsite, [attr, value])
1889 assert res != null
1890 v.write_attribute(mproperty, recv, res)
1891 end
1892 end
1893
1894 redef class AIssetAttrExpr
1895 redef fun expr(v)
1896 do
1897 var recv = v.expr(self.n_expr)
1898 if recv == null then return null
1899 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1900 var mproperty = self.mproperty.as(not null)
1901 return v.bool_instance(v.isset_attribute(mproperty, recv))
1902 end
1903 end
1904
1905 redef class AVarargExpr
1906 redef fun expr(v)
1907 do
1908 return v.expr(self.n_expr)
1909 end
1910 end
1911
1912 redef class ANamedargExpr
1913 redef fun expr(v)
1914 do
1915 return v.expr(self.n_expr)
1916 end
1917 end
1918
1919 redef class ADebugTypeExpr
1920 redef fun stmt(v)
1921 do
1922 # do nothing
1923 end
1924 end