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