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