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