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