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