5d996ff7d9c238eb9a4b127ad123dbae58624403
[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. Expected `{implicit_cast_to}`, got `{i.mtype}`")
174 end
175
176 #n.debug("OUT Execute expr: value is {i}")
177 #if not is_subtype(i.mtype, n.mtype.as(not null)) then n.debug("Expected {n.mtype.as(not null)} got {i}")
178 frame.current_node = old
179 return i
180 end
181
182 # Evaluate `n` as a statement in the current context.
183 # Do nothing if `n` is null.
184 # If `n` cannot be evaluated, then aborts.
185 fun stmt(n: nullable AExpr)
186 do
187 if n != null then
188 var frame = self.frame
189 var old = frame.current_node
190 frame.current_node = n
191 #n.debug("Execute stmt")
192 n.stmt(self)
193 frame.current_node = old
194 end
195 end
196
197 # Map used to store values of nodes that must be evaluated once in the system (`AOnceExpr`)
198 var onces: Map[ANode, Instance] = new HashMap[ANode, Instance]
199
200 # Return the boolean instance associated with `val`.
201 fun bool_instance(val: Bool): Instance
202 do
203 if val then return self.true_instance else return self.false_instance
204 end
205
206 # Return the integer instance associated with `val`.
207 fun int_instance(val: Int): Instance
208 do
209 var ic = self.mainmodule.get_primitive_class("Int")
210 return new PrimitiveInstance[Int](ic.mclass_type, val)
211 end
212
213 # Return the char instance associated with `val`.
214 fun char_instance(val: Char): Instance
215 do
216 var ic = self.mainmodule.get_primitive_class("Char")
217 return new PrimitiveInstance[Char](ic.mclass_type, val)
218 end
219
220 # Return the float instance associated with `val`.
221 fun float_instance(val: Float): Instance
222 do
223 var ic = self.mainmodule.get_primitive_class("Float")
224 return new PrimitiveInstance[Float](ic.mclass_type, val)
225 end
226
227 # The unique intance of the `true` value.
228 var true_instance: Instance
229
230 # The unique intance of the `false` value.
231 var false_instance: Instance
232
233 # The unique intance of the `null` value.
234 var null_instance: Instance
235
236 # Return a new array made of `values`.
237 # The dynamic type of the result is Array[elttype].
238 fun array_instance(values: Array[Instance], elttype: MType): Instance
239 do
240 assert not elttype.need_anchor
241 var nat = new PrimitiveInstance[Array[Instance]](self.mainmodule.get_primitive_class("NativeArray").get_mtype([elttype]), values)
242 var mtype = self.mainmodule.get_primitive_class("Array").get_mtype([elttype])
243 var res = new MutableInstance(mtype)
244 self.init_instance(res)
245 self.send(self.force_get_primitive_method("with_native", mtype), [res, nat, self.int_instance(values.length)])
246 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 var amtype = mtype.anchor_to(self.mainmodule, anchor)
380 if not args[i+1].mtype.is_subtype(self.mainmodule, anchor, amtype) then
381 node.fatal(self, "Cast failed. Expected `{mtype}`, got `{args[i+1].mtype}`")
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_same_instance(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_same_instance(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 == "is_same_instance" then
658 return v.bool_instance(args[1] != null and args[0].eq_is(args[1]))
659 else if pname == "exit" then
660 exit(args[1].to_i)
661 abort
662 else if pname == "sys" then
663 return v.mainobj
664 else if cname == "Int" then
665 if pname == "unary -" then
666 return v.int_instance(-args[0].to_i)
667 else if pname == "succ" then
668 return v.int_instance(args[0].to_i + 1)
669 else if pname == "prec" then
670 return v.int_instance(args[0].to_i - 1)
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.int_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.bool_instance(args[0].to_i >= args[1].to_i)
689 else if pname == "<=>" then
690 return v.int_instance(args[0].to_i <=> args[1].to_i)
691 else if pname == "ascii" then
692 return v.char_instance(args[0].to_i.ascii)
693 else if pname == "to_f" then
694 return v.float_instance(args[0].to_i.to_f)
695 else if pname == "lshift" then
696 return v.int_instance(args[0].to_i.lshift(args[1].to_i))
697 else if pname == "rshift" then
698 return v.int_instance(args[0].to_i.rshift(args[1].to_i))
699 end
700 else if cname == "Char" then
701 var recv = args[0].val.as(Char)
702 if pname == "ascii" then
703 return v.int_instance(recv.ascii)
704 else if pname == "succ" then
705 return v.char_instance(recv.succ)
706 else if pname == "prec" then
707 return v.char_instance(recv.prec)
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.bool_instance(recv >= args[1].val.as(Char))
716 else if pname == "<=>" then
717 return v.int_instance(recv <=> args[1].val.as(Char))
718 end
719 else if cname == "Float" then
720 var recv = args[0].to_f
721 if pname == "unary -" then
722 return v.float_instance(-recv)
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.float_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 == ">=" then
738 return v.bool_instance(recv >= args[1].to_f)
739 else if pname == "to_i" then
740 return v.int_instance(recv.to_i)
741 end
742 else if cname == "NativeString" then
743 var recvval = args.first.val.as(Buffer)
744 if pname == "[]" then
745 var arg1 = args[1].to_i
746 if arg1 >= recvval.length or arg1 < 0 then
747 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
748 end
749 return v.char_instance(recvval[arg1])
750 else if pname == "[]=" then
751 var arg1 = args[1].to_i
752 if arg1 >= recvval.length or arg1 < 0 then
753 debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
754 end
755 recvval[arg1] = args[2].val.as(Char)
756 return null
757 else if pname == "copy_to" then
758 # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
759 var destval = args[1].val.as(Buffer)
760 var lenval = args[2].to_i
761 var fromval = args[3].to_i
762 var toval = args[4].to_i
763 if fromval < 0 then
764 debug("Illegal access on {recvval} for element {fromval}/{recvval.length}")
765 end
766 if fromval + lenval >= recvval.length then
767 debug("Illegal access on {recvval} for element {fromval}+{lenval}/{recvval.length}")
768 end
769 if toval < 0 then
770 debug("Illegal access on {destval} for element {toval}/{destval.length}")
771 end
772 if toval + lenval >= destval.length then
773 debug("Illegal access on {destval} for element {toval}+{lenval}/{destval.length}")
774 end
775 recvval.copy(fromval, lenval, destval, toval)
776 return null
777 else if pname == "atoi" then
778 return v.int_instance(recvval.to_i)
779 end
780 else if pname == "calloc_string" then
781 return v.native_string_instance("!" * args[1].to_i)
782 else if cname == "NativeArray" then
783 var recvval = args.first.val.as(Array[Instance])
784 if pname == "[]" then
785 if args[1].to_i >= recvval.length or args[1].to_i < 0 then
786 debug("Illegal access on {recvval} for element {args[1].to_i}/{recvval.length}")
787 end
788 return recvval[args[1].to_i]
789 else if pname == "[]=" then
790 recvval[args[1].to_i] = args[2]
791 return null
792 else if pname == "copy_to" then
793 recvval.copy(0, args[2].to_i, args[1].val.as(Array[Instance]), 0)
794 return null
795 end
796 else if pname == "calloc_array" then
797 var recvtype = args.first.mtype.as(MClassType)
798 var mtype: MType
799 mtype = recvtype.supertype_to(v.mainmodule, recvtype, v.mainmodule.get_primitive_class("ArrayCapable"))
800 mtype = mtype.arguments.first
801 var val = new Array[Instance].filled_with(v.null_instance, args[1].to_i)
802 return new PrimitiveInstance[Array[Instance]](v.mainmodule.get_primitive_class("NativeArray").get_mtype([mtype]), val)
803 else if pname == "native_argc" then
804 return v.int_instance(v.arguments.length)
805 else if pname == "native_argv" then
806 var txt = v.arguments[args[1].to_i]
807 return v.native_string_instance(txt)
808 end
809 fatal(v, "NOT YET IMPLEMENTED intern {mpropdef}")
810 abort
811 end
812 end
813
814 redef class AbstractArray[E]
815 fun copy(start: Int, len: Int, dest: AbstractArray[E], new_start: Int)
816 do
817 self.copy_to(start, len, dest, new_start)
818 end
819 end
820
821 redef class AExternInitPropdef
822 redef fun call(v, mpropdef, args)
823 do
824 var pname = mpropdef.mproperty.name
825 var cname = mpropdef.mclassdef.mclass.name
826 if pname == "native_stdout" then
827 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stdout)
828 else if pname == "native_stdin" then
829 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, stdin)
830 else if pname == "native_stderr" then
831 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, stderr)
832 else if pname == "io_open_read" then
833 var a1 = args[1].val.as(Buffer)
834 return new PrimitiveInstance[IStream](mpropdef.mclassdef.mclass.mclass_type, new IFStream.open(a1.to_s))
835 else if pname == "io_open_write" then
836 var a1 = args[1].val.as(Buffer)
837 return new PrimitiveInstance[OStream](mpropdef.mclassdef.mclass.mclass_type, new OFStream.open(a1.to_s))
838 end
839 fatal(v, "NOT YET IMPLEMENTED extern init {mpropdef}")
840 abort
841 end
842 end
843
844 redef class AExternMethPropdef
845 super TablesCapable
846 redef fun call(v, mpropdef, args)
847 do
848 var pname = mpropdef.mproperty.name
849 var cname = mpropdef.mclassdef.mclass.name
850 if cname == "Int" then
851 var recvval = args.first.val.as(Int)
852 if pname == "rand" then
853 var res = recvval.rand
854 return v.int_instance(res)
855 else if pname == "native_int_to_s" then
856 return v.native_string_instance(recvval.to_s)
857 end
858 else if cname == "NativeFile" then
859 var recvval = args.first.val
860 if pname == "io_write" then
861 var a1 = args[1].val.as(Buffer)
862 recvval.as(OStream).write(a1.substring(0, args[2].to_i))
863 return args[2]
864 else if pname == "io_read" then
865 var str = recvval.as(IStream).read(args[2].to_i)
866 var a1 = args[1].val.as(Buffer)
867 new Buffer.from(str).copy(0, str.length, a1, 0)
868 return v.int_instance(str.length)
869 else if pname == "io_close" then
870 recvval.as(IOS).close
871 return v.int_instance(0)
872 end
873 else if cname == "NativeString" then
874 var recvval = args.first.val.as(Buffer)
875 if pname == "file_exists" then
876 return v.bool_instance(recvval.to_s.file_exists)
877 else if pname == "file_mkdir" then
878 recvval.to_s.mkdir
879 return null
880 else if pname == "file_chdir" then
881 recvval.to_s.chdir
882 return null
883 else if pname == "get_environ" then
884 var txt = recvval.to_s.environ
885 return v.native_string_instance(txt)
886 else if pname == "system" then
887 var res = sys.system(recvval.to_s)
888 return v.int_instance(res)
889 else if pname == "atof" then
890 return v.float_instance(recvval.to_f)
891 end
892 else if cname == "Int" then
893 if pname == "rand" then
894 return v.int_instance(args[0].to_i.rand)
895 end
896 else if cname == "Float" then
897 if pname == "cos" then
898 return v.float_instance(args[0].to_f.cos)
899 else if pname == "sin" then
900 return v.float_instance(args[0].to_f.sin)
901 else if pname == "tan" then
902 return v.float_instance(args[0].to_f.tan)
903 else if pname == "acos" then
904 return v.float_instance(args[0].to_f.acos)
905 else if pname == "asin" then
906 return v.float_instance(args[0].to_f.asin)
907 else if pname == "atan" then
908 return v.float_instance(args[0].to_f.atan)
909 else if pname == "sqrt" then
910 return v.float_instance(args[0].to_f.sqrt)
911 else if pname == "exp" then
912 return v.float_instance(args[0].to_f.exp)
913 else if pname == "log" then
914 return v.float_instance(args[0].to_f.log)
915 else if pname == "pow" then
916 return v.float_instance(args[0].to_f.pow(args[1].to_f))
917 else if pname == "rand" then
918 return v.float_instance(args[0].to_f.rand)
919 end
920 else if pname == "native_argc" then
921 return v.int_instance(v.arguments.length)
922 else if pname == "native_argv" then
923 var txt = v.arguments[args[1].to_i]
924 return v.native_string_instance(txt)
925 else if pname == "get_time" then
926 return v.int_instance(get_time)
927 else if pname == "srand_from" then
928 srand_from(args[1].to_i)
929 return null
930 else if pname == "atan2" then
931 return v.float_instance(atan2(args[1].to_f, args[2].to_f))
932 else if pname == "pi" then
933 return v.float_instance(pi)
934 else if pname == "lexer_goto" then
935 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
936 else if pname == "lexer_accept" then
937 return v.int_instance(lexer_accept(args[1].to_i))
938 else if pname == "parser_goto" then
939 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
940 else if pname == "parser_action" then
941 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
942 else if pname == "file_getcwd" then
943 return v.native_string_instance(getcwd)
944 end
945 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
946 abort
947 end
948 end
949
950 redef class AAttrPropdef
951 redef fun call(v, mpropdef, args)
952 do
953 var recv = args.first
954 assert recv isa MutableInstance
955 var attr = self.mpropdef.mproperty
956 if args.length == 1 then
957 return v.read_attribute(attr, recv)
958 else
959 assert args.length == 2
960 recv.attributes[attr] = args[1]
961 return null
962 end
963 end
964
965 # Evaluate and set the default value of the attribute in `recv`
966 private fun init_expr(v: NaiveInterpreter, recv: Instance)
967 do
968 assert recv isa MutableInstance
969 var nexpr = self.n_expr
970 if nexpr != null then
971 var f = new Frame(self, self.mpropdef.as(not null), [recv])
972 v.frames.unshift(f)
973 var val = v.expr(nexpr)
974 assert val != null
975 v.frames.shift
976 assert not v.is_escaping
977 recv.attributes[self.mpropdef.mproperty] = val
978 return
979 end
980 var mtype = self.mpropdef.static_mtype.as(not null)
981 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
982 if mtype isa MNullableType then
983 recv.attributes[self.mpropdef.mproperty] = v.null_instance
984 end
985 end
986 end
987
988 redef class ADeferredMethPropdef
989 redef fun call(v, mpropdef, args)
990 do
991 fatal(v, "Abstract method `{mpropdef.mproperty.name}` called on `{args.first.mtype}`")
992 abort
993 end
994 end
995
996 redef class AClassdef
997 # Execute an implicit `mpropdef` associated with the current node.
998 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
999 do
1000 var super_inits = self.super_inits
1001 if super_inits != null then
1002 assert args.length == 1
1003 for su in super_inits do
1004 v.send(su, args)
1005 end
1006 return null
1007 end
1008 var recv = args.first
1009 assert recv isa MutableInstance
1010 var i = 1
1011 # Collect undefined attributes
1012 for npropdef in self.n_propdefs do
1013 if npropdef isa AAttrPropdef and npropdef.n_expr == null then
1014 recv.attributes[npropdef.mpropdef.mproperty] = args[i]
1015 i += 1
1016 end
1017 end
1018 return null
1019 end
1020 end
1021
1022 redef class AExpr
1023 # Evaluate the node as a possible expression.
1024 # Return a possible value
1025 # NOTE: Do not call this method directly, but use `v.expr`
1026 # This method is here to be implemented by subclasses.
1027 private fun expr(v: NaiveInterpreter): nullable Instance
1028 do
1029 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1030 abort
1031 end
1032
1033 # Evaluate the node as a statement.
1034 # NOTE: Do not call this method directly, but use `v.stmt`
1035 # This method is here to be implemented by subclasses (no need to return something).
1036 private fun stmt(v: NaiveInterpreter)
1037 do
1038 expr(v)
1039 end
1040
1041 end
1042
1043 redef class ABlockExpr
1044 redef fun expr(v)
1045 do
1046 var last = self.n_expr.last
1047 for e in self.n_expr do
1048 if e == last then break
1049 v.stmt(e)
1050 if v.is_escaping then return null
1051 end
1052 return last.expr(v)
1053 end
1054
1055 redef fun stmt(v)
1056 do
1057 for e in self.n_expr do
1058 v.stmt(e)
1059 if v.is_escaping then return
1060 end
1061 end
1062 end
1063
1064 redef class AVardeclExpr
1065 redef fun stmt(v)
1066 do
1067 var ne = self.n_expr
1068 if ne != null then
1069 var i = v.expr(ne)
1070 if i == null then return
1071 v.frame.map[self.variable.as(not null)] = i
1072 end
1073 end
1074 end
1075
1076 redef class AVarExpr
1077 redef fun expr(v)
1078 do
1079 return v.frame.map[self.variable.as(not null)]
1080 end
1081 end
1082
1083 redef class AVarAssignExpr
1084 redef fun expr(v)
1085 do
1086 var i = v.expr(self.n_value)
1087 if i == null then return null
1088 v.frame.map[self.variable.as(not null)] = i
1089 return i
1090 end
1091 end
1092
1093 redef class AVarReassignExpr
1094 redef fun stmt(v)
1095 do
1096 var vari = v.frame.map[self.variable.as(not null)]
1097 var value = v.expr(self.n_value)
1098 if value == null then return
1099 var res = v.send(reassign_property.mproperty, [vari, value])
1100 assert res != null
1101 v.frame.map[self.variable.as(not null)] = res
1102 end
1103 end
1104
1105 redef class ASelfExpr
1106 redef fun expr(v)
1107 do
1108 return v.frame.arguments.first
1109 end
1110 end
1111
1112 redef class AContinueExpr
1113 redef fun stmt(v)
1114 do
1115 var ne = self.n_expr
1116 if ne != null then
1117 var i = v.expr(ne)
1118 if i == null then return
1119 v.escapevalue = i
1120 end
1121 v.continuemark = self.escapemark
1122 end
1123 end
1124
1125 redef class ABreakExpr
1126 redef fun stmt(v)
1127 do
1128 var ne = self.n_expr
1129 if ne != null then
1130 var i = v.expr(ne)
1131 if i == null then return
1132 v.escapevalue = i
1133 end
1134 v.breakmark = self.escapemark
1135 end
1136 end
1137
1138 redef class AReturnExpr
1139 redef fun stmt(v)
1140 do
1141 var ne = self.n_expr
1142 if ne != null then
1143 var i = v.expr(ne)
1144 if i == null then return
1145 v.escapevalue = i
1146 end
1147 v.returnmark = v.frame
1148 end
1149 end
1150
1151 redef class AAbortExpr
1152 redef fun stmt(v)
1153 do
1154 fatal(v, "Aborted")
1155 exit(1)
1156 end
1157 end
1158
1159 redef class AIfExpr
1160 redef fun expr(v)
1161 do
1162 var cond = v.expr(self.n_expr)
1163 if cond == null then return null
1164 if cond.is_true then
1165 return v.expr(self.n_then.as(not null))
1166 else
1167 return v.expr(self.n_else.as(not null))
1168 end
1169 end
1170
1171 redef fun stmt(v)
1172 do
1173 var cond = v.expr(self.n_expr)
1174 if cond == null then return
1175 if cond.is_true then
1176 v.stmt(self.n_then)
1177 else
1178 v.stmt(self.n_else)
1179 end
1180 end
1181 end
1182
1183 redef class AIfexprExpr
1184 redef fun expr(v)
1185 do
1186 var cond = v.expr(self.n_expr)
1187 if cond == null then return null
1188 if cond.is_true then
1189 return v.expr(self.n_then)
1190 else
1191 return v.expr(self.n_else)
1192 end
1193 end
1194 end
1195
1196 redef class ADoExpr
1197 redef fun stmt(v)
1198 do
1199 v.stmt(self.n_block)
1200 v.is_break(self.escapemark) # Clear the break (if any)
1201 end
1202 end
1203
1204 redef class AWhileExpr
1205 redef fun stmt(v)
1206 do
1207 loop
1208 var cond = v.expr(self.n_expr)
1209 if cond == null then return
1210 if not cond.is_true then return
1211 v.stmt(self.n_block)
1212 if v.is_break(self.escapemark) then return
1213 v.is_continue(self.escapemark) # Clear the break
1214 if v.is_escaping then return
1215 end
1216 end
1217 end
1218
1219 redef class ALoopExpr
1220 redef fun stmt(v)
1221 do
1222 loop
1223 v.stmt(self.n_block)
1224 if v.is_break(self.escapemark) then return
1225 v.is_continue(self.escapemark) # Clear the break
1226 if v.is_escaping then return
1227 end
1228 end
1229 end
1230
1231 redef class AForExpr
1232 redef fun stmt(v)
1233 do
1234 var col = v.expr(self.n_expr)
1235 if col == null then return
1236 #self.debug("col {col}")
1237 var iter = v.send(v.force_get_primitive_method("iterator", col.mtype), [col]).as(not null)
1238 #self.debug("iter {iter}")
1239 loop
1240 var isok = v.send(v.force_get_primitive_method("is_ok", iter.mtype), [iter]).as(not null)
1241 if not isok.is_true then return
1242 if self.variables.length == 1 then
1243 var item = v.send(v.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
1244 #self.debug("item {item}")
1245 v.frame.map[self.variables.first] = item
1246 else if self.variables.length == 2 then
1247 var key = v.send(v.force_get_primitive_method("key", iter.mtype), [iter]).as(not null)
1248 v.frame.map[self.variables[0]] = key
1249 var item = v.send(v.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
1250 v.frame.map[self.variables[1]] = item
1251 else
1252 abort
1253 end
1254 v.stmt(self.n_block)
1255 if v.is_break(self.escapemark) then return
1256 v.is_continue(self.escapemark) # Clear the break
1257 if v.is_escaping then return
1258 v.send(v.force_get_primitive_method("next", iter.mtype), [iter])
1259 end
1260 end
1261 end
1262
1263 redef class AAssertExpr
1264 redef fun stmt(v)
1265 do
1266 var cond = v.expr(self.n_expr)
1267 if cond == null then return
1268 if not cond.is_true then
1269 v.stmt(self.n_else)
1270 if v.is_escaping then return
1271 var nid = self.n_id
1272 if nid != null then
1273 fatal(v, "Assert '{nid.text}' failed")
1274 else
1275 fatal(v, "Assert failed")
1276 end
1277 exit(1)
1278 end
1279 end
1280 end
1281
1282 redef class AOrExpr
1283 redef fun expr(v)
1284 do
1285 var cond = v.expr(self.n_expr)
1286 if cond == null then return null
1287 if cond.is_true then return cond
1288 return v.expr(self.n_expr2)
1289 end
1290 end
1291
1292 redef class AImpliesExpr
1293 redef fun expr(v)
1294 do
1295 var cond = v.expr(self.n_expr)
1296 if cond == null then return null
1297 if not cond.is_true then return v.true_instance
1298 return v.expr(self.n_expr2)
1299 end
1300 end
1301
1302 redef class AAndExpr
1303 redef fun expr(v)
1304 do
1305 var cond = v.expr(self.n_expr)
1306 if cond == null then return null
1307 if not cond.is_true then return cond
1308 return v.expr(self.n_expr2)
1309 end
1310 end
1311
1312 redef class ANotExpr
1313 redef fun expr(v)
1314 do
1315 var cond = v.expr(self.n_expr)
1316 if cond == null then return null
1317 return v.bool_instance(not cond.is_true)
1318 end
1319 end
1320
1321 redef class AOrElseExpr
1322 redef fun expr(v)
1323 do
1324 var i = v.expr(self.n_expr)
1325 if i == null then return null
1326 if i != v.null_instance then return i
1327 return v.expr(self.n_expr2)
1328 end
1329 end
1330
1331 redef class AEeExpr
1332 redef fun expr(v)
1333 do
1334 var i = v.expr(self.n_expr)
1335 if i == null then return null
1336 var i2 = v.expr(self.n_expr2)
1337 if i2 == null then return null
1338 return v.bool_instance(i.eq_is(i2))
1339 end
1340 end
1341
1342 redef class AIntExpr
1343 redef fun expr(v)
1344 do
1345 return v.int_instance(self.value.as(not null))
1346 end
1347 end
1348
1349 redef class AFloatExpr
1350 redef fun expr(v)
1351 do
1352 return v.float_instance(self.value.as(not null))
1353 end
1354 end
1355
1356 redef class ACharExpr
1357 redef fun expr(v)
1358 do
1359 return v.char_instance(self.value.as(not null))
1360 end
1361 end
1362
1363 redef class AArrayExpr
1364 redef fun expr(v)
1365 do
1366 var val = new Array[Instance]
1367 for nexpr in self.n_exprs.n_exprs do
1368 var i = v.expr(nexpr)
1369 if i == null then return null
1370 val.add(i)
1371 end
1372 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1373 var elttype = mtype.arguments.first
1374 return v.array_instance(val, elttype)
1375 end
1376 end
1377
1378 redef class AStringFormExpr
1379 redef fun expr(v)
1380 do
1381 var txt = self.value.as(not null)
1382 var nat = v.native_string_instance(txt)
1383 var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null)
1384 return res
1385 end
1386 end
1387
1388 redef class ASuperstringExpr
1389 redef fun expr(v)
1390 do
1391 var array = new Array[Instance]
1392 for nexpr in n_exprs do
1393 var i = v.expr(nexpr)
1394 if i == null then return null
1395 array.add(i)
1396 end
1397 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1398 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1399 assert res != null
1400 return res
1401 end
1402 end
1403
1404 redef class ACrangeExpr
1405 redef fun expr(v)
1406 do
1407 var e1 = v.expr(self.n_expr)
1408 if e1 == null then return null
1409 var e2 = v.expr(self.n_expr2)
1410 if e2 == null then return null
1411 var mtype = v.unanchor_type(self.mtype.as(not null))
1412 var res = new MutableInstance(mtype)
1413 v.init_instance(res)
1414 v.send(v.force_get_primitive_method("init", mtype), [res, e1, e2])
1415 v.check_init_instance(res)
1416 return res
1417 end
1418 end
1419
1420 redef class AOrangeExpr
1421 redef fun expr(v)
1422 do
1423 var e1 = v.expr(self.n_expr)
1424 if e1 == null then return null
1425 var e2 = v.expr(self.n_expr2)
1426 if e2 == null then return null
1427 var mtype = v.unanchor_type(self.mtype.as(not null))
1428 var res = new MutableInstance(mtype)
1429 v.init_instance(res)
1430 v.send(v.force_get_primitive_method("without_last", mtype), [res, e1, e2])
1431 v.check_init_instance(res)
1432 return res
1433 end
1434 end
1435
1436 redef class ATrueExpr
1437 redef fun expr(v)
1438 do
1439 return v.bool_instance(true)
1440 end
1441 end
1442
1443 redef class AFalseExpr
1444 redef fun expr(v)
1445 do
1446 return v.bool_instance(false)
1447 end
1448 end
1449
1450 redef class ANullExpr
1451 redef fun expr(v)
1452 do
1453 return v.null_instance
1454 end
1455 end
1456
1457 redef class AIsaExpr
1458 redef fun expr(v)
1459 do
1460 var i = v.expr(self.n_expr)
1461 if i == null then return null
1462 var mtype = v.unanchor_type(self.cast_type.as(not null))
1463 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1464 end
1465 end
1466
1467 redef class AAsCastExpr
1468 redef fun expr(v)
1469 do
1470 var i = v.expr(self.n_expr)
1471 if i == null then return null
1472 var mtype = self.mtype.as(not null)
1473 var amtype = v.unanchor_type(mtype)
1474 if not v.is_subtype(i.mtype, amtype) then
1475 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1476 end
1477 return i
1478 end
1479 end
1480
1481 redef class AAsNotnullExpr
1482 redef fun expr(v)
1483 do
1484 var i = v.expr(self.n_expr)
1485 if i == null then return null
1486 var mtype = v.unanchor_type(self.mtype.as(not null))
1487 if i.mtype isa MNullType then
1488 fatal(v, "Cast failed")
1489 end
1490 return i
1491 end
1492 end
1493
1494 redef class AParExpr
1495 redef fun expr(v)
1496 do
1497 return v.expr(self.n_expr)
1498 end
1499 end
1500
1501 redef class AOnceExpr
1502 redef fun expr(v)
1503 do
1504 if v.onces.has_key(self) then
1505 return v.onces[self]
1506 else
1507 var res = v.expr(self.n_expr)
1508 if res == null then return null
1509 v.onces[self] = res
1510 return res
1511 end
1512 end
1513 end
1514
1515 redef class ASendExpr
1516 redef fun expr(v)
1517 do
1518 var recv = v.expr(self.n_expr)
1519 if recv == null then return null
1520 var args = [recv]
1521 for a in self.raw_arguments.as(not null) do
1522 var i = v.expr(a)
1523 if i == null then return null
1524 args.add(i)
1525 end
1526 var mproperty = self.mproperty.as(not null)
1527
1528 var res = v.send(mproperty, args)
1529 return res
1530 end
1531 end
1532
1533 redef class ASendReassignFormExpr
1534 redef fun stmt(v)
1535 do
1536 var recv = v.expr(self.n_expr)
1537 if recv == null then return
1538 var args = [recv]
1539 for a in self.raw_arguments.as(not null) do
1540 var i = v.expr(a)
1541 if i == null then return
1542 args.add(i)
1543 end
1544 var value = v.expr(self.n_value)
1545 if value == null then return
1546
1547 var mproperty = self.mproperty.as(not null)
1548 var read = v.send(mproperty, args)
1549 assert read != null
1550
1551 var write = v.send(self.reassign_property.mproperty, [read, value])
1552 assert write != null
1553
1554 args.add(write)
1555
1556 v.send(self.write_mproperty.as(not null), args)
1557 end
1558 end
1559
1560 redef class ASuperExpr
1561 redef fun expr(v)
1562 do
1563 var recv = v.frame.arguments.first
1564 var args = [recv]
1565 for a in self.n_args.n_exprs do
1566 var i = v.expr(a)
1567 if i == null then return null
1568 args.add(i)
1569 end
1570 if args.length == 1 then
1571 args = v.frame.arguments
1572 end
1573
1574 var mproperty = self.mproperty
1575 if mproperty != null then
1576 if mproperty.intro.msignature.arity == 0 then
1577 args = [recv]
1578 end
1579 # Super init call
1580 var res = v.send(mproperty, args)
1581 return res
1582 end
1583
1584 # stantard call-next-method
1585 var mpropdef = v.frame.mpropdef
1586 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1587 assert mpropdef isa MMethodDef
1588 var res = v.call_without_varargs(mpropdef, args)
1589 return res
1590 end
1591 end
1592
1593 redef class ANewExpr
1594 redef fun expr(v)
1595 do
1596 var mtype = v.unanchor_type(self.mtype.as(not null))
1597 var recv: Instance = new MutableInstance(mtype)
1598 v.init_instance(recv)
1599 var args = [recv]
1600 for a in self.n_args.n_exprs do
1601 var i = v.expr(a)
1602 if i == null then return null
1603 args.add(i)
1604 end
1605 var mproperty = self.mproperty.as(not null)
1606 var res2 = v.send(mproperty, args)
1607 if res2 != null then
1608 #self.debug("got {res2} from {mproperty}. drop {recv}")
1609 return res2
1610 end
1611 v.check_init_instance(recv)
1612 return recv
1613 end
1614 end
1615
1616 redef class AAttrExpr
1617 redef fun expr(v)
1618 do
1619 var recv = v.expr(self.n_expr)
1620 if recv == null then return null
1621 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1622 var mproperty = self.mproperty.as(not null)
1623 return v.read_attribute(mproperty, recv)
1624 end
1625 end
1626
1627 redef class AAttrAssignExpr
1628 redef fun stmt(v)
1629 do
1630 var recv = v.expr(self.n_expr)
1631 if recv == null then return
1632 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1633 var i = v.expr(self.n_value)
1634 if i == null then return
1635 var mproperty = self.mproperty.as(not null)
1636 assert recv isa MutableInstance
1637 recv.attributes[mproperty] = i
1638 end
1639 end
1640
1641 redef class AAttrReassignExpr
1642 redef fun stmt(v)
1643 do
1644 var recv = v.expr(self.n_expr)
1645 if recv == null then return
1646 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1647 var value = v.expr(self.n_value)
1648 if value == null then return
1649 var mproperty = self.mproperty.as(not null)
1650 var attr = v.read_attribute(mproperty, recv)
1651 var res = v.send(reassign_property.mproperty, [attr, value])
1652 assert res != null
1653 assert recv isa MutableInstance
1654 recv.attributes[mproperty] = res
1655 end
1656 end
1657
1658 redef class AIssetAttrExpr
1659 redef fun expr(v)
1660 do
1661 var recv = v.expr(self.n_expr)
1662 if recv == null then return null
1663 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1664 var mproperty = self.mproperty.as(not null)
1665 assert recv isa MutableInstance
1666 return v.bool_instance(recv.attributes.has_key(mproperty))
1667 end
1668 end
1669
1670 redef class ADebugTypeExpr
1671 redef fun stmt(v)
1672 do
1673 # do nothing
1674 end
1675 end