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