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