parser: extern stuff accepts types and dot
[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 == "file_realpath" then
904 return v.native_string_instance(recvval.to_s.realpath)
905 else if pname == "get_environ" then
906 var txt = recvval.to_s.environ
907 return v.native_string_instance(txt)
908 else if pname == "system" then
909 var res = sys.system(recvval.to_s)
910 return v.int_instance(res)
911 else if pname == "atof" then
912 return v.float_instance(recvval.to_f)
913 end
914 else if cname == "Int" then
915 if pname == "rand" then
916 return v.int_instance(args[0].to_i.rand)
917 end
918 else if cname == "Float" then
919 if pname == "cos" then
920 return v.float_instance(args[0].to_f.cos)
921 else if pname == "sin" then
922 return v.float_instance(args[0].to_f.sin)
923 else if pname == "tan" then
924 return v.float_instance(args[0].to_f.tan)
925 else if pname == "acos" then
926 return v.float_instance(args[0].to_f.acos)
927 else if pname == "asin" then
928 return v.float_instance(args[0].to_f.asin)
929 else if pname == "atan" then
930 return v.float_instance(args[0].to_f.atan)
931 else if pname == "sqrt" then
932 return v.float_instance(args[0].to_f.sqrt)
933 else if pname == "exp" then
934 return v.float_instance(args[0].to_f.exp)
935 else if pname == "log" then
936 return v.float_instance(args[0].to_f.log)
937 else if pname == "pow" then
938 return v.float_instance(args[0].to_f.pow(args[1].to_f))
939 else if pname == "rand" then
940 return v.float_instance(args[0].to_f.rand)
941 end
942 else if pname == "native_argc" then
943 return v.int_instance(v.arguments.length)
944 else if pname == "native_argv" then
945 var txt = v.arguments[args[1].to_i]
946 return v.native_string_instance(txt)
947 else if pname == "get_time" then
948 return v.int_instance(get_time)
949 else if pname == "srand_from" then
950 srand_from(args[1].to_i)
951 return null
952 else if pname == "atan2" then
953 return v.float_instance(atan2(args[1].to_f, args[2].to_f))
954 else if pname == "pi" then
955 return v.float_instance(pi)
956 else if pname == "lexer_goto" then
957 return v.int_instance(lexer_goto(args[1].to_i, args[2].to_i))
958 else if pname == "lexer_accept" then
959 return v.int_instance(lexer_accept(args[1].to_i))
960 else if pname == "parser_goto" then
961 return v.int_instance(parser_goto(args[1].to_i, args[2].to_i))
962 else if pname == "parser_action" then
963 return v.int_instance(parser_action(args[1].to_i, args[2].to_i))
964 else if pname == "file_getcwd" then
965 return v.native_string_instance(getcwd)
966 end
967 fatal(v, "NOT YET IMPLEMENTED extern {mpropdef}")
968 abort
969 end
970 end
971
972 redef class AAttrPropdef
973 redef fun call(v, mpropdef, args)
974 do
975 var recv = args.first
976 assert recv isa MutableInstance
977 var attr = self.mpropdef.mproperty
978 if args.length == 1 then
979 return v.read_attribute(attr, recv)
980 else
981 assert args.length == 2
982 recv.attributes[attr] = args[1]
983 return null
984 end
985 end
986
987 # Evaluate and set the default value of the attribute in `recv`
988 private fun init_expr(v: NaiveInterpreter, recv: Instance)
989 do
990 assert recv isa MutableInstance
991 var nexpr = self.n_expr
992 if nexpr != null then
993 var f = new Frame(self, self.mpropdef.as(not null), [recv])
994 v.frames.unshift(f)
995 var val = v.expr(nexpr)
996 assert val != null
997 v.frames.shift
998 assert not v.is_escaping
999 recv.attributes[self.mpropdef.mproperty] = val
1000 return
1001 end
1002 var mtype = self.mpropdef.static_mtype.as(not null)
1003 mtype = mtype.anchor_to(v.mainmodule, recv.mtype.as(MClassType))
1004 if mtype isa MNullableType then
1005 recv.attributes[self.mpropdef.mproperty] = v.null_instance
1006 end
1007 end
1008 end
1009
1010 redef class ADeferredMethPropdef
1011 redef fun call(v, mpropdef, args)
1012 do
1013 fatal(v, "Abstract method `{mpropdef.mproperty.name}` called on `{args.first.mtype}`")
1014 abort
1015 end
1016 end
1017
1018 redef class AClassdef
1019 # Execute an implicit `mpropdef` associated with the current node.
1020 private fun call(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
1021 do
1022 var super_inits = self.super_inits
1023 if super_inits != null then
1024 assert args.length == 1
1025 for su in super_inits do
1026 v.send(su, args)
1027 end
1028 return null
1029 end
1030 var recv = args.first
1031 assert recv isa MutableInstance
1032 var i = 1
1033 # Collect undefined attributes
1034 for npropdef in self.n_propdefs do
1035 if npropdef isa AAttrPropdef and npropdef.n_expr == null then
1036 recv.attributes[npropdef.mpropdef.mproperty] = args[i]
1037 i += 1
1038 end
1039 end
1040 return null
1041 end
1042 end
1043
1044 redef class AExpr
1045 # Evaluate the node as a possible expression.
1046 # Return a possible value
1047 # NOTE: Do not call this method directly, but use `v.expr`
1048 # This method is here to be implemented by subclasses.
1049 private fun expr(v: NaiveInterpreter): nullable Instance
1050 do
1051 fatal(v, "NOT YET IMPLEMENTED expr {class_name}")
1052 abort
1053 end
1054
1055 # Evaluate the node as a statement.
1056 # NOTE: Do not call this method directly, but use `v.stmt`
1057 # This method is here to be implemented by subclasses (no need to return something).
1058 private fun stmt(v: NaiveInterpreter)
1059 do
1060 expr(v)
1061 end
1062
1063 end
1064
1065 redef class ABlockExpr
1066 redef fun expr(v)
1067 do
1068 var last = self.n_expr.last
1069 for e in self.n_expr do
1070 if e == last then break
1071 v.stmt(e)
1072 if v.is_escaping then return null
1073 end
1074 return last.expr(v)
1075 end
1076
1077 redef fun stmt(v)
1078 do
1079 for e in self.n_expr do
1080 v.stmt(e)
1081 if v.is_escaping then return
1082 end
1083 end
1084 end
1085
1086 redef class AVardeclExpr
1087 redef fun stmt(v)
1088 do
1089 var ne = self.n_expr
1090 if ne != null then
1091 var i = v.expr(ne)
1092 if i == null then return
1093 v.frame.map[self.variable.as(not null)] = i
1094 end
1095 end
1096 end
1097
1098 redef class AVarExpr
1099 redef fun expr(v)
1100 do
1101 return v.frame.map[self.variable.as(not null)]
1102 end
1103 end
1104
1105 redef class AVarAssignExpr
1106 redef fun expr(v)
1107 do
1108 var i = v.expr(self.n_value)
1109 if i == null then return null
1110 v.frame.map[self.variable.as(not null)] = i
1111 return i
1112 end
1113 end
1114
1115 redef class AVarReassignExpr
1116 redef fun stmt(v)
1117 do
1118 var vari = v.frame.map[self.variable.as(not null)]
1119 var value = v.expr(self.n_value)
1120 if value == null then return
1121 var res = v.send(reassign_property.mproperty, [vari, value])
1122 assert res != null
1123 v.frame.map[self.variable.as(not null)] = res
1124 end
1125 end
1126
1127 redef class ASelfExpr
1128 redef fun expr(v)
1129 do
1130 return v.frame.arguments.first
1131 end
1132 end
1133
1134 redef class AContinueExpr
1135 redef fun stmt(v)
1136 do
1137 var ne = self.n_expr
1138 if ne != null then
1139 var i = v.expr(ne)
1140 if i == null then return
1141 v.escapevalue = i
1142 end
1143 v.continuemark = self.escapemark
1144 end
1145 end
1146
1147 redef class ABreakExpr
1148 redef fun stmt(v)
1149 do
1150 var ne = self.n_expr
1151 if ne != null then
1152 var i = v.expr(ne)
1153 if i == null then return
1154 v.escapevalue = i
1155 end
1156 v.breakmark = self.escapemark
1157 end
1158 end
1159
1160 redef class AReturnExpr
1161 redef fun stmt(v)
1162 do
1163 var ne = self.n_expr
1164 if ne != null then
1165 var i = v.expr(ne)
1166 if i == null then return
1167 v.escapevalue = i
1168 end
1169 v.returnmark = v.frame
1170 end
1171 end
1172
1173 redef class AAbortExpr
1174 redef fun stmt(v)
1175 do
1176 fatal(v, "Aborted")
1177 exit(1)
1178 end
1179 end
1180
1181 redef class AIfExpr
1182 redef fun expr(v)
1183 do
1184 var cond = v.expr(self.n_expr)
1185 if cond == null then return null
1186 if cond.is_true then
1187 return v.expr(self.n_then.as(not null))
1188 else
1189 return v.expr(self.n_else.as(not null))
1190 end
1191 end
1192
1193 redef fun stmt(v)
1194 do
1195 var cond = v.expr(self.n_expr)
1196 if cond == null then return
1197 if cond.is_true then
1198 v.stmt(self.n_then)
1199 else
1200 v.stmt(self.n_else)
1201 end
1202 end
1203 end
1204
1205 redef class AIfexprExpr
1206 redef fun expr(v)
1207 do
1208 var cond = v.expr(self.n_expr)
1209 if cond == null then return null
1210 if cond.is_true then
1211 return v.expr(self.n_then)
1212 else
1213 return v.expr(self.n_else)
1214 end
1215 end
1216 end
1217
1218 redef class ADoExpr
1219 redef fun stmt(v)
1220 do
1221 v.stmt(self.n_block)
1222 v.is_break(self.escapemark) # Clear the break (if any)
1223 end
1224 end
1225
1226 redef class AWhileExpr
1227 redef fun stmt(v)
1228 do
1229 loop
1230 var cond = v.expr(self.n_expr)
1231 if cond == null then return
1232 if not cond.is_true then return
1233 v.stmt(self.n_block)
1234 if v.is_break(self.escapemark) then return
1235 v.is_continue(self.escapemark) # Clear the break
1236 if v.is_escaping then return
1237 end
1238 end
1239 end
1240
1241 redef class ALoopExpr
1242 redef fun stmt(v)
1243 do
1244 loop
1245 v.stmt(self.n_block)
1246 if v.is_break(self.escapemark) then return
1247 v.is_continue(self.escapemark) # Clear the break
1248 if v.is_escaping then return
1249 end
1250 end
1251 end
1252
1253 redef class AForExpr
1254 redef fun stmt(v)
1255 do
1256 var col = v.expr(self.n_expr)
1257 if col == null then return
1258 #self.debug("col {col}")
1259 var iter = v.send(v.force_get_primitive_method("iterator", col.mtype), [col]).as(not null)
1260 #self.debug("iter {iter}")
1261 loop
1262 var isok = v.send(v.force_get_primitive_method("is_ok", iter.mtype), [iter]).as(not null)
1263 if not isok.is_true then return
1264 if self.variables.length == 1 then
1265 var item = v.send(v.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
1266 #self.debug("item {item}")
1267 v.frame.map[self.variables.first] = item
1268 else if self.variables.length == 2 then
1269 var key = v.send(v.force_get_primitive_method("key", iter.mtype), [iter]).as(not null)
1270 v.frame.map[self.variables[0]] = key
1271 var item = v.send(v.force_get_primitive_method("item", iter.mtype), [iter]).as(not null)
1272 v.frame.map[self.variables[1]] = item
1273 else
1274 abort
1275 end
1276 v.stmt(self.n_block)
1277 if v.is_break(self.escapemark) then return
1278 v.is_continue(self.escapemark) # Clear the break
1279 if v.is_escaping then return
1280 v.send(v.force_get_primitive_method("next", iter.mtype), [iter])
1281 end
1282 end
1283 end
1284
1285 redef class AAssertExpr
1286 redef fun stmt(v)
1287 do
1288 var cond = v.expr(self.n_expr)
1289 if cond == null then return
1290 if not cond.is_true then
1291 v.stmt(self.n_else)
1292 if v.is_escaping then return
1293 var nid = self.n_id
1294 if nid != null then
1295 fatal(v, "Assert '{nid.text}' failed")
1296 else
1297 fatal(v, "Assert failed")
1298 end
1299 exit(1)
1300 end
1301 end
1302 end
1303
1304 redef class AOrExpr
1305 redef fun expr(v)
1306 do
1307 var cond = v.expr(self.n_expr)
1308 if cond == null then return null
1309 if cond.is_true then return cond
1310 return v.expr(self.n_expr2)
1311 end
1312 end
1313
1314 redef class AImpliesExpr
1315 redef fun expr(v)
1316 do
1317 var cond = v.expr(self.n_expr)
1318 if cond == null then return null
1319 if not cond.is_true then return v.true_instance
1320 return v.expr(self.n_expr2)
1321 end
1322 end
1323
1324 redef class AAndExpr
1325 redef fun expr(v)
1326 do
1327 var cond = v.expr(self.n_expr)
1328 if cond == null then return null
1329 if not cond.is_true then return cond
1330 return v.expr(self.n_expr2)
1331 end
1332 end
1333
1334 redef class ANotExpr
1335 redef fun expr(v)
1336 do
1337 var cond = v.expr(self.n_expr)
1338 if cond == null then return null
1339 return v.bool_instance(not cond.is_true)
1340 end
1341 end
1342
1343 redef class AOrElseExpr
1344 redef fun expr(v)
1345 do
1346 var i = v.expr(self.n_expr)
1347 if i == null then return null
1348 if i != v.null_instance then return i
1349 return v.expr(self.n_expr2)
1350 end
1351 end
1352
1353 redef class AIntExpr
1354 redef fun expr(v)
1355 do
1356 return v.int_instance(self.value.as(not null))
1357 end
1358 end
1359
1360 redef class AFloatExpr
1361 redef fun expr(v)
1362 do
1363 return v.float_instance(self.value.as(not null))
1364 end
1365 end
1366
1367 redef class ACharExpr
1368 redef fun expr(v)
1369 do
1370 return v.char_instance(self.value.as(not null))
1371 end
1372 end
1373
1374 redef class AArrayExpr
1375 redef fun expr(v)
1376 do
1377 var val = new Array[Instance]
1378 for nexpr in self.n_exprs.n_exprs do
1379 var i = v.expr(nexpr)
1380 if i == null then return null
1381 val.add(i)
1382 end
1383 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1384 var elttype = mtype.arguments.first
1385 return v.array_instance(val, elttype)
1386 end
1387 end
1388
1389 redef class AStringFormExpr
1390 redef fun expr(v)
1391 do
1392 var txt = self.value.as(not null)
1393 var nat = v.native_string_instance(txt)
1394 var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null)
1395 return res
1396 end
1397 end
1398
1399 redef class ASuperstringExpr
1400 redef fun expr(v)
1401 do
1402 var array = new Array[Instance]
1403 for nexpr in n_exprs do
1404 var i = v.expr(nexpr)
1405 if i == null then return null
1406 array.add(i)
1407 end
1408 var i = v.array_instance(array, v.mainmodule.get_primitive_class("Object").mclass_type)
1409 var res = v.send(v.force_get_primitive_method("to_s", i.mtype), [i])
1410 assert res != null
1411 return res
1412 end
1413 end
1414
1415 redef class ACrangeExpr
1416 redef fun expr(v)
1417 do
1418 var e1 = v.expr(self.n_expr)
1419 if e1 == null then return null
1420 var e2 = v.expr(self.n_expr2)
1421 if e2 == null then return null
1422 var mtype = v.unanchor_type(self.mtype.as(not null))
1423 var res = new MutableInstance(mtype)
1424 v.init_instance(res)
1425 v.send(v.force_get_primitive_method("init", mtype), [res, e1, e2])
1426 v.check_init_instance(res)
1427 return res
1428 end
1429 end
1430
1431 redef class AOrangeExpr
1432 redef fun expr(v)
1433 do
1434 var e1 = v.expr(self.n_expr)
1435 if e1 == null then return null
1436 var e2 = v.expr(self.n_expr2)
1437 if e2 == null then return null
1438 var mtype = v.unanchor_type(self.mtype.as(not null))
1439 var res = new MutableInstance(mtype)
1440 v.init_instance(res)
1441 v.send(v.force_get_primitive_method("without_last", mtype), [res, e1, e2])
1442 v.check_init_instance(res)
1443 return res
1444 end
1445 end
1446
1447 redef class ATrueExpr
1448 redef fun expr(v)
1449 do
1450 return v.bool_instance(true)
1451 end
1452 end
1453
1454 redef class AFalseExpr
1455 redef fun expr(v)
1456 do
1457 return v.bool_instance(false)
1458 end
1459 end
1460
1461 redef class ANullExpr
1462 redef fun expr(v)
1463 do
1464 return v.null_instance
1465 end
1466 end
1467
1468 redef class AIsaExpr
1469 redef fun expr(v)
1470 do
1471 var i = v.expr(self.n_expr)
1472 if i == null then return null
1473 var mtype = v.unanchor_type(self.cast_type.as(not null))
1474 return v.bool_instance(v.is_subtype(i.mtype, mtype))
1475 end
1476 end
1477
1478 redef class AAsCastExpr
1479 redef fun expr(v)
1480 do
1481 var i = v.expr(self.n_expr)
1482 if i == null then return null
1483 var mtype = self.mtype.as(not null)
1484 var amtype = v.unanchor_type(mtype)
1485 if not v.is_subtype(i.mtype, amtype) then
1486 fatal(v, "Cast failed. Expected `{amtype}`, got `{i.mtype}`")
1487 end
1488 return i
1489 end
1490 end
1491
1492 redef class AAsNotnullExpr
1493 redef fun expr(v)
1494 do
1495 var i = v.expr(self.n_expr)
1496 if i == null then return null
1497 var mtype = v.unanchor_type(self.mtype.as(not null))
1498 if i.mtype isa MNullType then
1499 fatal(v, "Cast failed")
1500 end
1501 return i
1502 end
1503 end
1504
1505 redef class AParExpr
1506 redef fun expr(v)
1507 do
1508 return v.expr(self.n_expr)
1509 end
1510 end
1511
1512 redef class AOnceExpr
1513 redef fun expr(v)
1514 do
1515 if v.onces.has_key(self) then
1516 return v.onces[self]
1517 else
1518 var res = v.expr(self.n_expr)
1519 if res == null then return null
1520 v.onces[self] = res
1521 return res
1522 end
1523 end
1524 end
1525
1526 redef class ASendExpr
1527 redef fun expr(v)
1528 do
1529 var recv = v.expr(self.n_expr)
1530 if recv == null then return null
1531 var args = [recv]
1532 for a in self.raw_arguments.as(not null) do
1533 var i = v.expr(a)
1534 if i == null then return null
1535 args.add(i)
1536 end
1537 var mproperty = self.mproperty.as(not null)
1538
1539 var res = v.send(mproperty, args)
1540 return res
1541 end
1542 end
1543
1544 redef class ASendReassignFormExpr
1545 redef fun stmt(v)
1546 do
1547 var recv = v.expr(self.n_expr)
1548 if recv == null then return
1549 var args = [recv]
1550 for a in self.raw_arguments.as(not null) do
1551 var i = v.expr(a)
1552 if i == null then return
1553 args.add(i)
1554 end
1555 var value = v.expr(self.n_value)
1556 if value == null then return
1557
1558 var mproperty = self.mproperty.as(not null)
1559 var read = v.send(mproperty, args)
1560 assert read != null
1561
1562 var write = v.send(self.reassign_property.mproperty, [read, value])
1563 assert write != null
1564
1565 args.add(write)
1566
1567 v.send(self.write_mproperty.as(not null), args)
1568 end
1569 end
1570
1571 redef class ASuperExpr
1572 redef fun expr(v)
1573 do
1574 var recv = v.frame.arguments.first
1575 var args = [recv]
1576 for a in self.n_args.n_exprs do
1577 var i = v.expr(a)
1578 if i == null then return null
1579 args.add(i)
1580 end
1581 if args.length == 1 then
1582 args = v.frame.arguments
1583 end
1584
1585 var mproperty = self.mproperty
1586 if mproperty != null then
1587 if mproperty.intro.msignature.arity == 0 then
1588 args = [recv]
1589 end
1590 # Super init call
1591 var res = v.send(mproperty, args)
1592 return res
1593 end
1594
1595 # stantard call-next-method
1596 var mpropdef = v.frame.mpropdef
1597 mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
1598 assert mpropdef isa MMethodDef
1599 var res = v.call_without_varargs(mpropdef, args)
1600 return res
1601 end
1602 end
1603
1604 redef class ANewExpr
1605 redef fun expr(v)
1606 do
1607 var mtype = v.unanchor_type(self.mtype.as(not null))
1608 var recv: Instance = new MutableInstance(mtype)
1609 v.init_instance(recv)
1610 var args = [recv]
1611 for a in self.n_args.n_exprs do
1612 var i = v.expr(a)
1613 if i == null then return null
1614 args.add(i)
1615 end
1616 var mproperty = self.mproperty.as(not null)
1617 var res2 = v.send(mproperty, args)
1618 if res2 != null then
1619 #self.debug("got {res2} from {mproperty}. drop {recv}")
1620 return res2
1621 end
1622 v.check_init_instance(recv)
1623 return recv
1624 end
1625 end
1626
1627 redef class AAttrExpr
1628 redef fun expr(v)
1629 do
1630 var recv = v.expr(self.n_expr)
1631 if recv == null then return null
1632 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1633 var mproperty = self.mproperty.as(not null)
1634 return v.read_attribute(mproperty, recv)
1635 end
1636 end
1637
1638 redef class AAttrAssignExpr
1639 redef fun stmt(v)
1640 do
1641 var recv = v.expr(self.n_expr)
1642 if recv == null then return
1643 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1644 var i = v.expr(self.n_value)
1645 if i == null then return
1646 var mproperty = self.mproperty.as(not null)
1647 assert recv isa MutableInstance
1648 recv.attributes[mproperty] = i
1649 end
1650 end
1651
1652 redef class AAttrReassignExpr
1653 redef fun stmt(v)
1654 do
1655 var recv = v.expr(self.n_expr)
1656 if recv == null then return
1657 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1658 var value = v.expr(self.n_value)
1659 if value == null then return
1660 var mproperty = self.mproperty.as(not null)
1661 var attr = v.read_attribute(mproperty, recv)
1662 var res = v.send(reassign_property.mproperty, [attr, value])
1663 assert res != null
1664 assert recv isa MutableInstance
1665 recv.attributes[mproperty] = res
1666 end
1667 end
1668
1669 redef class AIssetAttrExpr
1670 redef fun expr(v)
1671 do
1672 var recv = v.expr(self.n_expr)
1673 if recv == null then return null
1674 if recv.mtype isa MNullType then fatal(v, "Reciever is null")
1675 var mproperty = self.mproperty.as(not null)
1676 assert recv isa MutableInstance
1677 return v.bool_instance(recv.attributes.has_key(mproperty))
1678 end
1679 end
1680
1681 redef class ADebugTypeExpr
1682 redef fun stmt(v)
1683 do
1684 # do nothing
1685 end
1686 end