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