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