Merge: Niti: small refactoring
[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 == "native_int_to_s" then
801 return v.native_string_instance(recvval.to_s)
802 else if pname == "strerror_ext" then
803 return v.native_string_instance(recvval.strerror)
804 end
805 else if cname == "Char" then
806 var recv = args[0].val.as(Char)
807 if pname == "ascii" then
808 return v.int_instance(recv.ascii)
809 else if pname == "successor" then
810 return v.char_instance(recv.successor(args[1].to_i))
811 else if pname == "predecessor" then
812 return v.char_instance(recv.predecessor(args[1].to_i))
813 else if pname == "<" then
814 return v.bool_instance(recv < args[1].val.as(Char))
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.int_instance(recv <=> args[1].val.as(Char))
823 end
824 else if cname == "Float" then
825 var recv = args[0].to_f
826 if pname == "unary -" then
827 return v.float_instance(-recv)
828 else if pname == "+" then
829 return v.float_instance(recv + args[1].to_f)
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.bool_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 == "to_i" then
845 return v.int_instance(recv.to_i)
846 else if pname == "cos" then
847 return v.float_instance(args[0].to_f.cos)
848 else if pname == "sin" then
849 return v.float_instance(args[0].to_f.sin)
850 else if pname == "tan" then
851 return v.float_instance(args[0].to_f.tan)
852 else if pname == "acos" then
853 return v.float_instance(args[0].to_f.acos)
854 else if pname == "asin" then
855 return v.float_instance(args[0].to_f.asin)
856 else if pname == "atan" then
857 return v.float_instance(args[0].to_f.atan)
858 else if pname == "sqrt" then
859 return v.float_instance(args[0].to_f.sqrt)
860 else if pname == "exp" then
861 return v.float_instance(args[0].to_f.exp)
862 else if pname == "log" then
863 return v.float_instance(args[0].to_f.log)
864 else if pname == "pow" then
865 return v.float_instance(args[0].to_f.pow(args[1].to_f))
866 else if pname == "rand" then
867 return v.float_instance(args[0].to_f.rand)
868 else if pname == "abs" then
869 return v.float_instance(args[0].to_f.abs)
870 else if pname == "hypot_with" then
871 return v.float_instance(args[0].to_f.hypot_with(args[1].to_f))
872 else if pname == "is_nan" then
873 return v.bool_instance(args[0].to_f.is_nan)
874 else if pname == "is_inf_extern" then
875 return v.bool_instance(args[0].to_f.is_inf != 0)
876 end
877 else if cname == "NativeString" then
878 if pname == "init" then
879 return v.native_string_instance("!" * args[1].to_i)
880 end
881 var recvval = args.first.val.as(Buffer)
882 if pname == "[]" then
883 var arg1 = args[1].to_i
884 if arg1 >= recvval.length or arg1 < 0 then
885 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
886 end
887 return v.char_instance(recvval.chars[arg1])
888 else if pname == "[]=" then
889 var arg1 = args[1].to_i
890 if arg1 >= recvval.length or arg1 < 0 then
891 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
892 end
893 recvval.chars[arg1] = args[2].val.as(Char)
894 return null
895 else if pname == "copy_to" then
896 # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
897 var destval = args[1].val.as(FlatBuffer)
898 var lenval = args[2].to_i
899 var fromval = args[3].to_i
900 var toval = args[4].to_i
901 if fromval < 0 then
902 debug("Illegal access on {recvval} for element {fromval}/{recvval.length}")
903 end
904 if fromval + lenval >= recvval.length then
905 debug("Illegal access on {recvval} for element {fromval}+{lenval}/{recvval.length}")
906 end
907 if toval < 0 then
908 debug("Illegal access on {destval} for element {toval}/{destval.length}")
909 end
910 if toval + lenval >= destval.length then
911 debug("Illegal access on {destval} for element {toval}+{lenval}/{destval.length}")
912 end
913 recvval.as(FlatBuffer).copy(fromval, lenval, destval, toval)
914 return null
915 else if pname == "atoi" then
916 return v.int_instance(recvval.to_i)
917 else if pname == "file_exists" then
918 return v.bool_instance(recvval.to_s.file_exists)
919 else if pname == "file_mkdir" then
920 recvval.to_s.mkdir
921 return null
922 else if pname == "file_chdir" then
923 recvval.to_s.chdir
924 return null
925 else if pname == "file_realpath" then
926 return v.native_string_instance(recvval.to_s.realpath)
927 else if pname == "get_environ" then
928 var txt = recvval.to_s.environ
929 return v.native_string_instance(txt)
930 else if pname == "system" then
931 var res = sys.system(recvval.to_s)
932 return v.int_instance(res)
933 else if pname == "atof" then
934 return v.float_instance(recvval.to_f)
935 end
936 else if pname == "calloc_string" then
937 return v.native_string_instance("!" * args[1].to_i)
938 else if cname == "NativeArray" then
939 if pname == "init" then
940 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
941 return new PrimitiveInstance[Array[Instance]](args[0].mtype, val)
942 end
943 var recvval = args.first.val.as(Array[Instance])
944 if pname == "[]" then
945 if args[1].to_i >= recvval.length or args[1].to_i < 0 then
946 debug("Illegal access on {recvval} for element {args[1].to_i}/{recvval.length}")
947 end
948 return recvval[args[1].to_i]
949 else if pname == "[]=" then
950 recvval[args[1].to_i] = args[2]
951 return null
952 else if pname == "length" then
953 return v.int_instance(recvval.length)
954 else if pname == "copy_to" then
955 recvval.copy(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
956 return null
957 end
958 else if cname == "NativeFile" then
959 if pname == "native_stdout" then
960 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdout)
961 else if pname == "native_stdin" then
962 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, sys.stdin)
963 else if pname == "native_stderr" then
964 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, sys.stderr)
965 else if pname == "io_open_read" then
966 var a1 = args[1].val.as(Buffer)
967 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
968 else if pname == "io_open_write" then
969 var a1 = args[1].val.as(Buffer)
970 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
971 end
972 var recvval = args.first.val
973 if pname == "io_write" then
974 var a1 = args[1].val.as(Buffer)
975 recvval.as(OStream).write(a1.substring(0, args[2].to_i).to_s)
976 return args[2]
977 else if pname == "io_read" then
978 var str = recvval.as(IStream).read(args[2].to_i)
979 var a1 = args[1].val.as(Buffer)
980 new FlatBuffer.from(str).copy(0, str.length, a1.as(FlatBuffer), 0)
981 return v.int_instance(str.length)
982 else if pname == "io_close" then
983 recvval.as(IOS).close
984 return v.int_instance(0)
985 else if pname == "address_is_null" then
986 return v.false_instance
987 end
988 else if pname == "calloc_array" then
989 var recvtype = args.first.mtype.as(MClassType)
990 var mtype: MType
991 mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.mainmodule.get_primitive_class("ArrayCapable"))
992 mtype = mtype.arguments.first
993 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
994 return new PrimitiveInstance[Array[Instance]](v.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype]), val)
995 else if pname == "native_argc" then
996 return v.int_instance(v.arguments.length)
997 else if pname == "native_argv" then
998 var txt = v.arguments[args[1].to_i]
999 return v.native_string_instance(txt)
1000 else if pname == "native_argc" then
1001 return v.int_instance(v.arguments.length)
1002 else if pname == "native_argv" then
1003 var txt = v.arguments[args[1].to_i]
1004 return v.native_string_instance(txt)
1005 else if pname == "get_time" then
1006 return v.int_instance(get_time)
1007 else if pname == "srand_from" then
1008 srand_from(args[1].to_i)
1009 return null
1010 else if pname == "atan2" then
1011 return v.float_instance(atan2(args[1].to_f, args[2].to_f))
1012 else if pname == "pi" then
1013 return v.float_instance(pi)
1014 else if pname == "lexer_goto" then
1015 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
1016 else if pname == "lexer_accept" then
1017 return v.int_instance(lexer_accept(args[1].to_i))
1018 else if pname == "parser_goto" then
1019 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
1020 else if pname == "parser_action" then
1021 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
1022 else if pname == "file_getcwd" then
1023 return v.native_string_instance(getcwd)
1024 else if pname == "errno" then
1025 return v.int_instance(sys.errno)
1026 else if pname == "address_is_null" then
1027 return v.false_instance
1028 end
1029 return v.error_instance
1030 end
1031 end
1032
1033 redef class AbstractArray[E]
1034 fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
1035 do
1036 self.copy_to(start, len, dest, new_start)
1037 end
1038 end
1039
1040 redef class AAttrPropdef
1041 redef fun call(v, mpropdef, args)
1042 do
1043 var recv = args.first
1044 assert recv isa MutableInstance
1045 var attr = self.mpropdef.mproperty
1046 if mpropdef == mreadpropdef then
1047 assert args.length == 1
1048 if not is_lazy or v.isset_attribute(attr, recv) then return v.read_attribute(attr, recv)
1049 return evaluate_expr(v, recv)
1050 else if mpropdef == mwritepropdef then
1051 assert args.length == 2
1052 v.write_attribute(attr, recv, args[1])
1053 return null
1054 else
1055 abort
1056 end
1057 end
1058
1059 # Evaluate and set the default value of the attribute in `recv`
1060 private fun init_expr(v: NaiveInterpreter, recv: Instance)
1061 do
1062 if is_lazy then return
1063 var nexpr = self.n_expr
1064 if nexpr != null then
1065 evaluate_expr(v, recv)
1066 return
1067 end
1068 var mtype = self.mpropdef.static_mtype.as(not null)
1069 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1070 if mtype isa MNullableType then
1071 v.write_attribute(self.mpropdef.mproperty, recv, v.null_instance)
1072 end
1073 end
1074
1075 private fun evaluate_expr(v: NaiveInterpreter, recv: Instance): Instance
1076 do
1077 assert recv isa MutableInstance
1078 var nexpr = self.n_expr
1079 assert nexpr != null
1080 var f = new Frame(self, self.mpropdef.as(not null), [recv])
1081 v.frames.unshift(f)
1082 var val = v.expr(nexpr)
1083 assert val != null
1084 v.frames.shift
1085 assert not v.is_escaping
1086 v.write_attribute(self.mpropdef.mproperty, recv, val)
1087 return val
1088 end
1089 end
1090
1091 redef class AClassdef
1092 # Execute an implicit `mpropdef` associated with the current node.
1093 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
1094 do
1095 if mpropdef.mproperty.is_root_init then
1096 assert args.length == 1
1097 if not mpropdef.is_intro then
1098 # standard call-next-method
1099 var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
1100 v.call_without_varargs(superpd, args)
1101 end
1102 return null
1103 else
1104 abort
1105 end
1106 end
1107 end
1108
1109 redef class AExpr
1110 # Evaluate the node as a possible expression.
1111 # Return a possible value
1112 # NOTE: Do not call this method directly, but use `v.expr`
1113 # This method is here to be implemented by subclasses.
1114 private fun expr(v: NaiveInterpreter): nullable Instance
1115 do
1116 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1117 abort
1118 end
1119
1120 # Evaluate the node as a statement.
1121 # NOTE: Do not call this method directly, but use `v.stmt`
1122 # This method is here to be implemented by subclasses (no need to return something).
1123 private fun stmt(v: NaiveInterpreter)
1124 do
1125 expr(v)
1126 end
1127
1128 end
1129
1130 redef class ABlockExpr
1131 redef fun expr(v)
1132 do
1133 var last = self.n_expr.last
1134 for e in self.n_expr do
1135 if e == last then break
1136 v.stmt(e)
1137 if v.is_escaping then return null
1138 end
1139 return last.expr(v)
1140 end
1141
1142 redef fun stmt(v)
1143 do
1144 for e in self.n_expr do
1145 v.stmt(e)
1146 if v.is_escaping then return
1147 end
1148 end
1149 end
1150
1151 redef class AVardeclExpr
1152 redef fun stmt(v)
1153 do
1154 var ne = self.n_expr
1155 if ne != null then
1156 var i = v.expr(ne)
1157 if i == null then return
1158 v.write_variable(self.variable.as(not null), i)
1159 end
1160 end
1161 end
1162
1163 redef class AVarExpr
1164 redef fun expr(v)
1165 do
1166 return v.read_variable(self.variable.as(not null))
1167 end
1168 end
1169
1170 redef class AVarAssignExpr
1171 redef fun expr(v)
1172 do
1173 var i = v.expr(self.n_value)
1174 if i == null then return null
1175 v.write_variable(self.variable.as(not null), i)
1176 return i
1177 end
1178 end
1179
1180 redef class AVarReassignExpr
1181 redef fun stmt(v)
1182 do
1183 var variable = self.variable.as(not null)
1184 var vari = v.read_variable(variable)
1185 var value = v.expr(self.n_value)
1186 if value == null then return
1187 var res = v.callsite(reassign_callsite, [vari, value])
1188 assert res != null
1189 v.write_variable(variable, res)
1190 end
1191 end
1192
1193 redef class ASelfExpr
1194 redef fun expr(v)
1195 do
1196 return v.frame.arguments.first
1197 end
1198 end
1199
1200 redef class AContinueExpr
1201 redef fun stmt(v)
1202 do
1203 var ne = self.n_expr
1204 if ne != null then
1205 var i = v.expr(ne)
1206 if i == null then return
1207 v.escapevalue = i
1208 end
1209 v.continuemark = self.escapemark
1210 end
1211 end
1212
1213 redef class ABreakExpr
1214 redef fun stmt(v)
1215 do
1216 var ne = self.n_expr
1217 if ne != null then
1218 var i = v.expr(ne)
1219 if i == null then return
1220 v.escapevalue = i
1221 end
1222 v.breakmark = self.escapemark
1223 end
1224 end
1225
1226 redef class AReturnExpr
1227 redef fun stmt(v)
1228 do
1229 var ne = self.n_expr
1230 if ne != null then
1231 var i = v.expr(ne)
1232 if i == null then return
1233 v.escapevalue = i
1234 end
1235 v.returnmark = v.frame
1236 end
1237 end
1238
1239 redef class AAbortExpr
1240 redef fun stmt(v)
1241 do
1242 fatal(v, "Aborted")
1243 exit(1)
1244 end
1245 end
1246
1247 redef class AIfExpr
1248 redef fun expr(v)
1249 do
1250 var cond = v.expr(self.n_expr)
1251 if cond == null then return null
1252 if cond.is_true then
1253 return v.expr(self.n_then.as(not null))
1254 else
1255 return v.expr(self.n_else.as(not null))
1256 end
1257 end
1258
1259 redef fun stmt(v)
1260 do
1261 var cond = v.expr(self.n_expr)
1262 if cond == null then return
1263 if cond.is_true then
1264 v.stmt(self.n_then)
1265 else
1266 v.stmt(self.n_else)
1267 end
1268 end
1269 end
1270
1271 redef class AIfexprExpr
1272 redef fun expr(v)
1273 do
1274 var cond = v.expr(self.n_expr)
1275 if cond == null then return null
1276 if cond.is_true then
1277 return v.expr(self.n_then)
1278 else
1279 return v.expr(self.n_else)
1280 end
1281 end
1282 end
1283
1284 redef class ADoExpr
1285 redef fun stmt(v)
1286 do
1287 v.stmt(self.n_block)
1288 v.is_break(self.escapemark) # Clear the break (if any)
1289 end
1290 end
1291
1292 redef class AWhileExpr
1293 redef fun stmt(v)
1294 do
1295 loop
1296 var cond = v.expr(self.n_expr)
1297 if cond == null then return
1298 if not cond.is_true then return
1299 v.stmt(self.n_block)
1300 if v.is_break(self.escapemark) then return
1301 v.is_continue(self.escapemark) # Clear the break
1302 if v.is_escaping then return
1303 end
1304 end
1305 end
1306
1307 redef class ALoopExpr
1308 redef fun stmt(v)
1309 do
1310 loop
1311 v.stmt(self.n_block)
1312 if v.is_break(self.escapemark) then return
1313 v.is_continue(self.escapemark) # Clear the break
1314 if v.is_escaping then return
1315 end
1316 end
1317 end
1318
1319 redef class AForExpr
1320 redef fun stmt(v)
1321 do
1322 var col = v.expr(self.n_expr)
1323 if col == null then return
1324 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1325
1326 #self.debug("col {col}")
1327 var iter = v.callsite(method_iterator, [col]).as(not null)
1328 #self.debug("iter {iter}")
1329 loop
1330 var isok = v.callsite(method_is_ok, [iter]).as(not null)
1331 if not isok.is_true then return
1332 if self.variables.length == 1 then
1333 var item = v.callsite(method_item, [iter]).as(not null)
1334 #self.debug("item {item}")
1335 v.write_variable(self.variables.first, item)
1336 else if self.variables.length == 2 then
1337 var key = v.callsite(method_key, [iter]).as(not null)
1338 v.write_variable(self.variables[0], key)
1339 var item = v.callsite(method_item, [iter]).as(not null)
1340 v.write_variable(self.variables[1], item)
1341 else
1342 abort
1343 end
1344 v.stmt(self.n_block)
1345 if v.is_break(self.escapemark) then return
1346 v.is_continue(self.escapemark) # Clear the break
1347 if v.is_escaping then return
1348 v.callsite(method_next, [iter])
1349 end
1350 end
1351 end
1352
1353 redef class AAssertExpr
1354 redef fun stmt(v)
1355 do
1356 var cond = v.expr(self.n_expr)
1357 if cond == null then return
1358 if not cond.is_true then
1359 v.stmt(self.n_else)
1360 if v.is_escaping then return
1361 var nid = self.n_id
1362 if nid != null then
1363 fatal(v, "Assert '{nid.text}' failed")
1364 else
1365 fatal(v, "Assert failed")
1366 end
1367 exit(1)
1368 end
1369 end
1370 end
1371
1372 redef class AOrExpr
1373 redef fun expr(v)
1374 do
1375 var cond = v.expr(self.n_expr)
1376 if cond == null then return null
1377 if cond.is_true then return cond
1378 return v.expr(self.n_expr2)
1379 end
1380 end
1381
1382 redef class AImpliesExpr
1383 redef fun expr(v)
1384 do
1385 var cond = v.expr(self.n_expr)
1386 if cond == null then return null
1387 if not cond.is_true then return v.true_instance
1388 return v.expr(self.n_expr2)
1389 end
1390 end
1391
1392 redef class AAndExpr
1393 redef fun expr(v)
1394 do
1395 var cond = v.expr(self.n_expr)
1396 if cond == null then return null
1397 if not cond.is_true then return cond
1398 return v.expr(self.n_expr2)
1399 end
1400 end
1401
1402 redef class ANotExpr
1403 redef fun expr(v)
1404 do
1405 var cond = v.expr(self.n_expr)
1406 if cond == null then return null
1407 return v.bool_instance(not cond.is_true)
1408 end
1409 end
1410
1411 redef class AOrElseExpr
1412 redef fun expr(v)
1413 do
1414 var i = v.expr(self.n_expr)
1415 if i == null then return null
1416 if i != v.null_instance then return i
1417 return v.expr(self.n_expr2)
1418 end
1419 end
1420
1421 redef class AIntExpr
1422 redef fun expr(v)
1423 do
1424 return v.int_instance(self.value.as(not null))
1425 end
1426 end
1427
1428 redef class AFloatExpr
1429 redef fun expr(v)
1430 do
1431 return v.float_instance(self.value.as(not null))
1432 end
1433 end
1434
1435 redef class ACharExpr
1436 redef fun expr(v)
1437 do
1438 return v.char_instance(self.value.as(not null))
1439 end
1440 end
1441
1442 redef class AArrayExpr
1443 redef fun expr(v)
1444 do
1445 var val = new Array[Instance]
1446 for nexpr in self.n_exprs.n_exprs do
1447 var i = v.expr(nexpr)
1448 if i == null then return null
1449 val.add(i)
1450 end
1451 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1452 var elttype = mtype.arguments.first
1453 return v.array_instance(val, elttype)
1454 end
1455 end
1456
1457 redef class AStringFormExpr
1458 redef fun expr(v)
1459 do
1460 var txt = self.value.as(not null)
1461 var nat = v.native_string_instance(txt)
1462 var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null)
1463 return res
1464 end
1465 end
1466
1467 redef class ASuperstringExpr
1468 redef fun expr(v)
1469 do
1470 var array = new Array[Instance]
1471 for nexpr in n_exprs do
1472 var i = v.expr(nexpr)
1473 if i == null then return null
1474 array.add(i)
1475 end
1476 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1477 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1478 assert res != null
1479 return res
1480 end
1481 end
1482
1483 redef class ACrangeExpr
1484 redef fun expr(v)
1485 do
1486 var e1 = v.expr(self.n_expr)
1487 if e1 == null then return null
1488 var e2 = v.expr(self.n_expr2)
1489 if e2 == null then return null
1490 var mtype = v.unanchor_type(self.mtype.as(not null))
1491 var res = new MutableInstance(mtype)
1492 v.init_instance(res)
1493 v.callsite(init_callsite, [res, e1, e2])
1494 return res
1495 end
1496 end
1497
1498 redef class AOrangeExpr
1499 redef fun expr(v)
1500 do
1501 var e1 = v.expr(self.n_expr)
1502 if e1 == null then return null
1503 var e2 = v.expr(self.n_expr2)
1504 if e2 == null then return null
1505 var mtype = v.unanchor_type(self.mtype.as(not null))
1506 var res = new MutableInstance(mtype)
1507 v.init_instance(res)
1508 v.callsite(init_callsite, [res, e1, e2])
1509 return res
1510 end
1511 end
1512
1513 redef class ATrueExpr
1514 redef fun expr(v)
1515 do
1516 return v.bool_instance(true)
1517 end
1518 end
1519
1520 redef class AFalseExpr
1521 redef fun expr(v)
1522 do
1523 return v.bool_instance(false)
1524 end
1525 end
1526
1527 redef class ANullExpr
1528 redef fun expr(v)
1529 do
1530 return v.null_instance
1531 end
1532 end
1533
1534 redef class AIsaExpr
1535 redef fun expr(v)
1536 do
1537 var i = v.expr(self.n_expr)
1538 if i == null then return null
1539 var mtype = v.unanchor_type(self.cast_type.as(not null))
1540 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1541 end
1542 end
1543
1544 redef class AAsCastExpr
1545 redef fun expr(v)
1546 do
1547 var i = v.expr(self.n_expr)
1548 if i == null then return null
1549 var mtype = self.mtype.as(not null)
1550 var amtype = v.unanchor_type(mtype)
1551 if not v.is_subtype(i.mtype, amtype) then
1552 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1553 end
1554 return i
1555 end
1556 end
1557
1558 redef class AAsNotnullExpr
1559 redef fun expr(v)
1560 do
1561 var i = v.expr(self.n_expr)
1562 if i == null then return null
1563 var mtype = v.unanchor_type(self.mtype.as(not null))
1564 if i.mtype isa MNullType then
1565 fatal(v, "Cast failed")
1566 end
1567 return i
1568 end
1569 end
1570
1571 redef class AParExpr
1572 redef fun expr(v)
1573 do
1574 return v.expr(self.n_expr)
1575 end
1576 end
1577
1578 redef class AOnceExpr
1579 redef fun expr(v)
1580 do
1581 if v.onces.has_key(self) then
1582 return v.onces[self]
1583 else
1584 var res = v.expr(self.n_expr)
1585 if res == null then return null
1586 v.onces[self] = res
1587 return res
1588 end
1589 end
1590 end
1591
1592 redef class ASendExpr
1593 redef fun expr(v)
1594 do
1595 var recv = v.expr(self.n_expr)
1596 if recv == null then return null
1597 var args = [recv]
1598 for a in self.raw_arguments do
1599 var i = v.expr(a)
1600 if i == null then return null
1601 args.add(i)
1602 end
1603
1604 var res = v.callsite(callsite, args)
1605 return res
1606 end
1607 end
1608
1609 redef class ASendReassignFormExpr
1610 redef fun stmt(v)
1611 do
1612 var recv = v.expr(self.n_expr)
1613 if recv == null then return
1614 var args = [recv]
1615 for a in self.raw_arguments do
1616 var i = v.expr(a)
1617 if i == null then return
1618 args.add(i)
1619 end
1620 var value = v.expr(self.n_value)
1621 if value == null then return
1622
1623 var read = v.callsite(callsite, args)
1624 assert read != null
1625
1626 var write = v.callsite(reassign_callsite, [read, value])
1627 assert write != null
1628
1629 args.add(write)
1630
1631 v.callsite(write_callsite, args)
1632 end
1633 end
1634
1635 redef class ASuperExpr
1636 redef fun expr(v)
1637 do
1638 var recv = v.frame.arguments.first
1639 var args = [recv]
1640 for a in self.n_args.n_exprs do
1641 var i = v.expr(a)
1642 if i == null then return null
1643 args.add(i)
1644 end
1645
1646 var callsite = self.callsite
1647 if callsite != null then
1648 # Add additionnals arguments for the super init call
1649 if args.length == 1 then
1650 for i in [0..callsite.msignature.arity[ do
1651 args.add(v.frame.arguments[i+1])
1652 end
1653 end
1654 # Super init call
1655 var res = v.callsite(callsite, args)
1656 return res
1657 end
1658
1659 if args.length == 1 then
1660 args = v.frame.arguments
1661 end
1662
1663 # stantard call-next-method
1664 var mpropdef = self.mpropdef
1665 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1666 var res = v.call_without_varargs(mpropdef, args)
1667 return res
1668 end
1669 end
1670
1671 redef class ANewExpr
1672 redef fun expr(v)
1673 do
1674 var mtype = v.unanchor_type(self.mtype.as(not null))
1675 var recv: Instance = new MutableInstance(mtype)
1676 v.init_instance(recv)
1677 var args = [recv]
1678 for a in self.n_args.n_exprs do
1679 var i = v.expr(a)
1680 if i == null then return null
1681 args.add(i)
1682 end
1683 var res2 = v.callsite(callsite, args)
1684 if res2 != null then
1685 #self.debug("got {res2} from {mproperty}. drop {recv}")
1686 return res2
1687 end
1688 return recv
1689 end
1690 end
1691
1692 redef class AAttrExpr
1693 redef fun expr(v)
1694 do
1695 var recv = v.expr(self.n_expr)
1696 if recv == null then return null
1697 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1698 var mproperty = self.mproperty.as(not null)
1699 return v.read_attribute(mproperty, recv)
1700 end
1701 end
1702
1703 redef class AAttrAssignExpr
1704 redef fun stmt(v)
1705 do
1706 var recv = v.expr(self.n_expr)
1707 if recv == null then return
1708 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1709 var i = v.expr(self.n_value)
1710 if i == null then return
1711 var mproperty = self.mproperty.as(not null)
1712 v.write_attribute(mproperty, recv, i)
1713 end
1714 end
1715
1716 redef class AAttrReassignExpr
1717 redef fun stmt(v)
1718 do
1719 var recv = v.expr(self.n_expr)
1720 if recv == null then return
1721 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1722 var value = v.expr(self.n_value)
1723 if value == null then return
1724 var mproperty = self.mproperty.as(not null)
1725 var attr = v.read_attribute(mproperty, recv)
1726 var res = v.callsite(reassign_callsite, [attr, value])
1727 assert res != null
1728 v.write_attribute(mproperty, recv, res)
1729 end
1730 end
1731
1732 redef class AIssetAttrExpr
1733 redef fun expr(v)
1734 do
1735 var recv = v.expr(self.n_expr)
1736 if recv == null then return null
1737 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1738 var mproperty = self.mproperty.as(not null)
1739 return v.bool_instance(v.isset_attribute(mproperty, recv))
1740 end
1741 end
1742
1743 redef class ADebugTypeExpr
1744 redef fun stmt(v)
1745 do
1746 # do nothing
1747 end
1748 end