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