lib&src: remove detected warnings
[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 recv = v.add_new_array(stype, n_exprs.length)
1003 for ne in n_exprs do
1004 var e = v.generate_expr(ne)
1005 v.add_call_array_add(recv, e)
1006 end
1007 return recv
1008 end
1009 end
1010
1011 redef class ACrangeExpr
1012 redef fun generate_icode(v)
1013 do
1014 var e = v.generate_expr(n_expr)
1015 var e2 = v.generate_expr(n_expr2)
1016 var prop = v.visitor.get_method(stype, once "init".to_symbol)
1017 return v.expr(new INew(stype, prop, [e, e2]), stype)
1018 end
1019 end
1020
1021 redef class AOrangeExpr
1022 redef fun generate_icode(v)
1023 do
1024 var e = v.generate_expr(n_expr)
1025 var e2 = v.generate_expr(n_expr2)
1026 var prop = v.visitor.get_method(stype, once "without_last".to_symbol)
1027 return v.expr(new INew(stype, prop, [e, e2]), stype)
1028 end
1029 end
1030
1031 redef class ASuperExpr
1032 redef fun generate_icode(v)
1033 do
1034 var arity = v.iroutine.params.length - 1
1035 if init_in_superclass != null then
1036 arity = init_in_superclass.signature.arity
1037 end
1038 var args = new Array[IRegister].with_capacity(arity + 1)
1039 args.add(v.iroutine.params[0])
1040 if n_args.length != arity then
1041 for i in [0..arity[ do
1042 args.add(v.iroutine.params[i + 1])
1043 end
1044 else
1045 for na in n_args do
1046 args.add(v.generate_expr(na))
1047 end
1048 end
1049 var p = init_in_superclass
1050 if p != null then
1051 var rtype = p.signature.return_type
1052 if rtype != null then
1053 return v.expr(new ICall(p, args), rtype)
1054 else
1055 v.stmt(new ICall(p, args))
1056 return null
1057 end
1058 else
1059 p = prop
1060 var rtype = p.signature.return_type
1061 if rtype == null then
1062 v.stmt(new ISuper(p, args))
1063 return null
1064 else
1065 return v.expr(new ISuper(p, args), rtype)
1066 end
1067 end
1068 end
1069 end
1070
1071 redef class AAttrExpr
1072 redef fun generate_icode(v)
1073 do
1074 var e = v.generate_expr(n_expr)
1075 if n_expr.stype.is_nullable then v.add_null_reciever_check(e)
1076 return v.add_attr_read(prop, e)
1077 end
1078 end
1079
1080 redef class AAttrAssignExpr
1081 redef fun generate_icode(v)
1082 do
1083 var e = v.generate_expr(n_expr)
1084 if n_expr.stype.is_nullable then v.add_null_reciever_check(e)
1085 var e2 = v.generate_expr(n_value)
1086 v.stmt(new IAttrWrite(prop, e, e2))
1087 return null
1088 end
1089 end
1090 redef class AAttrReassignExpr
1091 redef fun generate_icode(v)
1092 do
1093 var e1 = v.generate_expr(n_expr)
1094 if n_expr.stype.is_nullable then v.add_null_reciever_check(e1)
1095 var e2 = v.expr(new IAttrRead(prop, e1), attr_type)
1096 var e3 = v.generate_expr(n_value)
1097 var e4 = v.expr(new ICall(assign_method, [e2, e3]), attr_type)
1098 v.stmt(new IAttrWrite(prop, e1, e4))
1099 return null
1100 end
1101 end
1102
1103 redef class AIssetAttrExpr
1104 redef fun generate_icode(v)
1105 do
1106 var e = v.generate_expr(n_expr)
1107 if n_expr.stype.is_nullable then v.add_null_reciever_check(e)
1108 return v.expr(new IAttrIsset(prop, e), stype)
1109 end
1110 end
1111
1112 redef class AAbsAbsSendExpr
1113 # Compile each argument and add them to the array
1114 fun generate_icode_for_arguments_in(v: A2IContext, args: Array[IRegister], signature: MMSignature)
1115 do
1116 var par_arity = signature.arity
1117 var par_vararg = signature.vararg_rank
1118 var raw_args = raw_arguments
1119 var raw_arity = raw_args.length
1120 var arg_idx = 0
1121 for par_idx in [0..par_arity[ do
1122 var a: AExpr
1123 var par_type = signature[par_idx]
1124 if par_idx == par_vararg then
1125 var arr = v.add_new_array(v.visitor.type_array(par_type), raw_arity-par_arity)
1126 for i in [0..(raw_arity-par_arity)] do
1127 a = raw_args[arg_idx]
1128 v.add_call_array_add(arr, v.generate_expr(a))
1129 arg_idx = arg_idx + 1
1130 end
1131 args.add(arr)
1132 else
1133 a = raw_args[arg_idx]
1134 args.add(v.generate_expr(a))
1135 arg_idx = arg_idx + 1
1136 end
1137 end
1138 end
1139 end
1140
1141 redef class ASendExpr
1142 redef fun generate_icode(v)
1143 do
1144 var recv = v.generate_expr(n_expr)
1145 var args = new Array[IRegister]
1146 args.add(recv)
1147 var prop = prop
1148 generate_icode_for_arguments_in(v, args, prop.signature.as(not null))
1149 var r: nullable IRegister = null # The full result of the send (raw call + breaks)
1150 var r2: nullable IRegister # The raw result of the call
1151
1152 # Prepare closures
1153 var seq_old = v.seq
1154 var closcns: nullable Array[nullable IClosureDef] = null
1155 if not prop_signature.closures.is_empty then
1156 var rtype = prop_signature.return_type
1157 if rtype != null then
1158 r = v.new_register(rtype)
1159 end
1160 var seq = new ISeq
1161 v.stmt(seq)
1162 v.seq = seq
1163 closcns = new Array[nullable IClosureDef]
1164 var cdarity = 0
1165 if closure_defs != null then cdarity = closure_defs.length
1166 var closure_defs = closure_defs
1167 for mmc in prop_signature.closures do
1168 var found = false
1169 var name = mmc.name
1170 if closure_defs != null then
1171 for cd in closure_defs do
1172 if cd.n_id.to_symbol != name then continue
1173 assert found == false
1174 found = true
1175 cd.escapable.break_seq = seq
1176 cd.escapable.break_value = r
1177 var cn = cd.generate_iclosuredef(v)
1178 closcns.add(cn)
1179 end
1180 end
1181 if not found then
1182 closcns.add(null)
1183 end
1184 end
1185 end
1186
1187 r2 = v.add_call(prop, args, closcns)
1188
1189 # Closure work
1190 if not prop_signature.closures.is_empty then
1191 if r != null and r2 != null then v.add_assignment(r, r2)
1192 v.seq = seq_old
1193 else
1194 r = r2
1195 end
1196
1197 if prop.global.is_init then
1198 v.invoke_super_init_calls_after(prop)
1199 end
1200 return r
1201 end
1202 end
1203
1204 redef class ASendReassignExpr
1205 redef fun generate_icode(v)
1206 do
1207 var recv = v.generate_expr(n_expr)
1208 if n_expr.stype.is_nullable then v.add_null_reciever_check(recv)
1209 var args = new Array[IRegister]
1210 args.add(recv)
1211 generate_icode_for_arguments_in(v, args, read_prop.signature.as(not null))
1212
1213 var e2 = v.expr(new ICall(read_prop, args), read_prop.signature.return_type.as(not null))
1214 var e3 = v.generate_expr(n_value)
1215 var e4 = v.expr(new ICall(assign_method, [e2, e3]), assign_method.signature.return_type.as(not null))
1216 var args2 = args.to_a
1217 args2.add(e4)
1218 v.stmt(new ICall(prop, args2))
1219 return null
1220 end
1221 end
1222
1223 redef class ANewExpr
1224 redef fun generate_icode(v)
1225 do
1226 var args = new Array[IRegister]
1227 generate_icode_for_arguments_in(v, args, prop.signature.as(not null))
1228 return v.expr(new INew(stype, prop, args), stype)
1229 end
1230 end
1231
1232 redef class AProxyExpr
1233 redef fun generate_icode(v)
1234 do
1235 return v.generate_expr(n_expr)
1236 end
1237 end
1238
1239 redef class AOnceExpr
1240 redef fun generate_icode(v)
1241 do
1242 var ionce = new IOnce
1243 var reg = v.expr(ionce, stype)
1244 var old_seq = v.seq
1245 v.seq = ionce.body
1246
1247 var e = v.generate_expr(n_expr)
1248 v.add_assignment(reg, e)
1249
1250 v.seq = old_seq
1251 return reg
1252 end
1253 end
1254
1255
1256 redef class AClosureDef
1257 var _iclosure_def: nullable IClosureDef
1258
1259 fun generate_iclosuredef(v: A2IContext): IClosureDef
1260 do
1261 # Prepare signature
1262 var args = new Array[IRegister]
1263 var sig = closure.signature
1264 for i in [0..sig.arity[ do
1265 args.add(v.new_register(sig[i]))
1266 end
1267 var ret: nullable IRegister = null
1268 var rtype = sig.return_type
1269 if rtype != null then
1270 ret = v.new_register(rtype)
1271 end
1272
1273 var iclos = new IClosureDef(args, ret)
1274 iclos.location = location
1275
1276 # Prepare env
1277 var seq_old = v.seq
1278 v.seq = iclos.body
1279 escapable.continue_seq = iclos.body
1280 escapable.continue_value = iclos.result
1281
1282 # Assign parameters
1283 for i in [0..variables.length[ do
1284 var res = v.variable(variables[i])
1285 v.add_assignment(res, iclos.params[i])
1286 end
1287
1288 v.generate_stmt(n_expr)
1289
1290 # Add a final break in case of break block witout value
1291 if closure.is_break and escapable.break_value == null then
1292 v.add_escape(escapable.break_seq.as(not null))
1293 end
1294
1295 v.seq = seq_old
1296 _iclosure_def = iclos
1297 return iclos
1298 end
1299 end
1300
1301 redef class AClosureCallExpr
1302 redef fun generate_icode(v)
1303 do
1304 # Geneate arguments
1305 var args = new Array[IRegister]
1306 generate_icode_for_arguments_in(v, args, variable.closure.signature)
1307
1308 # Prepare icall
1309 var closdecl = v.closurevariables[variable]
1310 var icall = new IClosCall(closdecl, args)
1311 var seq_old = v.seq
1312
1313 # Fill break of ical
1314 if n_closure_defs.length == 1 then do
1315 var iseq = new ISeq
1316 icall.break_seq = iseq
1317 v.seq = iseq
1318 v.generate_stmt(n_closure_defs.first.n_expr)
1319 v.seq = seq_old
1320 end
1321
1322 # Prepare in case of default block
1323 var iif: nullable IIf = null # The iif of default block
1324 var closdecl_default = closdecl.default # The default (if any)
1325 if closdecl_default != null then
1326 iif = new IIf(v.expr(new IHasClos(closdecl), v.visitor.type_bool))
1327 v.stmt(iif)
1328 v.seq = iif.then_seq
1329 end
1330
1331 # Add the icall
1332 var r2: nullable IRegister = null # the result of the icall
1333 var rtype = variable.closure.signature.return_type
1334 if rtype == null then
1335 v.stmt(icall)
1336 else
1337 r2 = v.expr(icall, rtype)
1338 end
1339
1340 # Process the case of default block
1341 var r: nullable IRegister = null # the real result
1342 if closdecl_default != null then
1343 assert iif != null
1344 if r2 != null then
1345 assert rtype != null
1346 r = v.new_register(rtype)
1347 v.add_assignment(r, r2)
1348 end
1349 v.seq = iif.else_seq
1350 var r3 = v.inline_routine(closdecl_default, args, null)
1351 if r != null then
1352 assert r3 != null
1353 v.add_assignment(r, r3)
1354 end
1355 v.seq = seq_old
1356 else
1357 r = r2
1358 end
1359 return r
1360 end
1361 end