icode: introduce intermediate code representation
[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, loc: Location)
33 do
34 super(name, dir, c, loc)
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 redef fun is_intern do return false
129 redef fun is_abstract do return false
130 end
131
132 # Concrete NIT source method for an automatic accesor
133 class MMAttrImplementationMethod
134 special MMSrcMethod
135 redef readable var _node: AAttrPropdef
136 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
137 do
138 super(name, cla)
139 _node = n
140 end
141 end
142
143 # Concrete NIT source method for an automatic read accesor
144 class MMReadImplementationMethod
145 special MMAttrImplementationMethod
146 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
147 do
148 super(name, cla, n)
149 end
150 end
151
152 # Concrete NIT source method for an automatic write accesor
153 class MMWriteImplementationMethod
154 special MMAttrImplementationMethod
155 init(name: Symbol, cla: MMLocalClass, n: AAttrPropdef)
156 do
157 super(name, cla, n)
158 end
159 end
160
161 # Concrete NIT source method for an explicit method
162 class MMMethSrcMethod
163 special MMSrcMethod
164 redef readable var _is_init: Bool
165 redef readable var _is_intern: Bool
166 redef readable var _is_abstract: Bool
167 redef readable var _node: nullable AMethPropdef
168 init(name: Symbol, cla: MMLocalClass, n: nullable AMethPropdef)
169 do
170 super(name, cla)
171 _node = n
172 _is_init = node isa AConcreteInitPropdef
173 _is_intern = node isa AInternMethPropdef
174 _is_abstract = node isa ADeferredMethPropdef
175 end
176 end
177
178 # Concrete NIT source virtual type
179 class MMSrcTypeProperty
180 special MMLocalProperty
181 special MMTypeProperty
182 redef readable var _node: ATypePropdef
183 init(name: Symbol, cla: MMLocalClass, n: ATypePropdef)
184 do
185 super(name, cla)
186 _node = n
187 end
188 end
189
190 # Concrete NIT implicit constructor
191 class MMImplicitInit
192 special MMMethSrcMethod
193 fun super_init: nullable MMLocalProperty is abstract
194 redef fun is_init do return true
195 readable var _unassigned_attributes: Array[MMSrcAttribute]
196 readable var _super_inits: Array[MMLocalProperty]
197 init(cla: MMLocalClass, unassigned_attributes: Array[MMSrcAttribute], super_inits: Array[MMLocalProperty])
198 do
199 super(once "init".to_symbol, cla, null)
200 _unassigned_attributes = unassigned_attributes
201 _super_inits = super_inits
202 end
203 end
204
205 # Local variables
206 abstract class Variable
207 # Name of the variable
208 readable var _name: Symbol
209
210 # Declaration AST node
211 readable var _decl: nullable PNode
212
213 # Static type
214 readable writable var _stype: nullable MMType
215
216 redef fun to_s do return _name.to_s
217
218 fun kind: String is abstract
219
220 init(n: Symbol, d: nullable PNode)
221 do
222 _name = n
223 _decl = d
224 end
225 end
226
227 # Variable declared with 'var'
228 class VarVariable
229 special Variable
230 redef fun kind do return once "variable"
231 init(n: Symbol, d: PNode) do super
232 end
233
234 # Parameter of method (declared in signature)
235 class ParamVariable
236 special Variable
237 redef fun kind do return once "parameter"
238 init(n: Symbol, d: nullable PNode) do super
239 end
240
241 # Automatic variable (like in the 'for' statement)
242 class AutoVariable
243 special Variable
244 redef fun kind do return once "automatic variable"
245 init(n: Symbol, d: PNode) do super
246 end
247
248 # False variable corresponding to closures declared in signatures
249 # Lives in the same namespace than variables
250 class ClosureVariable
251 special Variable
252 redef fun kind do return once "closure"
253
254 # The signature of the closure
255 readable var _closure: MMClosure
256
257 init(n: Symbol, d: PNode, c: MMClosure)
258 do
259 super(n, d)
260 _closure = c
261 end
262 end
263
264 ###############################################################################
265
266 # Visitor used during the syntax analysis
267 class AbsSyntaxVisitor
268 special Visitor
269 # The root type Object
270 fun type_object: MMType
271 do
272 return _module.class_by_name(once ("Object".to_symbol)).get_type
273 end
274
275 # The primitive type Bool
276 fun type_bool: MMType
277 do
278 return _module.class_by_name(once ("Bool".to_symbol)).get_type
279 end
280
281 # The primitive type Int
282 fun type_int: MMType
283 do
284 return _module.class_by_name(once ("Int".to_symbol)).get_type
285 end
286
287 # The primitive type Float
288 fun type_float: MMType
289 do
290 return _module.class_by_name(once ("Float".to_symbol)).get_type
291 end
292
293 # The primitive type Char
294 fun type_char: MMType
295 do
296 return _module.class_by_name(once ("Char".to_symbol)).get_type
297 end
298
299 # The primitive type String
300 fun type_string: MMType
301 do
302 return _module.class_by_name(once ("String".to_symbol)).get_type
303 end
304
305 # The primitive type Collection[nullable Object]
306 fun type_collection: MMType
307 do
308 return _module.class_by_name(once ("Collection".to_symbol)).get_instantiate_type([type_object.as_nullable])
309 end
310
311 # The primitive type NativeString
312 fun type_nativestring: MMType
313 do
314 return _module.class_by_name(once ("NativeString".to_symbol)).get_type
315 end
316
317 # The primitive type Array[?]
318 fun type_array(stype: MMType): MMType
319 do
320 return _module.class_by_name(once ("Array".to_symbol)).get_instantiate_type([stype])
321 end
322
323 # The primitive type Discrete
324 fun type_discrete: MMType
325 do
326 return _module.class_by_name(once ("Discrete".to_symbol)).get_type
327 end
328
329 # The primitive type Range[?]
330 fun type_range(stype: MMType): MMType
331 do
332 return _module.class_by_name(once ("Range".to_symbol)).get_instantiate_type([stype])
333 end
334
335 # The primitive type of null
336 fun type_none: MMType
337 do
338 return _module.type_none
339 end
340
341 fun get_method(recv: MMType, name: Symbol): MMMethod
342 do
343 if not recv.local_class.has_global_property_by_name(name) then
344 error(current_node, "Fatal Error: {recv} must have a property named {name}.")
345 exit(1)
346 end
347 return recv.local_class.select_method(name)
348 end
349
350 # The current module
351 readable var _module: MMSrcModule
352
353 # The current class
354 fun local_class: MMSrcLocalClass do return _local_class.as(not null)
355 writable var _local_class: nullable MMSrcLocalClass
356
357 # The current property
358 fun local_property: MMLocalProperty do return _local_property.as(not null)
359 writable var _local_property: nullable MMLocalProperty
360
361 # The current tool configuration/status
362 readable var _tc: ToolContext
363
364 # Display an error for a given syntax node
365 fun error(n: nullable PNode, s: String)
366 do
367 _tc.error(if n == null then null else n.location, s)
368 end
369
370 # Add an error, show errors and quit
371 fun fatal_error(n: nullable PNode, s: String)
372 do
373 _tc.fatal_error(if n == null then null else n.location, s)
374 end
375
376 # Display a warning for a given syntax node
377 fun warning(n: nullable PNode, s: String)
378 do
379 _tc.warning(if n == null then null else n.location, s)
380 end
381
382 # Check conformity and display error
383 fun check_conform(n: PNode, subtype: nullable MMType, stype: nullable MMType): Bool
384 do
385 if stype == null or subtype == null then
386 return false
387 end
388 if subtype < stype then
389 return true
390 end
391 error(n, "Type error: expected {stype}, got {subtype}")
392 return false
393 end
394
395 # Check that an expression has a static type and that
396 # Display an error and return false if n is a statement
397 # Require that the static type of n is known
398 fun check_expr(n: PExpr): Bool
399 do
400 if not n.is_typed then
401 if tc.error_count == 0 then
402 var loc = n.location
403 if loc == null then
404 print("Unknown node not typed but not error")
405 else
406 print("{loc} not typed but not error")
407 end
408 abort
409 end
410 # An error occured in a sub node,
411 # sillently cascade fail
412 return false
413 else if n.is_statement then
414 error(n, "Type error: expected expression.")
415 return false
416 end
417 return true
418 end
419
420 # Combine check_conform and check_expr
421 fun check_conform_expr(n: PExpr, stype: nullable MMType): Bool
422 do
423 if stype == null then return false
424 if check_expr(n) then return check_conform(n, n.stype, stype) else return false
425 end
426
427 # Check conformance between multiple expressions and a static type
428 # Conformance is granted if among them there is a most general type
429 # Return the most general type if a conformance is found
430 # Display an error and return null if no conformance is found
431 # The only allowed combinaison is with the nullable marker
432 # @param stype is a possible additional type (without node)
433 # Examples:
434 # Int, Int, Object => return Object
435 # Int, Float => display error, return null
436 # nullable Int, Object => return nullable Object
437 fun check_conform_multiexpr(stype: nullable MMType, nodes: Collection[PExpr]): nullable MMType
438 do
439 var node: nullable PExpr = null # candidate node
440 for n in nodes do
441 if not check_expr(n) then return null
442 var ntype = n.stype
443 if stype != null and stype.is_nullable != ntype.is_nullable then
444 # nullable combinaison: if one of them is nulable, considers that both are
445 stype = stype.as_nullable
446 ntype = ntype.as_nullable
447 end
448 if stype == null or stype < ntype then
449 stype = ntype
450 node = n
451 end
452 end
453 for n in nodes do
454 if not n.stype < stype.as(not null) then
455 if node == null then
456 error(n, "Type error: no most general type. Got {n.stype} and {stype}.")
457 else
458 var loc = node.location
459 if loc == null then
460 error(n, "Type error: no most general type. Got {n.stype} and {stype} at ????.")
461 else
462 error(n, "Type error: no most general type. Got {n.stype} and {stype} at {loc.relative_to(n.location)}.")
463 end
464 end
465 return null
466 end
467 end
468 return stype
469 end
470
471 protected init(tc: ToolContext, module: MMSrcModule)
472 do
473 _tc = tc
474 _module = module
475 end
476 end
477
478 ###############################################################################
479
480 redef class PNode
481 protected fun accept_abs_syntax_visitor(v: AbsSyntaxVisitor) do visit_all(v)
482 end
483
484 redef class Token
485 var _symbol_cache: nullable Symbol
486
487 # Symbol associated with the text
488 # Lazily computed
489 fun to_symbol: Symbol
490 do
491 var s = _symbol_cache
492 if s == null then
493 s = text.to_symbol
494 _symbol_cache = s
495 end
496 return s
497 end
498 end
499
500 redef class PClassdef
501 # Associated class (MM entity)
502 fun local_class: MMSrcLocalClass is abstract
503 end
504
505 redef class PPropdef
506 # Associated 'self' variable
507 fun self_var: ParamVariable is abstract
508 end
509
510 redef class AAttrPropdef
511 # Associated attribute (MM entity)
512 fun prop: MMSrcAttribute is abstract
513
514 # Associated read accessor (MM entity)
515 fun readmethod: nullable MMSrcMethod is abstract
516
517 # Associated write accessor (MM entity)
518 fun writemethod: nullable MMSrcMethod is abstract
519 end
520
521 redef class AConcreteInitPropdef
522 readable var _super_init_calls: Array[MMMethod] = new Array[MMMethod]
523 readable var _explicit_super_init_calls: Array[MMMethod] = new Array[MMMethod]
524 end
525
526 redef class AMethPropdef
527 # Associated method (MM entity)
528 fun method: MMMethSrcMethod is abstract
529 end
530
531 redef class ATypePropdef
532 # Associated formal type (MM entity)
533 fun prop: MMSrcTypeProperty is abstract
534 end
535
536 redef class PParam
537 # Position in the signature
538 fun position: Int is abstract
539
540 # Associated local variable
541 fun variable: ParamVariable is abstract
542 end
543
544 redef class PClosureDecl
545 # Position in the signature
546 fun position: Int is abstract
547
548 # Associated closure variable
549 fun variable: ClosureVariable is abstract
550 end
551
552 redef class PType
553 # Retrieve the local class corresponding to the type.
554 # Display an error and return null if there is no class
555 # Display an error and return null if the type is not class based (formal one)
556 fun get_local_class(v: AbsSyntaxVisitor): nullable MMLocalClass is abstract
557
558 # Retrieve corresponding static type.
559 # Display an error and return null if there is a problem
560 fun get_stype(v: AbsSyntaxVisitor): nullable MMType is abstract
561
562 # Retrieve corresponding static type.
563 # Display an error and return null if there is a problem
564 # But do not performs any subtype check.
565 # get_unchecked_stype should be called to check that the static type is fully valid
566 fun get_unchecked_stype(v: AbsSyntaxVisitor): nullable MMType is abstract
567
568 # Check that a static definition type is conform with regard to formal types
569 # Useful with get_unchecked_stype
570 # Remember that conformance check need that ancestors are totaly computed
571 fun check_conform(v: AbsSyntaxVisitor) is abstract
572
573 # Is the node correcly typed
574 # Return false if typed was not yet computed or
575 # if an error occured during the typing computation
576 fun is_typed: Bool is abstract
577
578 # Return corresponding static type. (require is_typed)
579 fun stype: MMType is abstract
580 end
581
582 redef class AType
583 var _stype_cache: nullable MMType = null
584 var _stype_cached: Bool = false
585
586 redef fun get_local_class(v)
587 do
588 var name = n_id.to_symbol
589 var mod = v.module
590 var cla = v.local_class
591
592 if cla.formal_dict.has_key(name) or cla.has_global_property_by_name(name) then
593 v.error(n_id, "Type error: {name} is a formal type")
594 _stype_cached = true
595 return null
596 end
597
598 if not mod.has_global_class_named(name) then
599 v.error(n_id, "Type error: class {name} not found in module {mod}.")
600 _stype_cached = true
601 return null
602 end
603
604 var local_class = mod.class_by_name(name)
605 local_class.global.check_visibility(v, self, mod)
606 return local_class
607 end
608
609 redef fun get_unchecked_stype(v)
610 do
611 if _stype_cached then return _stype_cache
612 _stype_cached = true
613
614 var name = n_id.to_symbol
615 var mod = v.module
616 var cla = v.local_class
617 var t: nullable MMType
618
619 if cla.formal_dict.has_key(name) then
620 if n_types.length > 0 then
621 v.error(self, "Type error: formal type {name} cannot have formal parameters.")
622 return null
623 end
624 t = cla.formal_dict[name]
625 if n_kwnullable != null then t = t.as_nullable
626 _stype_cache = t
627 return t
628 end
629
630 if cla.has_global_property_by_name(name) then
631 if n_types.length > 0 then
632 v.error(self, "Type error: formal type {name} cannot have formal parameters.")
633 return null
634 end
635 t = cla.get_type.local_class.select_virtual_type(name).stype_for(cla.get_type)
636 if t == null then
637 v.error(self, "Type error: circular definition in formal type {name}.")
638 return null
639 end
640 if n_kwnullable != null then t = t.as_nullable
641 _stype_cache = t
642 return t
643 end
644
645 var local_class = get_local_class(v)
646 if local_class == null then return null
647
648 var arity = n_types.length
649 if local_class.arity != arity then
650 if arity == 0 then
651 v.error(self, "Type error: '{local_class}' is a generic class.")
652 else if local_class.arity == 0 then
653 v.error(self, "Type error: '{local_class}' is not a generic class.")
654 else
655 v.error(self, "Type error: '{local_class}' has {local_class.arity} parameters ({arity} are provided).")
656 end
657 return null
658 end
659
660 if arity > 0 then
661 var tab = new Array[MMType]
662 for p in n_types do
663 var t2 = p.get_unchecked_stype(v)
664 if t2 == null then return null
665 tab.add(t2)
666 end
667 t = local_class.get_instantiate_type(tab)
668 else
669 t = local_class.get_type
670 end
671 if n_kwnullable != null then t = t.as_nullable
672 _stype_cache = t
673 return t
674 end
675
676 redef fun get_stype(v)
677 do
678 var t = get_unchecked_stype(v)
679 if t == null then return null
680 if not t.is_valid then return null
681 check_conform(v)
682 return t
683 end
684
685 redef fun check_conform(v)
686 do
687 var st = get_unchecked_stype(v)
688 if st == null then return
689 var local_class = st.local_class
690 var arity = n_types.length
691 if arity > 0 then
692 for i in [0..arity[ do
693 var p = n_types[i]
694 var pt = p.get_stype(v)
695 var b = local_class.get_formal(i)
696 if not b.is_valid then return
697 var bt = b.bound
698 bt = bt.adapt_to(st) # We need to abapt because of F-genericity
699 v.check_conform(p, pt, bt)
700 end
701 end
702 end
703 end
704
705 redef class PExpr
706 # Is the expression node correcly typed
707 # Return false if typed was not yet computed or
708 # if an error occured during the typing computation
709 fun is_typed: Bool is abstract
710
711 # Is the expression node a statement? (ie has no return value)
712 # require: is_typed
713 fun is_statement: Bool is abstract
714
715 # The static type of the expression
716 # require: is_typed and not is_statement
717 fun stype: MMType is abstract
718 end
719
720 class AAbsAbsSendExpr
721 special PExpr
722 # The signature of the called property (require is_typed)
723 fun prop_signature: MMSignature is abstract
724
725 # The real arguments used (after star transformation) (require is_typed)
726 fun arguments: Array[PExpr] is abstract
727 end
728
729 class AAbsSendExpr
730 special AAbsAbsSendExpr
731 # The invoked method (require is_typed)
732 fun prop: MMMethod is abstract
733
734 # The return type (if any) (once computed)
735 fun return_type: nullable MMType is abstract
736 end
737
738 class ASuperInitCall
739 special AAbsSendExpr
740 end
741
742 redef class ASuperExpr
743 special ASuperInitCall
744 fun init_in_superclass: nullable MMMethod is abstract
745 end
746
747 redef class ANewExpr
748 special AAbsSendExpr
749 end
750
751 redef class ASendExpr
752 special ASuperInitCall
753 # Closure definitions
754 fun closure_defs: nullable Array[PClosureDef] is abstract
755 end
756
757 redef class AReassignFormExpr
758 # Method used through the reassigment operator (require is_typed)
759 fun assign_method: MMMethod is abstract
760 end
761
762 class ASendReassignExpr
763 special ASendExpr
764 special AReassignFormExpr
765 # The invoked method used to read (require is_typed)
766 # prop is the method used to write
767 fun read_prop: MMMethod is abstract
768 end
769
770 redef class ACallReassignExpr
771 special ASendReassignExpr
772 end
773
774 redef class ABraReassignExpr
775 special ASendReassignExpr
776 end
777
778 redef class AAttrFormExpr
779 # Attribute accessed (require is_typed)
780 fun prop: MMAttribute is abstract
781
782 # Attribute type of the acceded attribute (require is_typed)
783 fun attr_type: MMType is abstract
784 end
785
786 redef class ASuperstringExpr
787 fun atype: MMType is abstract
788 end
789
790 redef class AVardeclExpr
791 # Assiociated local variable
792 fun variable: VarVariable is abstract
793 #readable writable var _variable: nullable VarVariable
794 end
795
796 redef class AForExpr
797 # Associated automatic local variable
798 fun variable: AutoVariable is abstract
799 end
800
801 redef class ASelfExpr
802 # Associated local variable
803 fun variable: ParamVariable is abstract
804 end
805
806 redef class AVarFormExpr
807 # Associated local variable
808 fun variable: Variable is abstract
809 end
810
811 redef class AClosureCallExpr
812 special AAbsAbsSendExpr
813 # Associated closure variable
814 fun variable: ClosureVariable is abstract
815 end
816
817 redef class PClosureDef
818 # Associated closure
819 fun closure: MMClosure is abstract
820
821 # Automatic variables
822 readable writable var _variables: nullable Array[AutoVariable]
823 end