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