Remove the now useless MMConcreteProperty class
[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
24 # Class specialization hierarchy sorter
25 private class CSHSorter
26 special AbstractSorter[MMLocalClass]
27 redef meth compare(a, b)
28 do
29 return a.cshe.rank <=> b.cshe.rank
30 end
31
32 init do end
33 end
34
35 redef class MMSrcModule
36 # Syntax analysis and MM construction for the module
37 # Require that supermodules are processed
38 meth do_mmbuilder(tc: ToolContext)
39 do
40 # Import global classes
41 import_global_classes
42
43 # Create local classes and attach them to global classes
44 var mmbv = new ClassBuilderVisitor(tc, self)
45 mmbv.visit(node)
46 if tc.error_count > 0 then exit(1)
47
48 # Import unrefined local classes and attach them to global classes
49 import_local_classes
50
51 # Resolve classes in super clauses
52 var mmbv1 = new ClassSpecializationBuilderVisitor(tc, self)
53 mmbv1.visit(node)
54 if tc.error_count > 0 then exit(1)
55
56 # Compute specialization relation
57 for c in local_classes do
58 if visibility_for(c.global.intro.module) < c.global.visibility_level then
59 continue
60 end
61 c.compute_super_classes
62 end
63
64 # Class that we will process now are those in the hierarchy
65 # Its mean all the visible classes and their super-classes
66 # Note that leaves invisible classes are not in the 'classes' set
67 var classes = class_specialization_hierarchy.to_a
68
69 # Prepare class list to process the following in a right order
70 var sorter = once new CSHSorter
71 sorter.sort(classes)
72
73 # Compute class ancestors types
74 var mmbv1b = new ClassAncestorBuilder(tc, self)
75 for c in classes do
76 c.accept_class_visitor(mmbv1b)
77 c.compute_ancestors
78 end
79 if tc.error_count > 0 then exit(1)
80
81 # Check class conformity
82 var mmbv1b = new ClassVerifierVisitor(tc, self)
83 for c in classes do
84 c.accept_class_visitor(mmbv1b)
85 end
86 if tc.error_count > 0 then exit(1)
87
88 # Property inhritance and introduction
89 var mmbv2 = new PropertyBuilderVisitor(tc, self)
90 for c in classes do
91 # Inherit global properties
92 c.inherit_global_properties
93
94 # Global property introduction and redefinition
95 c.accept_class_visitor(mmbv2)
96 if c isa MMSrcLocalClass then
97 end
98
99 # Note that inherited unredefined property are processed on demand latter
100 end
101 if tc.error_count > 0 then exit(1)
102
103 # Property signature analysis and inheritance conformance
104 var mmbv3 = new PropertyVerifierVisitor(tc, self)
105 for c in classes do
106 c.accept_properties_visitor(mmbv3)
107 end
108
109 # Check inherited local properties
110 for c in classes do
111 for g in c.global_properties do
112 if visibility_for(g.intro.module) < g.visibility_level then continue
113 var p = c[g]
114 end
115 end
116
117 if tc.error_count > 0 then exit(1)
118 end
119 end
120
121 redef class MMLocalClass
122 # Accept a class visitor (on class nodes)
123 private meth accept_class_visitor(v: AbsSyntaxVisitor)
124 do
125 end
126
127 # Accept a class visitor (on class properties)
128 private meth accept_properties_visitor(v: AbsSyntaxVisitor)
129 do
130 end
131 end
132
133 redef class MMSrcLocalClass
134 redef meth accept_class_visitor(v)
135 do
136 for n in nodes do
137 v.visit(n)
138 end
139 end
140
141 # Accept a class visitor (on class properties)
142 redef meth accept_properties_visitor(v)
143 do
144 for n in nodes do
145 v.visit(n)
146 end
147
148 for p in src_local_properties do
149 p.accept_property_visitor(v)
150 end
151 end
152 # Add a source property
153 # Register it to the class and attach it to global property
154 private meth add_src_local_property(v: PropertyBuilderVisitor, prop: MMLocalProperty)
155 do
156 var pname = prop.name
157 # Check double definition in the same class
158 if src_local_properties.has_key(pname) then
159 v.error(prop.node, "Error: A property {pname} is already defined in class {name}.")
160 return
161 end
162 src_local_properties[pname] = prop
163
164 # Intro or redefinition ?
165 if has_global_property_by_name(pname) then
166 var globs = properties_by_name[pname]
167 if globs.length > 1 then
168 v.error(prop.node, "Name error: {self} inherits {globs.length} global properties named {pname}.")
169 end
170 var g = globs.first
171 prop.inherit_global(g)
172 end
173
174 if prop.global == null then
175 #print "{prop.full_name} is an introduction"
176 prop.new_global
177 prop.global.is_init = prop.node isa AConcreteInitPropdef
178 end
179 end
180 end
181
182 redef class MMLocalProperty
183 private meth accept_property_visitor(v: AbsSyntaxVisitor)
184 do
185 end
186 end
187 # Concrete NIT class specialization relation
188 class MMSrcAncestor
189 special MMAncestor
190 # The related AST node
191 readable attr _node: ASuperclass
192 redef readable attr _local_class: MMLocalClass
193
194 init(n: ASuperclass, c: MMLocalClass)
195 do
196 _node = n
197 _local_class = c
198 end
199 end
200
201 ###############################################################################
202
203 # A pass visitor for syntax analysis.
204 # * Build the classes and attach them to global classes
205 # * Collect generic formal parameters.
206 private class ClassBuilderVisitor
207 special AbsSyntaxVisitor
208 # Current class arity
209 readable writable attr _local_class_arity: Int
210
211 # Current class formal parameters
212 readable writable attr _formals: Map[Symbol, MMTypeFormalParameter]
213
214 redef meth visit(n) do n.accept_class_builder(self)
215 init(tc, m) do super
216 end
217
218 # Another pass visitor for syntax analysis.
219 # * Build ancertors (with only class informations not the type one)
220 private class ClassSpecializationBuilderVisitor
221 special AbsSyntaxVisitor
222 redef meth visit(n) do n.accept_class_specialization_builder(self)
223 init(tc, m) do super
224 end
225
226 # Another pass visitor for syntax analysis.
227 # * Compute types in ancestors
228 private class ClassAncestorBuilder
229 special AbsSyntaxVisitor
230 redef meth visit(n) do n.accept_class_ancestor_builder(self)
231 init(tc, m) do super
232 end
233
234 # Another pass visitor for syntax analysis.
235 # * Checks classes in regard to superclasses
236 private class ClassVerifierVisitor
237 special AbsSyntaxVisitor
238 redef meth visit(n) do n.accept_class_verifier(self)
239 init(tc, m) do super
240 end
241
242
243 # Another pass visitor for syntax analysis.
244 # * Build propertie names
245 # * Build local properties and attache them to global properties
246 # * Attach bound to formal types
247 private class PropertyBuilderVisitor
248 special AbsSyntaxVisitor
249 redef meth visit(n) do n.accept_property_builder(self)
250 init(tc, m) do super
251 end
252
253 # Another pass pass visitor for syntax analysis.
254 # * Check property conformance
255 private class PropertyVerifierVisitor
256 special AbsSyntaxVisitor
257 # Current visited parameter types
258 readable writable attr _params: Array[PParam]
259
260 # Visited parameters without type information added
261 readable writable attr _untyped_params: Array[PParam]
262
263 # Position of the current star parameter
264 readable writable attr _vararg_rank: Int
265
266 # Current signature
267 readable writable attr _signature: MMSignature
268
269 redef meth visit(n) do n.accept_property_verifier(self)
270
271 init(tc, m) do super
272 end
273
274 ###############################################################################
275
276 redef class PNode
277 private meth accept_class_builder(v: ClassBuilderVisitor) do accept_abs_syntax_visitor(v)
278 private meth accept_class_specialization_builder(v: ClassSpecializationBuilderVisitor) do accept_abs_syntax_visitor(v)
279 private meth accept_class_ancestor_builder(v: ClassAncestorBuilder) do accept_abs_syntax_visitor(v)
280 private meth accept_class_verifier(v: ClassVerifierVisitor) do accept_abs_syntax_visitor(v)
281 private meth accept_property_builder(v: PropertyBuilderVisitor) do accept_abs_syntax_visitor(v)
282 private meth accept_property_verifier(v: PropertyVerifierVisitor) do accept_abs_syntax_visitor(v)
283 end
284
285 redef class AModule
286 # Import supermodules and compute visibility
287 meth import_super_modules(tc: ToolContext, mod: MMSrcModule)
288 do
289 # Import super-modules
290 var module_names_to_import = new Array[Symbol]
291 var module_visibility = new HashMap[Symbol, Int]
292 var no_import: PImport = null
293 for i in n_imports do
294 var n = i.module_name
295 if n != null then
296 module_names_to_import.add(n)
297 module_visibility[n] = i.visibility_level
298 else
299 no_import = i
300 end
301 end
302 if no_import != null then
303 if not module_names_to_import.is_empty then
304 tc.error("{no_import.locate}: Error: Top modules cannot import other modules.")
305 end
306 else if module_names_to_import.is_empty then
307 var stdname = once "standard".to_symbol
308 module_names_to_import.add(stdname)
309 module_visibility[stdname] = 1
310 end
311
312 mod.import_supers_modules(module_names_to_import)
313
314 for mname in module_names_to_import do
315 var level = module_visibility[mname]
316 var m = tc.get_module(mname, mod)
317 mod.add_super_module(m, level)
318 end
319 end
320 end
321
322 redef class APackagedecl
323 redef meth accept_class_builder(v)
324 do
325 if n_id.to_symbol != v.module.name then
326 v.error(n_id, "Error: Package name missmatch between {v.module.name} and {n_id.to_symbol}")
327 end
328 end
329 end
330
331 redef class PImport
332 # Imported module name (or null)
333 meth module_name: Symbol is abstract
334
335 # Visibility level (intrude/public/private)
336 meth visibility_level: Int is abstract
337 end
338 redef class AImport
339 redef meth module_name
340 do
341 return n_id.to_symbol
342 end
343 redef meth visibility_level
344 do
345 return n_visibility.level
346 end
347 end
348 redef class ANoImport
349 redef meth module_name
350 do
351 return null
352 end
353 end
354
355 redef class PVisibility
356 # Visibility level
357 meth level: Int is abstract
358 end
359 redef class APublicVisibility
360 redef meth level do return 1
361 end
362 redef class AProtectedVisibility
363 redef meth level do return 2
364 end
365 redef class APrivateVisibility
366 redef meth level do return 3
367 end
368 redef class AIntrudeVisibility
369 redef meth level do return 0
370 end
371
372
373 redef class PClassdef
374 redef readable attr _local_class: MMSrcLocalClass
375
376 # Name of the class
377 meth name: Symbol is abstract
378
379 # Number of formal parameters
380 meth arity: Int do return 0
381
382 # Visibility of the class
383 meth visibility_level: Int do return 1
384
385 redef meth accept_class_builder(v)
386 do
387 var local_class: MMSrcLocalClass
388 var mod = v.module
389 var local_classes = mod.src_local_classes
390 if (local_classes.has_key(name)) then
391 local_class = local_classes[name]
392 if self isa AClassdef then
393 # If we are not a special implicit class then rant
394 v.error(self, "Error: A class {name} is already defined at line {local_class.nodes.first.first_token.line}.")
395 return
396 end
397 local_class.nodes.add(self)
398 else
399 local_class = new MMSrcLocalClass(name, self, arity)
400 mod.add_local_class(local_class)
401 local_classes[name] = local_class
402 var g = mod.global_class_named(name)
403 if g == null then
404 # Intro
405 local_class.new_global
406 g = local_class.global
407 else
408 local_class.set_global(g)
409 end
410
411 end
412 _local_class = local_class
413 v.local_class_arity = 0
414 v.formals = new HashMap[Symbol, MMTypeFormalParameter]
415
416 #####
417 super
418 #####
419
420 _local_class.formal_dict = v.formals
421 v.formals = null
422 end
423
424 redef meth accept_abs_syntax_visitor(v)
425 do
426 v.local_class = _local_class
427 super
428 v.local_class = null
429 end
430 end
431
432 redef class PClasskind
433 meth is_interface: Bool do return false
434 meth is_universal: Bool do return false
435 meth is_abstract: Bool do return false
436 end
437
438 redef class AInterfaceClasskind
439 redef meth is_interface do return true
440 end
441 redef class AUniversalClasskind
442 redef meth is_universal do return true
443 end
444 redef class AAbstractClasskind
445 redef meth is_abstract do return true
446 end
447
448 redef class AClassdef
449 redef meth name
450 do
451 return n_id.to_symbol
452 end
453 redef meth arity
454 do
455 return n_formaldefs.length
456 end
457 redef meth accept_class_verifier(v)
458 do
459 super
460 var glob = _local_class.global
461 if glob.intro == _local_class then
462 # Intro
463 glob.visibility_level = visibility_level
464 glob.is_interface = n_classkind.is_interface
465 glob.is_abstract = n_classkind.is_abstract
466 glob.is_universal = n_classkind.is_universal
467 if n_kwredef != null then
468 v.error(self, "Redef error: No class {name} is imported. Remove the redef keyword to define a new class.")
469 end
470
471 for c in _local_class.cshe.direct_greaters do
472 var cg = c.global
473 if glob.is_interface then
474 if cg.is_universal then
475 v.error(self, "Special error: Interface {name} try to specialise universal class {c.name}.")
476 else if not cg.is_interface then
477 v.error(self, "Special error: Interface {name} try to specialise class {c.name}.")
478 end
479 else if glob.is_universal then
480 if not cg.is_interface and not cg.is_universal then
481 v.error(self, "Special error: Universal class {name} try to specialise class {c.name}.")
482 end
483 else
484 if cg.is_universal then
485 v.error(self, "Special error: Class {name} try to specialise universal class {c.name}.")
486 end
487 end
488
489 end
490 return
491 end
492
493 # Redef
494
495 glob.check_visibility(v, self, v.module)
496 if n_kwredef == null then
497 v.error(self, "Redef error: {name} is an imported class. Add the redef keyword to refine it.")
498 return
499 end
500
501 if glob.intro.arity != _local_class.arity then
502 v.error(self, "Redef error: Formal parameter arity missmatch; got {_local_class.arity}, expected {glob.intro.arity}.")
503 end
504
505 if
506 not glob.is_interface and n_classkind.is_interface or
507 not glob.is_abstract and n_classkind.is_abstract or
508 not glob.is_universal and n_classkind.is_universal
509 then
510 v.error(self, "Redef error: cannot change kind of class {name}.")
511 end
512 end
513
514 redef meth visibility_level
515 do
516 return n_visibility.level
517 end
518 end
519
520 redef class AMainClassdef
521 redef meth name
522 do
523 return once "Sys".to_symbol
524 end
525 end
526
527 redef class ATopClassdef
528 redef meth name
529 do
530 return once "Object".to_symbol
531 end
532 end
533
534 class MMSrcTypeFormalParameter
535 special MMTypeFormalParameter
536 # The associated node
537 readable attr _node: AFormaldef
538
539 init(name: Symbol, pos: Int, local_class: MMLocalClass, n: AFormaldef)
540 do
541 super(name, pos, local_class)
542 _node = n
543 end
544 end
545
546 redef class AFormaldef
547 # The associated formal generic parameter (MM entity)
548 attr _formal: MMSrcTypeFormalParameter
549
550 redef meth accept_class_builder(v)
551 do
552 var name = n_id.to_symbol
553 var formal_type = new MMSrcTypeFormalParameter(name, v.local_class_arity, v.local_class, self)
554 _formal = formal_type
555 v.local_class_arity = v.local_class_arity + 1
556 v.local_class.register_formal(formal_type)
557 v.formals[name] = formal_type
558 super
559 end
560
561 redef meth accept_class_verifier(v)
562 do
563 super
564 var c = v.local_class
565 var o = c.global.intro
566 if c == o then
567 if n_type == null then
568 _formal.bound = v.module.type_any
569 else
570 _formal.bound = n_type.get_stype(v)
571 end
572 else
573 var ob = o.get_formal(_formal.position).bound.for_module(v.module)
574 if n_type == null then
575 _formal.bound = ob
576 else
577 _formal.bound = n_type.get_stype(v)
578 if _formal.bound != ob then
579 v.error(self, "Redef error: Cannot change formal parameter type of class {c}; got {_formal.bound}, expected {ob}.")
580 end
581 end
582 end
583 end
584 end
585
586 redef class ASuperclass
587 readable attr _ancestor: MMSrcAncestor
588
589 redef meth accept_class_specialization_builder(v)
590 do
591 super
592 var c = n_type.get_local_class(v)
593 var ancestor = new MMSrcAncestor(self, c)
594 _ancestor = ancestor
595 v.local_class.add_direct_parent(ancestor)
596 end
597
598 redef meth accept_class_ancestor_builder(v)
599 do
600 super
601 _ancestor.stype = n_type.get_unchecked_stype(v)
602 _ancestor.inheriter = v.local_class.get_type
603 end
604
605 redef meth accept_class_verifier(v)
606 do
607 super
608 n_type.check_conform(v)
609 end
610 end
611
612 redef class PPropdef
613 # Process and check properties of the property.
614 # * Distinguish inits and methods
615 # * Inherit or check visibility.
616 # * Check redef errors.
617 # * Check forbiden attribute definitions.
618 # * Check signature conformance.
619 private meth process_and_check(v: PropertyVerifierVisitor, prop: MMLocalProperty, has_redef: Bool, visibility_level: Int)
620 do
621 if prop.global.intro == prop then
622 do_and_check_intro(v, prop, has_redef, visibility_level)
623 else
624 do_and_check_redef(v, prop, has_redef, visibility_level)
625 end
626 end
627
628 # The part of process_and_check when prop is an introduction
629 private meth do_and_check_intro(v: PropertyVerifierVisitor, prop: MMLocalProperty, has_redef: Bool, visibility_level: Int)
630 do
631 var glob = prop.global
632 var gbc = prop.local_class.global
633 if v.local_class.global.visibility_level >= 3 then
634 # Method of private classes are private
635 visibility_level = 3
636 end
637 glob.visibility_level = visibility_level
638 if has_redef and not glob.is_init then
639 v.error(self, "Error: No property {prop.local_class}::{prop} is inherited. Remove the redef keyword to define a new property.")
640 end
641 if glob.is_attribute then
642 if gbc.is_interface then
643 v.error(self, "Error: Attempt to define attribute {prop} in the interface {prop.local_class}.")
644 else if gbc.is_universal then
645 v.error(self, "Error: Attempt to define attribute {prop} in the universal class {prop.local_class}.")
646 end
647 else if glob.is_init then
648 if gbc.is_interface then
649 v.error(self, "Error: Attempt to define a constructor {prop} in the class {prop.local_class}.")
650 else if gbc.is_universal then
651 v.error(self, "Error: Attempt to define a constructor {prop} in the universal {prop.local_class}.")
652 end
653 end
654 if prop.signature == null then
655 if glob.is_init then
656 var supers = prop.local_class.super_methods_named(prop.name)
657 inherit_signature(v, prop, supers)
658 end
659 if prop.signature != null then
660 # ok
661 else if not v.untyped_params.is_empty then
662 v.error(v.untyped_params.first, "Error: Untyped parameter.")
663 else
664 prop.signature = new MMSignature(new Array[MMType], null, v.local_class.get_type)
665 end
666 end
667 end
668
669 private meth inherit_signature(v: PropertyVerifierVisitor, prop: MMLocalProperty, supers: Array[MMLocalProperty])
670 do
671 var s = prop.signature
672 for ip in supers do
673 var isig = ip.signature.adaptation_to(v.local_class.get_type)
674
675 if s == null then
676 if v.params.length != isig.arity then
677 prop.node.printl("v.params.length {v.params.length} != isig.arity {isig.arity} ; {prop.full_name} vs {ip.full_name}")
678 return
679 end
680 for p in v.params do
681 var t = isig[p.position]
682 p.stype = t
683 if p.position == isig.vararg_rank then
684 t = v.type_array(t)
685 end
686 p.variable.stype = t
687 end
688
689 s = isig
690 prop.signature = s
691 end
692 end
693 end
694
695 # The part of process_and_check when prop is a redefinition
696 private meth do_and_check_redef(v: PropertyVerifierVisitor, prop: MMLocalProperty, has_redef: Bool, visibility_level: Int)
697 do
698 var is_init = self isa AConcreteInitPropdef
699 var glob = prop.global
700
701 if not has_redef and prop.name != once "init".to_symbol then
702 v.error(self, "Redef error: {prop.local_class}::{prop} is an inherited property. To redefine it, add the redef keyword.")
703 return
704 end
705 if glob.is_init and not is_init then
706 v.error(self, "Redef error: A method {prop.local_class}::{prop} cannot redefine a constructor.")
707 else if not glob.is_init and is_init then
708 v.error(self, "Redef error: A constructor {prop.local_class}::{prop} cannot redefine a method.")
709 end
710
711 var s = prop.signature
712 #print "process {prop.local_class.module}::{prop.local_class}::{prop} from global {prop.global.local_property.local_class.module}::{prop.global.local_property.local_class}::{prop.global.local_property}"
713 for i in prop.prhe.direct_greaters do
714 var ip = i.local_class[prop.global]
715 var isig = i.signature.adaptation_to(v.local_class.get_type)
716
717 if s == null then
718 #print "{prop.full_name} inherits signature from {ip.full_name}"
719 if v.params.length != isig.arity then
720 v.error(self, "Redef error: {prop.local_class}::{prop} redefines {ip.local_class}::{ip} with {isig.arity} parameter(s).")
721 return
722 end
723 for p in v.params do
724 var t = isig[p.position]
725 p.stype = t
726 if p.position == isig.vararg_rank then
727 t = v.type_array(t)
728 end
729 p.variable.stype = t
730 end
731 s = isig
732 prop.signature = s
733 end
734
735 #print "orig signature: {i.signature.recv} . {i.signature}"
736 #print "inh signature: {isig.recv} . {isig}"
737 #print "redef signature: {s.recv} . {s}"
738
739 if glob.is_init and i.local_class.global != prop.local_class.global then
740 # Do not check signature
741 else if s.arity != isig.arity then
742 v.error(self, "Redef error: {prop.local_class}::{prop} redefines {ip.local_class}::{ip} with {isig.arity} parameter(s).")
743 else
744 for i in [0..s.arity[ do
745 if s[i] != isig[i] then
746 v.error(self, "Redef error: Expected {isig[i]} (as in {ip.local_class}::{ip}), got {s[i]} in {prop.local_class}::{prop}.")
747 end
748 end
749 end
750
751 var srt = s.return_type
752 var isrt = isig.return_type
753 if srt == null and isrt != null then
754 v.error(self, "Redef error: The procedure {prop.local_class}::{prop} redefines the function {ip.local_class}::{ip}.")
755 else if srt != null and isrt == null then
756 v.error(self, "Redef error: The function {prop.local_class}::{prop} redefines the procedure {ip.local_class}::{ip}.")
757 else if srt != null and isrt != null and not srt < isrt then
758 v.error(self, "Redef error: Expected {isrt} (as in {ip.local_class}::{ip}), got {srt} in {prop.local_class}::{prop}.")
759 else if srt != null and isrt != null and srt != isrt and prop isa MMAttribute then
760 # FIXME: To remove
761 v.warning(self, "Redef warning: Expected {isrt} (as in {ip.local_class}::{ip}), got {srt} in {prop.local_class}::{prop}.")
762 end
763 end
764
765 if visibility_level != 1 and glob.visibility_level != visibility_level then
766 v.error(self, "Redef error: {prop.local_class}::{prop} redefinition cannot change visibility.")
767 end
768 glob.check_visibility(v, self, v.module, true)
769 end
770 end
771
772 redef class AAttrPropdef
773 redef readable attr _readmethod: MMSrcMethod
774 redef readable attr _writemethod: MMSrcMethod
775 redef readable attr _prop: MMSrcAttribute
776
777 redef meth accept_property_builder(v)
778 do
779 super
780 var name = n_id.to_symbol
781 var prop = new MMSrcAttribute(name, v.local_class, self)
782 _prop = prop
783 v.local_class.add_src_local_property(v, prop)
784
785 if n_readable != null then
786 name = n_id.text.substring_from(1).to_symbol
787 _readmethod = new MMReadImplementationMethod(name, v.local_class, self)
788 v.local_class.add_src_local_property(v, _readmethod)
789 end
790 if n_writable != null then
791 name = (n_id.text.substring_from(1) + "=").to_symbol
792 _writemethod = new MMWriteImplementationMethod(name, v.local_class, self)
793 v.local_class.add_src_local_property(v, _writemethod)
794 end
795 end
796
797 redef meth accept_property_verifier(v)
798 do
799 super
800 var t: MMType
801 if n_type != null then
802 t = n_type.get_stype(v)
803 else
804 v.error(self, "Not yet implemented: Attribute definition {_prop.local_class}::{_prop} requires an explicit type.")
805 return
806 end
807
808 var signature = new MMSignature(new Array[MMType], t, v.local_class.get_type)
809 _prop.signature = signature
810 var visibility_level = n_visibility.level
811 process_and_check(v, _prop, n_kwredef != null, visibility_level)
812 if n_readable != null then
813 _readmethod.signature = signature
814 process_and_check(v, _readmethod, n_readable.n_kwredef != null, visibility_level)
815 n_type.check_visibility(v, _readmethod)
816 end
817 if n_writable != null then
818 _writemethod.signature = new MMSignature(new Array[MMType].with(t), null, v.local_class.get_type)
819 process_and_check(v, _writemethod, n_writable.n_kwredef != null, visibility_level)
820 n_type.check_visibility(v, _writemethod)
821 end
822 end
823
824 redef meth accept_abs_syntax_visitor(v)
825 do
826 v.local_property = prop
827 super
828 v.local_property = null
829 end
830 end
831
832 redef class AMethPropdef
833 # Name of the method
834 readable attr _name: Symbol
835
836 redef readable attr _method: MMMethSrcMethod
837
838 redef meth accept_property_builder(v)
839 do
840 super
841 if n_methid == null then
842 if self isa AConcreteInitPropdef then
843 _name = once "init".to_symbol
844 else
845 _name = once "main".to_symbol
846 end
847 else
848 _name = n_methid.name
849 # FIXME: Add the 'unary' keyword
850 if n_methid.name == (once "-".to_symbol) then
851 var ns = n_signature
852 if ns isa ASignature and ns.n_params.length == 0 then
853 _name = once "unary -".to_symbol
854 end
855 end
856 end
857 var prop = new MMMethSrcMethod(_name, v.local_class, self)
858 _method = prop
859 v.local_class.add_src_local_property(v, prop)
860 end
861
862 redef meth accept_property_verifier(v)
863 do
864 v.params = new Array[PParam]
865 v.untyped_params = new Array[PParam]
866 v.signature = null
867 v.vararg_rank = -1
868
869 super
870
871 if v.signature == null then
872 #_method.signature = new MMSignature(new Array[MMType], null, v.local_class.get_type)
873 else
874 _method.signature = v.signature
875 end
876 var visibility_level = 1
877 if n_visibility != null and n_visibility.level > 1 then
878 visibility_level = n_visibility.level
879 end
880 process_and_check(v, _method, n_kwredef != null, visibility_level)
881 if n_signature != null then n_signature.check_visibility(v, _method)
882 end
883
884 redef meth accept_abs_syntax_visitor(v)
885 do
886 v.local_property = method
887 super
888 v.local_property = null
889 end
890 end
891
892 redef class AMainMethPropdef
893 redef meth process_and_check(v, prop, has_redef, visibility_level)
894 do
895 prop.global.visibility_level = visibility_level
896 prop.signature = new MMSignature(new Array[MMType], null, v.local_class.get_type)
897 # Disable all checks for main
898 end
899 end
900
901 redef class ATypePropdef
902 redef readable attr _prop: MMSrcTypeProperty
903
904 redef meth accept_property_builder(v)
905 do
906 super
907 var name = n_id.to_symbol
908 var prop = new MMSrcTypeProperty(name, v.local_class, self)
909 _prop = prop
910 v.local_class.add_src_local_property(v, prop)
911 end
912
913 redef meth accept_property_verifier(v)
914 do
915 super
916 var signature = new MMSignature(new Array[MMType], n_type.get_stype(v), v.local_class.get_type)
917 _prop.signature = signature
918 var visibility_level = n_visibility.level
919 process_and_check(v, _prop, n_kwredef != null, visibility_level)
920 end
921
922 redef meth accept_abs_syntax_visitor(v)
923 do
924 v.local_property = prop
925 super
926 v.local_property = null
927 end
928 end
929
930 # Visitor used to build a full method name from multiple tokens
931 private class MethidAccumulator
932 special Visitor
933 readable attr _name: String
934 redef meth visit(n)
935 do
936 if n isa Token then
937 _name.append(n.text)
938 else
939 n.visit_all(self)
940 end
941 end
942
943 init
944 do
945 _name = new String
946 end
947 end
948
949 redef class PMethid
950 # Method name
951 readable attr _name: Symbol
952
953 redef meth accept_property_builder(v)
954 do
955 var accumulator = new MethidAccumulator
956 accumulator.visit(self)
957 _name = accumulator.name.to_symbol
958 super
959 end
960 end
961
962 redef class PSignature
963 # Check that visibilities of types in the signature are compatible with the visibility of the property.
964 meth check_visibility(v: AbsSyntaxVisitor, p: MMLocalProperty) is abstract
965 end
966
967 redef class ASignature
968 redef meth accept_property_verifier(v)
969 do
970 super
971 if not v.untyped_params.is_empty then
972 if v.untyped_params.first != v.params.first or n_type != null then
973 v.error(v.untyped_params.first, "Syntax error: untyped parameter.")
974 return
975 end
976 else if not v.params.is_empty or n_type != null then
977 var pars = new Array[MMType]
978 for p in v.params do
979 pars.add(p.stype)
980 end
981 var ret: MMType = null
982 if n_type != null then
983 ret = n_type.get_stype(v)
984 end
985 v.signature = new MMSignature(pars, ret, v.local_class.get_type)
986 if v.vararg_rank >= 0 then
987 v.signature.vararg_rank = v.vararg_rank
988 end
989 end
990 end
991
992 redef meth check_visibility(v, p)
993 do
994 if p.global.visibility_level >= 3 then return
995 for n in n_params do
996 if n.n_type != null then n.n_type.check_visibility(v, p)
997 end
998 if n_type != null then n_type.check_visibility(v, p)
999 end
1000 end
1001
1002 redef class PParam
1003 redef readable attr _position: Int
1004
1005 redef readable attr _variable: Variable
1006
1007 # The type of the parameter in signature
1008 readable writable attr _stype: MMType
1009
1010 redef meth accept_property_verifier(v)
1011 do
1012 super
1013 _position = v.params.length
1014 _variable = new Variable(n_id.to_symbol, self)
1015 v.params.add(self)
1016 v.untyped_params.add(self)
1017 if n_type != null then
1018 var stype = n_type.get_stype(v)
1019 for p in v.untyped_params do
1020 p.stype = stype
1021 if is_vararg then
1022 if v.vararg_rank == -1 then
1023 v.vararg_rank = p.position
1024 else
1025 v.error(self, "Error: A vararg parameter is already defined.")
1026 end
1027 stype = v.type_array(stype)
1028 end
1029 p.variable.stype = stype
1030 end
1031 v.untyped_params.clear
1032 end
1033 end
1034
1035 meth is_vararg: Bool is abstract
1036 end
1037
1038 redef class AParam
1039 redef meth is_vararg do return n_dotdotdot != null
1040 end
1041
1042 redef class PType
1043 # Check that visibilities of types in the signature are compatible with the visibility of the property.
1044 private meth check_visibility(v: AbsSyntaxVisitor, p: MMLocalProperty) is abstract
1045 end
1046
1047 redef class AType
1048 redef meth check_visibility(v, p)
1049 do
1050 if p.global.visibility_level >= 3 then return
1051 var t = get_stype(v)
1052 if t == null then return
1053 var bc = t.local_class
1054 if bc == null then return
1055 if bc.global.visibility_level >= 3 then
1056 v.error(self, "Access error: Class {bc} is private and cannot be used in the signature of the non-private property {p}.")
1057 end
1058 for n in n_types do
1059 n.check_visibility(v, p)
1060 end
1061 end
1062 end
1063
1064 redef class PExpr
1065 redef meth accept_class_builder(v) do end
1066 redef meth accept_property_builder(v) do end
1067 redef meth accept_property_verifier(v) do end
1068 end