nitg: Modified compilation routine to avoid use of String contructors
[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 AAndExpr
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 cond
1329 return v.expr(self.n_expr2)
1330 end
1331 end
1332
1333 redef class ANotExpr
1334 redef fun expr(v)
1335 do
1336 var cond = v.expr(self.n_expr)
1337 if cond == null then return null
1338 return v.bool_instance(not cond.is_true)
1339 end
1340 end
1341
1342 redef class AOrElseExpr
1343 redef fun expr(v)
1344 do
1345 var i = v.expr(self.n_expr)
1346 if i == null then return null
1347 if i != v.null_instance then return i
1348 return v.expr(self.n_expr2)
1349 end
1350 end
1351
1352 redef class AEeExpr
1353 redef fun expr(v)
1354 do
1355 var i = v.expr(self.n_expr)
1356 if i == null then return null
1357 var i2 = v.expr(self.n_expr2)
1358 if i2 == null then return null
1359 return v.bool_instance(i.eq_is(i2))
1360 end
1361 end
1362
1363 redef class AIntExpr
1364 redef fun expr(v)
1365 do
1366 return v.int_instance(self.value.as(not null))
1367 end
1368 end
1369
1370 redef class AFloatExpr
1371 redef fun expr(v)
1372 do
1373 return v.float_instance(self.value.as(not null))
1374 end
1375 end
1376
1377 redef class ACharExpr
1378 redef fun expr(v)
1379 do
1380 return v.char_instance(self.value.as(not null))
1381 end
1382 end
1383
1384 redef class AArrayExpr
1385 redef fun expr(v)
1386 do
1387 var val = new Array[Instance]
1388 for nexpr in self.n_exprs.n_exprs do
1389 var i = v.expr(nexpr)
1390 if i == null then return null
1391 val.add(i)
1392 end
1393 var mtype = v.unanchor_type(self.mtype.as(not null)).as(MClassType)
1394 var elttype = mtype.arguments.first
1395 return v.array_instance(val, elttype)
1396 end
1397 end
1398
1399 redef class AStringFormExpr
1400 redef fun expr(v)
1401 do
1402 var txt = self.value.as(not null)
1403 var nat = v.native_string_instance(txt)
1404 var res = v.send(v.force_get_primitive_method("to_s", nat.mtype), [nat]).as(not null)
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