ni: native_interface/frontier and its clients use syntax stuff
[nit.git] / src / syntax / mmbuilder.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 # Build MM entity from NIT AST and check conformance of these entities.
18 # This module introduce specific MM class (MMSrcXXX) that specialize the abstract one from metamodel
19 #
20 package mmbuilder
21
22 import syntax_base
23 private import primitive_info
24
25 # Class specialization hierarchy sorter
26 private class CSHSorter
27 super AbstractSorter[MMLocalClass]
28 redef fun compare(a, b)
29 do
30 return a.cshe.rank <=> b.cshe.rank
31 end
32
33 init do end
34 end
35
36 redef class MMSrcModule
37 # Syntax analysis and MM construction for the module
38 # Require that supermodules are processed
39 fun do_mmbuilder(tc: ToolContext)
40 do
41 # Import global classes
42 import_global_classes
43
44 # Create local classes and attach them to global classes
45 var mmbv = new ClassBuilderVisitor(tc, self)
46 mmbv.enter_visit(node)
47 tc.check_errors
48
49 if mhe.direct_greaters.is_empty then
50 process_default_classes(tc)
51 end
52
53 # Import unrefined local classes and attach them to global classes
54 import_local_classes
55
56 # Resolve classes in super clauses
57 var mmbv1 = new ClassSpecializationBuilderVisitor(tc, self)
58 mmbv1.enter_visit(node)
59 tc.check_errors
60
61 # Compute specialization relation
62 for c in local_classes do
63 if visibility_for(c.global.intro.mmmodule) < c.global.visibility_level then
64 continue
65 end
66 c.compute_super_classes
67 end
68 tc.check_errors
69
70 # Class that we will process now are those in the hierarchy
71 # Its mean all the visible classes and their super-classes
72 # Note that leaves invisible classes are not in the 'classes' set
73 var classes = class_specialization_hierarchy.to_a
74
75 # Prepare class list to process the following in a right order
76 var sorter = once new CSHSorter
77 sorter.sort(classes)
78
79 # Compute class ancestors types
80 var mmbv1b = new ClassAncestorBuilder(tc, self)
81 for c in classes do
82 c.accept_class_visitor(mmbv1b)
83 tc.check_errors
84 c.compute_ancestors
85 end
86
87 # Check class conformity
88 var mmbv1c = new ClassVerifierVisitor(tc, self)
89 for c in classes do
90 c.accept_class_visitor(mmbv1c)
91 end
92 tc.check_errors
93
94 # Property inhritance and introduction
95 var mmbv2 = new PropertyBuilderVisitor(tc, self)
96 for c in classes do
97 # Global property introduction and redefinition
98 c.accept_class_visitor(mmbv2)
99
100 # Default and inherited constructor if needed
101 if c isa MMSrcLocalClass and c.global.intro == c and not c.global.is_enum and not c.global.is_extern and not c.global.is_interface then
102 c.process_default_constructors(mmbv2)
103 end
104
105 # Note that inherited unredefined property are processed on demand latter
106 end
107 tc.check_errors
108
109 # Property signature analysis and inheritance conformance
110 var mmbv3 = new PropertyVerifierVisitor(tc, self)
111 for c in classes do
112 c.accept_properties_visitor(mmbv3)
113 end
114
115 tc.check_errors
116 end
117
118 # Create some primitive default classes if they do not exists
119 fun process_default_classes(tc: ToolContext)
120 do
121 var name = once ("Object".to_symbol)
122 if not has_global_class_named(name) then
123 var c = new MMSrcLocalClass(self, name, null, 0)
124 c.new_global
125 src_local_classes[name] = c
126 end
127 name = once ("Bool".to_symbol)
128 if not has_global_class_named(name) then
129 var c = new MMSrcLocalClass(self, name, null, 0)
130 c.new_global
131 src_local_classes[name] = c
132 end
133 end
134 end
135
136 redef class MMLocalClass
137 # Accept a class visitor (on class nodes)
138 private fun accept_class_visitor(v: AbsSyntaxVisitor)
139 do
140 end
141
142 # Accept a class visitor (on class properties)
143 private fun accept_properties_visitor(v: AbsSyntaxVisitor)
144 do
145 end
146 end
147
148 redef class MMSrcLocalClass
149 redef fun accept_class_visitor(v)
150 do
151 var n = node
152 while n != null do
153 v.enter_visit(n)
154 n = n.next_node
155 end
156 end
157
158 # Accept a class visitor (on class properties)
159 redef fun accept_properties_visitor(v)
160 do
161 var n = node
162 while n != null do
163 v.enter_visit(n)
164 n = n.next_node
165 end
166
167 for p in src_local_properties do
168 p.accept_property_visitor(v)
169 end
170 end
171
172 # Introduce or inherit default constructors
173 private fun process_default_constructors(v: PropertyBuilderVisitor)
174 do
175 # Is there already a constructor ?
176 for gp in global_properties do
177 if gp.is_init then
178 # Return if explicit constructor in the class
179 if gp.intro.local_class == self then return
180 end
181 end
182
183 # Collect visible constructors in super stateful classes
184 var super_inits = new ArraySet[MMLocalProperty]
185 var super_constructors = new ArraySet[MMGlobalProperty]
186 for sc in che.direct_greaters do
187 if sc.global.is_enum and not sc.global.is_extern or sc.global.is_interface then continue
188 for gp in sc.global_properties do
189 if not gp.is_init then continue
190 super_constructors.add(gp)
191 end
192 var initname = once ("init".to_symbol)
193 if sc.has_global_property_by_name(initname) then
194 var gp = sc.get_property_by_name(initname)
195 super_inits.add(self[gp])
196 end
197 end
198
199 # Collect unassigned attributes
200 var unassigned_attributes = new Array[MMSrcAttribute]
201 for a in src_local_properties do
202 if a isa MMSrcAttribute then
203 var n = a.node
204 if n.n_expr == null then unassigned_attributes.add(a)
205 end
206 end
207
208 if not super_constructors.is_empty then
209 # Select most specific classes introducing inheritable constructors
210 # Mixin classes are skipped
211 var supers = new Array[MMLocalClass]
212 for gp in super_constructors do
213 var sc = gp.local_class
214 if supers.has(sc) then continue
215 if not sc.global.is_mixin then
216 supers.add(sc)
217 end
218 end
219 supers = che.order.select_smallests(supers)
220
221 # A mixin class can only have 0 or 1 most specific non-mixin superclass
222 var superclass: nullable MMLocalClass = null # This most specific non-mixin superclass (if any)
223
224 if supers.length > 1 then
225 v.error(node, "Error: Explicit constructor required in {self} since multiple inheritance of constructor is forbiden. Conflicting classes are {supers.join(", ")}. Costructors are {super_constructors.join(", ")}.")
226 return
227 else if supers.length == 1 then
228 superclass = supers.first
229 end
230
231 for gp in super_constructors do
232 # Inherit constructors : the one of the non-mixin super class or all from the all mixin super-classes
233 if superclass == null or gp.local_class == superclass then
234 make_visible_an_inherited_global_property(gp)
235 end
236 end
237 global.mixin_of = superclass.as(not null).global # FIXME Dear! this should break!
238 else
239 # v.error(nodes.first, "Error, constructor required in {self} since no anonimous init found in {sc}.")
240
241 # unassigned attributes, then implicit consructors are generated
242 var p = new MMImplicitInit(self, unassigned_attributes, super_inits.to_a)
243 add_src_local_property(v, p)
244 #print("Create implicit init {p} in {self} from {super_inits.join(", ")} + {unassigned_attributes.length} args")
245 end
246 end
247
248 # Add a source property
249 # Register it to the class and attach it to global property
250 private fun add_src_local_property(v: PropertyBuilderVisitor, prop: MMLocalProperty)
251 do
252 var pname = prop.name
253 # Check double definition in the same class
254 if src_local_properties.has_key(pname) then
255 v.error(prop.node, "Error: A property {pname} is already defined in class {name}.")
256 return
257 end
258 src_local_properties[pname] = prop
259
260 # Intro or redefinition ?
261 if has_global_property_by_name(pname) then
262 var g = get_property_by_name(pname)
263 prop.inherit_global(g)
264 end
265
266 if not prop.is_global_set then
267 prop.new_global
268 prop.global.is_init = prop.is_init
269 end
270 end
271 end
272
273 redef class MMLocalProperty
274 private fun accept_property_visitor(v: AbsSyntaxVisitor)
275 do
276 end
277 end
278
279 redef class MMImplicitInit
280 redef readable var _super_init: nullable MMLocalProperty = null
281 redef fun accept_property_visitor(v)
282 do
283 var base: nullable MMLocalProperty = null
284 for p in super_inits do
285 if p.signature.arity > 0 then
286 if base == null then
287 base = p
288 else
289 v.error(null, "Error: explicit constructor needed in {local_class} since both super-constructor {base.full_name} and {p.full_name} have paramters")
290 return
291 end
292 end
293 end
294 _super_init = base
295
296 var params = new Array[MMParam]
297 if base != null then
298 var sig = base.signature
299 for i in [0..sig.arity[ do
300 params.add(sig.params[i])
301 end
302 end
303 for a in unassigned_attributes do
304 var sig = a.signature
305 if sig == null then return # Broken attribute definition
306 params.add( new MMParam( sig.return_type.as(not null), once "recv".to_symbol))
307 end
308 signature = new MMSignature(params, null, local_class.get_type)
309 end
310 end
311
312
313 # Concrete NIT class specialization relation
314 class MMSrcAncestor
315 super MMAncestor
316 redef readable var _local_class: MMLocalClass
317
318 init(c: MMLocalClass)
319 do
320 _local_class = c
321 end
322 end
323
324 ###############################################################################
325
326 # A pass visitor for syntax analysis.
327 # * Build the classes and attach them to global classes
328 # * Collect generic formal parameters.
329 private class ClassBuilderVisitor
330 super AbsSyntaxVisitor
331 # Current class arity
332 readable writable var _local_class_arity: Int = 0
333
334 # Current class formal parameters
335 readable writable var _formals: nullable Map[Symbol, MMTypeFormalParameter]
336
337 redef fun visit(n) do n.accept_class_builder(self)
338 init(tc, m) do super
339 end
340
341 # Another pass visitor for syntax analysis.
342 # * Build ancertors (with only class informations not the type one)
343 private class ClassSpecializationBuilderVisitor
344 super AbsSyntaxVisitor
345 redef fun visit(n) do n.accept_class_specialization_builder(self)
346 init(tc, m) do super
347 end
348
349 # Another pass visitor for syntax analysis.
350 # * Compute types in ancestors
351 private class ClassAncestorBuilder
352 super AbsSyntaxVisitor
353 redef fun visit(n) do n.accept_class_ancestor_builder(self)
354 init(tc, m) do super
355 end
356
357 # Another pass visitor for syntax analysis.
358 # * Checks classes in regard to superclasses
359 private class ClassVerifierVisitor
360 super AbsSyntaxVisitor
361 redef fun visit(n) do n.accept_class_verifier(self)
362 init(tc, m) do super
363 end
364
365
366 # Another pass visitor for syntax analysis.
367 # * Build propertie names
368 # * Build local properties and attache them to global properties
369 # * Attach bound to formal types
370 private class PropertyBuilderVisitor
371 super AbsSyntaxVisitor
372 redef fun visit(n) do n.accept_property_builder(self)
373 init(tc, m) do super
374 end
375
376 # Another pass pass visitor for syntax analysis.
377 # * Check property conformance
378 private class PropertyVerifierVisitor
379 super AbsSyntaxVisitor
380
381 # The signature currently build
382 readable writable var _signature_builder: SignatureBuilder
383
384 redef fun visit(n) do n.accept_property_verifier(self)
385
386 init(tc, m)
387 do
388 super
389 _signature_builder = new SignatureBuilder
390 end
391 end
392
393 # Information about a signature currently build
394 private class SignatureBuilder
395 # Current visited parameter types
396 readable writable var _params: Array[AParam] = new Array[AParam]
397
398 # Visited parameters without type information added
399 readable writable var _untyped_params: Array[AParam] = new Array[AParam]
400
401 # Position of the current star parameter
402 readable writable var _vararg_rank: Int = -1
403
404 # Current closure declarations
405 readable writable var _closure_decls: Array[AClosureDecl] = new Array[AClosureDecl]
406
407 # True is a problen occured durring building
408 readable writable var _has_error_occured: Bool = false
409
410 # Current signature
411 readable writable var _signature: nullable MMSignature = null
412 end
413
414 ###############################################################################
415
416 redef class ANode
417 private fun accept_class_builder(v: ClassBuilderVisitor) do accept_abs_syntax_visitor(v)
418 private fun accept_class_specialization_builder(v: ClassSpecializationBuilderVisitor) do accept_abs_syntax_visitor(v)
419 private fun accept_class_ancestor_builder(v: ClassAncestorBuilder) do accept_abs_syntax_visitor(v)
420 private fun accept_class_verifier(v: ClassVerifierVisitor) do accept_abs_syntax_visitor(v)
421 private fun accept_property_builder(v: PropertyBuilderVisitor) do accept_abs_syntax_visitor(v)
422 private fun accept_property_verifier(v: PropertyVerifierVisitor) do accept_abs_syntax_visitor(v)
423 end
424
425 redef class AModule
426 # Import supermodules and compute visibility
427 fun import_super_modules(tc: ToolContext, mod: MMSrcModule)
428 do
429 # Import super-modules
430 var supers = new Array[MMModule]
431 var no_import: nullable AImport = null
432 for i in n_imports do
433 var n = i.module_name
434 if n != null then
435 var m = tc.get_module(n, mod)
436 supers.add(m)
437 mod.add_super_module(m, i.visibility_level)
438 else
439 no_import = i
440 end
441 end
442 if no_import != null then
443 if not supers.is_empty then
444 tc.error(no_import.location, "Error: Top modules cannot import other modules.")
445 end
446 else if supers.is_empty then
447 var stdname = once "standard".to_symbol
448 var m = tc.get_module(stdname, mod)
449 supers.add(m)
450 mod.add_super_module(m, 1)
451 end
452
453 tc.add_module(mod, supers)
454 end
455 end
456
457 redef class AModuledecl
458 redef fun accept_class_builder(v)
459 do
460 if n_name.n_id.to_symbol != v.mmmodule.name then
461 v.error(n_name.n_id, "Error: Module name mismatch between {v.mmmodule.name} and {n_name.n_id.to_symbol}")
462 end
463 end
464 end
465
466 redef class AImport
467 # Imported module name (or null)
468 fun module_name: nullable Symbol is abstract
469
470 # Visibility level (intrude/public/private)
471 fun visibility_level: Int is abstract
472 end
473 redef class AStdImport
474 redef fun module_name
475 do
476 return n_name.n_id.to_symbol
477 end
478 redef fun visibility_level
479 do
480 return n_visibility.level
481 end
482 end
483 redef class ANoImport
484 redef fun module_name
485 do
486 return null
487 end
488 end
489
490 redef class AVisibility
491 # Visibility level
492 fun level: Int is abstract
493 end
494 redef class APublicVisibility
495 redef fun level do return 1
496 end
497 redef class AProtectedVisibility
498 redef fun level do return 2
499 end
500 redef class APrivateVisibility
501 redef fun level do return 3
502 end
503 redef class AIntrudeVisibility
504 redef fun level do return 0
505 end
506
507
508 redef class AClassdef
509 redef fun local_class: MMSrcLocalClass do return _local_class.as(not null)
510 var _local_class: nullable MMSrcLocalClass
511
512 # Name of the class
513 fun name: Symbol is abstract
514
515 # Number of formal parameters
516 fun arity: Int do return 0
517
518 # Visibility of the class
519 fun visibility_level: Int do return 1
520
521 redef fun accept_class_builder(v)
522 do
523 var local_class: MMSrcLocalClass
524 var mod = v.mmmodule
525 var local_classes = mod.src_local_classes
526 if (local_classes.has_key(name)) then
527 local_class = local_classes[name]
528 _local_class = local_class
529 if self isa AStdClassdef then
530 # If we are not a special implicit class then rant
531 v.error(self, "Error: A class {name} is already defined at line {local_class.node.location.line_start}.")
532 return
533 end
534 # Add the new node after the last node
535 var n = local_class.node
536 while n.next_node != null do n = n.next_node
537 n.next_node = self
538 else
539 local_class = new MMSrcLocalClass(mod, name, self, arity)
540 _local_class = local_class
541 local_classes[name] = local_class
542 if not mod.has_global_class_named(name) then
543 build_class_introduction(v)
544 else
545 var glob = mod.global_class_named(name)
546 build_class_refinement(v, glob)
547 end
548
549 end
550 v.local_class_arity = 0
551 v.formals = local_class.formal_dict
552
553 #####
554 super
555 #####
556
557 v.formals = null
558 end
559
560 fun build_class_introduction(v: AbsSyntaxVisitor)
561 do
562 local_class.new_global
563 var glob = local_class.global
564
565 glob.visibility_level = visibility_level
566 if self isa AStdClassdef then
567 if n_kwredef != null then
568 v.error(self, "Redef error: No class {name} is imported. Remove the redef keyword to define a new class.")
569 return
570 end
571 glob.is_interface = n_classkind.is_interface
572 glob.is_abstract = n_classkind.is_abstract
573 glob.is_enum = n_classkind.is_enum
574 end
575 end
576
577 fun build_class_refinement(v: AbsSyntaxVisitor, glob: MMGlobalClass)
578 do
579 local_class.set_global(glob)
580
581 glob.check_visibility(v, self, v.mmmodule)
582 if self isa AStdClassdef and n_kwredef == null then
583 v.error(self, "Redef error: {name} is an imported class. Add the redef keyword to refine it.")
584 return
585 end
586
587 if glob.intro.arity != _local_class.arity then
588 v.error(self, "Redef error: Formal parameter arity missmatch; got {_local_class.arity}, expected {glob.intro.arity}.")
589 end
590
591 if self isa AStdClassdef and (not glob.is_interface and n_classkind.is_interface or
592 not glob.is_abstract and n_classkind.is_abstract or
593 not glob.is_enum and n_classkind.is_enum)
594 then
595 v.error(self, "Redef error: cannot change kind of class {name}.")
596 end
597 end
598
599 redef fun accept_class_verifier(v)
600 do
601 super
602 var glob = _local_class.global
603 for c in _local_class.cshe.direct_greaters do
604 var cg = c.global
605 if glob.is_interface then
606 if cg.is_enum then
607 v.error(self, "Special error: Interface {name} try to specialise enum class {c.name}.")
608 else if not cg.is_interface then
609 v.error(self, "Special error: Interface {name} try to specialise class {c.name}.")
610 end
611 else if glob.is_enum then
612 if not cg.is_interface and not cg.is_enum then
613 v.error(self, "Special error: Enum class {name} try to specialise class {c.name}.")
614 end
615 else
616 if cg.is_enum then
617 v.error(self, "Special error: Class {name} try to specialise enum class {c.name}.")
618 end
619 end
620
621 end
622 end
623
624 redef fun accept_abs_syntax_visitor(v)
625 do
626 v.local_class = _local_class
627 super
628 v.local_class = null
629 end
630 end
631
632 redef class AClasskind
633 fun is_interface: Bool do return false
634 fun is_enum: Bool do return false
635 fun is_abstract: Bool do return false
636 fun is_extern : Bool do return false
637 end
638
639 redef class AInterfaceClasskind
640 redef fun is_interface do return true
641 end
642 redef class AEnumClasskind
643 redef fun is_enum do return true
644 end
645 redef class AExternClasskind
646 redef fun is_extern do return true
647 end
648 redef class AAbstractClasskind
649 redef fun is_abstract do return true
650 end
651
652 redef class AStdClassdef
653 redef fun name
654 do
655 return n_id.to_symbol
656 end
657 redef fun arity
658 do
659 return n_formaldefs.length
660 end
661 redef fun accept_class_specialization_builder(v)
662 do
663 super
664
665 var glob = local_class.global
666 if glob.intro == local_class then
667 glob.is_interface = n_classkind.is_interface
668 glob.is_abstract = n_classkind.is_abstract
669 glob.is_enum = n_classkind.is_enum
670 glob.is_extern = n_classkind.is_extern
671 glob.visibility_level = visibility_level
672 end
673 end
674 redef fun accept_class_verifier(v)
675 do
676 super
677 var glob = _local_class.global
678 if glob.intro == _local_class then
679 # Intro
680 if n_kwredef != null then
681 v.error(self, "Redef error: No class {name} is imported. Remove the redef keyword to define a new class.")
682 end
683 if glob.is_extern then
684 glob.mmmodule.is_extern_hybrid = true
685 end
686
687 for c in _local_class.cshe.direct_greaters do
688 var cg = c.global
689 if glob.is_interface then
690 if cg.is_enum then
691 v.error(self, "Special error: Interface {name} try to specialise enum class {c.name}.")
692 else if not cg.is_interface then
693 v.error(self, "Special error: Interface {name} try to specialise class {c.name}.")
694 end
695 else if glob.is_enum then
696 if not cg.is_interface and not cg.is_enum then
697 v.error(self, "Special error: Enum class {name} try to specialise class {c.name}.")
698 end
699 else if glob.is_extern then
700 if not cg.is_interface and not cg.is_extern then
701 v.error(self, "Special error: Extern class {name} try to specialise class {c.name}.")
702 end
703 else
704 if cg.is_enum then
705 v.error(self, "Special error: Class {name} try to specialise enum class {c.name}.")
706 else if cg.is_extern then
707 v.error(self, "Special error: Class {name} try to specialise extern class {c.name}.")
708 end
709 end
710
711 end
712 return
713 end
714
715 # Redef
716
717 glob.check_visibility(v, self, v.mmmodule)
718 if n_kwredef == null then
719 v.error(self, "Redef error: {name} is an imported class. Add the redef keyword to refine it.")
720 return
721 end
722
723 if glob.intro.arity != _local_class.arity then
724 v.error(self, "Redef error: Formal parameter arity mismatch; got {_local_class.arity}, expected {glob.intro.arity}.")
725 end
726
727 if
728 not glob.is_interface and n_classkind.is_interface or
729 not glob.is_abstract and n_classkind.is_abstract or
730 not glob.is_enum and n_classkind.is_enum or
731 not glob.is_extern and n_classkind.is_extern
732 then
733 v.error(self, "Redef error: cannot change kind of class {name}.")
734 end
735 end
736
737 redef fun visibility_level
738 do
739 return n_visibility.level
740 end
741 end
742
743 redef class AMainClassdef
744 redef fun name
745 do
746 return once "Sys".to_symbol
747 end
748 end
749
750 redef class ATopClassdef
751 redef fun name
752 do
753 return once "Object".to_symbol
754 end
755 end
756
757 redef class AFormaldef
758 # The associated formal generic parameter (MM entity)
759 var _formal: nullable MMTypeFormalParameter
760
761 redef fun accept_class_builder(v)
762 do
763 var name = n_id.to_symbol
764 var formal_type = new MMTypeFormalParameter(name, v.local_class_arity, v.local_class)
765 _formal = formal_type
766 v.local_class_arity = v.local_class_arity + 1
767 v.local_class.register_formal(formal_type)
768 v.formals[name] = formal_type
769 super
770 end
771
772 redef fun accept_class_verifier(v)
773 do
774 super
775 var c = v.local_class
776 var o = c.global.intro
777 if c == o then
778 if n_type == null then
779 _formal.bound = v.mmmodule.type_any.as_nullable
780 else
781 var stype = n_type.get_stype(v)
782 if stype == null then return
783 _formal.bound = stype
784 end
785 else
786 var ob = o.get_formal(_formal.position).bound.for_module(v.mmmodule)
787 if n_type == null then
788 _formal.bound = ob
789 else
790 var stype = n_type.get_stype(v)
791 if stype == null then return
792 _formal.bound = stype
793 if _formal.bound != ob then
794 v.error(self, "Redef error: Cannot change formal parameter type of class {c}; got {_formal.bound}, expected {ob}.")
795 end
796 end
797 end
798 end
799 end
800
801 redef class ASuperclass
802 readable var _ancestor: nullable MMSrcAncestor
803
804 redef fun accept_class_specialization_builder(v)
805 do
806 super
807 var c = n_type.get_local_class(v)
808 if c == null then return
809 var ancestor = new MMSrcAncestor(c)
810 _ancestor = ancestor
811 v.local_class.add_direct_parent(ancestor)
812 end
813
814 redef fun accept_class_ancestor_builder(v)
815 do
816 super
817 _ancestor.stype = n_type.get_unchecked_stype(v)
818 _ancestor.inheriter = v.local_class.get_type
819 end
820
821 redef fun accept_class_verifier(v)
822 do
823 super
824 n_type.check_conform(v)
825 end
826 end
827
828 redef class APropdef
829 # Process and check properties of the property.
830 # * Distinguish inits and methods
831 # * Inherit or check visibility.
832 # * Check redef errors.
833 # * Check forbiden attribute definitions.
834 # * Check signature conformance.
835 private fun process_and_check(v: PropertyVerifierVisitor, prop: MMLocalProperty, has_redef: Bool, visibility_level: Int)
836 do
837 if prop.global.intro == prop then
838 do_and_check_intro(v, prop, has_redef, visibility_level)
839 else
840 do_and_check_redef(v, prop, has_redef, visibility_level)
841 end
842 end
843
844 # The part of process_and_check when prop is an introduction
845 private fun do_and_check_intro(v: PropertyVerifierVisitor, prop: MMLocalProperty, has_redef: Bool, visibility_level: Int)
846 do
847 var glob = prop.global
848 var gbc = prop.local_class.global
849 if v.local_class.global.visibility_level >= 3 then
850 # Method of private classes are private
851 visibility_level = 3
852 end
853 glob.visibility_level = visibility_level
854 if has_redef then
855 v.error(self, "Error: No property {prop.local_class}::{prop} is inherited. Remove the redef keyword to define a new property.")
856 end
857 if glob.is_attribute then
858 if gbc.is_interface then
859 v.error(self, "Error: Attempt to define attribute {prop} in the interface {prop.local_class}.")
860 else if gbc.is_enum then
861 v.error(self, "Error: Attempt to define attribute {prop} in the enum class {prop.local_class}.")
862 else if gbc.is_extern then
863 v.error(self, "Error: Attempt to define attribute {prop} in the extern class {prop.local_class}.")
864 end
865 else if glob.is_init then
866 if gbc.is_interface then
867 v.error(self, "Error: Attempt to define a constructor {prop} in the class {prop.local_class}.")
868 else if gbc.is_enum then
869 v.error(self, "Error: Attempt to define a constructor {prop} in the enum {prop.local_class}.")
870 end
871
872 # ok in extern
873 end
874 if prop.signature == null then
875 if glob.is_init then
876 var supers = prop.local_class.super_methods_named(prop.name)
877 inherit_signature(v, prop, supers)
878 end
879 if prop.signature != null or v.signature_builder.has_error_occured then
880 # ok
881 else if not v.signature_builder.untyped_params.is_empty then
882 v.error(v.signature_builder.untyped_params.first, "Error: Untyped parameter.")
883 else
884 prop.signature = new MMSignature(new Array[MMParam], null, v.local_class.get_type)
885 for clos in v.signature_builder.closure_decls do
886 prop.signature.closures.add(clos.variable.closure)
887 end
888 end
889 end
890 end
891
892 private fun inherit_signature(v: PropertyVerifierVisitor, prop: MMLocalProperty, supers: Array[MMLocalProperty])
893 do
894 var s = prop.signature
895 for ip in supers do
896 var isig = ip.signature.adaptation_to(v.local_class.get_type)
897
898 if s == null then
899 if v.signature_builder.params.length != isig.arity then
900 return
901 end
902 for p in v.signature_builder.params do
903 var t = isig[p.position]
904 p.stype = t
905 if p.position == isig.vararg_rank then
906 t = v.type_array(t)
907 end
908 p.variable.stype = t
909 end
910
911 s = isig
912 prop.signature = s
913 end
914 end
915 end
916
917 # The part of process_and_check when prop is a redefinition
918 private fun do_and_check_redef(v: PropertyVerifierVisitor, prop: MMLocalProperty, has_redef: Bool, visibility_level: Int)
919 do
920 var is_init = self isa AInitPropdef
921 var glob = prop.global
922
923 if not has_redef then
924 v.error(self, "Redef error: {prop.local_class}::{prop} is an inherited property. To redefine it, add the redef keyword.")
925 return
926 end
927 if glob.is_init and not is_init then
928 v.error(self, "Redef error: A method {prop.local_class}::{prop} cannot redefine a constructor.")
929 else if not glob.is_init and is_init then
930 v.error(self, "Redef error: A constructor {prop.local_class}::{prop} cannot redefine a method.")
931 end
932
933 var s = prop.signature
934 #print "process {prop.local_class.mmmodule}::{prop.local_class}::{prop} from global {prop.global.local_property.local_class.mmmodule}::{prop.global.local_property.local_class}::{prop.global.local_property}"
935 for i in prop.prhe.direct_greaters do
936 var ip = i.local_class[prop.global]
937 var isig = i.signature
938 if isig == null then break # previous signature is invalid
939 isig = isig.adaptation_to(v.local_class.get_type)
940
941 if s == null then
942 #print "{prop.full_name} inherits signature from {ip.full_name}"
943 if v.signature_builder.params.length != isig.arity then
944 v.error(self, "Redef error: {prop.local_class}::{prop} redefines {ip.local_class}::{ip} with {isig.arity} parameter(s).")
945 return
946 end
947 if v.signature_builder.closure_decls.length != isig.closures.length then
948 v.error(self, "Redef error: {prop.local_class}::{prop} redefines {ip.local_class}::{ip} with {isig.arity} closure(s).")
949 return
950 end
951 for p in v.signature_builder.params do
952 var t = isig[p.position]
953 p.stype = t
954 if p.position == isig.vararg_rank then
955 t = v.type_array(t)
956 end
957 p.variable.stype = t
958 end
959 s = isig
960 prop.signature = s
961 #print "s is null"
962 end
963
964 var nberr = v.tc.error_count
965 #print "Check {prop.local_class}::{prop}{s} vs {ip.local_class}::{ip}{isig}"
966 #print "s={s.object_id} isig={isig.object_id} isigorig={i.signature.object_id}"
967
968 #print "orig signature: {i.signature.recv} . {i.signature}"
969 #print "inh signature: {isig.recv} . {isig}"
970 #print "redef signature: {s.recv} . {s}"
971
972 if s.arity != isig.arity then
973 v.error(self, "Redef error: {prop.local_class}::{prop} redefines {ip.local_class}::{ip} with {isig.arity} parameter(s).")
974 else if s.arity > 0 then
975 if self isa AMethPropdef then
976 # A standard method
977 for j in [0..s.arity[ do
978 if s[j] != isig[j] then
979 v.error(n_signature.n_params[j], "Redef error: Expected {isig[j]}, as in {ip.local_class}::{ip}.")
980 end
981 end
982 else if self isa AAttrPropdef then
983 # A write accessor
984 if s[0] != isig[0] then
985 v.error(n_type, "Redef error: Expected {isig[0]}, as in the parameter of {ip.local_class}::{ip}.")
986 end
987
988 else
989 abort #
990 end
991 end
992
993 var srt = s.return_type
994 var isrt = isig.return_type
995 if srt == null and isrt != null then
996 v.error(self, "Redef error: The procedure {prop.local_class}::{prop} redefines the function {ip.local_class}::{ip}.")
997 else if srt != null and isrt == null then
998 v.error(self, "Redef error: The function {prop.local_class}::{prop} redefines the procedure {ip.local_class}::{ip}.")
999 else if srt != null and isrt != null and not srt < isrt then
1000 var n: nullable ANode = null
1001 if self isa AMethPropdef then
1002 n = self.n_signature.n_type
1003 else if self isa AAttrPropdef then
1004 n = self.n_type
1005 else if self isa ATypePropdef then
1006 n = self.n_type
1007 end
1008 v.error(n, "Redef error: Expected {isrt}, as in {ip.local_class}::{ip}.")
1009 else if not s < isig and nberr == v.tc.error_count then
1010 # Systematic fallback for conformance check
1011 v.error(self, "Redef error: Incompatible redefinition of {ip.local_class}::{ip} with {prop.local_class}::{prop}")
1012 else if srt != null and isrt != null and srt != isrt and prop isa MMAttribute then
1013 # FIXME: To remove
1014 v.warning(self, "Redef warning: Expected {isrt}, as in {ip.local_class}::{ip}.")
1015 end
1016 end
1017
1018 if visibility_level != 1 and glob.visibility_level != visibility_level then
1019 v.error(self, "Redef error: {prop.local_class}::{prop} redefinition cannot change visibility.")
1020 end
1021 glob.check_visibility(v, self, v.mmmodule, true)
1022 end
1023 end
1024
1025 redef class AAttrPropdef
1026 redef readable var _readmethod: nullable MMSrcMethod
1027 redef readable var _writemethod: nullable MMSrcMethod
1028 var _prop: nullable MMSrcAttribute
1029 redef fun prop do return _prop.as(not null)
1030
1031 redef fun accept_property_builder(v)
1032 do
1033 super
1034 var name: Symbol
1035 if n_id != null then
1036 name = n_id.to_symbol
1037 else
1038 name = ("@" + n_id2.text).to_symbol
1039 end
1040 var lc = v.local_class
1041 var prop = new MMSrcAttribute(name, lc, self)
1042 _prop = prop
1043 v.local_class.add_src_local_property(v, prop)
1044
1045 if n_readable != null or n_id == null then
1046 if n_id != null then
1047 name = n_id.text.substring_from(1).to_symbol
1048 else
1049 name = n_id2.to_symbol
1050 end
1051 var readmethod = new MMReadImplementationMethod(name, lc, self)
1052 _readmethod = readmethod
1053 v.local_class.add_src_local_property(v, readmethod)
1054 end
1055 if n_writable != null or n_id == null then
1056 if n_id != null then
1057 name = (n_id.text.substring_from(1) + "=").to_symbol
1058 else
1059 name = (n_id2.text + "=").to_symbol
1060 end
1061 var writemethod = new MMWriteImplementationMethod(name, lc, self)
1062 _writemethod = writemethod
1063 v.local_class.add_src_local_property(v, writemethod)
1064 end
1065 end
1066
1067 redef fun accept_property_verifier(v)
1068 do
1069 super
1070 var t: MMType
1071 if n_type != null then
1072 var t0 = n_type.get_stype(v)
1073 if t0 != null then t = t0 else return
1074 else
1075 v.error(self, "Not yet implemented: Attribute definition {prop.local_class}::{prop} requires an explicit type.")
1076 return
1077 end
1078
1079 var prop = prop
1080 var signature = new MMSignature(new Array[MMParam], t, v.local_class.get_type)
1081 prop.signature = signature
1082 var visibility_level = n_visibility.level
1083 process_and_check(v, prop, n_id != null and n_kwredef != null, visibility_level)
1084 if n_readable != null or n_id == null then
1085 var m = _readmethod.as(not null)
1086 m.signature = signature
1087 process_and_check(v, m, (n_readable != null and n_readable.n_kwredef != null) or (n_id == null and n_kwredef != null), visibility_level)
1088 n_type.check_visibility(v, m)
1089 end
1090 if n_writable != null or n_id == null then
1091 var m = _writemethod.as(not null)
1092 m.signature = new MMSignature(new Array[MMParam].with_items(new MMParam(t, once "value".to_symbol)), null, v.local_class.get_type)
1093 var vl = visibility_level
1094 if n_id == null then
1095 if n_writable == null then vl = 3 else vl = n_writable.n_visibility.level # write accessor has a specific visibility
1096 end
1097 process_and_check(v, m, n_writable != null and n_writable.n_kwredef != null, vl)
1098 n_type.check_visibility(v, m)
1099 end
1100 end
1101
1102 redef fun accept_abs_syntax_visitor(v)
1103 do
1104 v.local_property = _prop
1105 super
1106 v.local_property = null
1107 end
1108 end
1109
1110 redef class AMethPropdef
1111 # Name of the method
1112 readable var _name: nullable Symbol
1113
1114 var _method: nullable MMMethSrcMethod
1115 redef fun method do return _method.as(not null)
1116
1117 redef fun accept_property_builder(v)
1118 do
1119 super
1120 var name: Symbol
1121 if n_methid == null then
1122 if self isa AInitPropdef then
1123 name = once "init".to_symbol
1124 else
1125 name = once "main".to_symbol
1126 end
1127 else
1128 name = n_methid.name.as(not null)
1129 # FIXME: Add the 'unary' keyword
1130 if n_methid.name == (once "-".to_symbol) then
1131 var ns = n_signature
1132 if ns != null and ns.n_params.length == 0 then
1133 name = once "unary -".to_symbol
1134 end
1135 end
1136 end
1137 _name = name
1138 var prop = new MMMethSrcMethod(name, v.local_class, self)
1139 _method = prop
1140 v.local_class.add_src_local_property(v, prop)
1141 end
1142
1143 redef fun accept_property_verifier(v)
1144 do
1145 v.signature_builder = new SignatureBuilder
1146 super
1147
1148 if v.signature_builder.has_error_occured then return
1149
1150 if v.signature_builder.signature == null then
1151 #_method.signature = new MMSignature(new Array[MMType], null, v.local_class.get_type)
1152 else
1153 method.signature = v.signature_builder.signature.as(not null)
1154 end
1155 var visibility_level = 1
1156 if n_visibility != null and n_visibility.level > 1 then
1157 visibility_level = n_visibility.level
1158 end
1159 process_and_check(v, method, n_kwredef != null, visibility_level)
1160 if n_signature != null then n_signature.check_visibility(v, method)
1161 end
1162
1163 redef fun accept_abs_syntax_visitor(v)
1164 do
1165 v.local_property = _method
1166 super
1167 v.local_property = null
1168 end
1169 end
1170
1171 redef class AMainMethPropdef
1172 redef fun process_and_check(v, prop, has_redef, visibility_level)
1173 do
1174 prop.global.visibility_level = visibility_level
1175 prop.signature = new MMSignature(new Array[MMParam], null, v.local_class.get_type)
1176 # Disable all checks for main
1177 end
1178 end
1179
1180 redef class AExternPropdef
1181 redef fun accept_property_verifier(v)
1182 do
1183 super # Compute signature
1184 var ename: String
1185 if n_extern != null then
1186 ename = n_extern.text
1187 ename = ename.substring(1, ename.length-2)
1188 else
1189 ename = method.default_extern_name
1190 end
1191 method.extern_name = ename
1192 end
1193 end
1194
1195 redef class ATypePropdef
1196 redef fun prop do return _prop.as(not null)
1197 var _prop: nullable MMSrcTypeProperty
1198
1199 redef fun accept_property_builder(v)
1200 do
1201 super
1202 var name = n_id.to_symbol
1203 var prop = new MMSrcTypeProperty(name, v.local_class, self)
1204 _prop = prop
1205 v.local_class.add_src_local_property(v, prop)
1206 end
1207
1208 redef fun accept_property_verifier(v)
1209 do
1210 super
1211 var signature = new MMSignature(new Array[MMParam], n_type.get_stype(v), v.local_class.get_type)
1212 prop.signature = signature
1213 var visibility_level = n_visibility.level
1214 process_and_check(v, prop, n_kwredef != null, visibility_level)
1215 end
1216
1217 redef fun accept_abs_syntax_visitor(v)
1218 do
1219 v.local_property = _prop
1220 super
1221 v.local_property = null
1222 end
1223 end
1224
1225 # Visitor used to build a full method name from multiple tokens
1226 private class MethidAccumulator
1227 super Visitor
1228 readable var _name: Buffer = new Buffer
1229 redef fun visit(n)
1230 do
1231 if n isa Token then
1232 _name.append(n.text)
1233 else
1234 n.visit_all(self)
1235 end
1236 end
1237 end
1238
1239 redef class AMethid
1240 redef readable var _name: nullable Symbol
1241
1242 redef fun accept_property_builder(v)
1243 do
1244 var accumulator = new MethidAccumulator
1245 accumulator.enter_visit(self)
1246 _name = accumulator.name.to_s.to_symbol
1247 super
1248 end
1249 end
1250
1251 redef class ASignature
1252 redef fun accept_property_verifier(v)
1253 do
1254 super
1255 if v.signature_builder.has_error_occured then
1256 return
1257 else if not v.signature_builder.untyped_params.is_empty then
1258 if v.signature_builder.untyped_params.first != v.signature_builder.params.first or n_type != null then
1259 v.error(v.signature_builder.untyped_params.first, "Syntax error: untyped parameter.")
1260 return
1261 end
1262 else if not v.signature_builder.params.is_empty or n_type != null then
1263 var pars = new Array[MMParam]
1264 for p in v.signature_builder.params do
1265 pars.add( new MMParam( p.stype.as(not null), p.n_id.to_symbol ) )
1266 end
1267 var ret: nullable MMType = null
1268 if n_type != null then
1269 ret = n_type.get_stype(v)
1270 if ret == null then
1271 v.signature_builder.has_error_occured = true
1272 return
1273 end
1274 end
1275 v.signature_builder.signature = new MMSignature(pars, ret, v.local_class.get_type)
1276 if v.signature_builder.vararg_rank >= 0 then
1277 v.signature_builder.signature.vararg_rank = v.signature_builder.vararg_rank
1278 end
1279 for clos in v.signature_builder.closure_decls do
1280 v.signature_builder.signature.closures.add(clos.variable.closure)
1281 end
1282 end
1283 end
1284
1285 # Check that visibilities of types in the signature are compatible with the visibility of the property.
1286 fun check_visibility(v: AbsSyntaxVisitor, p: MMLocalProperty)
1287 do
1288 if p.global.visibility_level >= 3 then return
1289 for n in n_params do
1290 if n.n_type != null then n.n_type.check_visibility(v, p)
1291 end
1292 if n_type != null then n_type.check_visibility(v, p)
1293 end
1294 end
1295
1296 redef class AParam
1297 redef readable var _position: Int = 0
1298
1299 redef fun variable: ParamVariable do return _variable.as(not null)
1300 var _variable: nullable ParamVariable
1301
1302 # The type of the parameter in signature
1303 readable writable var _stype: nullable MMType
1304
1305 redef fun accept_property_verifier(v)
1306 do
1307 super
1308 _position = v.signature_builder.params.length
1309 _variable = new ParamVariable(n_id.to_symbol, n_id)
1310 v.signature_builder.params.add(self)
1311 v.signature_builder.untyped_params.add(self)
1312 if n_type != null then
1313 var stype = n_type.get_stype(v)
1314 if stype == null then
1315 v.signature_builder.has_error_occured = true
1316 return
1317 end
1318 for p in v.signature_builder.untyped_params do
1319 p.stype = stype
1320 if is_vararg then
1321 if v.signature_builder.vararg_rank == -1 then
1322 v.signature_builder.vararg_rank = p.position
1323 else
1324 v.error(self, "Error: A vararg parameter is already defined.")
1325 end
1326 stype = v.type_array(stype)
1327 end
1328 p.variable.stype = stype
1329 end
1330 v.signature_builder.untyped_params.clear
1331 end
1332 end
1333
1334 fun is_vararg: Bool do return n_dotdotdot != null
1335 end
1336
1337 redef class AClosureDecl
1338 redef readable var _position: Int = 0
1339
1340 redef fun variable: ClosureVariable do return _variable.as(not null)
1341 var _variable: nullable ClosureVariable
1342
1343 redef fun accept_property_verifier(v)
1344 do
1345 var old_signature_builder = v.signature_builder
1346 v.signature_builder = new SignatureBuilder
1347 super
1348 if v.signature_builder.has_error_occured then
1349 return
1350 end
1351 var sig = v.signature_builder.signature
1352 if sig == null then
1353 sig = new MMSignature(new Array[MMParam], null, v.local_class.get_type)
1354 end
1355 if sig.return_type != null and n_kwbreak != null then
1356 v.error(self, "Syntax Error: A break block cannot have a return value.")
1357 end
1358
1359 # Add the finalizer to the closure signature
1360 var finalize_sig = new MMSignature(new Array[MMParam], null, v.mmmodule.type_any) # FIXME should be no receiver
1361 var finalizer_clos = new MMClosure(once ("break".to_symbol), finalize_sig, false, true)
1362 sig.closures.add(finalizer_clos)
1363
1364 var name = n_id.to_symbol
1365 var clos = new MMClosure(name, sig, n_kwbreak != null, n_expr != null)
1366 for c in old_signature_builder.closure_decls do
1367 if c.n_id.to_symbol == name then
1368 v.error(n_id, "A closure '!{name}' already defined at {c.n_id.location.relative_to(n_id.location)}.")
1369 return
1370 end
1371 end
1372 v.signature_builder = old_signature_builder
1373 _position = old_signature_builder.closure_decls.length
1374 old_signature_builder.closure_decls.add(self)
1375 _variable = new ClosureVariable(n_id.to_symbol, n_id, clos)
1376 end
1377 end
1378
1379 redef class AType
1380 # Check that visibilities of types in the signature are compatible with the visibility of the property.
1381 private fun check_visibility(v: AbsSyntaxVisitor, p: MMLocalProperty)
1382 do
1383 if p.global.visibility_level >= 3 then return
1384 var t = get_stype(v)
1385 if t == null then return
1386 var bc = t.local_class
1387 if bc.global.visibility_level >= 3 then
1388 v.error(self, "Access error: Class {bc} is private and cannot be used in the signature of the non-private property {p}.")
1389 end
1390 for n in n_types do
1391 n.check_visibility(v, p)
1392 end
1393 end
1394 end
1395
1396 redef class AExpr
1397 redef fun accept_class_builder(v) do end
1398 redef fun accept_property_builder(v) do end
1399 redef fun accept_property_verifier(v) do end
1400 end