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