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