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