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