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