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