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