niti, nitg & rta: use lookup_first_definition
[nit.git] / src / syntax / icode_generation.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2009 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 # Things needed by typing.nit to generate intermediate code from AST
18 package icode_generation
19
20 import icode
21 import syntax_base
22 private import typing
23 private import primitive_info
24
25 # An AST2ICode context stores the currently built icode informations
26 class A2IContext
27 super ICodeBuilder
28 redef fun stmt(s: ICode)
29 do
30 if _current_node != null then
31 current_location = _current_node.location
32 else if visitor.current_node != null then
33 current_location = visitor.current_node.location
34 end
35 super
36 end
37
38 # Prepare a new array of length item
39 fun add_new_array(stype: MMType, length: Int): IRegister
40 do
41 var prop = visitor.get_method(stype, once "with_capacity".to_symbol)
42 var ni = expr(new IIntValue(length.to_s), visitor.type_int)
43 return expr(new INew(stype, prop, [ni]), stype)
44 end
45
46 # Add an array add
47 fun add_call_array_add(recv, item: IRegister)
48 do
49 var stype = recv.stype
50 var prop = visitor.get_method(stype, once "add".to_symbol)
51 stmt(new ICall(prop, [recv, item]))
52 end
53
54 # Get the iregister associated with a variable
55 # Or assign one if none exists
56 fun variable(v: Variable): IRegister
57 do
58 if _variables.has_key(v) then
59 return _variables[v]
60 else
61 var reg = new_register(v.stype.as(not null))
62 _variables[v] = reg
63 return reg
64 end
65 end
66
67 # Current registered variable
68 var _variables: HashMap[Variable, IRegister] = new HashMap[Variable, IRegister]
69
70 # Current registered closurevariables
71 readable var _closurevariables: HashMap[ClosureVariable, IClosureDecl] = new HashMap[ClosureVariable, IClosureDecl]
72
73 # The current syntax visitor
74 readable var _visitor: AbsSyntaxVisitor
75
76 # Where a nit return must branch
77 readable writable var _return_seq: nullable ISeq
78
79 # Register where a functionnal nit return must store its value
80 readable writable var _return_value: nullable IRegister
81
82 # The method associated to the iroutine (if any)
83 readable var _method: nullable MMMethod
84
85 # The register of self (if any)
86 var selfreg: nullable IRegister writable
87
88 init(visitor: AbsSyntaxVisitor, r: IRoutine, m: nullable MMMethod)
89 do
90 super(visitor.mmmodule, r)
91 _visitor = visitor
92 _return_seq = r.body
93 _return_value = r.result
94 _method = m
95 end
96
97 # Insert implicit super init calls
98 fun invoke_super_init_calls_after(start_prop: nullable MMMethod)
99 do
100 var p = method
101 assert p isa MMSrcMethod
102 var n = p.node
103 assert n isa AConcreteInitPropdef
104
105 if n.super_init_calls.is_empty then return
106 var i = 0
107 var j = 0
108 if start_prop != null then
109 while n.super_init_calls[i] != start_prop do
110 i += 1
111 end
112 i += 1
113
114 while n.explicit_super_init_calls[j] != start_prop do
115 j += 1
116 end
117 j += 1
118 end
119 var stop_prop: nullable MMMethod = null
120 if j < n.explicit_super_init_calls.length then
121 stop_prop = n.explicit_super_init_calls[j]
122 end
123 var l = n.super_init_calls.length
124 while i < l do
125 var sp = n.super_init_calls[i]
126 if sp == stop_prop then break
127 var cargs = new Array[IRegister]
128 if sp.signature.arity == 0 then
129 cargs.add(iroutine.params.first)
130 else
131 for va in iroutine.params do
132 cargs.add(va)
133 end
134 end
135 stmt(new ICall(sp, cargs))
136 i += 1
137 end
138 end
139
140 # The current AExpr
141 var _current_node: nullable AExpr = null
142
143 # Generate icode in the current sequence from a statement
144 fun generate_stmt(n: nullable AExpr)
145 do
146 if n == null then return
147 var old = _current_node
148 _current_node = n
149 n.generate_icode(self)
150 _current_node = old
151 end
152
153 # Generate icode in the current sequence from an expression
154 fun generate_expr(n: AExpr): IRegister
155 do
156 var old = _current_node
157 _current_node = n
158 var reg = n.generate_icode(self).as(not null)
159 _current_node = old
160 return reg
161 end
162 end
163
164 redef class EscapableBlock
165 # Where a nit break must branch
166 readable writable var _break_seq: nullable ISeq
167
168 # Where a nit continue must branch
169 readable writable var _continue_seq: nullable ISeq
170
171 # Register where a functionnal nit break must store its value
172 readable writable var _break_value: nullable IRegister
173
174 # Register where a functionnal nit continue must store its value
175 readable writable var _continue_value: nullable IRegister
176 end
177
178 redef class MMSrcModule
179 # Generate icode for method bodies
180 fun generate_icode(tc: ToolContext)
181 do
182 var v = new A2IVisitor(tc, self)
183 for c in src_local_classes.values do
184 for p in c.src_local_properties.values do
185 if p isa MMSrcMethod then
186 p.generate_iroutine(v)
187 else if p isa MMSrcAttribute then
188 p.generate_iroutine(v)
189 end
190 end
191 end
192 end
193 end
194
195 redef class MMSrcAttribute
196 redef readable writable var _iroutine: nullable IRoutine
197
198 # Generate the initialization iroutine
199 fun generate_iroutine(visitor: A2IVisitor)
200 do
201 if node.n_expr != null then
202 var iroutine = signature.generate_empty_iroutine
203 iroutine.location = node.location
204 var v = new A2IContext(visitor, iroutine, null)
205 visitor.icode_ctx = v
206 visitor.enter_visit(node)
207 visitor.icode_ctx = null
208 _iroutine = iroutine
209 end
210 end
211 end
212
213 redef class MMSrcMethod
214 redef readable writable var _iroutine: nullable IRoutine
215
216 # Generate the body iroutine
217 fun generate_iroutine(visitor: A2IVisitor)
218 do
219 var iroutine = signature.generate_empty_iroutine
220 if node != null then
221 iroutine.location = node.location
222 end
223 var v = new A2IContext(visitor, iroutine, self)
224 visitor.icode_ctx = v
225 inner_generate_iroutine(v)
226 visitor.icode_ctx = null
227 _iroutine = iroutine
228 end
229
230 # Generate the body iroutine (specific part)
231 fun inner_generate_iroutine(v: A2IContext) is abstract
232 end
233
234 redef class MMReadImplementationMethod
235 redef fun inner_generate_iroutine(v)
236 do
237 var e = v.add_attr_read(node.prop, v.iroutine.params.first)
238 v.add_return_value(e)
239 end
240 end
241
242 redef class MMWriteImplementationMethod
243 redef fun inner_generate_iroutine(v)
244 do
245 var params = v.iroutine.params
246 v.stmt(new IAttrWrite(node.prop, params[0], params[1]))
247 end
248 end
249
250 redef class MMMethSrcMethod
251 redef fun inner_generate_iroutine(v)
252 do
253 v.visitor.enter_visit(node)
254 end
255 end
256
257 redef class MMImplicitInit
258 redef fun inner_generate_iroutine(v)
259 do
260 var params = v.iroutine.params
261 var f = params.length - unassigned_attributes.length
262 var recv = params.first
263 for sp in super_inits do
264 assert sp isa MMMethod
265 var args_recv = [recv]
266 if sp == super_init then
267 var args = new Array[IRegister].with_capacity(f)
268 args.add(recv)
269 for i in [1..f[ do
270 args.add(params[i])
271 end
272 v.stmt(new ICall(sp, args))
273 else
274 v.stmt(new ICall(sp, args_recv))
275 end
276 end
277 for i in [f..params.length[ do
278 var attribute = unassigned_attributes[i-f]
279 v.stmt(new IAttrWrite(attribute, recv, params[i]))
280 end
281 end
282 end
283
284 class A2IVisitor
285 super AbsSyntaxVisitor
286 writable var _icode_ctx: nullable A2IContext
287 fun icode_ctx: A2IContext do return _icode_ctx.as(not null)
288 redef fun visit(n) do n.accept_icode_generation(self)
289 init(tc, m) do super
290 end
291
292
293 ###############################################################################
294
295 redef class ANode
296 fun accept_icode_generation(v: A2IVisitor) do accept_abs_syntax_visitor(v) end
297 end
298
299 redef class AAttrPropdef
300 redef fun accept_icode_generation(vv)
301 do
302 var v = vv.icode_ctx
303 v.stmt(new IMove(v.variable(self_var), v.iroutine.params.first))
304 super
305 var ne = n_expr
306 if ne != null then
307 v.stmt(new IMove(v.iroutine.result.as(not null), v.generate_expr(ne)))
308 end
309 end
310 end
311
312 redef class AMethPropdef
313 redef fun accept_icode_generation(vv)
314 do
315 super
316 fill_iroutine(vv.icode_ctx, method)
317 end
318
319 # Compile the method body common preambule (before specific body stuff if any)
320 fun fill_iroutine(v: A2IContext, method: MMSrcMethod) is abstract
321 end
322
323 redef class ASignature
324 fun fill_iroutine_parameters(v: A2IContext, orig_sig: MMSignature, params: Sequence[IRegister], closdecls: nullable Sequence[IClosureDecl])
325 do
326 for ap in n_params do
327 var reg = v.variable(ap.variable)
328 var orig_type = orig_sig[ap.position]
329 var apst = ap.variable.stype.as(not null)
330 if not orig_type < apst then
331 v.add_type_cast(params[ap.position], apst)
332 end
333 v.stmt(new IMove(reg, params[ap.position]))
334 end
335 for i in [0..n_closure_decls.length[ do
336 var wd = n_closure_decls[i]
337 v.closurevariables[wd.variable] = closdecls[i]
338 end
339 end
340 end
341
342 redef class AClosureDecl
343 redef fun accept_icode_generation(vv)
344 do
345 var v = vv.icode_ctx
346 var iclos = variable.closure.signature.generate_empty_iclosuredef(v)
347 var old_seq = v.seq
348 v.seq = iclos.body
349 escapable.continue_seq = iclos.body
350 escapable.continue_value = iclos.result
351 escapable.break_seq = v.return_seq
352 escapable.break_value = v.return_value
353 n_signature.fill_iroutine_parameters(v, variable.closure.signature, iclos.params, null)
354
355 if n_expr != null then
356 v.generate_stmt(n_expr)
357 v.iroutine.closure_decls[position].default = iclos
358
359 # Add a final break in case of break block witout value
360 if variable.closure.is_break and v.return_value == null then
361 v.add_escape(v.return_seq.as(not null))
362 end
363 end
364 v.seq = old_seq
365 end
366 end
367
368 redef class AConcreteMethPropdef
369 redef fun fill_iroutine(v, method)
370 do
371 var params = v.iroutine.params.to_a
372 var selfreg = v.variable(self_var)
373 v.stmt(new IMove(selfreg, params[0]))
374 v.selfreg = selfreg
375 params.shift
376
377 var orig_meth: MMLocalProperty = method.global.intro
378 var orig_sig = orig_meth.signature_for(method.signature.recv)
379 if n_signature != null then
380 n_signature.fill_iroutine_parameters(v, orig_sig, params, v.iroutine.closure_decls)
381 end
382
383 if self isa AConcreteInitPropdef then
384 v.invoke_super_init_calls_after(null)
385 end
386
387 if n_block != null then
388 v.generate_stmt(n_block)
389 end
390 v.selfreg = null
391 end
392 end
393
394 redef class AExternPropdef
395 redef fun fill_iroutine(v, method)
396 do
397 # add all explicit extern calls for this extern method
398 for explicit_import in method.as(MMMethSrcMethod).explicit_imports
399 do
400 var prop = explicit_import.method
401 var ic : IAbsCall
402 if prop.is_init then
403 ic = new INew(prop.signature.recv, prop, new List[IRegister])
404 else
405 ic = new ICall(prop, new List[IRegister])
406 end
407 ic.is_explicit_from_extern = true
408 v.stmt(ic)
409 end
410 end
411 end
412
413 redef class AExternInitPropdef
414 redef fun fill_iroutine(v, method)
415 do
416 var params = v.iroutine.params
417 var sig = method.signature
418 assert params.length == sig.arity + 1
419 var rtype = sig.recv # sig.return_type
420 v.add_assignment(new IRegister(rtype), v.expr(new INative(method, params), rtype))
421
422 super
423 end
424 end
425
426 redef class ADeferredMethPropdef
427 redef fun fill_iroutine(v, method)
428 do
429 v.add_abort("Deferred method called")
430 end
431 end
432
433 redef class AExternMethPropdef
434 redef fun fill_iroutine(v, method)
435 do
436 var params = v.iroutine.params
437 var rtype = method.signature.return_type
438 if rtype != null then
439 v.add_return_value(v.expr(new INative(method, params), rtype))
440 else
441 v.stmt(new INative(method, params))
442 end
443
444 super
445 end
446 end
447
448 redef class AInternMethPropdef
449 redef fun fill_iroutine(v, method)
450 do
451 var params = v.iroutine.params
452 var rtype = method.signature.return_type
453 if rtype != null then
454 v.add_return_value(v.expr(new INative(method, params), rtype))
455 else
456 v.stmt(new INative(method, params))
457 end
458 end
459 end
460
461 ###############################################################################
462
463 redef class AExpr
464 redef fun accept_icode_generation(v) do end
465
466 # Generate icode sequence in the current A2IContext
467 # This method should not be called direclty: use generate_expr and generate_stmt from A2IContext instead
468 protected fun generate_icode(v: A2IContext): nullable IRegister is abstract
469 end
470
471 redef class AVardeclExpr
472 redef fun generate_icode(v)
473 do
474 var reg = v.variable(variable)
475 var ne = n_expr
476 if ne != null then
477 v.add_assignment(reg, v.generate_expr(ne))
478 end
479 return null
480 end
481 end
482
483 redef class ABlockExpr
484 redef fun generate_icode(v)
485 do
486 for ne in n_expr do v.generate_stmt(ne)
487 return null
488 end
489 end
490
491 redef class ADoExpr
492 redef fun generate_icode(v)
493 do
494 var seq_old = v.seq
495 var seq = new ISeq
496 v.stmt(seq)
497 escapable.break_seq = seq
498 v.seq = seq
499
500 v.generate_stmt(n_block)
501
502 v.seq = seq_old
503 return null
504 end
505 end
506
507 redef class AReturnExpr
508 redef fun generate_icode(v)
509 do
510 var ne = n_expr
511 if ne != null then
512 v.add_assignment(v.return_value.as(not null), v.generate_expr(ne))
513 end
514 v.add_escape(v.return_seq.as(not null))
515 return null
516 end
517 end
518
519 redef class ABreakExpr
520 redef fun generate_icode(v)
521 do
522 var ne = n_expr
523 if ne != null then
524 v.add_assignment(escapable.break_value.as(not null), v.generate_expr(ne))
525 end
526 v.add_escape(escapable.break_seq.as(not null))
527 return null
528 end
529 end
530
531 redef class AContinueExpr
532 redef fun generate_icode(v)
533 do
534 var ne = n_expr
535 if ne != null then
536 v.add_assignment(escapable.continue_value.as(not null), v.generate_expr(ne))
537 end
538 v.add_escape(escapable.continue_seq.as(not null))
539 return null
540 end
541 end
542
543 redef class AAbortExpr
544 redef fun generate_icode(v)
545 do
546 v.add_abort("Aborted")
547 return null
548 end
549 end
550
551 redef class AIfExpr
552 redef fun generate_icode(v)
553 do
554 var iif = new IIf(v.generate_expr(n_expr))
555 v.stmt(iif)
556 var seq_old = v.seq
557
558 if n_then != null then
559 v.seq = iif.then_seq
560 v.generate_stmt(n_then)
561 end
562
563 if n_else != null then
564 v.seq = iif.else_seq
565 v.generate_stmt(n_else)
566 end
567
568 v.seq = seq_old
569 return null
570 end
571 end
572
573 redef class AWhileExpr
574 redef fun generate_icode(v)
575 do
576 var seq_old = v.seq
577 var iloop = new ILoop
578 v.stmt(iloop)
579 escapable.break_seq = iloop
580 v.seq = iloop
581
582 # Process condition
583 var iif = new IIf(v.generate_expr(n_expr))
584 v.stmt(iif)
585
586 # Process inside (condition is true)
587 if n_block != null then
588 v.seq = iif.then_seq
589 escapable.continue_seq = iif.then_seq
590 v.generate_stmt(n_block)
591 end
592
593 # Process escape (condition is false)
594 v.seq = iif.else_seq
595 v.add_escape(iloop)
596
597 v.seq = seq_old
598 return null
599 end
600 end
601
602 redef class ALoopExpr
603 redef fun generate_icode(v)
604 do
605 var seq_old = v.seq
606 var iloop = new ILoop
607 v.stmt(iloop)
608 escapable.break_seq = iloop
609 v.seq = iloop
610
611 # Process inside
612 if n_block != null then
613 var seq = new ISeq
614 v.stmt(seq)
615 v.seq = seq
616 escapable.continue_seq = seq
617 v.generate_stmt(n_block)
618 end
619
620 v.seq = seq_old
621 return null
622 end
623 end
624
625 redef class AForExpr
626 redef fun generate_icode(v)
627 do
628 var ne = n_expr
629 var expr_type = ne.stype
630 var tint = v.visitor.type_int
631 var meth # The method that call the closure
632 var args # The arguments of meth
633
634 if ne isa ARangeExpr and expr_type == v.visitor.type_range(tint) then
635 # Shortcut. No Range[Int] object allocated.
636 # 'for x in [y..z] do' become 'y.enumerate_to(z) !each(x) do'
637 # 'for x in [y..z[ do' become 'y.enumerate_before(z) !each(x) do'
638 # And both methods may be inlined
639 args = [v.generate_expr(ne.n_expr), v.generate_expr(ne.n_expr2)]
640 if ne isa ACrangeExpr then
641 meth = v.visitor.get_method(tint, once "enumerate_to".to_symbol)
642 else
643 assert ne isa AOrangeExpr
644 meth = v.visitor.get_method(tint, once "enumerate_before".to_symbol)
645 end
646 else
647 # Standard way.
648 # 'for x in e do' become 'e.iterate !each(x) do'
649 # Some iterate methods may be inlined (eg. the Array one)
650 meth = v.visitor.get_method(expr_type, once "iterate".to_symbol)
651 args = [v.generate_expr(n_expr)]
652 end
653
654 # Build closure
655 var iclos = meth.signature.closures.first.signature.generate_empty_iclosuredef(v)
656 var old_seq = v.seq
657
658 var seq = new ISeq
659 v.stmt(seq)
660 v.seq = seq
661 escapable.break_seq = seq
662 escapable.break_value = null
663
664 v.seq = iclos.body
665 escapable.continue_seq = iclos.body
666 escapable.continue_value = null
667 for i in [0..variables.length[ do
668 v.stmt(new IMove(v.variable(variables[i]), iclos.params[i]))
669 end
670 v.generate_stmt(n_block)
671
672 # Call closure
673 v.seq = seq
674 v.add_call(meth, args, [iclos])
675
676 v.seq = old_seq
677 return null
678 end
679 end
680
681 redef class AAssertExpr
682 redef fun generate_icode(v)
683 do
684 var e = v.generate_expr(n_expr)
685 var iif = new IIf(e)
686 v.stmt(iif)
687 var seq_old = v.seq
688 v.seq = iif.else_seq
689 v.generate_stmt(n_else)
690 var id = n_id
691 if id == null then
692 v.add_abort("Assert failed")
693 else
694 v.add_abort("Assert '%s' failed", id.text.to_s)
695 end
696 v.seq = seq_old
697 return null
698 end
699 end
700
701 redef class AVarExpr
702 redef fun generate_icode(v)
703 do
704 return v.variable(variable)
705 end
706 end
707
708 redef class AVarAssignExpr
709 redef fun generate_icode(v)
710 do
711 var e = v.generate_expr(n_value)
712 v.add_assignment(v.variable(variable), e)
713 return null
714 end
715 end
716
717 redef class AVarReassignExpr
718 redef fun generate_icode(v)
719 do
720 var e1 = v.variable(variable)
721 var e2 = v.generate_expr(n_value)
722 var e3 = v.expr(new ICall(assign_method, [e1, e2]), assign_method.signature.return_type.as(not null))
723 v.add_assignment(e1, e3)
724 return null
725 end
726 end
727
728 redef class ASelfExpr
729 redef fun generate_icode(v)
730 do
731 return v.variable(variable)
732 end
733 end
734
735 redef class AIfexprExpr
736 redef fun generate_icode(v)
737 do
738 # Process condition
739 var iif = new IIf(v.generate_expr(n_expr))
740 v.stmt(iif)
741 var seq_old = v.seq
742
743 # Prepare result
744 var reg = v.new_register(stype)
745
746 # Process 'then'
747 v.seq = iif.then_seq
748 v.add_assignment(reg, v.generate_expr(n_then))
749
750 # Process 'else'
751 v.seq = iif.else_seq
752 v.add_assignment(reg, v.generate_expr(n_else))
753
754 v.seq = seq_old
755 return reg
756 end
757 end
758
759 redef class AEeExpr
760 redef fun generate_icode(v)
761 do
762 var e = v.generate_expr(n_expr)
763 var e2 = v.generate_expr(n_expr2)
764 return v.expr(new IIs(e, e2), stype)
765 end
766 end
767
768 redef class AOrExpr
769 redef fun generate_icode(v)
770 do
771 # Prepare result
772 var reg = v.new_register(stype)
773
774 # Process left operand (in a if/then)
775 var iif = new IIf(v.generate_expr(n_expr))
776 v.stmt(iif)
777 var seq_old = v.seq
778 v.seq = iif.then_seq
779 v.add_assignment(reg, v.lit_true_reg)
780
781 # Process right operand (in the else)
782 v.seq = iif.else_seq
783 v.add_assignment(reg, v.generate_expr(n_expr2))
784
785 v.seq = seq_old
786 return reg
787 end
788 end
789
790 redef class AAndExpr
791 redef fun generate_icode(v)
792 do
793 # Prepare result
794 var reg = v.new_register(stype)
795
796 # Process left operand (in a if/else)
797 var iif = new IIf(v.generate_expr(n_expr))
798 v.stmt(iif)
799 var seq_old = v.seq
800 v.seq = iif.else_seq
801 v.add_assignment(reg, v.lit_false_reg)
802
803 # Process right operand (in the then)
804 v.seq = iif.then_seq
805 v.add_assignment(reg, v.generate_expr(n_expr2))
806
807 v.seq = seq_old
808 return reg
809 end
810 end
811
812 redef class ANotExpr
813 redef fun generate_icode(v)
814 do
815 var e = v.generate_expr(n_expr)
816 return v.expr(new INot(e), stype)
817 end
818 end
819
820 redef class AOrElseExpr
821 redef fun generate_icode(v)
822 do
823 # Compute left operand
824 var e = v.generate_expr(n_expr)
825
826 # Prepare result
827 var reg = v.new_register(stype)
828
829 # Compare left and null
830 var n = v.lit_null_reg
831 var c = v.expr(new IIs(e, n), v.mmmodule.type_bool)
832 var iif = new IIf(c)
833 v.stmt(iif)
834 var old_seq = v.seq
835
836 # if equal, result = right opr
837 v.seq = iif.then_seq
838 v.add_assignment(reg, v.generate_expr(n_expr2))
839
840 # else, result = left operand
841 v.seq = iif.else_seq
842 v.add_assignment(reg, e)
843
844 v.seq = old_seq
845
846 return reg
847 end
848 end
849
850 redef class AIsaExpr
851 redef fun generate_icode(v)
852 do
853 var e = v.generate_expr(n_expr)
854 return v.expr(new ITypeCheck(v.selfreg.as(not null), e, n_type.stype), stype)
855 end
856 end
857
858 redef class AAsCastExpr
859 redef fun generate_icode(v)
860 do
861 var e = v.generate_expr(n_expr)
862 v.add_type_cast(e, stype)
863 return e
864 end
865 end
866
867 redef class AAsNotnullExpr
868 redef fun generate_icode(v)
869 do
870 var e = v.generate_expr(n_expr)
871 v.add_type_cast(e, stype)
872 return e
873 end
874 end
875
876 redef class ATrueExpr
877 redef fun generate_icode(v)
878 do
879 return v.lit_true_reg
880 end
881 end
882
883 redef class AFalseExpr
884 redef fun generate_icode(v)
885 do
886 return v.lit_false_reg
887 end
888 end
889
890 redef class AIntExpr
891 redef fun generate_icode(v)
892 do
893 return v.expr(new IIntValue(n_number.text), stype)
894 end
895 end
896
897 redef class AFloatExpr
898 redef fun generate_icode(v)
899 do
900 return v.expr(new IFloatValue(n_float.text), stype)
901 end
902 end
903
904 redef class ACharExpr
905 redef fun generate_icode(v)
906 do
907 return v.expr(new ICharValue(n_char.text), stype)
908 end
909 end
910
911 redef class AStringFormExpr
912 redef fun generate_icode(v)
913 do
914 compute_string_infos
915 var old_seq = v.seq
916 var ionce = new IOnce
917 var reg = v.expr(ionce, stype)
918 v.seq = ionce.body
919 var ns = v.expr(new IStringValue(_cstring.as(not null)), v.visitor.type_nativestring)
920 var ni = v.expr(new IIntValue(_cstring_length.to_s), v.visitor.type_int)
921 var prop = v.visitor.get_method(stype, once "with_native".to_symbol)
922 var e = v.expr(new INew(stype, prop, [ns, ni]), stype)
923 v.add_assignment(reg, e)
924 v.seq = old_seq
925 return reg
926 end
927
928 # The raw string value
929 protected fun string_text: String is abstract
930
931 # The string in a C native format
932 protected var _cstring: nullable String
933
934 # The string length in bytes
935 protected var _cstring_length: nullable Int
936
937 # Compute _cstring and _cstring_length using string_text
938 protected fun compute_string_infos
939 do
940 var len = 0
941 var str = string_text
942 var res = new Buffer
943 var i = 0
944 while i < str.length do
945 var c = str[i]
946 if c == '\\' then
947 i = i + 1
948 var c2 = str[i]
949 if c2 != '{' and c2 != '}' then
950 res.add(c)
951 end
952 c = c2
953 end
954 len = len + 1
955 res.add(c)
956 i = i + 1
957 end
958 _cstring = res.to_s
959 _cstring_length = len
960 end
961 end
962
963 redef class AStringExpr
964 redef fun string_text do return n_string.text.substring(1, n_string.text.length - 2)
965 end
966 redef class AStartStringExpr
967 redef fun string_text do return n_string.text.substring(1, n_string.text.length - 2)
968 end
969 redef class AMidStringExpr
970 redef fun string_text do return n_string.text.substring(1, n_string.text.length - 2)
971 end
972 redef class AEndStringExpr
973 redef fun string_text do return n_string.text.substring(1, n_string.text.length - 2)
974 end
975
976 redef class ASuperstringExpr
977 redef fun generate_icode(v)
978 do
979 var array = v.add_new_array(atype, n_exprs.length)
980 var prop_to_s = v.visitor.get_method(v.visitor.type_object, once "to_s".to_symbol)
981 for ne in n_exprs do
982 var e = v.generate_expr(ne)
983 if ne.stype != stype then
984 e = v.expr(new ICall(prop_to_s, [e]), stype)
985 end
986 v.add_call_array_add(array, e)
987 end
988 return v.expr(new ICall(prop_to_s, [array]), stype)
989 end
990 end
991
992 redef class ANullExpr
993 redef fun generate_icode(v)
994 do
995 return v.lit_null_reg
996 end
997 end
998
999 redef class AArrayExpr
1000 redef fun generate_icode(v)
1001 do
1002 var nes = n_exprs.n_exprs
1003 var recv = v.add_new_array(stype, nes.length)
1004 for ne in nes do
1005 var e = v.generate_expr(ne)
1006 v.add_call_array_add(recv, e)
1007 end
1008 return recv
1009 end
1010 end
1011
1012 redef class ACrangeExpr
1013 redef fun generate_icode(v)
1014 do
1015 var e = v.generate_expr(n_expr)
1016 var e2 = v.generate_expr(n_expr2)
1017 var prop = v.visitor.get_method(stype, once "init".to_symbol)
1018 return v.expr(new INew(stype, prop, [e, e2]), stype)
1019 end
1020 end
1021
1022 redef class AOrangeExpr
1023 redef fun generate_icode(v)
1024 do
1025 var e = v.generate_expr(n_expr)
1026 var e2 = v.generate_expr(n_expr2)
1027 var prop = v.visitor.get_method(stype, once "without_last".to_symbol)
1028 return v.expr(new INew(stype, prop, [e, e2]), stype)
1029 end
1030 end
1031
1032 redef class ASuperExpr
1033 redef fun generate_icode(v)
1034 do
1035 var arity = v.iroutine.params.length - 1
1036 if init_in_superclass != null then
1037 arity = init_in_superclass.signature.arity
1038 end
1039 var args = new Array[IRegister].with_capacity(arity + 1)
1040 args.add(v.iroutine.params[0])
1041 var nas = n_args.n_exprs
1042 if nas.length != arity then
1043 for i in [0..arity[ do
1044 args.add(v.iroutine.params[i + 1])
1045 end
1046 else
1047 for na in nas do
1048 args.add(v.generate_expr(na))
1049 end
1050 end
1051 var p = init_in_superclass
1052 if p != null then
1053 var rtype = p.signature.return_type
1054 if rtype != null then
1055 return v.expr(new ICall(p, args), rtype)
1056 else
1057 v.stmt(new ICall(p, args))
1058 return null
1059 end
1060 else
1061 p = prop
1062 var rtype = p.signature.return_type
1063 if rtype == null then
1064 v.stmt(new ISuper(p, args))
1065 return null
1066 else
1067 return v.expr(new ISuper(p, args), rtype)
1068 end
1069 end
1070 end
1071 end
1072
1073 redef class AAttrExpr
1074 redef fun generate_icode(v)
1075 do
1076 var e = v.generate_expr(n_expr)
1077 if n_expr.stype.is_nullable then v.add_null_reciever_check(e)
1078 return v.add_attr_read(prop, e)
1079 end
1080 end
1081
1082 redef class AAttrAssignExpr
1083 redef fun generate_icode(v)
1084 do
1085 var e = v.generate_expr(n_expr)
1086 if n_expr.stype.is_nullable then v.add_null_reciever_check(e)
1087 var e2 = v.generate_expr(n_value)
1088 v.stmt(new IAttrWrite(prop, e, e2))
1089 return null
1090 end
1091 end
1092 redef class AAttrReassignExpr
1093 redef fun generate_icode(v)
1094 do
1095 var e1 = v.generate_expr(n_expr)
1096 if n_expr.stype.is_nullable then v.add_null_reciever_check(e1)
1097 var e2 = v.expr(new IAttrRead(prop, e1), attr_type)
1098 var e3 = v.generate_expr(n_value)
1099 var e4 = v.expr(new ICall(assign_method, [e2, e3]), attr_type)
1100 v.stmt(new IAttrWrite(prop, e1, e4))
1101 return null
1102 end
1103 end
1104
1105 redef class AIssetAttrExpr
1106 redef fun generate_icode(v)
1107 do
1108 var e = v.generate_expr(n_expr)
1109 if n_expr.stype.is_nullable then v.add_null_reciever_check(e)
1110 return v.expr(new IAttrIsset(prop, e), stype)
1111 end
1112 end
1113
1114 redef class AAbsAbsSendExpr
1115 # Compile each argument and add them to the array
1116 fun generate_icode_for_arguments_in(v: A2IContext, args: Array[IRegister], signature: MMSignature)
1117 do
1118 var par_arity = signature.arity
1119 var par_vararg = signature.vararg_rank
1120 var raw_args = raw_arguments
1121 var raw_arity = raw_args.length
1122 var arg_idx = 0
1123 for par_idx in [0..par_arity[ do
1124 var a: AExpr
1125 var par_type = signature[par_idx]
1126 if par_idx == par_vararg then
1127 var arr = v.add_new_array(v.visitor.type_array(par_type), raw_arity-par_arity)
1128 for i in [0..(raw_arity-par_arity)] do
1129 a = raw_args[arg_idx]
1130 v.add_call_array_add(arr, v.generate_expr(a))
1131 arg_idx = arg_idx + 1
1132 end
1133 args.add(arr)
1134 else
1135 a = raw_args[arg_idx]
1136 args.add(v.generate_expr(a))
1137 arg_idx = arg_idx + 1
1138 end
1139 end
1140 end
1141 end
1142
1143 redef class ASendExpr
1144 redef fun generate_icode(v)
1145 do
1146 var recv = v.generate_expr(n_expr)
1147 var args = new Array[IRegister]
1148 args.add(recv)
1149 var prop = prop
1150 generate_icode_for_arguments_in(v, args, prop.signature.as(not null))
1151 var r: nullable IRegister = null # The full result of the send (raw call + breaks)
1152 var r2: nullable IRegister # The raw result of the call
1153
1154 # Prepare closures
1155 var seq_old = v.seq
1156 var closcns: nullable Array[nullable IClosureDef] = null
1157 if not prop_signature.closures.is_empty then
1158 var rtype = prop_signature.return_type
1159 if rtype != null then
1160 r = v.new_register(rtype)
1161 end
1162 var seq = new ISeq
1163 v.stmt(seq)
1164 v.seq = seq
1165 closcns = new Array[nullable IClosureDef]
1166 var cdarity = 0
1167 if closure_defs != null then cdarity = closure_defs.length
1168 var closure_defs = closure_defs
1169 for mmc in prop_signature.closures do
1170 var found = false
1171 var name = mmc.name
1172 if closure_defs != null then
1173 for cd in closure_defs do
1174 if cd.n_id.to_symbol != name then continue
1175 assert found == false
1176 found = true
1177 cd.escapable.break_seq = seq
1178 cd.escapable.break_value = r
1179 var cn = cd.generate_iclosuredef(v)
1180 closcns.add(cn)
1181 end
1182 end
1183 if not found then
1184 closcns.add(null)
1185 end
1186 end
1187 end
1188
1189 r2 = v.add_call(prop, args, closcns)
1190
1191 # Closure work
1192 if not prop_signature.closures.is_empty then
1193 if r != null and r2 != null then v.add_assignment(r, r2)
1194 v.seq = seq_old
1195 else
1196 r = r2
1197 end
1198
1199 if prop.global.is_init then
1200 v.invoke_super_init_calls_after(prop)
1201 end
1202 return r
1203 end
1204 end
1205
1206 redef class ASendReassignExpr
1207 redef fun generate_icode(v)
1208 do
1209 var recv = v.generate_expr(n_expr)
1210 if n_expr.stype.is_nullable then v.add_null_reciever_check(recv)
1211 var args = new Array[IRegister]
1212 args.add(recv)
1213 generate_icode_for_arguments_in(v, args, read_prop.signature.as(not null))
1214
1215 var e2 = v.expr(new ICall(read_prop, args), read_prop.signature.return_type.as(not null))
1216 var e3 = v.generate_expr(n_value)
1217 var e4 = v.expr(new ICall(assign_method, [e2, e3]), assign_method.signature.return_type.as(not null))
1218 var args2 = args.to_a
1219 args2.add(e4)
1220 v.stmt(new ICall(prop, args2))
1221 return null
1222 end
1223 end
1224
1225 redef class ANewExpr
1226 redef fun generate_icode(v)
1227 do
1228 var args = new Array[IRegister]
1229 generate_icode_for_arguments_in(v, args, prop.signature.as(not null))
1230 return v.expr(new INew(stype, prop, args), stype)
1231 end
1232 end
1233
1234 redef class AProxyExpr
1235 redef fun generate_icode(v)
1236 do
1237 return v.generate_expr(n_expr)
1238 end
1239 end
1240
1241 redef class AOnceExpr
1242 redef fun generate_icode(v)
1243 do
1244 var ionce = new IOnce
1245 var reg = v.expr(ionce, stype)
1246 var old_seq = v.seq
1247 v.seq = ionce.body
1248
1249 var e = v.generate_expr(n_expr)
1250 v.add_assignment(reg, e)
1251
1252 v.seq = old_seq
1253 return reg
1254 end
1255 end
1256
1257
1258 redef class AClosureDef
1259 var _iclosure_def: nullable IClosureDef
1260
1261 fun generate_iclosuredef(v: A2IContext): IClosureDef
1262 do
1263 # Prepare signature
1264 var args = new Array[IRegister]
1265 var sig = closure.signature
1266 for i in [0..sig.arity[ do
1267 args.add(v.new_register(sig[i]))
1268 end
1269 var ret: nullable IRegister = null
1270 var rtype = sig.return_type
1271 if rtype != null then
1272 ret = v.new_register(rtype)
1273 end
1274
1275 var iclos = new IClosureDef(args, ret)
1276 iclos.location = location
1277
1278 # Prepare env
1279 var seq_old = v.seq
1280 v.seq = iclos.body
1281 escapable.continue_seq = iclos.body
1282 escapable.continue_value = iclos.result
1283
1284 # Assign parameters
1285 for i in [0..variables.length[ do
1286 var res = v.variable(variables[i])
1287 v.add_assignment(res, iclos.params[i])
1288 end
1289
1290 v.generate_stmt(n_expr)
1291
1292 # Add a final break in case of break block witout value
1293 if closure.is_break and escapable.break_value == null then
1294 v.add_escape(escapable.break_seq.as(not null))
1295 end
1296
1297 v.seq = seq_old
1298 _iclosure_def = iclos
1299 return iclos
1300 end
1301 end
1302
1303 redef class AClosureCallExpr
1304 redef fun generate_icode(v)
1305 do
1306 # Geneate arguments
1307 var args = new Array[IRegister]
1308 generate_icode_for_arguments_in(v, args, variable.closure.signature)
1309
1310 # Prepare icall
1311 var closdecl = v.closurevariables[variable]
1312 var icall = new IClosCall(closdecl, args)
1313 var seq_old = v.seq
1314
1315 # Fill break of ical
1316 if n_closure_defs.length == 1 then do
1317 var iseq = new ISeq
1318 icall.break_seq = iseq
1319 v.seq = iseq
1320 v.generate_stmt(n_closure_defs.first.n_expr)
1321 v.seq = seq_old
1322 end
1323
1324 # Prepare in case of default block
1325 var iif: nullable IIf = null # The iif of default block
1326 var closdecl_default = closdecl.default # The default (if any)
1327 if closdecl_default != null then
1328 iif = new IIf(v.expr(new IHasClos(closdecl), v.visitor.type_bool))
1329 v.stmt(iif)
1330 v.seq = iif.then_seq
1331 end
1332
1333 # Add the icall
1334 var r2: nullable IRegister = null # the result of the icall
1335 var rtype = variable.closure.signature.return_type
1336 if rtype == null then
1337 v.stmt(icall)
1338 else
1339 r2 = v.expr(icall, rtype)
1340 end
1341
1342 # Process the case of default block
1343 var r: nullable IRegister = null # the real result
1344 if closdecl_default != null then
1345 assert iif != null
1346 if r2 != null then
1347 assert rtype != null
1348 r = v.new_register(rtype)
1349 v.add_assignment(r, r2)
1350 end
1351 v.seq = iif.else_seq
1352 var r3 = v.inline_routine(closdecl_default, args, null)
1353 if r != null then
1354 assert r3 != null
1355 v.add_assignment(r, r3)
1356 end
1357 v.seq = seq_old
1358 else
1359 r = r2
1360 end
1361 return r
1362 end
1363 end
1364
1365 redef class ADebugTypeExpr
1366 redef fun generate_icode(v)
1367 do
1368 # Do nothing.
1369 return null
1370 end
1371 end