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