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