syntax: remove AbsSyntaxVisitor::type_collection
[nit.git] / src / syntax / syntax_base.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 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 # Common syntax structures for syntax analysis of NIT AST.
18 package syntax_base
19
20 import parser
21 import mmloader
22
23 # Concrete NIT source module
24 class MMSrcModule
25 super MMModule
26 # A source module can locate AST nodes of related MM entities
27 # Once a source module AST is no more needed, _nodes is set to null
28 # See ToolContext::keep_ast property in syntax.nit for details
29 var _nodes: nullable HashMap[Object, nullable ANode] = new HashMap[Object, nullable ANode]
30
31 # Release the AST
32 fun clear_ast do _nodes = null
33
34 # The related AST node
35 fun node: AModule do return nodes(self).as(AModule)
36
37 # Concrete NIT source local classs by name
38 readable var _src_local_classes: Map[Symbol, MMSrcLocalClass]
39
40 init(c: MMContext, source: AModule, dir: MMDirectory, name: Symbol, loc: Location)
41 do
42 super(name, dir, c, loc)
43 nodes(self) = source
44 _src_local_classes = new HashMap[Symbol, MMSrcLocalClass]
45 end
46
47 redef fun nodes(o: Object): nullable ANode
48 do
49 if _nodes != null and _nodes.has_key(o) then return _nodes[o] else return null
50 end
51 redef fun nodes=(o: Object, n: nullable ANode)
52 do
53 assert not _nodes.has_key(o)
54 _nodes[o] = n
55 end
56 end
57
58 redef class MMModule
59 # The AST node of some entity
60 private fun nodes(o: Object): nullable ANode do return null
61 # The AST node of some entity
62 private fun nodes=(o: Object, n: nullable ANode) do abort
63 end
64
65 redef class MMGlobalClass
66 # Check that a module can access a class
67 fun check_visibility(v: AbsSyntaxVisitor, n: ANode, cm: MMSrcModule): Bool do
68 var pm = intro.mmmodule
69 assert pm isa MMSrcModule
70 var vpm = cm.visibility_for(pm)
71 if vpm == 3 then
72 return true
73 else if vpm == 0 then
74 v.error(n, "Visibility error: Class {self} comes from the hidden module {cm}.") # TODO: should not occur
75 return false
76 else if visibility_level >= 3 then
77 v.error(n, "Visibility error: Class {self} is private.")
78 return false
79 end
80 return true
81 end
82 end
83
84 # Concrete NIT source local classes
85 class MMSrcLocalClass
86 super MMConcreteClass
87 # The first related AST node (if any)
88 fun node: nullable AClassdef do return mmmodule.nodes(self).as(nullable AClassdef)
89
90 # Concrete NIT source generic formal parameter by name
91 readable var _formal_dict: Map[Symbol, MMTypeFormalParameter] = new HashMap[Symbol, MMTypeFormalParameter]
92
93 # Concrete NIT source properties by name
94 readable var _src_local_properties: Map[Symbol, MMLocalProperty]
95
96 init(mod: MMSrcModule, n: Symbol, cla: nullable AClassdef, a: Int)
97 do
98 super(mod, n, a)
99 mod.nodes(self) = cla
100 _src_local_properties = new HashMap[Symbol, MMLocalProperty]
101 end
102 end
103
104 redef class MMGlobalProperty
105 # Check that a module can access a property
106 fun check_visibility(v: AbsSyntaxVisitor, n: ANode, cm: MMSrcModule, allows_protected: Bool): Bool do
107 var pm = local_class.mmmodule
108 assert pm isa MMSrcModule
109 var vpm = cm.visibility_for(pm)
110 if vpm == 3 then
111 return true
112 else if vpm == 0 then
113 # TODO: should not occurs
114 v.error(n, "Visibility error: Property {self} comes from the hidden module {cm}.")
115 return false
116 else if visibility_level >= 3 then
117 v.error(n, "Visibility error: Property {self} is private.")
118 return false
119 else if visibility_level >= 2 and not allows_protected then
120 v.error(n, "Visibility error: Property {self} is protected and can only acceded by self.")
121 return false
122 end
123 return true
124 end
125 end
126
127 redef class MMLocalProperty
128 # The attached node (if any)
129 fun node: nullable ANode do return null
130
131 # Is the concrete method defined as init
132 fun is_init: Bool do return false
133 end
134
135 # Concrete NIT source attribute
136 class MMSrcAttribute
137 super MMAttribute
138 redef fun node: nullable AAttrPropdef do return mmmodule.nodes(self).as(nullable AAttrPropdef)
139 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
140 do
141 super(name, cla)
142 cla.mmmodule.nodes(self) = n
143 end
144 end
145
146 # Concrete NIT source method
147 class MMSrcMethod
148 super MMMethod
149 redef fun is_intern do return false
150 redef fun is_abstract do return false
151 redef fun extern_name do return null
152 end
153
154 # Concrete NIT source method for an automatic accesor
155 class MMAttrImplementationMethod
156 super MMSrcMethod
157 redef fun node: nullable AAttrPropdef do return mmmodule.nodes(self).as(nullable AAttrPropdef)
158 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
159 do
160 super(name, cla)
161 cla.mmmodule.nodes(self) = n
162 end
163 end
164
165 # Concrete NIT source method for an automatic read accesor
166 class MMReadImplementationMethod
167 super MMAttrImplementationMethod
168 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
169 do
170 super(name, cla, n)
171 end
172 end
173
174 # Concrete NIT source method for an automatic write accesor
175 class MMWriteImplementationMethod
176 super MMAttrImplementationMethod
177 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
178 do
179 super(name, cla, n)
180 end
181 end
182
183 # Concrete NIT source method for an explicit method
184 class MMMethSrcMethod
185 super MMSrcMethod
186 redef readable var _is_init: Bool
187 redef readable var _is_intern: Bool
188 redef readable var _is_abstract: Bool
189 redef readable writable var _extern_name: nullable String # Will be computed during MMBuilder
190 redef fun node: nullable AMethPropdef do return mmmodule.nodes(self).as(nullable AMethPropdef)
191 init(name: Symbol, cla: MMLocalClass, n: nullable AMethPropdef)
192 do
193 super(name, cla)
194 cla.mmmodule.nodes(self) = n
195 _is_init = node isa AConcreteInitPropdef
196 _is_intern = node isa AInternMethPropdef
197 _is_abstract = node isa ADeferredMethPropdef
198 _extern_name = null
199 end
200 end
201
202 # Concrete NIT source virtual type
203 class MMSrcTypeProperty
204 super MMLocalProperty
205 super MMTypeProperty
206 init(name: Symbol, cla: MMLocalClass, n: ATypePropdef)
207 do
208 super(name, cla)
209 end
210 end
211
212 # Concrete NIT implicit constructor
213 class MMImplicitInit
214 super MMMethSrcMethod
215 fun super_init: nullable MMLocalProperty is abstract
216 redef fun is_init do return true
217 readable var _unassigned_attributes: Array[MMSrcAttribute]
218 readable var _super_inits: Array[MMLocalProperty]
219 init(cla: MMLocalClass, unassigned_attributes: Array[MMSrcAttribute], super_inits: Array[MMLocalProperty])
220 do
221 super(once "init".to_symbol, cla, null)
222 _unassigned_attributes = unassigned_attributes
223 _super_inits = super_inits
224 end
225 end
226
227 # Local variables
228 abstract class Variable
229 # Name of the variable
230 readable var _name: Symbol
231
232 # Declaration AST node
233 readable var _decl: nullable ANode
234
235 # Static type
236 readable writable var _stype: nullable MMType
237
238 redef fun to_s do return _name.to_s
239
240 fun kind: String is abstract
241
242 init(n: Symbol, d: nullable ANode)
243 do
244 _name = n
245 _decl = d
246 end
247 end
248
249 # Variable declared with 'var'
250 class VarVariable
251 super Variable
252 redef fun kind do return once "variable"
253 init(n: Symbol, d: ANode) do super
254 end
255
256 # Parameter of method (declared in signature)
257 class ParamVariable
258 super Variable
259 redef fun kind do return once "parameter"
260 init(n: Symbol, d: nullable ANode) do super
261 end
262
263 # Automatic variable (like in the 'for' statement)
264 class AutoVariable
265 super Variable
266 redef fun kind do return once "automatic variable"
267 init(n: Symbol, d: ANode) do super
268 end
269
270 # False variable corresponding to closures declared in signatures
271 # Lives in the same namespace than variables
272 class ClosureVariable
273 super Variable
274 redef fun kind do return once "closure"
275
276 # The signature of the closure
277 readable var _closure: MMClosure
278
279 init(n: Symbol, d: ANode, c: MMClosure)
280 do
281 super(n, d)
282 _closure = c
283 end
284 end
285
286 ###############################################################################
287
288 # Visitor used during the syntax analysis
289 class AbsSyntaxVisitor
290 super Visitor
291 fun get_type_by_name(clsname: Symbol): MMType
292 do
293 if not _mmmodule.has_global_class_named(clsname) then _tc.fatal_error(_mmmodule.location, "Missing necessary class: \"{clsname}\"")
294 var cls = _mmmodule.class_by_name(clsname)
295 return cls.get_type
296 end
297
298 fun get_instantiated_type_by_name(clsname: Symbol, vtype: Array[MMType]): MMType
299 do
300 if not _mmmodule.has_global_class_named(clsname) then _tc.fatal_error(_mmmodule.location, "Missing necessary class: \"{clsname}\"")
301 var cls = _mmmodule.class_by_name(clsname)
302 return cls.get_instantiate_type(vtype)
303 end
304
305 # The root type Object
306 fun type_object: MMType
307 do
308 return get_type_by_name(once ("Object".to_symbol))
309 end
310
311 # The primitive type Bool
312 fun type_bool: MMType
313 do
314 return get_type_by_name(once ("Bool".to_symbol))
315 end
316
317 # The primitive type Int
318 fun type_int: MMType
319 do
320 return get_type_by_name(once ("Int".to_symbol))
321 end
322
323 # The primitive type Float
324 fun type_float: MMType
325 do
326 return get_type_by_name(once ("Float".to_symbol))
327 end
328
329 # The primitive type Char
330 fun type_char: MMType
331 do
332 return get_type_by_name(once ("Char".to_symbol))
333 end
334
335 # The primitive type String
336 fun type_string: MMType
337 do
338 return get_type_by_name(once ("String".to_symbol))
339 end
340
341 # The primitive type NativeString
342 fun type_nativestring: MMType
343 do
344 return get_type_by_name(once ("NativeString".to_symbol))
345 end
346
347 # The primitive type Array[?]
348 fun type_array(stype: MMType): MMType
349 do
350 return get_instantiated_type_by_name(once ("Array".to_symbol), [stype])
351 end
352
353 # The primitive type Discrete
354 fun type_discrete: MMType
355 do
356 return get_type_by_name(once ("Discrete".to_symbol))
357 end
358
359 # The primitive type Range[?]
360 fun type_range(stype: MMType): MMType
361 do
362 return get_instantiated_type_by_name(once ("Range".to_symbol), [stype])
363 end
364
365 # The primitive type of null
366 fun type_none: MMType
367 do
368 return _mmmodule.type_none
369 end
370
371 fun get_method(recv: MMType, name: Symbol): MMMethod
372 do
373 if not recv.local_class.has_global_property_by_name(name) then
374 fatal_error(current_node, "Fatal Error: {recv} must have a property named {name}.")
375 end
376 return recv.local_class.select_method(name)
377 end
378
379 # The current module
380 readable var _mmmodule: MMSrcModule
381
382 # The current class
383 fun local_class: MMSrcLocalClass do return _local_class.as(not null)
384 writable var _local_class: nullable MMSrcLocalClass
385
386 # The current property
387 fun local_property: MMLocalProperty do return _local_property.as(not null)
388 writable var _local_property: nullable MMLocalProperty
389
390 # The current tool configuration/status
391 readable var _tc: ToolContext
392
393 # Display an error for a given syntax node
394 fun error(n: nullable ANode, s: String)
395 do
396 _tc.error(if n == null then null else n.location, s)
397 end
398
399 # Add an error, show errors and quit
400 fun fatal_error(n: nullable ANode, s: String)
401 do
402 _tc.fatal_error(if n == null then null else n.location, s)
403 end
404
405 # Display a warning for a given syntax node
406 fun warning(n: nullable ANode, s: String)
407 do
408 _tc.warning(if n == null then null else n.location, s)
409 end
410
411 # Check conformity and display error
412 fun check_conform(n: ANode, subtype: nullable MMType, stype: nullable MMType): Bool
413 do
414 if stype == null or subtype == null then
415 return false
416 end
417 if subtype < stype then
418 return true
419 end
420 error(n, "Type error: expected {stype}, got {subtype}")
421 return false
422 end
423
424 # Check that an expression has a static type and that
425 # Display an error and return false if n is a statement
426 # Require that the static type of n is known
427 fun check_expr(n: AExpr): Bool
428 do
429 if not n.is_typed then
430 if tc.error_count == 0 then
431 print("{n.location} not typed but not error")
432 abort
433 end
434 # An error occured in a sub node,
435 # sillently cascade fail
436 return false
437 else if n.is_statement then
438 error(n, "Type error: expected expression.")
439 return false
440 end
441 return true
442 end
443
444 # Combine check_conform and check_expr
445 fun check_conform_expr(n: AExpr, stype: nullable MMType): Bool
446 do
447 if stype == null then return false
448 if check_expr(n) then return check_conform(n, n.stype, stype) else return false
449 end
450
451 # Check conformance between multiple expressions and a static type
452 # Conformance is granted if among them there is a most general type
453 # Return the most general type if a conformance is found
454 # Display an error and return null if no conformance is found
455 # The only allowed combinaison is with the nullable marker
456 # @param stype is a possible additional type (without node)
457 # Examples:
458 # Int, Int, Object => return Object
459 # Int, Float => display error, return null
460 # nullable Int, Object => return nullable Object
461 fun check_conform_multiexpr(stype: nullable MMType, nodes: Collection[AExpr]): nullable MMType
462 do
463 var node: nullable AExpr = null # candidate node
464 for n in nodes do
465 if not check_expr(n) then return null
466 var ntype = n.stype
467 if stype != null and stype.is_nullable != ntype.is_nullable then
468 # nullable combinaison: if one of them is nulable, considers that both are
469 stype = stype.as_nullable
470 ntype = ntype.as_nullable
471 end
472 if stype == null or stype < ntype then
473 stype = ntype
474 node = n
475 end
476 end
477 assert stype != null
478 for n in nodes do
479 if not n.stype < stype then
480 if node == null then
481 error(n, "Type error: no most general type. Got {n.stype} and {stype}.")
482 else
483 error(n, "Type error: no most general type. Got {n.stype} and {stype} at {node.location.relative_to(n.location)}.")
484 end
485 return null
486 end
487 end
488 return stype
489 end
490
491 protected init(tc: ToolContext, mmmodule: MMSrcModule)
492 do
493 _tc = tc
494 _mmmodule = mmmodule
495 end
496 end
497
498 ###############################################################################
499
500 redef class ANode
501 protected fun accept_abs_syntax_visitor(v: AbsSyntaxVisitor) do visit_all(v)
502 end
503
504 redef class Token
505 var _symbol_cache: nullable Symbol
506
507 # Symbol associated with the text
508 # Lazily computed
509 fun to_symbol: Symbol
510 do
511 var s = _symbol_cache
512 if s == null then
513 s = text.to_symbol
514 _symbol_cache = s
515 end
516 return s
517 end
518 end
519
520 redef class AClassdef
521 # Associated class (MM entity)
522 fun local_class: MMSrcLocalClass is abstract
523
524 # Next AClassdef of the same class (if any)
525 readable writable var _next_node: nullable AClassdef = null
526 end
527
528 redef class APropdef
529 # Associated 'self' variable
530 fun self_var: ParamVariable is abstract
531 end
532
533 redef class AAttrPropdef
534 # Associated attribute (MM entity)
535 fun prop: MMSrcAttribute is abstract
536
537 # Associated read accessor (MM entity)
538 fun readmethod: nullable MMSrcMethod is abstract
539
540 # Associated write accessor (MM entity)
541 fun writemethod: nullable MMSrcMethod is abstract
542 end
543
544 redef class AConcreteInitPropdef
545 readable var _super_init_calls: Array[MMMethod] = new Array[MMMethod]
546 readable var _explicit_super_init_calls: Array[MMMethod] = new Array[MMMethod]
547 end
548
549 redef class AMethPropdef
550 # Associated method (MM entity)
551 fun method: MMMethSrcMethod is abstract
552 end
553
554 redef class ATypePropdef
555 # Associated formal type (MM entity)
556 fun prop: MMSrcTypeProperty is abstract
557 end
558
559 redef class AParam
560 # Position in the signature
561 fun position: Int is abstract
562
563 # Associated local variable
564 fun variable: ParamVariable is abstract
565 end
566
567 redef class AClosureDecl
568 # Position in the signature
569 fun position: Int is abstract
570
571 # Associated closure variable
572 fun variable: ClosureVariable is abstract
573 end
574
575 redef class AType
576 # Is the node correcly typed
577 # Return false if typed was not yet computed or
578 # if an error occured during the typing computation
579 fun is_typed: Bool is abstract
580
581 # Return corresponding static type. (require is_typed)
582 fun stype: MMType is abstract
583
584 var _stype_cache: nullable MMType = null
585 var _stype_cached: Bool = false
586
587 # Retrieve the local class corresponding to the type.
588 # Display an error and return null if there is no class
589 # Display an error and return null if the type is not class based (formal one)
590 fun get_local_class(v: AbsSyntaxVisitor): nullable MMLocalClass
591 do
592 var name = n_id.to_symbol
593 var mod = v.mmmodule
594 var cla = v.local_class
595
596 if cla.formal_dict.has_key(name) or cla.has_global_property_by_name(name) then
597 v.error(n_id, "Type error: {name} is a formal type")
598 _stype_cached = true
599 return null
600 end
601
602 if not mod.has_global_class_named(name) then
603 v.error(n_id, "Type error: class {name} not found in module {mod}.")
604 _stype_cached = true
605 return null
606 end
607
608 var local_class = mod.class_by_name(name)
609 local_class.global.check_visibility(v, self, mod)
610 return local_class
611 end
612
613 # Retrieve corresponding static type.
614 # Display an error and return null if there is a problem
615 # But do not performs any subtype check.
616 # get_unchecked_stype should be called to check that the static type is fully valid
617 fun get_unchecked_stype(v: AbsSyntaxVisitor): nullable MMType
618 do
619 if _stype_cached then return _stype_cache
620 _stype_cached = true
621
622 var name = n_id.to_symbol
623 var mod = v.mmmodule
624 var cla = v.local_class
625 var t: nullable MMType
626
627 if cla.formal_dict.has_key(name) then
628 if n_types.length > 0 then
629 v.error(self, "Type error: formal type {name} cannot have formal parameters.")
630 return null
631 end
632 t = cla.formal_dict[name]
633 if n_kwnullable != null then t = t.as_nullable
634 _stype_cache = t
635 return t
636 end
637
638 if cla.has_global_property_by_name(name) then
639 if n_types.length > 0 then
640 v.error(self, "Type error: formal type {name} cannot have formal parameters.")
641 return null
642 end
643 t = cla.get_type.local_class.select_virtual_type(name).stype_for(cla.get_type)
644 if t == null then
645 v.error(self, "Type error: circular definition in formal type {name}.")
646 return null
647 end
648 if n_kwnullable != null then t = t.as_nullable
649 _stype_cache = t
650 return t
651 end
652
653 var local_class = get_local_class(v)
654 if local_class == null then return null
655
656 var arity = n_types.length
657 if local_class.arity != arity then
658 if arity == 0 then
659 v.error(self, "Type error: '{local_class}' is a generic class.")
660 else if local_class.arity == 0 then
661 v.error(self, "Type error: '{local_class}' is not a generic class.")
662 else
663 v.error(self, "Type error: '{local_class}' has {local_class.arity} parameters ({arity} are provided).")
664 end
665 return null
666 end
667
668 if arity > 0 then
669 var tab = new Array[MMType]
670 for p in n_types do
671 var t2 = p.get_unchecked_stype(v)
672 if t2 == null then return null
673 tab.add(t2)
674 end
675 t = local_class.get_instantiate_type(tab)
676 else
677 t = local_class.get_type
678 end
679 if n_kwnullable != null then t = t.as_nullable
680 _stype_cache = t
681 return t
682 end
683
684 # Retrieve corresponding static type.
685 # Display an error and return null if there is a problem
686 fun get_stype(v: AbsSyntaxVisitor): nullable MMType
687 do
688 var t = get_unchecked_stype(v)
689 if t == null then return null
690 if not t.is_valid then return null
691 check_conform(v)
692 return t
693 end
694
695 # Check that a static definition type is conform with regard to formal types
696 # Useful with get_unchecked_stype
697 # Remember that conformance check need that ancestors are totaly computed
698 fun check_conform(v: AbsSyntaxVisitor)
699 do
700 var st = get_unchecked_stype(v)
701 if st == null then return
702 var local_class = st.local_class
703 var arity = n_types.length
704 if arity > 0 then
705 for i in [0..arity[ do
706 var p = n_types[i]
707 var pt = p.get_stype(v)
708 var b = local_class.get_formal(i)
709 if not b.is_valid then return
710 var bt = b.bound
711 bt = bt.adapt_to(st) # We need to abapt because of F-genericity
712 v.check_conform(p, pt, bt)
713 end
714 end
715 end
716 end
717
718 redef class AExpr
719 # Is the expression node correcly typed
720 # Return false if typed was not yet computed or
721 # if an error occured during the typing computation
722 fun is_typed: Bool is abstract
723
724 # Is the expression node a statement? (ie has no return value)
725 # require: is_typed
726 fun is_statement: Bool is abstract
727
728 # The static type of the expression
729 # require: is_typed and not is_statement
730 fun stype: MMType is abstract
731 end
732
733 class AAbsAbsSendExpr
734 super AExpr
735 # The signature of the called property (require is_typed)
736 fun prop_signature: MMSignature is abstract
737
738 # The raw arguments used (without vararg transformation) (require is_typed)
739 fun raw_arguments: Array[AExpr] is abstract
740 end
741
742 class AAbsSendExpr
743 super AAbsAbsSendExpr
744 # The invoked method (require is_typed)
745 fun prop: MMMethod is abstract
746
747 # The return type (if any) (once computed)
748 fun return_type: nullable MMType is abstract
749 end
750
751 class ASuperInitCall
752 super AAbsSendExpr
753 end
754
755 redef class ASuperExpr
756 super ASuperInitCall
757 fun init_in_superclass: nullable MMMethod is abstract
758 end
759
760 redef class ANewExpr
761 super AAbsSendExpr
762 end
763
764 redef class ASendExpr
765 super ASuperInitCall
766 # Closure definitions
767 fun closure_defs: nullable Array[AClosureDef] is abstract
768 end
769
770 redef class AReassignFormExpr
771 # Method used through the reassigment operator (require is_typed)
772 fun assign_method: MMMethod is abstract
773 end
774
775 class ASendReassignExpr
776 super ASendExpr
777 super AReassignFormExpr
778 # The invoked method used to read (require is_typed)
779 # prop is the method used to write
780 fun read_prop: MMMethod is abstract
781 end
782
783 redef class ACallReassignExpr
784 super ASendReassignExpr
785 end
786
787 redef class ABraReassignExpr
788 super ASendReassignExpr
789 end
790
791 redef class AAttrFormExpr
792 # Attribute accessed (require is_typed)
793 fun prop: MMAttribute is abstract
794
795 # Attribute type of the acceded attribute (require is_typed)
796 fun attr_type: MMType is abstract
797 end
798
799 redef class ASuperstringExpr
800 fun atype: MMType is abstract
801 end
802
803 redef class AVardeclExpr
804 # Assiociated local variable
805 fun variable: VarVariable is abstract
806 #readable writable var _variable: nullable VarVariable
807 end
808
809 redef class AForExpr
810 # Associated automatic local variable
811 fun variables: Array[AutoVariable] is abstract
812 end
813
814 redef class ASelfExpr
815 # Associated local variable
816 fun variable: ParamVariable is abstract
817 end
818
819 redef class AVarFormExpr
820 # Associated local variable
821 fun variable: Variable is abstract
822 end
823
824 redef class AClosureCallExpr
825 super AAbsAbsSendExpr
826 # Associated closure variable
827 fun variable: ClosureVariable is abstract
828 end
829
830 redef class AClosureDef
831 # Associated closure
832 fun closure: MMClosure is abstract
833
834 # Automatic variables
835 readable writable var _variables: nullable Array[AutoVariable]
836 end