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