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