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