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