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