062cebb4dcfddff1df5de6f1c543f38afdc7bb6c
[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 # The related AST node
27 readable var _node: AModule
28
29 # Concrete NIT source local classs by name
30 readable var _src_local_classes: Map[Symbol, MMSrcLocalClass]
31
32 init(c: MMContext, source: AModule, dir: MMDirectory, name: Symbol, filename: String)
33 do
34 super(name, dir, c, filename)
35 _node = source
36 _src_local_classes = new HashMap[Symbol, MMSrcLocalClass]
37 end
38 end
39
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
43 var pm = intro.module
44 assert pm isa MMSrcModule
45 var vpm = cm.visibility_for(pm)
46 if vpm == 3 then
47 return true
48 else if vpm == 0 then
49 v.error(n, "Visibility error: Class {self} comes from the hidden module {cm}.") # TODO: should not occur
50 return false
51 else if visibility_level >= 3 then
52 v.error(n, "Visibility error: Class {self} is private.")
53 return false
54 end
55 return true
56 end
57 end
58
59 # Concrete NIT source local classes
60 class MMSrcLocalClass
61 special MMConcreteClass
62 # The related AST nodes
63 readable var _nodes: Array[PClassdef]
64
65 # Concrete NIT source generic formal parameter by name
66 readable var _formal_dict: Map[Symbol, MMTypeFormalParameter] = new HashMap[Symbol, MMTypeFormalParameter]
67
68 # Concrete NIT source properties by name
69 readable var _src_local_properties: Map[Symbol, MMLocalProperty]
70
71 init(mod: MMSrcModule, n: Symbol, cla: nullable PClassdef, a: Int)
72 do
73 super(mod, n, a)
74 if cla == null then
75 _nodes = new Array[PClassdef]
76 else
77 _nodes = [cla]
78 end
79 _src_local_properties = new HashMap[Symbol, MMLocalProperty]
80 end
81 end
82
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)
89 if vpm == 3 then
90 return true
91 else if vpm == 0 then
92 # TODO: should not occurs
93 v.error(n, "Visibility error: Property {self} comes from the hidden module {cm}.")
94 return false
95 else if visibility_level >= 3 then
96 v.error(n, "Visibility error: Property {self} is private.")
97 return false
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.")
100 return false
101 end
102 return true
103 end
104 end
105
106 redef class MMLocalProperty
107 # The attached node (if any)
108 fun node: nullable PNode do return null
109
110 # Is the concrete method defined as init
111 fun is_init: Bool do return false
112 end
113
114 # Concrete NIT source attribute
115 class MMSrcAttribute
116 special MMAttribute
117 redef readable var _node: AAttrPropdef
118 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
119 do
120 super(name, cla)
121 _node = n
122 end
123 end
124
125 # Concrete NIT source method
126 class MMSrcMethod
127 special MMMethod
128 end
129
130 # Concrete NIT source method for an automatic accesor
131 class MMAttrImplementationMethod
132 special MMSrcMethod
133 redef readable var _node: AAttrPropdef
134 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
135 do
136 super(name, cla)
137 _node = n
138 end
139 end
140
141 # Concrete NIT source method for an automatic read accesor
142 class MMReadImplementationMethod
143 special MMAttrImplementationMethod
144 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
145 do
146 super(name, cla, n)
147 end
148 end
149
150 # Concrete NIT source method for an automatic write accesor
151 class MMWriteImplementationMethod
152 special MMAttrImplementationMethod
153 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
154 do
155 super(name, cla, n)
156 end
157 end
158
159 # Concrete NIT source method for an explicit method
160 class MMMethSrcMethod
161 special MMSrcMethod
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)
165 do
166 super(name, cla)
167 _node = n
168 end
169 end
170
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)
177 do
178 super(name, cla)
179 _node = n
180 end
181 end
182
183 # Concrete NIT implicit constructor
184 class MMImplicitInit
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])
191 do
192 super(once "init".to_symbol, cla, null)
193 _unassigned_attributes = unassigned_attributes
194 _super_inits = super_inits
195 end
196 end
197
198 # Local variables
199 abstract class Variable
200 # Name of the variable
201 readable var _name: Symbol
202
203 # Declaration AST node
204 readable var _decl: nullable PNode
205
206 # Static type
207 readable writable var _stype: nullable MMType
208
209 redef fun to_s do return _name.to_s
210
211 fun kind: String is abstract
212
213 init(n: Symbol, d: nullable PNode)
214 do
215 _name = n
216 _decl = d
217 end
218 end
219
220 # Variable declared with 'var'
221 class VarVariable
222 special Variable
223 redef fun kind do return once "variable"
224 init(n: Symbol, d: PNode) do super
225 end
226
227 # Parameter of method (declared in signature)
228 class ParamVariable
229 special Variable
230 redef fun kind do return once "parameter"
231 init(n: Symbol, d: nullable PNode) do super
232 end
233
234 # Automatic variable (like in the 'for' statement)
235 class AutoVariable
236 special Variable
237 redef fun kind do return once "automatic variable"
238 init(n: Symbol, d: PNode) do super
239 end
240
241 # False variable corresponding to closures declared in signatures
242 # Lives in the same namespace than variables
243 class ClosureVariable
244 special Variable
245 redef fun kind do return once "closure"
246
247 # The signature of the closure
248 readable var _closure: MMClosure
249
250 init(n: Symbol, d: PNode, c: MMClosure)
251 do
252 super(n, d)
253 _closure = c
254 end
255 end
256
257 ###############################################################################
258
259 # Visitor used during the syntax analysis
260 class AbsSyntaxVisitor
261 special Visitor
262 # The root type Object
263 fun type_object: MMType
264 do
265 return _module.class_by_name(once ("Object".to_symbol)).get_type
266 end
267
268 # The primitive type Bool
269 fun type_bool: MMType
270 do
271 return _module.class_by_name(once ("Bool".to_symbol)).get_type
272 end
273
274 # The primitive type Int
275 fun type_int: MMType
276 do
277 return _module.class_by_name(once ("Int".to_symbol)).get_type
278 end
279
280 # The primitive type Float
281 fun type_float: MMType
282 do
283 return _module.class_by_name(once ("Float".to_symbol)).get_type
284 end
285
286 # The primitive type Char
287 fun type_char: MMType
288 do
289 return _module.class_by_name(once ("Char".to_symbol)).get_type
290 end
291
292 # The primitive type String
293 fun type_string: MMType
294 do
295 return _module.class_by_name(once ("String".to_symbol)).get_type
296 end
297
298 # The primitive type Collection[nullable Object]
299 fun type_collection: MMType
300 do
301 return _module.class_by_name(once ("Collection".to_symbol)).get_instantiate_type([type_object.as_nullable])
302 end
303
304 # The primitive type NativeString
305 fun type_nativestring: MMType
306 do
307 return _module.class_by_name(once ("NativeString".to_symbol)).get_type
308 end
309
310 # The primitive type Array[?]
311 fun type_array(stype: MMType): MMType
312 do
313 return _module.class_by_name(once ("Array".to_symbol)).get_instantiate_type([stype])
314 end
315
316 # The primitive type Discrete
317 fun type_discrete: MMType
318 do
319 return _module.class_by_name(once ("Discrete".to_symbol)).get_type
320 end
321
322 # The primitive type Range[?]
323 fun type_range(stype: MMType): MMType
324 do
325 return _module.class_by_name(once ("Range".to_symbol)).get_instantiate_type([stype])
326 end
327
328 # The primitive type of null
329 fun type_none: MMType
330 do
331 return _module.type_none
332 end
333
334 # The current module
335 readable var _module: MMSrcModule
336
337 # The current class
338 fun local_class: MMSrcLocalClass do return _local_class.as(not null)
339 writable var _local_class: nullable MMSrcLocalClass
340
341 # The current property
342 fun local_property: MMLocalProperty do return _local_property.as(not null)
343 writable var _local_property: nullable MMLocalProperty
344
345 # The current tool configuration/status
346 readable var _tc: ToolContext
347
348 # Display an error for a given syntax node
349 fun error(n: nullable PNode, s: String)
350 do
351 _tc.error("{locate(n)}: {s}")
352 end
353
354 # Display a warning for a given syntax node
355 fun warning(n: nullable PNode, s: String)
356 do
357 _tc.warning("{locate(n)}: {s}")
358 end
359
360 #
361 fun locate(n: nullable PNode): String
362 do
363 if n != null then return n.locate
364 return _module.filename
365 end
366
367 # Check conformity and display error
368 fun check_conform(n: PNode, subtype: nullable MMType, stype: nullable MMType): Bool
369 do
370 if stype == null or subtype == null then
371 return false
372 end
373 if subtype < stype then
374 return true
375 end
376 error(n, "Type error: expected {stype}, got {subtype}")
377 return false
378 end
379
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
384 do
385 if not n.is_typed then
386 if tc.error_count == 0 then
387 print("{n.locate} not typed but not error")
388 abort
389 end
390 # An error occured in a sub node,
391 # sillently cascade fail
392 return false
393 else if n.is_statement then
394 error(n, "Type error: expected expression.")
395 return false
396 end
397 return true
398 end
399
400 # Combine check_conform and check_expr
401 fun check_conform_expr(n: PExpr, stype: nullable MMType): Bool
402 do
403 if stype == null then return false
404 if check_expr(n) then return check_conform(n, n.stype, stype) else return false
405 end
406
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)
413 # Examples:
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
418 do
419 var node: nullable PExpr = null # candidate node
420 for n in nodes do
421 if not check_expr(n) then return null
422 var ntype = n.stype
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
427 end
428 if stype == null or stype < ntype then
429 stype = ntype
430 node = n
431 end
432 end
433 for n in nodes do
434 if not n.stype < stype.as(not null) then
435 if node == null then
436 error(n, "Type error: no most general type. Got {n.stype} and {stype}.")
437 else
438 error(n, "Type error: no most general type. Got {n.stype} and {stype} at {node.locate}.")
439 end
440 return null
441 end
442 end
443 return stype
444 end
445
446 protected init(tc: ToolContext, module: MMSrcModule)
447 do
448 _tc = tc
449 _module = module
450 end
451 end
452
453 ###############################################################################
454
455 redef class PNode
456 protected fun accept_abs_syntax_visitor(v: AbsSyntaxVisitor) do visit_all(v)
457 end
458
459 redef class Token
460 var _symbol_cache: nullable Symbol
461
462 # Symbol associated with the text
463 # Lazily computed
464 fun to_symbol: Symbol
465 do
466 var s = _symbol_cache
467 if s == null then
468 s = text.to_symbol
469 _symbol_cache = s
470 end
471 return s
472 end
473 end
474
475 redef class PClassdef
476 # Associated class (MM entity)
477 fun local_class: MMSrcLocalClass is abstract
478 end
479
480 redef class AAttrPropdef
481 # Associated attribute (MM entity)
482 fun prop: MMSrcAttribute is abstract
483
484 # Associated read accessor (MM entity)
485 fun readmethod: nullable MMSrcMethod is abstract
486
487 # Associated write accessor (MM entity)
488 fun writemethod: nullable MMSrcMethod is abstract
489 end
490
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]
494 end
495
496 redef class AMethPropdef
497 # Associated method (MM entity)
498 fun method: MMMethSrcMethod is abstract
499
500 # Associated 'self' variable
501 fun self_var: ParamVariable is abstract
502 end
503
504 redef class ATypePropdef
505 # Associated formal type (MM entity)
506 fun prop: MMSrcTypeProperty is abstract
507 end
508
509 redef class PParam
510 # Position in the signature
511 fun position: Int is abstract
512
513 # Associated local variable
514 fun variable: ParamVariable is abstract
515 end
516
517 redef class PClosureDecl
518 # Associated closure variable
519 fun variable: ClosureVariable is abstract
520 end
521
522 redef class PType
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
527
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
531
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
537
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
542
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
547
548 # Return corresponding static type. (require is_typed)
549 fun stype: MMType is abstract
550 end
551
552 redef class AType
553 var _stype_cache: nullable MMType = null
554 var _stype_cached: Bool = false
555
556 redef fun get_local_class(v)
557 do
558 var name = n_id.to_symbol
559 var mod = v.module
560 var cla = v.local_class
561
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")
564 _stype_cached = true
565 return null
566 end
567
568 if not mod.has_global_class_named(name) then
569 v.error(n_id, "Type error: class {name} not found in module {mod}.")
570 _stype_cached = true
571 return null
572 end
573
574 var local_class = mod.class_by_name(name)
575 local_class.global.check_visibility(v, self, mod)
576 return local_class
577 end
578
579 redef fun get_unchecked_stype(v)
580 do
581 if _stype_cached then return _stype_cache
582 _stype_cached = true
583
584 var name = n_id.to_symbol
585 var mod = v.module
586 var cla = v.local_class
587 var t: nullable MMType
588
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.")
592 return null
593 end
594 t = cla.formal_dict[name]
595 if n_kwnullable != null then t = t.as_nullable
596 _stype_cache = t
597 return t
598 end
599
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.")
603 return null
604 end
605 t = cla.get_type.local_class.select_virtual_type(name).stype_for(cla.get_type)
606 if t == null then
607 v.error(self, "Type error: circular definition in formal type {name}.")
608 return null
609 end
610 if n_kwnullable != null then t = t.as_nullable
611 _stype_cache = t
612 return t
613 end
614
615 var local_class = get_local_class(v)
616 if local_class == null then return null
617
618 var arity = n_types.length
619 if local_class.arity != arity then
620 if arity == 0 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.")
624 else
625 v.error(self, "Type error: '{local_class}' has {local_class.arity} parameters ({arity} are provided).")
626 end
627 return null
628 end
629
630 if arity > 0 then
631 var tab = new Array[MMType]
632 for p in n_types do
633 var t2 = p.get_unchecked_stype(v)
634 if t2 == null then return null
635 tab.add(t2)
636 end
637 t = local_class.get_instantiate_type(tab)
638 else
639 t = local_class.get_type
640 end
641 if n_kwnullable != null then t = t.as_nullable
642 _stype_cache = t
643 return t
644 end
645
646 redef fun get_stype(v)
647 do
648 var t = get_unchecked_stype(v)
649 if t == null then return null
650 if not t.is_valid then return null
651 check_conform(v)
652 return t
653 end
654
655 redef fun check_conform(v)
656 do
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
661 if arity > 0 then
662 for i in [0..arity[ do
663 var p = n_types[i]
664 var pt = p.get_stype(v)
665 var b = local_class.get_formal(i)
666 if not b.is_valid then return
667 var bt = b.bound
668 bt = bt.adapt_to(st) # We need to abapt because of F-genericity
669 v.check_conform(p, pt, bt)
670 end
671 end
672 end
673 end
674
675 redef class PExpr
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
680
681 # Is the expression node a statement? (ie has no return value)
682 # require: is_typed
683 fun is_statement: Bool is abstract
684
685 # The static type of the expression
686 # require: is_typed and not is_statement
687 fun stype: MMType is abstract
688 end
689
690 class AAbsAbsSendExpr
691 special PExpr
692 # The signature of the called property (require is_typed)
693 fun prop_signature: MMSignature is abstract
694
695 # The real arguments used (after star transformation) (require is_typed)
696 fun arguments: Array[PExpr] is abstract
697 end
698
699 class AAbsSendExpr
700 special AAbsAbsSendExpr
701 # The invoked method (require is_typed)
702 fun prop: MMMethod is abstract
703
704 # The return type (if any) (once computed)
705 fun return_type: nullable MMType is abstract
706 end
707
708 class ASuperInitCall
709 special AAbsSendExpr
710 end
711
712 redef class ASuperExpr
713 special ASuperInitCall
714 fun init_in_superclass: nullable MMMethod is abstract
715 end
716
717 redef class ANewExpr
718 special AAbsSendExpr
719 end
720
721 redef class ASendExpr
722 special ASuperInitCall
723 # Closure definitions
724 fun closure_defs: nullable Array[PClosureDef] is abstract
725 end
726
727 redef class AReassignFormExpr
728 # Method used through the reassigment operator (require is_typed)
729 fun assign_method: MMMethod is abstract
730 end
731
732 class ASendReassignExpr
733 special ASendExpr
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
738 end
739
740 redef class ACallReassignExpr
741 special ASendReassignExpr
742 end
743
744 redef class ABraReassignExpr
745 special ASendReassignExpr
746 end
747
748 redef class AAttrFormExpr
749 # Attribute accessed (require is_typed)
750 fun prop: MMAttribute is abstract
751
752 # Attribute type of the acceded attribute (require is_typed)
753 fun attr_type: MMType is abstract
754 end
755
756 redef class AStringFormExpr
757 fun meth_with_native: MMMethod is abstract
758 end
759
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
765 end
766
767 redef class AArrayExpr
768 fun meth_with_capacity: MMMethod is abstract
769 fun meth_add: MMMethod is abstract
770 end
771
772 redef class ARangeExpr
773 fun meth_init: MMMethod is abstract
774 end
775
776 redef class AVardeclExpr
777 # Assiociated local variable
778 fun variable: VarVariable is abstract
779 #readable writable var _variable: nullable VarVariable
780 end
781
782 redef class AForExpr
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
789 end
790
791 redef class ASelfExpr
792 # Associated local variable
793 fun variable: ParamVariable is abstract
794 #readable writable var _variable: nullable ParamVariable
795 end
796
797 redef class AVarFormExpr
798 # Associated local variable
799 fun variable: Variable is abstract
800 #readable writable var _variable: nullable Variable
801 end
802
803 redef class AClosureCallExpr
804 special AAbsAbsSendExpr
805 # Associated closure variable
806 fun variable: ClosureVariable is abstract
807 #readable writable var _variable: nullable ClosureVariable
808 end
809
810 redef class PClosureDef
811 # Associated closure
812 #readable writable var _closure: nullable MMClosure
813 fun closure: MMClosure is abstract
814
815 # Automatic variables
816 readable writable var _variables: nullable Array[AutoVariable]
817 end