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