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