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