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