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