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