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