09b757373e19407ad657a58307fec04b05ea63d8
[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 print("{n.location} not typed but not error")
436 abort
437 end
438 # An error occured in a sub node,
439 # sillently cascade fail
440 return false
441 else if n.is_statement then
442 error(n, "Type error: expected expression.")
443 return false
444 end
445 return true
446 end
447
448 # Combine check_conform and check_expr
449 fun check_conform_expr(n: AExpr, stype: nullable MMType): Bool
450 do
451 if stype == null then return false
452 if check_expr(n) then return check_conform(n, n.stype, stype) else return false
453 end
454
455 # Check conformance between multiple expressions and a static type
456 # Conformance is granted if among them there is a most general type
457 # Return the most general type if a conformance is found
458 # Display an error and return null if no conformance is found
459 # The only allowed combinaison is with the nullable marker
460 # @param stype is a possible additional type (without node)
461 # Examples:
462 # Int, Int, Object => return Object
463 # Int, Float => display error, return null
464 # nullable Int, Object => return nullable Object
465 fun check_conform_multiexpr(stype: nullable MMType, nodes: Collection[AExpr]): nullable MMType
466 do
467 var node: nullable AExpr = null # candidate node
468 for n in nodes do
469 if not check_expr(n) then return null
470 var ntype = n.stype
471 if stype != null and stype.is_nullable != ntype.is_nullable then
472 # nullable combinaison: if one of them is nulable, considers that both are
473 stype = stype.as_nullable
474 ntype = ntype.as_nullable
475 end
476 if stype == null or stype < ntype then
477 stype = ntype
478 node = n
479 end
480 end
481 for n in nodes do
482 if not n.stype < stype.as(not null) then
483 if node == null then
484 error(n, "Type error: no most general type. Got {n.stype} and {stype}.")
485 else
486 error(n, "Type error: no most general type. Got {n.stype} and {stype} at {node.location.relative_to(n.location)}.")
487 end
488 return null
489 end
490 end
491 return stype
492 end
493
494 protected init(tc: ToolContext, module: MMSrcModule)
495 do
496 _tc = tc
497 _module = module
498 end
499 end
500
501 ###############################################################################
502
503 redef class ANode
504 protected fun accept_abs_syntax_visitor(v: AbsSyntaxVisitor) do visit_all(v)
505 end
506
507 redef class Token
508 var _symbol_cache: nullable Symbol
509
510 # Symbol associated with the text
511 # Lazily computed
512 fun to_symbol: Symbol
513 do
514 var s = _symbol_cache
515 if s == null then
516 s = text.to_symbol
517 _symbol_cache = s
518 end
519 return s
520 end
521 end
522
523 redef class AClassdef
524 # Associated class (MM entity)
525 fun local_class: MMSrcLocalClass is abstract
526
527 # Next AClassdef of the same class (if any)
528 readable writable var _next_node: nullable AClassdef = null
529 end
530
531 redef class APropdef
532 # Associated 'self' variable
533 fun self_var: ParamVariable is abstract
534 end
535
536 redef class AAttrPropdef
537 # Associated attribute (MM entity)
538 fun prop: MMSrcAttribute is abstract
539
540 # Associated read accessor (MM entity)
541 fun readmethod: nullable MMSrcMethod is abstract
542
543 # Associated write accessor (MM entity)
544 fun writemethod: nullable MMSrcMethod is abstract
545 end
546
547 redef class AConcreteInitPropdef
548 readable var _super_init_calls: Array[MMMethod] = new Array[MMMethod]
549 readable var _explicit_super_init_calls: Array[MMMethod] = new Array[MMMethod]
550 end
551
552 redef class AMethPropdef
553 # Associated method (MM entity)
554 fun method: MMMethSrcMethod is abstract
555 end
556
557 redef class ATypePropdef
558 # Associated formal type (MM entity)
559 fun prop: MMSrcTypeProperty is abstract
560 end
561
562 redef class AParam
563 # Position in the signature
564 fun position: Int is abstract
565
566 # Associated local variable
567 fun variable: ParamVariable is abstract
568 end
569
570 redef class AClosureDecl
571 # Position in the signature
572 fun position: Int is abstract
573
574 # Associated closure variable
575 fun variable: ClosureVariable is abstract
576 end
577
578 redef class AType
579 # Is the node correcly typed
580 # Return false if typed was not yet computed or
581 # if an error occured during the typing computation
582 fun is_typed: Bool is abstract
583
584 # Return corresponding static type. (require is_typed)
585 fun stype: MMType is abstract
586
587 var _stype_cache: nullable MMType = null
588 var _stype_cached: Bool = false
589
590 # Retrieve the local class corresponding to the type.
591 # Display an error and return null if there is no class
592 # Display an error and return null if the type is not class based (formal one)
593 fun get_local_class(v: AbsSyntaxVisitor): nullable MMLocalClass
594 do
595 var name = n_id.to_symbol
596 var mod = v.module
597 var cla = v.local_class
598
599 if cla.formal_dict.has_key(name) or cla.has_global_property_by_name(name) then
600 v.error(n_id, "Type error: {name} is a formal type")
601 _stype_cached = true
602 return null
603 end
604
605 if not mod.has_global_class_named(name) then
606 v.error(n_id, "Type error: class {name} not found in module {mod}.")
607 _stype_cached = true
608 return null
609 end
610
611 var local_class = mod.class_by_name(name)
612 local_class.global.check_visibility(v, self, mod)
613 return local_class
614 end
615
616 # Retrieve corresponding static type.
617 # Display an error and return null if there is a problem
618 # But do not performs any subtype check.
619 # get_unchecked_stype should be called to check that the static type is fully valid
620 fun get_unchecked_stype(v: AbsSyntaxVisitor): nullable MMType
621 do
622 if _stype_cached then return _stype_cache
623 _stype_cached = true
624
625 var name = n_id.to_symbol
626 var mod = v.module
627 var cla = v.local_class
628 var t: nullable MMType
629
630 if cla.formal_dict.has_key(name) then
631 if n_types.length > 0 then
632 v.error(self, "Type error: formal type {name} cannot have formal parameters.")
633 return null
634 end
635 t = cla.formal_dict[name]
636 if n_kwnullable != null then t = t.as_nullable
637 _stype_cache = t
638 return t
639 end
640
641 if cla.has_global_property_by_name(name) then
642 if n_types.length > 0 then
643 v.error(self, "Type error: formal type {name} cannot have formal parameters.")
644 return null
645 end
646 t = cla.get_type.local_class.select_virtual_type(name).stype_for(cla.get_type)
647 if t == null then
648 v.error(self, "Type error: circular definition in formal type {name}.")
649 return null
650 end
651 if n_kwnullable != null then t = t.as_nullable
652 _stype_cache = t
653 return t
654 end
655
656 var local_class = get_local_class(v)
657 if local_class == null then return null
658
659 var arity = n_types.length
660 if local_class.arity != arity then
661 if arity == 0 then
662 v.error(self, "Type error: '{local_class}' is a generic class.")
663 else if local_class.arity == 0 then
664 v.error(self, "Type error: '{local_class}' is not a generic class.")
665 else
666 v.error(self, "Type error: '{local_class}' has {local_class.arity} parameters ({arity} are provided).")
667 end
668 return null
669 end
670
671 if arity > 0 then
672 var tab = new Array[MMType]
673 for p in n_types do
674 var t2 = p.get_unchecked_stype(v)
675 if t2 == null then return null
676 tab.add(t2)
677 end
678 t = local_class.get_instantiate_type(tab)
679 else
680 t = local_class.get_type
681 end
682 if n_kwnullable != null then t = t.as_nullable
683 _stype_cache = t
684 return t
685 end
686
687 # Retrieve corresponding static type.
688 # Display an error and return null if there is a problem
689 fun get_stype(v: AbsSyntaxVisitor): nullable MMType
690 do
691 var t = get_unchecked_stype(v)
692 if t == null then return null
693 if not t.is_valid then return null
694 check_conform(v)
695 return t
696 end
697
698 # Check that a static definition type is conform with regard to formal types
699 # Useful with get_unchecked_stype
700 # Remember that conformance check need that ancestors are totaly computed
701 fun check_conform(v: AbsSyntaxVisitor)
702 do
703 var st = get_unchecked_stype(v)
704 if st == null then return
705 var local_class = st.local_class
706 var arity = n_types.length
707 if arity > 0 then
708 for i in [0..arity[ do
709 var p = n_types[i]
710 var pt = p.get_stype(v)
711 var b = local_class.get_formal(i)
712 if not b.is_valid then return
713 var bt = b.bound
714 bt = bt.adapt_to(st) # We need to abapt because of F-genericity
715 v.check_conform(p, pt, bt)
716 end
717 end
718 end
719 end
720
721 redef class AExpr
722 # Is the expression node correcly typed
723 # Return false if typed was not yet computed or
724 # if an error occured during the typing computation
725 fun is_typed: Bool is abstract
726
727 # Is the expression node a statement? (ie has no return value)
728 # require: is_typed
729 fun is_statement: Bool is abstract
730
731 # The static type of the expression
732 # require: is_typed and not is_statement
733 fun stype: MMType is abstract
734 end
735
736 class AAbsAbsSendExpr
737 special AExpr
738 # The signature of the called property (require is_typed)
739 fun prop_signature: MMSignature is abstract
740
741 # The raw arguments used (without vararg transformation) (require is_typed)
742 fun raw_arguments: Array[AExpr] is abstract
743 end
744
745 class AAbsSendExpr
746 special AAbsAbsSendExpr
747 # The invoked method (require is_typed)
748 fun prop: MMMethod is abstract
749
750 # The return type (if any) (once computed)
751 fun return_type: nullable MMType is abstract
752 end
753
754 class ASuperInitCall
755 special AAbsSendExpr
756 end
757
758 redef class ASuperExpr
759 special ASuperInitCall
760 fun init_in_superclass: nullable MMMethod is abstract
761 end
762
763 redef class ANewExpr
764 special AAbsSendExpr
765 end
766
767 redef class ASendExpr
768 special ASuperInitCall
769 # Closure definitions
770 fun closure_defs: nullable Array[AClosureDef] is abstract
771 end
772
773 redef class AReassignFormExpr
774 # Method used through the reassigment operator (require is_typed)
775 fun assign_method: MMMethod is abstract
776 end
777
778 class ASendReassignExpr
779 special ASendExpr
780 special AReassignFormExpr
781 # The invoked method used to read (require is_typed)
782 # prop is the method used to write
783 fun read_prop: MMMethod is abstract
784 end
785
786 redef class ACallReassignExpr
787 special ASendReassignExpr
788 end
789
790 redef class ABraReassignExpr
791 special ASendReassignExpr
792 end
793
794 redef class AAttrFormExpr
795 # Attribute accessed (require is_typed)
796 fun prop: MMAttribute is abstract
797
798 # Attribute type of the acceded attribute (require is_typed)
799 fun attr_type: MMType is abstract
800 end
801
802 redef class ASuperstringExpr
803 fun atype: MMType is abstract
804 end
805
806 redef class AVardeclExpr
807 # Assiociated local variable
808 fun variable: VarVariable is abstract
809 #readable writable var _variable: nullable VarVariable
810 end
811
812 redef class AForExpr
813 # Associated automatic local variable
814 fun variable: AutoVariable is abstract
815 end
816
817 redef class ASelfExpr
818 # Associated local variable
819 fun variable: ParamVariable is abstract
820 end
821
822 redef class AVarFormExpr
823 # Associated local variable
824 fun variable: Variable is abstract
825 end
826
827 redef class AClosureCallExpr
828 special AAbsAbsSendExpr
829 # Associated closure variable
830 fun variable: ClosureVariable is abstract
831 end
832
833 redef class AClosureDef
834 # Associated closure
835 fun closure: MMClosure is abstract
836
837 # Automatic variables
838 readable writable var _variables: nullable Array[AutoVariable]
839 end