gitignore nit* in bin/
[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
802 mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.mainmodule.get_primitive_class("ArrayCapable"))
803 mtype = mtype.arguments.first
804 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
805 return new PrimitiveInstance[Array[Instance]](v.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype]), val)
806 end
807 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
808 abort
809 end
810 end
811
812 redef class AbstractArray[E]
813 fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
814 do
815 self.copy_to(start, len, dest, new_start)
816 end
817 end
818
819 redef class AExternInitPropdef
820 redef fun call(v, mpropdef, args)
821 do
822 var pname = mpropdef.mproperty.name
823 var cname = mpropdef.mclassdef.mclass.name
824 if pname == "native_stdout" then
825 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stdout)
826 else if pname == "native_stdin" then
827 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, stdin)
828 else if pname == "native_stderr" then
829 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stderr)
830 else if pname == "io_open_read" then
831 var a1 = args[1].val.as(Buffer)
832 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
833 else if pname == "io_open_write" then
834 var a1 = args[1].val.as(Buffer)
835 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
836 end
837 fatal(v, "NOT YET IMPLEMENTED extern init {mpropdef}")
838 abort
839 end
840 end
841
842 redef class AExternMethPropdef
843 super TablesCapable
844 redef fun call(v, mpropdef, args)
845 do
846 var pname = mpropdef.mproperty.name
847 var cname = mpropdef.mclassdef.mclass.name
848 if cname == "Int" then
849 var recvval = args.first.val.as(Int)
850 if pname == "rand" then
851 var res = recvval.rand
852 return v.int_instance(res)
853 end
854 else if cname == "NativeFile" then
855 var recvval = args.first.val
856 if pname == "io_write" then
857 var a1 = args[1].val.as(Buffer)
858 recvval.as(OStream).write(a1.substring(0, args[2].to_i))
859 return args[2]
860 else if pname == "io_read" then
861 var str = recvval.as(IStream).read(args[2].to_i)
862 var a1 = args[1].val.as(Buffer)
863 new Buffer.from(str).copy(0, str.length, a1, 0)
864 return v.int_instance(str.length)
865 else if pname == "io_close" then
866 recvval.as(IOS).close
867 return v.int_instance(0)
868 end
869 else if cname == "NativeString" then
870 var recvval = args.first.val.as(Buffer)
871 if pname == "file_exists" then
872 return v.bool_instance(recvval.to_s.file_exists)
873 else if pname == "file_mkdir" then
874 recvval.to_s.mkdir
875 return null
876 else if pname == "get_environ" then
877 var txt = recvval.to_s.environ
878 return v.native_string_instance(txt)
879 else if pname == "system" then
880 var res = sys.system(recvval.to_s)
881 return v.int_instance(res)
882 end
883 else if cname == "Int" then
884 if pname == "rand" then
885 return v.int_instance(args[0].to_i.rand)
886 end
887 else if cname == "Float" then
888 if pname == "cos" then
889 return v.float_instance(args[0].to_f.cos)
890 else if pname == "sin" then
891 return v.float_instance(args[0].to_f.sin)
892 end
893 else if pname == "native_argc" then
894 return v.int_instance(v.arguments.length)
895 else if pname == "native_argv" then
896 var txt = v.arguments[args[1].to_i]
897 return v.native_string_instance(txt)
898 else if pname == "get_time" then
899 return v.int_instance(get_time)
900 else if pname == "atan2" then
901 return v.float_instance(atan2(args[1].to_f, args[2].to_f))
902 else if pname == "pi" then
903 return v.float_instance(pi)
904 else if pname == "lexer_goto" then
905 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
906 else if pname == "lexer_accept" then
907 return v.int_instance(lexer_accept(args[1].to_i))
908 else if pname == "parser_goto" then
909 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
910 else if pname == "parser_action" then
911 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
912 end
913 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
914 abort
915 end
916 end
917
918 redef class AAttrPropdef
919 redef fun call(v, mpropdef, args)
920 do
921 var recv = args.first
922 assert recv isa MutableInstance
923 var attr = self.mpropdef.mproperty
924 if args.length == 1 then
925 return v.read_attribute(attr, recv)
926 else
927 assert args.length == 2
928 recv.attributes[attr] = args[1]
929 return null
930 end
931 end
932
933 # Evaluate and set the default value of the attribute in `recv'
934 private fun init_expr(v: NaiveInterpreter, recv: Instance)
935 do
936 assert recv isa MutableInstance
937 var nexpr = self.n_expr
938 if nexpr != null then
939 var f = new Frame(self, self.mpropdef.as(not null), [recv])
940 v.frames.unshift(f)
941 var val = v.expr(nexpr)
942 assert val != null
943 v.frames.shift
944 assert not v.is_escaping
945 recv.attributes[self.mpropdef.mproperty] = val
946 return
947 end
948 var mtype = self.mpropdef.static_mtype.as(not null)
949 # TODO The needinit info is statically computed, move it to modelbuilder or whatever
950 mtype = mtype.resolve_for(self.mpropdef.mclassdef.bound_mtype, self.mpropdef.mclassdef.bound_mtype, self.mpropdef.mclassdef.mmodule, true)
951 if mtype isa MNullableType then
952 recv.attributes[self.mpropdef.mproperty] = v.null_instance
953 end
954 end
955 end
956
957 redef class ADeferredMethPropdef
958 redef fun call(v, mpropdef, args)
959 do
960 fatal(v, "Deferred method called")
961 abort
962 end
963 end
964
965 redef class AClassdef
966 # Execute an implicit `mpropdef' associated with the current node.
967 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
968 do
969 var super_inits = self.super_inits
970 if super_inits != null then
971 assert args.length == 1
972 for su in super_inits do
973 v.send(su, args)
974 end
975 return null
976 end
977 var recv = args.first
978 assert recv isa MutableInstance
979 var i = 1
980 # Collect undefined attributes
981 for npropdef in self.n_propdefs do
982 if npropdef isa AAttrPropdef and npropdef.n_expr == null then
983 recv.attributes[npropdef.mpropdef.mproperty] = args[i]
984 i += 1
985 end
986 end
987 return null
988 end
989 end
990
991 redef class AExpr
992 # Evaluate the node as a possible expression.
993 # Return a possible value
994 # NOTE: Do not call this method directly, but use `v.expr'
995 # This method is here to be implemented by subclasses.
996 private fun expr(v: NaiveInterpreter): nullable Instance
997 do
998 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
999 abort
1000 end
1001
1002 # Evaluate the node as a statement.
1003 # NOTE: Do not call this method directly, but use `v.stmt'
1004 # This method is here to be implemented by subclasses (no need to return something).
1005 private fun stmt(v: NaiveInterpreter)
1006 do
1007 expr(v)
1008 end
1009
1010 end
1011
1012 redef class ABlockExpr
1013 redef fun stmt(v)
1014 do
1015 for e in self.n_expr do
1016 v.stmt(e)
1017 if v.is_escaping then return
1018 end
1019 end
1020 end
1021
1022 redef class AVardeclExpr
1023 redef fun stmt(v)
1024 do
1025 var ne = self.n_expr
1026 if ne != null then
1027 var i = v.expr(ne)
1028 if i == null then return
1029 v.frame.map[self.variable.as(not null)] = i
1030 end
1031 end
1032 end
1033
1034 redef class AVarExpr
1035 redef fun expr(v)
1036 do
1037 return v.frame.map[self.variable.as(not null)]
1038 end
1039 end
1040
1041 redef class AVarAssignExpr
1042 redef fun stmt(v)
1043 do
1044 var i = v.expr(self.n_value)
1045 if i == null then return
1046 v.frame.map[self.variable.as(not null)] = i
1047 end
1048 end
1049
1050 redef class AVarReassignExpr
1051 redef fun stmt(v)
1052 do
1053 var vari = v.frame.map[self.variable.as(not null)]
1054 var value = v.expr(self.n_value)
1055 if value == null then return
1056 var res = v.send(reassign_property.mproperty, [vari, value])
1057 assert res != null
1058 v.frame.map[self.variable.as(not null)] = res
1059 end
1060 end
1061
1062 redef class ASelfExpr
1063 redef fun expr(v)
1064 do
1065 return v.frame.arguments.first
1066 end
1067 end
1068
1069 redef class AContinueExpr
1070 redef fun stmt(v)
1071 do
1072 var ne = self.n_expr
1073 if ne != null then
1074 var i = v.expr(ne)
1075 if i == null then return
1076 v.escapevalue = i
1077 end
1078 v.continuemark = self.escapemark
1079 end
1080 end
1081
1082 redef class ABreakExpr
1083 redef fun stmt(v)
1084 do
1085 var ne = self.n_expr
1086 if ne != null then
1087 var i = v.expr(ne)
1088 if i == null then return
1089 v.escapevalue = i
1090 end
1091 v.breakmark = self.escapemark
1092 end
1093 end
1094
1095 redef class AReturnExpr
1096 redef fun stmt(v)
1097 do
1098 var ne = self.n_expr
1099 if ne != null then
1100 var i = v.expr(ne)
1101 if i == null then return
1102 v.escapevalue = i
1103 end
1104 v.returnmark = v.frame
1105 end
1106 end
1107
1108 redef class AAbortExpr
1109 redef fun stmt(v)
1110 do
1111 fatal(v, "Aborted")
1112 exit(1)
1113 end
1114 end
1115
1116 redef class AIfExpr
1117 redef fun stmt(v)
1118 do
1119 var cond = v.expr(self.n_expr)
1120 if cond == null then return
1121 if cond.is_true then
1122 v.stmt(self.n_then)
1123 else
1124 v.stmt(self.n_else)
1125 end
1126 end
1127 end
1128
1129 redef class AIfexprExpr
1130 redef fun expr(v)
1131 do
1132 var cond = v.expr(self.n_expr)
1133 if cond == null then return null
1134 if cond.is_true then
1135 return v.expr(self.n_then)
1136 else
1137 return v.expr(self.n_else)
1138 end
1139 end
1140 end
1141
1142 redef class ADoExpr
1143 redef fun stmt(v)
1144 do
1145 v.stmt(self.n_block)
1146 v.is_break(self.escapemark) # Clear the break (if any)
1147 end
1148 end
1149
1150 redef class AWhileExpr
1151 redef fun stmt(v)
1152 do
1153 loop
1154 var cond = v.expr(self.n_expr)
1155 if cond == null then return
1156 if not cond.is_true then return
1157 v.stmt(self.n_block)
1158 if v.is_break(self.escapemark) then return
1159 v.is_continue(self.escapemark) # Clear the break
1160 if v.is_escaping then return
1161 end
1162 end
1163 end
1164
1165 redef class ALoopExpr
1166 redef fun stmt(v)
1167 do
1168 loop
1169 v.stmt(self.n_block)
1170 if v.is_break(self.escapemark) then return
1171 v.is_continue(self.escapemark) # Clear the break
1172 if v.is_escaping then return
1173 end
1174 end
1175 end
1176
1177 redef class AForExpr
1178 redef fun stmt(v)
1179 do
1180 var col = v.expr(self.n_expr)
1181 if col == null then return
1182 #self.debug("col {col}")
1183 var iter = v.send(v.force_get_primitive_method("iterator", col.mtype), [col]).as(not null)
1184 #self.debug("iter {iter}")
1185 loop
1186 var isok = v.send(v.force_get_primitive_method("is_ok", iter.mtype), [iter]).as(not null)
1187 if not isok.is_true then return
1188 if self.variables.length == 1 then
1189 var item = v.send(v.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
1190 #self.debug("item {item}")
1191 v.frame.map[self.variables.first] = item
1192 else if self.variables.length == 2 then
1193 var key = v.send(v.force_get_primitive_method("key", iter.mtype), [iter]).as(not null)
1194 v.frame.map[self.variables[0]] = key
1195 var item = v.send(v.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
1196 v.frame.map[self.variables[1]] = item
1197 else
1198 abort
1199 end
1200 v.stmt(self.n_block)
1201 if v.is_break(self.escapemark) then return
1202 v.is_continue(self.escapemark) # Clear the break
1203 if v.is_escaping then return
1204 v.send(v.force_get_primitive_method("next", iter.mtype), [iter])
1205 end
1206 end
1207 end
1208
1209 redef class AAssertExpr
1210 redef fun stmt(v)
1211 do
1212 var cond = v.expr(self.n_expr)
1213 if cond == null then return
1214 if not cond.is_true then
1215 v.stmt(self.n_else)
1216 if v.is_escaping then return
1217 var nid = self.n_id
1218 if nid != null then
1219 fatal(v, "Assert '{nid.text}' failed")
1220 else
1221 fatal(v, "Assert failed")
1222 end
1223 exit(1)
1224 end
1225 end
1226 end
1227
1228 redef class AOrExpr
1229 redef fun expr(v)
1230 do
1231 var cond = v.expr(self.n_expr)
1232 if cond == null then return null
1233 if cond.is_true then return cond
1234 return v.expr(self.n_expr2)
1235 end
1236 end
1237
1238 redef class AAndExpr
1239 redef fun expr(v)
1240 do
1241 var cond = v.expr(self.n_expr)
1242 if cond == null then return null
1243 if not cond.is_true then return cond
1244 return v.expr(self.n_expr2)
1245 end
1246 end
1247
1248 redef class ANotExpr
1249 redef fun expr(v)
1250 do
1251 var cond = v.expr(self.n_expr)
1252 if cond == null then return null
1253 return v.bool_instance(not cond.is_true)
1254 end
1255 end
1256
1257 redef class AOrElseExpr
1258 redef fun expr(v)
1259 do
1260 var i = v.expr(self.n_expr)
1261 if i == null then return null
1262 if i != v.null_instance then return i
1263 return v.expr(self.n_expr2)
1264 end
1265 end
1266
1267 redef class AEeExpr
1268 redef fun expr(v)
1269 do
1270 var i = v.expr(self.n_expr)
1271 if i == null then return null
1272 var i2 = v.expr(self.n_expr2)
1273 if i2 == null then return null
1274 return v.bool_instance(i.eq_is(i2))
1275 end
1276 end
1277
1278 redef class AIntExpr
1279 redef fun expr(v)
1280 do
1281 return v.int_instance(self.value.as(not null))
1282 end
1283 end
1284
1285 redef class AFloatExpr
1286 redef fun expr(v)
1287 do
1288 return v.float_instance(self.value.as(not null))
1289 end
1290 end
1291
1292 redef class ACharExpr
1293 redef fun expr(v)
1294 do
1295 return v.char_instance(self.value.as(not null))
1296 end
1297 end
1298
1299 redef class AArrayExpr
1300 redef fun expr(v)
1301 do
1302 var val = new Array[Instance]
1303 for nexpr in self.n_exprs.n_exprs do
1304 var i = v.expr(nexpr)
1305 if i == null then return null
1306 val.add(i)
1307 end
1308 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1309 var elttype = mtype.arguments.first
1310 return v.array_instance(val, elttype)
1311 end
1312 end
1313
1314 redef class AStringFormExpr
1315 redef fun expr(v)
1316 do
1317 var txt = self.value.as(not null)
1318 var nat = v.native_string_instance(txt)
1319 var res = new MutableInstance(v.mainmodule.get_primitive_class("String").mclass_type)
1320 v.init_instance(res)
1321 v.send(v.force_get_primitive_method("from_cstring", res.mtype), [res, nat])
1322 v.check_init_instance(res)
1323 return res
1324 end
1325 end
1326
1327 redef class ASuperstringExpr
1328 redef fun expr(v)
1329 do
1330 var array = new Array[Instance]
1331 for nexpr in n_exprs do
1332 var i = v.expr(nexpr)
1333 if i == null then return null
1334 array.add(i)
1335 end
1336 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1337 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1338 assert res != null
1339 return res
1340 end
1341 end
1342
1343 redef class ACrangeExpr
1344 redef fun expr(v)
1345 do
1346 var e1 = v.expr(self.n_expr)
1347 if e1 == null then return null
1348 var e2 = v.expr(self.n_expr2)
1349 if e2 == null then return null
1350 var mtype = v.unanchor_type(self.mtype.as(not null))
1351 var res = new MutableInstance(mtype)
1352 v.init_instance(res)
1353 v.send(v.force_get_primitive_method("init", mtype), [res, e1, e2])
1354 v.check_init_instance(res)
1355 return res
1356 end
1357 end
1358
1359 redef class AOrangeExpr
1360 redef fun expr(v)
1361 do
1362 var e1 = v.expr(self.n_expr)
1363 if e1 == null then return null
1364 var e2 = v.expr(self.n_expr2)
1365 if e2 == null then return null
1366 var mtype = v.unanchor_type(self.mtype.as(not null))
1367 var res = new MutableInstance(mtype)
1368 v.init_instance(res)
1369 v.send(v.force_get_primitive_method("without_last", mtype), [res, e1, e2])
1370 v.check_init_instance(res)
1371 return res
1372 end
1373 end
1374
1375 redef class ATrueExpr
1376 redef fun expr(v)
1377 do
1378 return v.bool_instance(true)
1379 end
1380 end
1381
1382 redef class AFalseExpr
1383 redef fun expr(v)
1384 do
1385 return v.bool_instance(false)
1386 end
1387 end
1388
1389 redef class ANullExpr
1390 redef fun expr(v)
1391 do
1392 return v.null_instance
1393 end
1394 end
1395
1396 redef class AIsaExpr
1397 redef fun expr(v)
1398 do
1399 var i = v.expr(self.n_expr)
1400 if i == null then return null
1401 var mtype = v.unanchor_type(self.cast_type.as(not null))
1402 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1403 end
1404 end
1405
1406 redef class AAsCastExpr
1407 redef fun expr(v)
1408 do
1409 var i = v.expr(self.n_expr)
1410 if i == null then return null
1411 var mtype = v.unanchor_type(self.mtype.as(not null))
1412 if not v.is_subtype(i.mtype, mtype) then
1413 #fatal(v, "Cast failed expected {mtype}, got {i}")
1414 fatal(v, "Cast failed")
1415 end
1416 return i
1417 end
1418 end
1419
1420 redef class AAsNotnullExpr
1421 redef fun expr(v)
1422 do
1423 var i = v.expr(self.n_expr)
1424 if i == null then return null
1425 var mtype = v.unanchor_type(self.mtype.as(not null))
1426 if i.mtype isa MNullType then
1427 fatal(v, "Cast failed")
1428 end
1429 return i
1430 end
1431 end
1432
1433 redef class AParExpr
1434 redef fun expr(v)
1435 do
1436 return v.expr(self.n_expr)
1437 end
1438 end
1439
1440 redef class AOnceExpr
1441 redef fun expr(v)
1442 do
1443 if v.onces.has_key(self) then
1444 return v.onces[self]
1445 else
1446 var res = v.expr(self.n_expr)
1447 if res == null then return null
1448 v.onces[self] = res
1449 return res
1450 end
1451 end
1452 end
1453
1454 redef class ASendExpr
1455 redef fun expr(v)
1456 do
1457 var recv = v.expr(self.n_expr)
1458 if recv == null then return null
1459 var args = [recv]
1460 for a in self.raw_arguments.as(not null) do
1461 var i = v.expr(a)
1462 if i == null then return null
1463 args.add(i)
1464 end
1465 for c in self.n_closure_defs do
1466 var mtype = c.mclosure.mtype
1467 var instance = new ClosureInstance(mtype, v.frame, c)
1468 args.add(instance)
1469 end
1470 var mproperty = self.mproperty.as(not null)
1471
1472 var res = v.send(mproperty, args)
1473 if v.is_break(self.escapemark) then
1474 res = v.escapevalue
1475 v.escapevalue = null
1476 end
1477 return res
1478 end
1479 end
1480
1481 redef class ASendReassignFormExpr
1482 redef fun stmt(v)
1483 do
1484 var recv = v.expr(self.n_expr)
1485 if recv == null then return
1486 var args = [recv]
1487 for a in self.raw_arguments.as(not null) do
1488 var i = v.expr(a)
1489 if i == null then return
1490 args.add(i)
1491 end
1492 var value = v.expr(self.n_value)
1493 if value == null then return
1494
1495 var mproperty = self.mproperty.as(not null)
1496 var read = v.send(mproperty, args)
1497 assert read != null
1498
1499 var write = v.send(self.reassign_property.mproperty, [read, value])
1500 assert write != null
1501
1502 args.add(write)
1503
1504 v.send(self.write_mproperty.as(not null), args)
1505 end
1506 end
1507
1508 redef class ASuperExpr
1509 redef fun expr(v)
1510 do
1511 var recv = v.frame.arguments.first
1512 var args = [recv]
1513 for a in self.n_args.n_exprs do
1514 var i = v.expr(a)
1515 if i == null then return null
1516 args.add(i)
1517 end
1518 if args.length == 1 then
1519 args = v.frame.arguments
1520 end
1521
1522 var mproperty = self.mproperty
1523 if mproperty != null then
1524 if mproperty.intro.msignature.arity == 0 then
1525 args = [recv]
1526 end
1527 # Super init call
1528 var res = v.send(mproperty, args)
1529 return res
1530 end
1531
1532 # stantard call-next-method
1533 var mpropdef = v.frame.mpropdef
1534 # FIXME: we do not want an ugly static call!
1535 var mpropdefs = mpropdef.mproperty.lookup_super_definitions(mpropdef.mclassdef.mmodule, mpropdef.mclassdef.bound_mtype)
1536 if mpropdefs.length != 1 then
1537 debug("Warning: NOT YET IMPLEMENTED: multiple MPRODFEFS for super {mpropdef} for {recv}: {mpropdefs.join(", ")}")
1538 end
1539 mpropdef = mpropdefs.first
1540 assert mpropdef isa MMethodDef
1541 var res = v.call(mpropdef, args)
1542 return res
1543 end
1544 end
1545
1546 redef class ANewExpr
1547 redef fun expr(v)
1548 do
1549 var mtype = v.unanchor_type(self.mtype.as(not null))
1550 var recv: Instance = new MutableInstance(mtype)
1551 v.init_instance(recv)
1552 var args = [recv]
1553 for a in self.n_args.n_exprs do
1554 var i = v.expr(a)
1555 if i == null then return null
1556 args.add(i)
1557 end
1558 var mproperty = self.mproperty.as(not null)
1559 var res2 = v.send(mproperty, args)
1560 if res2 != null then
1561 #self.debug("got {res2} from {mproperty}. drop {recv}")
1562 return res2
1563 end
1564 v.check_init_instance(recv)
1565 return recv
1566 end
1567 end
1568
1569 redef class AAttrExpr
1570 redef fun expr(v)
1571 do
1572 var recv = v.expr(self.n_expr)
1573 if recv == null then return null
1574 var mproperty = self.mproperty.as(not null)
1575 return v.read_attribute(mproperty, recv)
1576 end
1577 end
1578
1579 redef class AAttrAssignExpr
1580 redef fun stmt(v)
1581 do
1582 var recv = v.expr(self.n_expr)
1583 if recv == null then return
1584 var i = v.expr(self.n_value)
1585 if i == null then return
1586 var mproperty = self.mproperty.as(not null)
1587 assert recv isa MutableInstance
1588 recv.attributes[mproperty] = i
1589 end
1590 end
1591
1592 redef class AAttrReassignExpr
1593 redef fun stmt(v)
1594 do
1595 var recv = v.expr(self.n_expr)
1596 if recv == null then return
1597 var value = v.expr(self.n_value)
1598 if value == null then return
1599 var mproperty = self.mproperty.as(not null)
1600 var attr = v.read_attribute(mproperty, recv)
1601 var res = v.send(reassign_property.mproperty, [attr, value])
1602 assert res != null
1603 assert recv isa MutableInstance
1604 recv.attributes[mproperty] = res
1605 end
1606 end
1607
1608 redef class AIssetAttrExpr
1609 redef fun expr(v)
1610 do
1611 var recv = v.expr(self.n_expr)
1612 if recv == null then return null
1613 var mproperty = self.mproperty.as(not null)
1614 assert recv isa MutableInstance
1615 return v.bool_instance(recv.attributes.has_key(mproperty))
1616 end
1617 end
1618
1619 redef class AClosureCallExpr
1620 redef fun expr(v)
1621 do
1622 var args = new Array[Instance]
1623 for a in self.n_args.n_exprs do
1624 var i = v.expr(a)
1625 if i == null then return null
1626 args.add(i)
1627 end
1628 var i = v.frame.map[self.variable.as(not null)]
1629 assert i isa ClosureInstance
1630 var res = v.call_closure(i, args)
1631 return res
1632 end
1633 end
1634
1635 redef class ADebugTypeExpr
1636 redef fun stmt(v)
1637 do
1638 # do nothing
1639 end
1640 end