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