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