1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2008 Jean Privat <jean@pryen.org>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # Common syntax structures for syntax analysis of NIT AST.
23 # Concrete NIT source module
26 # The related AST node
27 readable var _node
: AModule
29 # Concrete NIT source local classs by name
30 readable var _src_local_classes
: Map[Symbol, MMSrcLocalClass]
32 init(c
: MMContext, source
: AModule, dir
: MMDirectory, name
: Symbol, filename
: String)
34 super(name
, dir
, c
, filename
)
36 _src_local_classes
= new HashMap[Symbol, MMSrcLocalClass]
40 redef class MMGlobalClass
41 # Check that a module can access a class
42 fun check_visibility
(v
: AbsSyntaxVisitor, n
: PNode, cm
: MMSrcModule): Bool do
44 assert pm
isa MMSrcModule
45 var vpm
= cm
.visibility_for
(pm
)
49 v
.error
(n
, "Visibility error: Class {self} comes from the hidden module {cm}.") # TODO: should not occur
51 else if visibility_level
>= 3 then
52 v
.error
(n
, "Visibility error: Class {self} is private.")
59 # Concrete NIT source local classes
61 special MMConcreteClass
62 # The related AST nodes
63 readable var _nodes
: Array[PClassdef]
65 # Concrete NIT source generic formal parameter by name
66 readable var _formal_dict
: Map[Symbol, MMTypeFormalParameter] = new HashMap[Symbol, MMTypeFormalParameter]
68 # Concrete NIT source properties by name
69 readable var _src_local_properties
: Map[Symbol, MMLocalProperty]
71 init(mod
: MMSrcModule, n
: Symbol, cla
: nullable PClassdef, a
: Int)
75 _nodes
= new Array[PClassdef]
79 _src_local_properties
= new HashMap[Symbol, MMLocalProperty]
83 redef class MMGlobalProperty
84 # Check that a module can access a property
85 fun check_visibility
(v
: AbsSyntaxVisitor, n
: PNode, cm
: MMSrcModule, allows_protected
: Bool): Bool do
86 var pm
= local_class
.module
87 assert pm
isa MMSrcModule
88 var vpm
= cm
.visibility_for
(pm
)
92 # TODO: should not occurs
93 v
.error
(n
, "Visibility error: Property {self} comes from the hidden module {cm}.")
95 else if visibility_level
>= 3 then
96 v
.error
(n
, "Visibility error: Property {self} is private.")
98 else if visibility_level
>= 2 and not allows_protected
then
99 v
.error
(n
, "Visibility error: Property {self} is protected and can only acceded by self.")
106 redef class MMLocalProperty
107 # The attached node (if any)
108 fun node
: nullable PNode do return null
110 # Is the concrete method defined as init
111 fun is_init
: Bool do return false
114 # Concrete NIT source attribute
117 redef readable var _node
: AAttrPropdef
118 init(name
: Symbol, cla
: MMLocalClass, n
: AAttrPropdef)
125 # Concrete NIT source method
130 # Concrete NIT source method for an automatic accesor
131 class MMAttrImplementationMethod
133 redef readable var _node
: AAttrPropdef
134 init(name
: Symbol, cla
: MMLocalClass, n
: AAttrPropdef)
141 # Concrete NIT source method for an automatic read accesor
142 class MMReadImplementationMethod
143 special MMAttrImplementationMethod
144 init(name
: Symbol, cla
: MMLocalClass, n
: AAttrPropdef)
150 # Concrete NIT source method for an automatic write accesor
151 class MMWriteImplementationMethod
152 special MMAttrImplementationMethod
153 init(name
: Symbol, cla
: MMLocalClass, n
: AAttrPropdef)
159 # Concrete NIT source method for an explicit method
160 class MMMethSrcMethod
162 redef fun is_init
do return _node
isa AConcreteInitPropdef
163 redef readable var _node
: nullable AMethPropdef
164 init(name
: Symbol, cla
: MMLocalClass, n
: nullable AMethPropdef)
171 # Concrete NIT source virtual type
172 class MMSrcTypeProperty
173 special MMLocalProperty
174 special MMTypeProperty
175 redef readable var _node
: ATypePropdef
176 init(name
: Symbol, cla
: MMLocalClass, n
: ATypePropdef)
183 # Concrete NIT implicit constructor
185 special MMMethSrcMethod
186 fun super_init
: nullable MMLocalProperty is abstract
187 redef fun is_init
do return true
188 readable var _unassigned_attributes
: Array[MMSrcAttribute]
189 readable var _super_inits
: Array[MMLocalProperty]
190 init(cla
: MMLocalClass, unassigned_attributes
: Array[MMSrcAttribute], super_inits
: Array[MMLocalProperty])
192 super(once
"init".to_symbol
, cla
, null)
193 _unassigned_attributes
= unassigned_attributes
194 _super_inits
= super_inits
199 abstract class Variable
200 # Name of the variable
201 readable var _name
: Symbol
203 # Declaration AST node
204 readable var _decl
: nullable PNode
207 readable writable var _stype
: nullable MMType
209 redef fun to_s
do return _name
.to_s
211 fun kind
: String is abstract
213 init(n
: Symbol, d
: nullable PNode)
220 # Variable declared with 'var'
223 redef fun kind
do return once
"variable"
224 init(n
: Symbol, d
: PNode) do super
227 # Parameter of method (declared in signature)
230 redef fun kind
do return once
"parameter"
231 init(n
: Symbol, d
: nullable PNode) do super
234 # Automatic variable (like in the 'for' statement)
237 redef fun kind
do return once
"automatic variable"
238 init(n
: Symbol, d
: PNode) do super
241 # False variable corresponding to closures declared in signatures
242 # Lives in the same namespace than variables
243 class ClosureVariable
245 redef fun kind
do return once
"closure"
247 # The signature of the closure
248 readable var _closure
: MMClosure
250 init(n
: Symbol, d
: PNode, c
: MMClosure)
257 ###############################################################################
259 # Visitor used during the syntax analysis
260 class AbsSyntaxVisitor
262 # The root type Object
263 fun type_object
: MMType
265 return _module
.class_by_name
(once
("Object".to_symbol
)).get_type
268 # The primitive type Bool
269 fun type_bool
: MMType
271 return _module
.class_by_name
(once
("Bool".to_symbol
)).get_type
274 # The primitive type Int
277 return _module
.class_by_name
(once
("Int".to_symbol
)).get_type
280 # The primitive type Float
281 fun type_float
: MMType
283 return _module
.class_by_name
(once
("Float".to_symbol
)).get_type
286 # The primitive type Char
287 fun type_char
: MMType
289 return _module
.class_by_name
(once
("Char".to_symbol
)).get_type
292 # The primitive type String
293 fun type_string
: MMType
295 return _module
.class_by_name
(once
("String".to_symbol
)).get_type
298 # The primitive type Collection[nullable Object]
299 fun type_collection
: MMType
301 return _module
.class_by_name
(once
("Collection".to_symbol
)).get_instantiate_type
([type_object
.as_nullable
])
304 # The primitive type NativeString
305 fun type_nativestring
: MMType
307 return _module
.class_by_name
(once
("NativeString".to_symbol
)).get_type
310 # The primitive type Array[?]
311 fun type_array
(stype
: MMType): MMType
313 return _module
.class_by_name
(once
("Array".to_symbol
)).get_instantiate_type
([stype
])
316 # The primitive type Discrete
317 fun type_discrete
: MMType
319 return _module
.class_by_name
(once
("Discrete".to_symbol
)).get_type
322 # The primitive type Range[?]
323 fun type_range
(stype
: MMType): MMType
325 return _module
.class_by_name
(once
("Range".to_symbol
)).get_instantiate_type
([stype
])
328 # The primitive type of null
329 fun type_none
: MMType
331 return _module
.type_none
335 readable var _module
: MMSrcModule
338 fun local_class
: MMSrcLocalClass do return _local_class
.as(not null)
339 writable var _local_class
: nullable MMSrcLocalClass
341 # The current property
342 fun local_property
: MMLocalProperty do return _local_property
.as(not null)
343 writable var _local_property
: nullable MMLocalProperty
345 # The current tool configuration/status
346 readable var _tc
: ToolContext
348 # Display an error for a given syntax node
349 fun error
(n
: nullable PNode, s
: String)
351 _tc
.error
("{locate(n)}: {s}")
354 # Display a warning for a given syntax node
355 fun warning
(n
: nullable PNode, s
: String)
357 _tc
.warning
("{locate(n)}: {s}")
361 fun locate
(n
: nullable PNode): String
363 if n
!= null then return n
.locate
364 return _module
.filename
367 # Check conformity and display error
368 fun check_conform
(n
: PNode, subtype
: nullable MMType, stype
: nullable MMType): Bool
370 if stype
== null or subtype
== null then
373 if subtype
< stype
then
376 error
(n
, "Type error: expected {stype}, got {subtype}")
380 # Check that an expression has a static type and that
381 # Display an error and return false if n is a statement
382 # Require that the static type of n is known
383 fun check_expr
(n
: PExpr): Bool
385 if not n
.is_typed
then
386 if tc
.error_count
== 0 then
387 print
("{n.locate} not typed but not error")
390 # An error occured in a sub node,
391 # sillently cascade fail
393 else if n
.is_statement
then
394 error
(n
, "Type error: expected expression.")
400 # Combine check_conform and check_expr
401 fun check_conform_expr
(n
: PExpr, stype
: nullable MMType): Bool
403 if stype
== null then return false
404 if check_expr
(n
) then return check_conform
(n
, n
.stype
, stype
) else return false
407 # Check conformance between multiple expressions and a static type
408 # Conformance is granted if among them there is a most general type
409 # Return the most general type if a conformance is found
410 # Display an error and return null if no conformance is found
411 # The only allowed combinaison is with the nullable marker
412 # @param stype is a possible additional type (without node)
414 # Int, Int, Object => return Object
415 # Int, Float => display error, return null
416 # nullable Int, Object => return nullable Object
417 fun check_conform_multiexpr
(stype
: nullable MMType, nodes
: Collection[PExpr]): nullable MMType
419 var node
: nullable PExpr = null # candidate node
421 if not check_expr
(n
) then return null
423 if stype
!= null and stype
.is_nullable
!= ntype
.is_nullable
then
424 # nullable combinaison: if one of them is nulable, considers that both are
425 stype
= stype
.as_nullable
426 ntype
= ntype
.as_nullable
428 if stype
== null or stype
< ntype
then
434 if not n
.stype
< stype
.as(not null) then
436 error
(n
, "Type error: no most general type. Got {n.stype} and {stype}.")
438 error
(n
, "Type error: no most general type. Got {n.stype} and {stype} at {node.locate}.")
446 protected init(tc
: ToolContext, module: MMSrcModule)
453 ###############################################################################
456 protected fun accept_abs_syntax_visitor
(v
: AbsSyntaxVisitor) do visit_all
(v
)
460 var _symbol_cache
: nullable Symbol
462 # Symbol associated with the text
464 fun to_symbol
: Symbol
466 var s
= _symbol_cache
475 redef class PClassdef
476 # Associated class (MM entity)
477 fun local_class
: MMSrcLocalClass is abstract
480 redef class AAttrPropdef
481 # Associated attribute (MM entity)
482 fun prop
: MMSrcAttribute is abstract
484 # Associated read accessor (MM entity)
485 fun readmethod
: nullable MMSrcMethod is abstract
487 # Associated write accessor (MM entity)
488 fun writemethod
: nullable MMSrcMethod is abstract
491 redef class AConcreteInitPropdef
492 readable var _super_init_calls
: Array[MMMethod] = new Array[MMMethod]
493 readable var _explicit_super_init_calls
: Array[MMMethod] = new Array[MMMethod]
496 redef class AMethPropdef
497 # Associated method (MM entity)
498 fun method
: MMMethSrcMethod is abstract
500 # Associated 'self' variable
501 fun self_var
: ParamVariable is abstract
504 redef class ATypePropdef
505 # Associated formal type (MM entity)
506 fun prop
: MMSrcTypeProperty is abstract
510 # Position in the signature
511 fun position
: Int is abstract
513 # Associated local variable
514 fun variable
: ParamVariable is abstract
517 redef class PClosureDecl
518 # Associated closure variable
519 fun variable
: ClosureVariable is abstract
523 # Retrieve the local class corresponding to the type.
524 # Display an error and return null if there is no class
525 # Display an error and return null if the type is not class based (formal one)
526 fun get_local_class
(v
: AbsSyntaxVisitor): nullable MMLocalClass is abstract
528 # Retrieve corresponding static type.
529 # Display an error and return null if there is a problem
530 fun get_stype
(v
: AbsSyntaxVisitor): nullable MMType is abstract
532 # Retrieve corresponding static type.
533 # Display an error and return null if there is a problem
534 # But do not performs any subtype check.
535 # get_unchecked_stype should be called to check that the static type is fully valid
536 fun get_unchecked_stype
(v
: AbsSyntaxVisitor): nullable MMType is abstract
538 # Check that a static definition type is conform with regard to formal types
539 # Useful with get_unchecked_stype
540 # Remember that conformance check need that ancestors are totaly computed
541 fun check_conform
(v
: AbsSyntaxVisitor) is abstract
543 # Is the node correcly typed
544 # Return false if typed was not yet computed or
545 # if an error occured during the typing computation
546 fun is_typed
: Bool is abstract
548 # Return corresponding static type. (require is_typed)
549 fun stype
: MMType is abstract
553 var _stype_cache
: nullable MMType = null
554 var _stype_cached
: Bool = false
556 redef fun get_local_class
(v
)
558 var name
= n_id
.to_symbol
560 var cla
= v
.local_class
562 if cla
.formal_dict
.has_key
(name
) or cla
.has_global_property_by_name
(name
) then
563 v
.error
(n_id
, "Type error: {name} is a formal type")
568 if not mod
.has_global_class_named
(name
) then
569 v
.error
(n_id
, "Type error: class {name} not found in module {mod}.")
574 var local_class
= mod
.class_by_name
(name
)
575 local_class
.global
.check_visibility
(v
, self, mod
)
579 redef fun get_unchecked_stype
(v
)
581 if _stype_cached
then return _stype_cache
584 var name
= n_id
.to_symbol
586 var cla
= v
.local_class
587 var t
: nullable MMType
589 if cla
.formal_dict
.has_key
(name
) then
590 if n_types
.length
> 0 then
591 v
.error
(self, "Type error: formal type {name} cannot have formal parameters.")
594 t
= cla
.formal_dict
[name
]
595 if n_kwnullable
!= null then t
= t
.as_nullable
600 if cla
.has_global_property_by_name
(name
) then
601 if n_types
.length
> 0 then
602 v
.error
(self, "Type error: formal type {name} cannot have formal parameters.")
605 t
= cla
.get_type
.local_class
.select_virtual_type
(name
).stype_for
(cla
.get_type
)
607 v
.error
(self, "Type error: circular definition in formal type {name}.")
610 if n_kwnullable
!= null then t
= t
.as_nullable
615 var local_class
= get_local_class
(v
)
616 if local_class
== null then return null
618 var arity
= n_types
.length
619 if local_class
.arity
!= arity
then
621 v
.error
(self, "Type error: '{local_class}' is a generic class.")
622 else if local_class
.arity
== 0 then
623 v
.error
(self, "Type error: '{local_class}' is not a generic class.")
625 v
.error
(self, "Type error: '{local_class}' has {local_class.arity} parameters ({arity} are provided).")
631 var tab
= new Array[MMType]
633 var t2
= p
.get_unchecked_stype
(v
)
634 if t2
== null then return null
637 t
= local_class
.get_instantiate_type
(tab
)
639 t
= local_class
.get_type
641 if n_kwnullable
!= null then t
= t
.as_nullable
646 redef fun get_stype
(v
)
648 var t
= get_unchecked_stype
(v
)
649 if t
== null then return null
650 if not t
.is_valid
then return null
655 redef fun check_conform
(v
)
657 var st
= get_unchecked_stype
(v
)
658 if st
== null then return
659 var local_class
= st
.local_class
660 var arity
= n_types
.length
662 for i
in [0..arity
[ do
664 var pt
= p
.get_stype
(v
)
665 var b
= local_class
.get_formal
(i
)
666 if not b
.is_valid
then return
668 bt
= bt
.adapt_to
(st
) # We need to abapt because of F-genericity
669 v
.check_conform
(p
, pt
, bt
)
676 # Is the expression node correcly typed
677 # Return false if typed was not yet computed or
678 # if an error occured during the typing computation
679 fun is_typed
: Bool is abstract
681 # Is the expression node a statement? (ie has no return value)
683 fun is_statement
: Bool is abstract
685 # The static type of the expression
686 # require: is_typed and not is_statement
687 fun stype
: MMType is abstract
690 class AAbsAbsSendExpr
692 # The signature of the called property (require is_typed)
693 fun prop_signature
: MMSignature is abstract
695 # The real arguments used (after star transformation) (require is_typed)
696 fun arguments
: Array[PExpr] is abstract
700 special AAbsAbsSendExpr
701 # The invoked method (require is_typed)
702 fun prop
: MMMethod is abstract
704 # The return type (if any) (once computed)
705 fun return_type
: nullable MMType is abstract
712 redef class ASuperExpr
713 special ASuperInitCall
714 fun init_in_superclass
: nullable MMMethod is abstract
721 redef class ASendExpr
722 special ASuperInitCall
723 # Closure definitions
724 fun closure_defs
: nullable Array[PClosureDef] is abstract
727 redef class AReassignFormExpr
728 # Method used through the reassigment operator (require is_typed)
729 fun assign_method
: MMMethod is abstract
732 class ASendReassignExpr
734 special AReassignFormExpr
735 # The invoked method used to read (require is_typed)
736 # prop is the method used to write
737 fun read_prop
: MMMethod is abstract
740 redef class ACallReassignExpr
741 special ASendReassignExpr
744 redef class ABraReassignExpr
745 special ASendReassignExpr
748 redef class AAttrFormExpr
749 # Attribute accessed (require is_typed)
750 fun prop
: MMAttribute is abstract
752 # Attribute type of the acceded attribute (require is_typed)
753 fun attr_type
: MMType is abstract
756 redef class AStringFormExpr
757 fun meth_with_native
: MMMethod is abstract
760 redef class ASuperstringExpr
761 fun meth_with_capacity
: MMMethod is abstract
762 fun meth_add
: MMMethod is abstract
763 fun meth_to_s
: MMMethod is abstract
764 fun atype
: MMType is abstract
767 redef class AArrayExpr
768 fun meth_with_capacity
: MMMethod is abstract
769 fun meth_add
: MMMethod is abstract
772 redef class ARangeExpr
773 fun meth_init
: MMMethod is abstract
776 redef class AVardeclExpr
777 # Assiociated local variable
778 fun variable
: VarVariable is abstract
779 #readable writable var _variable: nullable VarVariable
783 # Associated automatic local variable
784 fun variable
: AutoVariable is abstract
785 fun meth_iterator
: MMMethod is abstract
786 fun meth_is_ok
: MMMethod is abstract
787 fun meth_item
: MMMethod is abstract
788 fun meth_next
: MMMethod is abstract
791 redef class ASelfExpr
792 # Associated local variable
793 fun variable
: ParamVariable is abstract
794 #readable writable var _variable: nullable ParamVariable
797 redef class AVarFormExpr
798 # Associated local variable
799 fun variable
: Variable is abstract
800 #readable writable var _variable: nullable Variable
803 redef class AClosureCallExpr
804 special AAbsAbsSendExpr
805 # Associated closure variable
806 fun variable
: ClosureVariable is abstract
807 #readable writable var _variable: nullable ClosureVariable
810 redef class PClosureDef
812 #readable writable var _closure: nullable MMClosure
813 fun closure
: MMClosure is abstract
815 # Automatic variables
816 readable writable var _variables
: nullable Array[AutoVariable]