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