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