niti: rename `init_naive_interpreter` as `Interpreter::start`
[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 private 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 private 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 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 private 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 self.super_inits == null
1097 assert args.length == 1
1098 if not mpropdef.is_intro then
1099 # standard call-next-method
1100 var superpd = mpropdef.lookup_next_definition(v.mainmodule, args.first.mtype)
1101 v.call_without_varargs(superpd, args)
1102 end
1103 return null
1104 end
1105
1106 var super_inits = self.super_inits
1107 if super_inits != null then
1108 var args_of_super = args
1109 if args.length > 1 then args_of_super = [args.first]
1110 for su in super_inits do
1111 v.send(su, args_of_super)
1112 end
1113 end
1114 var recv = args.first
1115 assert recv isa MutableInstance
1116 var i = 1
1117 # Collect undefined attributes
1118 for npropdef in self.n_propdefs do
1119 if npropdef isa AAttrPropdef and not npropdef.noinit and npropdef.n_expr == null then
1120 v.write_attribute(npropdef.mpropdef.mproperty, recv, args[i])
1121 i += 1
1122 end
1123 end
1124 return null
1125 end
1126 end
1127
1128 redef class AExpr
1129 # Evaluate the node as a possible expression.
1130 # Return a possible value
1131 # NOTE: Do not call this method directly, but use `v.expr`
1132 # This method is here to be implemented by subclasses.
1133 private fun expr(v: NaiveInterpreter): nullable Instance
1134 do
1135 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1136 abort
1137 end
1138
1139 # Evaluate the node as a statement.
1140 # NOTE: Do not call this method directly, but use `v.stmt`
1141 # This method is here to be implemented by subclasses (no need to return something).
1142 private fun stmt(v: NaiveInterpreter)
1143 do
1144 expr(v)
1145 end
1146
1147 end
1148
1149 redef class ABlockExpr
1150 redef fun expr(v)
1151 do
1152 var last = self.n_expr.last
1153 for e in self.n_expr do
1154 if e == last then break
1155 v.stmt(e)
1156 if v.is_escaping then return null
1157 end
1158 return last.expr(v)
1159 end
1160
1161 redef fun stmt(v)
1162 do
1163 for e in self.n_expr do
1164 v.stmt(e)
1165 if v.is_escaping then return
1166 end
1167 end
1168 end
1169
1170 redef class AVardeclExpr
1171 redef fun stmt(v)
1172 do
1173 var ne = self.n_expr
1174 if ne != null then
1175 var i = v.expr(ne)
1176 if i == null then return
1177 v.write_variable(self.variable.as(not null), i)
1178 end
1179 end
1180 end
1181
1182 redef class AVarExpr
1183 redef fun expr(v)
1184 do
1185 return v.read_variable(self.variable.as(not null))
1186 end
1187 end
1188
1189 redef class AVarAssignExpr
1190 redef fun expr(v)
1191 do
1192 var i = v.expr(self.n_value)
1193 if i == null then return null
1194 v.write_variable(self.variable.as(not null), i)
1195 return i
1196 end
1197 end
1198
1199 redef class AVarReassignExpr
1200 redef fun stmt(v)
1201 do
1202 var variable = self.variable.as(not null)
1203 var vari = v.read_variable(variable)
1204 var value = v.expr(self.n_value)
1205 if value == null then return
1206 var res = v.callsite(reassign_callsite, [vari, value])
1207 assert res != null
1208 v.write_variable(variable, res)
1209 end
1210 end
1211
1212 redef class ASelfExpr
1213 redef fun expr(v)
1214 do
1215 return v.frame.arguments.first
1216 end
1217 end
1218
1219 redef class AContinueExpr
1220 redef fun stmt(v)
1221 do
1222 var ne = self.n_expr
1223 if ne != null then
1224 var i = v.expr(ne)
1225 if i == null then return
1226 v.escapevalue = i
1227 end
1228 v.continuemark = self.escapemark
1229 end
1230 end
1231
1232 redef class ABreakExpr
1233 redef fun stmt(v)
1234 do
1235 var ne = self.n_expr
1236 if ne != null then
1237 var i = v.expr(ne)
1238 if i == null then return
1239 v.escapevalue = i
1240 end
1241 v.breakmark = self.escapemark
1242 end
1243 end
1244
1245 redef class AReturnExpr
1246 redef fun stmt(v)
1247 do
1248 var ne = self.n_expr
1249 if ne != null then
1250 var i = v.expr(ne)
1251 if i == null then return
1252 v.escapevalue = i
1253 end
1254 v.returnmark = v.frame
1255 end
1256 end
1257
1258 redef class AAbortExpr
1259 redef fun stmt(v)
1260 do
1261 fatal(v, "Aborted")
1262 exit(1)
1263 end
1264 end
1265
1266 redef class AIfExpr
1267 redef fun expr(v)
1268 do
1269 var cond = v.expr(self.n_expr)
1270 if cond == null then return null
1271 if cond.is_true then
1272 return v.expr(self.n_then.as(not null))
1273 else
1274 return v.expr(self.n_else.as(not null))
1275 end
1276 end
1277
1278 redef fun stmt(v)
1279 do
1280 var cond = v.expr(self.n_expr)
1281 if cond == null then return
1282 if cond.is_true then
1283 v.stmt(self.n_then)
1284 else
1285 v.stmt(self.n_else)
1286 end
1287 end
1288 end
1289
1290 redef class AIfexprExpr
1291 redef fun expr(v)
1292 do
1293 var cond = v.expr(self.n_expr)
1294 if cond == null then return null
1295 if cond.is_true then
1296 return v.expr(self.n_then)
1297 else
1298 return v.expr(self.n_else)
1299 end
1300 end
1301 end
1302
1303 redef class ADoExpr
1304 redef fun stmt(v)
1305 do
1306 v.stmt(self.n_block)
1307 v.is_break(self.escapemark) # Clear the break (if any)
1308 end
1309 end
1310
1311 redef class AWhileExpr
1312 redef fun stmt(v)
1313 do
1314 loop
1315 var cond = v.expr(self.n_expr)
1316 if cond == null then return
1317 if not cond.is_true then return
1318 v.stmt(self.n_block)
1319 if v.is_break(self.escapemark) then return
1320 v.is_continue(self.escapemark) # Clear the break
1321 if v.is_escaping then return
1322 end
1323 end
1324 end
1325
1326 redef class ALoopExpr
1327 redef fun stmt(v)
1328 do
1329 loop
1330 v.stmt(self.n_block)
1331 if v.is_break(self.escapemark) then return
1332 v.is_continue(self.escapemark) # Clear the break
1333 if v.is_escaping then return
1334 end
1335 end
1336 end
1337
1338 redef class AForExpr
1339 redef fun stmt(v)
1340 do
1341 var col = v.expr(self.n_expr)
1342 if col == null then return
1343 if col.mtype isa MNullType then fatal(v, "Receiver is null")
1344
1345 #self.debug("col {col}")
1346 var iter = v.callsite(method_iterator, [col]).as(not null)
1347 #self.debug("iter {iter}")
1348 loop
1349 var isok = v.callsite(method_is_ok, [iter]).as(not null)
1350 if not isok.is_true then return
1351 if self.variables.length == 1 then
1352 var item = v.callsite(method_item, [iter]).as(not null)
1353 #self.debug("item {item}")
1354 v.write_variable(self.variables.first, item)
1355 else if self.variables.length == 2 then
1356 var key = v.callsite(method_key, [iter]).as(not null)
1357 v.write_variable(self.variables[0], key)
1358 var item = v.callsite(method_item, [iter]).as(not null)
1359 v.write_variable(self.variables[1], item)
1360 else
1361 abort
1362 end
1363 v.stmt(self.n_block)
1364 if v.is_break(self.escapemark) then return
1365 v.is_continue(self.escapemark) # Clear the break
1366 if v.is_escaping then return
1367 v.callsite(method_next, [iter])
1368 end
1369 end
1370 end
1371
1372 redef class AAssertExpr
1373 redef fun stmt(v)
1374 do
1375 var cond = v.expr(self.n_expr)
1376 if cond == null then return
1377 if not cond.is_true then
1378 v.stmt(self.n_else)
1379 if v.is_escaping then return
1380 var nid = self.n_id
1381 if nid != null then
1382 fatal(v, "Assert '{nid.text}' failed")
1383 else
1384 fatal(v, "Assert failed")
1385 end
1386 exit(1)
1387 end
1388 end
1389 end
1390
1391 redef class AOrExpr
1392 redef fun expr(v)
1393 do
1394 var cond = v.expr(self.n_expr)
1395 if cond == null then return null
1396 if cond.is_true then return cond
1397 return v.expr(self.n_expr2)
1398 end
1399 end
1400
1401 redef class AImpliesExpr
1402 redef fun expr(v)
1403 do
1404 var cond = v.expr(self.n_expr)
1405 if cond == null then return null
1406 if not cond.is_true then return v.true_instance
1407 return v.expr(self.n_expr2)
1408 end
1409 end
1410
1411 redef class AAndExpr
1412 redef fun expr(v)
1413 do
1414 var cond = v.expr(self.n_expr)
1415 if cond == null then return null
1416 if not cond.is_true then return cond
1417 return v.expr(self.n_expr2)
1418 end
1419 end
1420
1421 redef class ANotExpr
1422 redef fun expr(v)
1423 do
1424 var cond = v.expr(self.n_expr)
1425 if cond == null then return null
1426 return v.bool_instance(not cond.is_true)
1427 end
1428 end
1429
1430 redef class AOrElseExpr
1431 redef fun expr(v)
1432 do
1433 var i = v.expr(self.n_expr)
1434 if i == null then return null
1435 if i != v.null_instance then return i
1436 return v.expr(self.n_expr2)
1437 end
1438 end
1439
1440 redef class AIntExpr
1441 redef fun expr(v)
1442 do
1443 return v.int_instance(self.value.as(not null))
1444 end
1445 end
1446
1447 redef class AFloatExpr
1448 redef fun expr(v)
1449 do
1450 return v.float_instance(self.value.as(not null))
1451 end
1452 end
1453
1454 redef class ACharExpr
1455 redef fun expr(v)
1456 do
1457 return v.char_instance(self.value.as(not null))
1458 end
1459 end
1460
1461 redef class AArrayExpr
1462 redef fun expr(v)
1463 do
1464 var val = new Array[Instance]
1465 for nexpr in self.n_exprs.n_exprs do
1466 var i = v.expr(nexpr)
1467 if i == null then return null
1468 val.add(i)
1469 end
1470 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1471 var elttype = mtype.arguments.first
1472 return v.array_instance(val, elttype)
1473 end
1474 end
1475
1476 redef class AStringFormExpr
1477 redef fun expr(v)
1478 do
1479 var txt = self.value.as(not null)
1480 var nat = v.native_string_instance(txt)
1481 var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null)
1482 return res
1483 end
1484 end
1485
1486 redef class ASuperstringExpr
1487 redef fun expr(v)
1488 do
1489 var array = new Array[Instance]
1490 for nexpr in n_exprs do
1491 var i = v.expr(nexpr)
1492 if i == null then return null
1493 array.add(i)
1494 end
1495 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1496 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1497 assert res != null
1498 return res
1499 end
1500 end
1501
1502 redef class ACrangeExpr
1503 redef fun expr(v)
1504 do
1505 var e1 = v.expr(self.n_expr)
1506 if e1 == null then return null
1507 var e2 = v.expr(self.n_expr2)
1508 if e2 == null then return null
1509 var mtype = v.unanchor_type(self.mtype.as(not null))
1510 var res = new MutableInstance(mtype)
1511 v.init_instance(res)
1512 v.callsite(init_callsite, [res, e1, e2])
1513 return res
1514 end
1515 end
1516
1517 redef class AOrangeExpr
1518 redef fun expr(v)
1519 do
1520 var e1 = v.expr(self.n_expr)
1521 if e1 == null then return null
1522 var e2 = v.expr(self.n_expr2)
1523 if e2 == null then return null
1524 var mtype = v.unanchor_type(self.mtype.as(not null))
1525 var res = new MutableInstance(mtype)
1526 v.init_instance(res)
1527 v.callsite(init_callsite, [res, e1, e2])
1528 return res
1529 end
1530 end
1531
1532 redef class ATrueExpr
1533 redef fun expr(v)
1534 do
1535 return v.bool_instance(true)
1536 end
1537 end
1538
1539 redef class AFalseExpr
1540 redef fun expr(v)
1541 do
1542 return v.bool_instance(false)
1543 end
1544 end
1545
1546 redef class ANullExpr
1547 redef fun expr(v)
1548 do
1549 return v.null_instance
1550 end
1551 end
1552
1553 redef class AIsaExpr
1554 redef fun expr(v)
1555 do
1556 var i = v.expr(self.n_expr)
1557 if i == null then return null
1558 var mtype = v.unanchor_type(self.cast_type.as(not null))
1559 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1560 end
1561 end
1562
1563 redef class AAsCastExpr
1564 redef fun expr(v)
1565 do
1566 var i = v.expr(self.n_expr)
1567 if i == null then return null
1568 var mtype = self.mtype.as(not null)
1569 var amtype = v.unanchor_type(mtype)
1570 if not v.is_subtype(i.mtype, amtype) then
1571 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1572 end
1573 return i
1574 end
1575 end
1576
1577 redef class AAsNotnullExpr
1578 redef fun expr(v)
1579 do
1580 var i = v.expr(self.n_expr)
1581 if i == null then return null
1582 var mtype = v.unanchor_type(self.mtype.as(not null))
1583 if i.mtype isa MNullType then
1584 fatal(v, "Cast failed")
1585 end
1586 return i
1587 end
1588 end
1589
1590 redef class AParExpr
1591 redef fun expr(v)
1592 do
1593 return v.expr(self.n_expr)
1594 end
1595 end
1596
1597 redef class AOnceExpr
1598 redef fun expr(v)
1599 do
1600 if v.onces.has_key(self) then
1601 return v.onces[self]
1602 else
1603 var res = v.expr(self.n_expr)
1604 if res == null then return null
1605 v.onces[self] = res
1606 return res
1607 end
1608 end
1609 end
1610
1611 redef class ASendExpr
1612 redef fun expr(v)
1613 do
1614 var recv = v.expr(self.n_expr)
1615 if recv == null then return null
1616 var args = [recv]
1617 for a in self.raw_arguments do
1618 var i = v.expr(a)
1619 if i == null then return null
1620 args.add(i)
1621 end
1622
1623 var res = v.callsite(callsite, args)
1624 return res
1625 end
1626 end
1627
1628 redef class ASendReassignFormExpr
1629 redef fun stmt(v)
1630 do
1631 var recv = v.expr(self.n_expr)
1632 if recv == null then return
1633 var args = [recv]
1634 for a in self.raw_arguments do
1635 var i = v.expr(a)
1636 if i == null then return
1637 args.add(i)
1638 end
1639 var value = v.expr(self.n_value)
1640 if value == null then return
1641
1642 var read = v.callsite(callsite, args)
1643 assert read != null
1644
1645 var write = v.callsite(reassign_callsite, [read, value])
1646 assert write != null
1647
1648 args.add(write)
1649
1650 v.callsite(write_callsite, args)
1651 end
1652 end
1653
1654 redef class ASuperExpr
1655 redef fun expr(v)
1656 do
1657 var recv = v.frame.arguments.first
1658 var args = [recv]
1659 for a in self.n_args.n_exprs do
1660 var i = v.expr(a)
1661 if i == null then return null
1662 args.add(i)
1663 end
1664
1665 var callsite = self.callsite
1666 if callsite != null then
1667 # Add additionnals arguments for the super init call
1668 if args.length == 1 then
1669 for i in [0..callsite.msignature.arity[ do
1670 args.add(v.frame.arguments[i+1])
1671 end
1672 end
1673 # Super init call
1674 var res = v.callsite(callsite, args)
1675 return res
1676 end
1677
1678 if args.length == 1 then
1679 args = v.frame.arguments
1680 end
1681
1682 # stantard call-next-method
1683 var mpropdef = self.mpropdef
1684 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1685 var res = v.call_without_varargs(mpropdef, args)
1686 return res
1687 end
1688 end
1689
1690 redef class ANewExpr
1691 redef fun expr(v)
1692 do
1693 var mtype = v.unanchor_type(self.mtype.as(not null))
1694 var recv: Instance = new MutableInstance(mtype)
1695 v.init_instance(recv)
1696 var args = [recv]
1697 for a in self.n_args.n_exprs do
1698 var i = v.expr(a)
1699 if i == null then return null
1700 args.add(i)
1701 end
1702 var res2 = v.callsite(callsite, args)
1703 if res2 != null then
1704 #self.debug("got {res2} from {mproperty}. drop {recv}")
1705 return res2
1706 end
1707 return recv
1708 end
1709 end
1710
1711 redef class AAttrExpr
1712 redef fun expr(v)
1713 do
1714 var recv = v.expr(self.n_expr)
1715 if recv == null then return null
1716 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1717 var mproperty = self.mproperty.as(not null)
1718 return v.read_attribute(mproperty, recv)
1719 end
1720 end
1721
1722 redef class AAttrAssignExpr
1723 redef fun stmt(v)
1724 do
1725 var recv = v.expr(self.n_expr)
1726 if recv == null then return
1727 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1728 var i = v.expr(self.n_value)
1729 if i == null then return
1730 var mproperty = self.mproperty.as(not null)
1731 v.write_attribute(mproperty, recv, i)
1732 end
1733 end
1734
1735 redef class AAttrReassignExpr
1736 redef fun stmt(v)
1737 do
1738 var recv = v.expr(self.n_expr)
1739 if recv == null then return
1740 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1741 var value = v.expr(self.n_value)
1742 if value == null then return
1743 var mproperty = self.mproperty.as(not null)
1744 var attr = v.read_attribute(mproperty, recv)
1745 var res = v.callsite(reassign_callsite, [attr, value])
1746 assert res != null
1747 v.write_attribute(mproperty, recv, res)
1748 end
1749 end
1750
1751 redef class AIssetAttrExpr
1752 redef fun expr(v)
1753 do
1754 var recv = v.expr(self.n_expr)
1755 if recv == null then return null
1756 if recv.mtype isa MNullType then fatal(v, "Receiver is null")
1757 var mproperty = self.mproperty.as(not null)
1758 return v.bool_instance(v.isset_attribute(mproperty, recv))
1759 end
1760 end
1761
1762 redef class ADebugTypeExpr
1763 redef fun stmt(v)
1764 do
1765 # do nothing
1766 end
1767 end