1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # Analysis and verification of property definitions to instantiate model element
18 module modelize_property
23 redef class ToolContext
24 var modelize_property_phase
: Phase = new ModelizePropertyPhase(self, [modelize_class_phase
])
27 private class ModelizePropertyPhase
29 redef fun process_nmodule
(nmodule
)
31 for nclassdef
in nmodule
.n_classdefs
do
32 if nclassdef
.all_defs
== null then continue # skip non principal classdef
33 toolcontext
.modelbuilder
.build_properties
(nclassdef
)
38 redef class ModelBuilder
39 # Register the npropdef associated to each mpropdef
40 # FIXME: why not refine the `MPropDef` class with a nullable attribute?
41 var mpropdef2npropdef
: HashMap[MPropDef, APropdef] = new HashMap[MPropDef, APropdef]
43 # Build the properties of `nclassdef`.
44 # REQUIRE: all superclasses are built.
45 private fun build_properties
(nclassdef
: AClassdef)
47 # Force building recursively
48 if nclassdef
.build_properties_is_done
then return
49 nclassdef
.build_properties_is_done
= true
50 var mclassdef
= nclassdef
.mclassdef
.as(not null)
51 if mclassdef
.in_hierarchy
== null then return # Skip error
52 for superclassdef
in mclassdef
.in_hierarchy
.direct_greaters
do
53 if not mclassdef2nclassdef
.has_key
(superclassdef
) then continue
54 build_properties
(mclassdef2nclassdef
[superclassdef
])
57 for nclassdef2
in nclassdef
.all_defs
do
58 for npropdef
in nclassdef2
.n_propdefs
do
59 npropdef
.build_property
(self, mclassdef
)
61 for npropdef
in nclassdef2
.n_propdefs
do
62 npropdef
.build_signature
(self)
64 for npropdef
in nclassdef2
.n_propdefs
do
65 npropdef
.check_signature
(self)
68 process_default_constructors
(nclassdef
)
71 # Introduce or inherit default constructor
72 # This is the last part of `build_properties`.
73 private fun process_default_constructors
(nclassdef
: AClassdef)
75 var mclassdef
= nclassdef
.mclassdef
.as(not null)
78 if not mclassdef
.is_intro
then return
80 # Is the class forbid constructors?
81 if not mclassdef
.mclass
.kind
.need_init
then return
83 # Is there already a constructor defined?
84 for mpropdef
in mclassdef
.mpropdefs
do
85 if not mpropdef
isa MMethodDef then continue
86 if mpropdef
.mproperty
.is_init
then return
89 if not nclassdef
isa AStdClassdef then return
91 var mmodule
= mclassdef
.mmodule
92 # Do we inherit for a constructor?
93 var combine
= new Array[MMethod]
94 var inhc
: nullable MClass = null
95 for st
in mclassdef
.supertypes
do
97 if not c
.kind
.need_init
then continue
98 st
= st
.anchor_to
(mmodule
, mclassdef
.bound_mtype
)
99 var candidate
= self.try_get_mproperty_by_name2
(nclassdef
, mmodule
, st
, "init").as(nullable MMethod)
100 if candidate
!= null then
101 if candidate
.intro
.msignature
!= null then
102 if candidate
.intro
.msignature
.arity
== 0 then
103 combine
.add
(candidate
)
108 var inhc2
= c
.inherit_init_from
109 if inhc2
== null then inhc2
= c
110 if inhc2
== inhc
then continue
112 self.error
(nclassdef
, "Error: Cannot provide a defaut constructor: conflict for {inhc} and {c}")
118 # Collect undefined attributes
119 var mparameters
= new Array[MParameter]
120 var anode
: nullable ANode = null
121 for npropdef
in nclassdef
.n_propdefs
do
122 if npropdef
isa AAttrPropdef and npropdef
.n_expr
== null then
123 if npropdef
.mpropdef
== null then return # Skip broken attribute
124 var paramname
= npropdef
.mpropdef
.mproperty
.name
.substring_from
(1)
125 var ret_type
= npropdef
.mpropdef
.static_mtype
126 if ret_type
== null then return
127 var mparameter
= new MParameter(paramname
, ret_type
, false)
128 mparameters
.add
(mparameter
)
129 if anode
== null then anode
= npropdef
132 if anode
== null then anode
= nclassdef
134 if combine
.is_empty
and inhc
!= null then
135 if not mparameters
.is_empty
then
136 self.error
(anode
,"Error: {mclassdef} cannot inherit constructors from {inhc} because there is attributes without initial values: {mparameters.join(", ")}")
140 # TODO: actively inherit the consturctor
141 self.toolcontext
.info
("{mclassdef} inherits all constructors from {inhc}", 3)
142 mclassdef
.mclass
.inherit_init_from
= inhc
146 if not combine
.is_empty
and inhc
!= null then
147 self.error
(nclassdef
, "Error: Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}")
151 if not combine
.is_empty
then
152 if mparameters
.is_empty
and combine
.length
== 1 then
153 # No need to create a local init, the inherited one is enough
154 inhc
= combine
.first
.intro_mclassdef
.mclass
155 mclassdef
.mclass
.inherit_init_from
= inhc
156 self.toolcontext
.info
("{mclassdef} inherits all constructors from {inhc}", 3)
159 nclassdef
.super_inits
= combine
162 var mprop
= new MMethod(mclassdef
, "init", mclassdef
.mclass
.visibility
)
163 var mpropdef
= new MMethodDef(mclassdef
, mprop
, nclassdef
.location
)
164 var msignature
= new MSignature(mparameters
, null)
165 mpropdef
.msignature
= msignature
167 nclassdef
.mfree_init
= mpropdef
168 self.toolcontext
.info
("{mclassdef} gets a free constructor for attributes {mpropdef}{msignature}", 3)
171 # Check the visibility of `mtype` as an element of the signature of `mpropdef`.
172 fun check_visibility
(node
: ANode, mtype
: MType, mpropdef
: MPropDef)
174 var mmodule
= mpropdef
.mclassdef
.mmodule
175 var mproperty
= mpropdef
.mproperty
177 # Extract visibility information of the main part of `mtype`
178 # It is a case-by case
179 var vis_type
: nullable MVisibility = null # The own visibility of the type
180 var mmodule_type
: nullable MModule = null # The origial module of the type
181 if mtype
isa MNullableType then mtype
= mtype
.mtype
182 if mtype
isa MClassType then
183 vis_type
= mtype
.mclass
.visibility
184 mmodule_type
= mtype
.mclass
.intro
.mmodule
185 else if mtype
isa MVirtualType then
186 vis_type
= mtype
.mproperty
.visibility
187 mmodule_type
= mtype
.mproperty
.intro_mclassdef
.mmodule
188 else if mtype
isa MParameterType then
189 # nothing, always visible
191 node
.debug
"Unexpected type {mtype}"
195 if vis_type
!= null then
196 assert mmodule_type
!= null
197 var vis_module_type
= mmodule
.visibility_for
(mmodule_type
) # the visibility of the original module
198 if mproperty
.visibility
> vis_type
then
199 error
(node
, "Error: The {mproperty.visibility} property `{mproperty}` cannot contain the {vis_type} type `{mtype}`")
201 else if mproperty
.visibility
> vis_module_type
then
202 error
(node
, "Error: The {mproperty.visibility} property `{mproperty}` cannot contain the type `{mtype}` from the {vis_module_type} module `{mmodule_type}`")
207 # No error, try to go deeper in generic types
208 if node
isa AType then
209 for a
in node
.n_types
do
211 if t
== null then continue # Error, thus skipped
212 check_visibility
(a
, t
, mpropdef
)
214 else if mtype
isa MGenericType then
215 for t
in mtype
.arguments
do check_visibility
(node
, t
, mpropdef
)
221 # The class whose self inherit all the constructors.
222 # FIXME: this is needed to implement the crazy constructor mixin thing of the of old compiler. We need to think what to do with since this cannot stay in the modelbuilder
223 var inherit_init_from
: nullable MClass = null
227 # Does the MPropDef contains a call to super or a call of a super-constructor?
228 # Subsequent phases of the frontend (esp. typing) set it if required
229 var has_supercall
: Bool writable = false
232 redef class AClassdef
233 var build_properties_is_done
: Bool = false
234 # The list of super-constructor to call at the start of the free constructor
235 # FIXME: this is needed to implement the crazy constructor thing of the of old compiler. We need to think what to do with since this cannot stay in the modelbuilder
236 var super_inits
: nullable Collection[MMethod] = null
238 # The free init (implicitely constructed by the class if required)
239 var mfree_init
: nullable MMethodDef = null
242 redef class MClassDef
243 # What is the `APropdef` associated to a `MProperty`?
244 # Used to check multiple definition of a property.
245 var mprop2npropdef
: Map[MProperty, APropdef] = new HashMap[MProperty, APropdef]
249 # Join the text of all tokens
250 # Used to get the 'real name' of method definitions.
251 fun collect_text
: String
253 var v
= new TextCollectorVisitor
260 private class TextCollectorVisitor
262 var text
: String = ""
265 if n
isa Token then text
+= n
.text
271 # The associated main model entity
272 type MPROPDEF: MPropDef
274 # The associated propdef once build by a `ModelBuilder`
275 var mpropdef
: nullable MPROPDEF writable
277 private fun build_property
(modelbuilder
: ModelBuilder, mclassdef
: MClassDef) is abstract
278 private fun build_signature
(modelbuilder
: ModelBuilder) is abstract
279 private fun check_signature
(modelbuilder
: ModelBuilder) is abstract
280 private fun new_property_visibility
(modelbuilder
: ModelBuilder, mclassdef
: MClassDef, nvisibility
: nullable AVisibility): MVisibility
282 var mvisibility
= public_visibility
283 if nvisibility
!= null then
284 mvisibility
= nvisibility
.mvisibility
285 if mvisibility
== intrude_visibility
then
286 modelbuilder
.error
(nvisibility
, "Error: intrude is not a legal visibility for properties.")
287 mvisibility
= public_visibility
290 if mclassdef
.mclass
.visibility
== private_visibility
then
291 if mvisibility
== protected_visibility
then
292 assert nvisibility
!= null
293 modelbuilder
.error
(nvisibility
, "Error: The only legal visibility for properties in a private class is private.")
294 else if mvisibility
== private_visibility
then
295 assert nvisibility
!= null
297 # modelbuilder.warning(nvisibility, "Warning: private is unrequired since the only legal visibility for properties in a private class is private.")
299 mvisibility
= private_visibility
304 private fun set_doc
(mpropdef
: MPropDef)
306 var ndoc
= self.n_doc
308 var mdoc
= ndoc
.to_mdoc
310 mdoc
.original_mentity
= mpropdef
314 private fun check_redef_property_visibility
(modelbuilder
: ModelBuilder, nvisibility
: nullable AVisibility, mprop
: MProperty)
316 if nvisibility
== null then return
317 var mvisibility
= nvisibility
.mvisibility
318 if mvisibility
!= mprop
.visibility
and mvisibility
!= public_visibility
then
319 modelbuilder
.error
(nvisibility
, "Error: redefinition changed the visibility from a {mprop.visibility} to a {mvisibility}")
323 private fun check_redef_keyword
(modelbuilder
: ModelBuilder, mclassdef
: MClassDef, kwredef
: nullable Token, need_redef
: Bool, mprop
: MProperty): Bool
325 if mclassdef
.mprop2npropdef
.has_key
(mprop
) then
326 modelbuilder
.error
(self, "Error: A property {mprop} is already defined in class {mclassdef.mclass} at line {mclassdef.mprop2npropdef[mprop].location.line_start}.")
329 if mprop
isa MMethod and mprop
.is_toplevel
!= (parent
isa ATopClassdef) then
330 if mprop
.is_toplevel
then
331 modelbuilder
.error
(self, "Error: {mprop} is a top level method.")
333 modelbuilder
.error
(self, "Error: {mprop} is not a top level method.")
338 if kwredef
== null then
340 modelbuilder
.error
(self, "Redef error: {mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.")
344 if not need_redef
then
345 modelbuilder
.error
(self, "Error: No property {mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.")
354 redef class ASignature
355 # Is the model builder has correctly visited the signature
356 var is_visited
= false
357 # Names of parameters from the AST
358 # REQUIRE: is_visited
359 var param_names
= new Array[String]
360 # Types of parameters from the AST
361 # REQUIRE: is_visited
362 var param_types
= new Array[MType]
363 # Rank of the vararg (of -1 if none)
364 # REQUIRE: is_visited
365 var vararg_rank
: Int = -1
367 var ret_type
: nullable MType = null
369 # Visit and fill information about a signature
370 private fun visit_signature
(modelbuilder
: ModelBuilder, mclassdef
: MClassDef): Bool
372 var mmodule
= mclassdef
.mmodule
373 var param_names
= self.param_names
374 var param_types
= self.param_types
375 for np
in self.n_params
do
376 param_names
.add
(np
.n_id
.text
)
377 var ntype
= np
.n_type
378 if ntype
!= null then
379 var mtype
= modelbuilder
.resolve_mtype
(mmodule
, mclassdef
, ntype
)
380 if mtype
== null then return false # Skip error
381 for i
in [0..param_names
.length-param_types
.length
[ do
382 param_types
.add
(mtype
)
384 if np
.n_dotdotdot
!= null then
385 if self.vararg_rank
!= -1 then
386 modelbuilder
.error
(np
, "Error: {param_names[self.vararg_rank]} is already a vararg")
389 self.vararg_rank
= param_names
.length
- 1
394 var ntype
= self.n_type
395 if ntype
!= null then
396 self.ret_type
= modelbuilder
.resolve_mtype
(mmodule
, mclassdef
, ntype
)
397 if self.ret_type
== null then return false # Skip errir
400 self.is_visited
= true
404 # Build a visited signature
405 fun build_signature
(modelbuilder
: ModelBuilder): nullable MSignature
407 if param_names
.length
!= param_types
.length
then
408 # Some parameters are typed, other parameters are not typed.
409 modelbuilder
.error
(self.n_params
[param_types
.length
], "Error: Untyped parameter `{param_names[param_types.length]}'.")
413 var mparameters
= new Array[MParameter]
414 for i
in [0..param_names
.length
[ do
415 var mparameter
= new MParameter(param_names
[i
], param_types
[i
], i
== vararg_rank
)
416 self.n_params
[i
].mparameter
= mparameter
417 mparameters
.add
(mparameter
)
420 var msignature
= new MSignature(mparameters
, ret_type
)
426 # The associated mparameter if any
427 var mparameter
: nullable MParameter = null
430 redef class AMethPropdef
431 redef type MPROPDEF: MMethodDef
433 redef fun build_property
(modelbuilder
, mclassdef
)
435 var n_kwinit
= n_kwinit
436 var n_kwnew
= n_kwnew
437 var is_init
= n_kwinit
!= null or n_kwnew
!= null
439 var amethodid
= self.n_methid
441 if amethodid
== null then
445 else if n_kwinit
!= null then
448 else if n_kwnew
!= null then
454 else if amethodid
isa AIdMethid then
455 name
= amethodid
.n_id
.text
456 name_node
= amethodid
458 # operator, bracket or assign
459 name
= amethodid
.collect_text
460 name_node
= amethodid
462 if name
== "-" and self.n_signature
.n_params
.length
== 0 then
467 var mprop
: nullable MMethod = null
468 if not is_init
or n_kwredef
!= null then mprop
= modelbuilder
.try_get_mproperty_by_name
(name_node
, mclassdef
, name
).as(nullable MMethod)
469 if mprop
== null then
470 var mvisibility
= new_property_visibility
(modelbuilder
, mclassdef
, self.n_visibility
)
471 mprop
= new MMethod(mclassdef
, name
, mvisibility
)
472 mprop
.is_init
= is_init
473 mprop
.is_new
= n_kwnew
!= null
474 if parent
isa ATopClassdef then mprop
.is_toplevel
= true
475 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, n_kwredef
, false, mprop
) then return
477 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, n_kwredef
, not self isa AMainMethPropdef, mprop
) then return
478 check_redef_property_visibility
(modelbuilder
, self.n_visibility
, mprop
)
480 mclassdef
.mprop2npropdef
[mprop
] = self
482 var mpropdef
= new MMethodDef(mclassdef
, mprop
, self.location
)
486 self.mpropdef
= mpropdef
487 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
488 if mpropdef
.is_intro
then
489 modelbuilder
.toolcontext
.info
("{mpropdef} introduces new method {mprop.full_name}", 3)
491 modelbuilder
.toolcontext
.info
("{mpropdef} redefines method {mprop.full_name}", 3)
495 redef fun build_signature
(modelbuilder
)
497 var mpropdef
= self.mpropdef
498 if mpropdef
== null then return # Error thus skiped
499 var mclassdef
= mpropdef
.mclassdef
500 var mmodule
= mclassdef
.mmodule
501 var nsig
= self.n_signature
503 # Retrieve info from the signature AST
504 var param_names
= new Array[String] # Names of parameters from the AST
505 var param_types
= new Array[MType] # Types of parameters from the AST
507 var ret_type
: nullable MType = null # Return type from the AST
509 if not nsig
.visit_signature
(modelbuilder
, mclassdef
) then return
510 param_names
= nsig
.param_names
511 param_types
= nsig
.param_types
512 vararg_rank
= nsig
.vararg_rank
513 ret_type
= nsig
.ret_type
516 # Look for some signature to inherit
517 # FIXME: do not inherit from the intro, but from the most specific
518 var msignature
: nullable MSignature = null
519 if not mpropdef
.is_intro
then
520 msignature
= mpropdef
.mproperty
.intro
.msignature
521 if msignature
== null then return # Skip error
523 # Check inherited signature arity
524 if param_names
.length
!= msignature
.arity
then
526 if nsig
!= null then node
= nsig
else node
= self
527 modelbuilder
.error
(node
, "Redef error: {mpropdef} redefines {mpropdef.mproperty.intro} with {param_names.length} parameter(s), {msignature.arity} expected. Signature is {mpropdef}{msignature}")
530 else if mpropdef
.mproperty
.is_init
then
531 # FIXME UGLY: inherit signature from a super-constructor
532 for msupertype
in mclassdef
.supertypes
do
533 msupertype
= msupertype
.anchor_to
(mmodule
, mclassdef
.bound_mtype
)
534 var candidate
= modelbuilder
.try_get_mproperty_by_name2
(self, mmodule
, msupertype
, mpropdef
.mproperty
.name
)
535 if candidate
!= null then
536 if msignature
== null then
537 msignature
= candidate
.intro
.as(MMethodDef).msignature
544 # Inherit the signature
545 if msignature
!= null and param_names
.length
!= param_types
.length
and param_names
.length
== msignature
.arity
and param_types
.length
== 0 then
546 # Parameters are untyped, thus inherit them
547 param_types
= new Array[MType]
548 for mparameter
in msignature
.mparameters
do
549 param_types
.add
(mparameter
.mtype
)
551 vararg_rank
= msignature
.vararg_rank
553 if msignature
!= null and ret_type
== null then
554 ret_type
= msignature
.return_mtype
557 if param_names
.length
!= param_types
.length
then
558 # Some parameters are typed, other parameters are not typed.
559 modelbuilder
.error
(nsig
.n_params
[param_types
.length
], "Error: Untyped parameter `{param_names[param_types.length]}'.")
563 var mparameters
= new Array[MParameter]
564 for i
in [0..param_names
.length
[ do
565 var mparameter
= new MParameter(param_names
[i
], param_types
[i
], i
== vararg_rank
)
566 if nsig
!= null then nsig
.n_params
[i
].mparameter
= mparameter
567 mparameters
.add
(mparameter
)
570 msignature
= new MSignature(mparameters
, ret_type
)
571 mpropdef
.msignature
= msignature
572 mpropdef
.is_abstract
= self isa ADeferredMethPropdef
573 mpropdef
.is_intern
= self isa AInternMethPropdef
574 mpropdef
.is_extern
= self isa AExternPropdef
577 redef fun check_signature
(modelbuilder
)
579 var mpropdef
= self.mpropdef
580 if mpropdef
== null then return # Error thus skiped
581 var mclassdef
= mpropdef
.mclassdef
582 var mmodule
= mclassdef
.mmodule
583 var nsig
= self.n_signature
584 var mysignature
= self.mpropdef
.msignature
585 if mysignature
== null then return # Error thus skiped
587 # Lookup for signature in the precursor
588 # FIXME all precursors should be considered
589 if not mpropdef
.is_intro
then
590 var msignature
= mpropdef
.mproperty
.intro
.msignature
591 if msignature
== null then return
593 var precursor_ret_type
= msignature
.return_mtype
594 var ret_type
= mysignature
.return_mtype
595 if ret_type
!= null and precursor_ret_type
== null then
596 modelbuilder
.error
(nsig
.n_type
.as(not null), "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
600 if mysignature
.arity
> 0 then
601 # Check parameters types
602 for i
in [0..mysignature
.arity
[ do
603 var myt
= mysignature
.mparameters
[i
].mtype
604 var prt
= msignature
.mparameters
[i
].mtype
605 if not myt
.is_subtype
(mmodule
, mclassdef
.bound_mtype
, prt
) or
606 not prt
.is_subtype
(mmodule
, mclassdef
.bound_mtype
, myt
) then
607 modelbuilder
.error
(nsig
.n_params
[i
], "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt} as in {mpropdef.mproperty.intro}.")
611 if precursor_ret_type
!= null then
612 if ret_type
== null then
613 # Inherit the return type
614 ret_type
= precursor_ret_type
615 else if not ret_type
.is_subtype
(mmodule
, mclassdef
.bound_mtype
, precursor_ret_type
) then
616 modelbuilder
.error
(nsig
.n_type
.as(not null), "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type} as in {mpropdef.mproperty.intro}.")
621 if mysignature
.arity
> 0 then
622 # Check parameters visibility
623 for i
in [0..mysignature
.arity
[ do
624 var nt
= nsig
.n_params
[i
].n_type
625 if nt
!= null then modelbuilder
.check_visibility
(nt
, nt
.mtype
.as(not null), mpropdef
)
628 if nt
!= null then modelbuilder
.check_visibility
(nt
, nt
.mtype
.as(not null), mpropdef
)
633 redef class AAttrPropdef
634 redef type MPROPDEF: MAttributeDef
636 # The associated getter (read accessor) if any
637 var mreadpropdef
: nullable MMethodDef writable
638 # The associated setter (write accessor) if any
639 var mwritepropdef
: nullable MMethodDef writable
640 redef fun build_property
(modelbuilder
, mclassdef
)
642 var mclass
= mclassdef
.mclass
645 if self.n_id
!= null then
646 name
= self.n_id
.text
648 name
= self.n_id2
.text
651 if mclass
.kind
== interface_kind
or mclassdef
.mclass
.kind
== enum_kind
then
652 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the interface {mclass}.")
653 else if mclass
.kind
== enum_kind
then
654 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the enum class {mclass}.")
655 else if mclass
.kind
== extern_kind
then
656 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the extern class {mclass}.")
661 # Old attribute style
662 var mprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, name
)
663 if mprop
== null then
664 var mvisibility
= new_property_visibility
(modelbuilder
, mclassdef
, self.n_visibility
)
665 mprop
= new MAttribute(mclassdef
, name
, mvisibility
)
666 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, self.n_kwredef
, false, mprop
) then return
668 assert mprop
isa MAttribute
669 check_redef_property_visibility
(modelbuilder
, self.n_visibility
, mprop
)
670 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, self.n_kwredef
, true, mprop
) then return
672 mclassdef
.mprop2npropdef
[mprop
] = self
674 var mpropdef
= new MAttributeDef(mclassdef
, mprop
, self.location
)
675 self.mpropdef
= mpropdef
676 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
679 var nreadable
= self.n_readable
680 if nreadable
!= null then modelbuilder
.error
(nreadable
, "Error: old-style getter no more supported")
681 var nwritable
= self.n_writable
682 if nwritable
!= null then modelbuilder
.error
(nwritable
, "Error: old-style setter no more supported")
684 # New attribute style
685 var nid2
= self.n_id2
.as(not null)
686 var mprop
= new MAttribute(mclassdef
, "_" + name
, private_visibility
)
687 var mpropdef
= new MAttributeDef(mclassdef
, mprop
, self.location
)
688 self.mpropdef
= mpropdef
689 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
693 var mreadprop
= modelbuilder
.try_get_mproperty_by_name
(nid2
, mclassdef
, readname
).as(nullable MMethod)
694 if mreadprop
== null then
695 var mvisibility
= new_property_visibility
(modelbuilder
, mclassdef
, self.n_visibility
)
696 mreadprop
= new MMethod(mclassdef
, readname
, mvisibility
)
697 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, n_kwredef
, false, mreadprop
) then return
699 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, n_kwredef
, true, mreadprop
) then return
700 check_redef_property_visibility
(modelbuilder
, self.n_visibility
, mreadprop
)
702 mclassdef
.mprop2npropdef
[mreadprop
] = self
704 var mreadpropdef
= new MMethodDef(mclassdef
, mreadprop
, self.location
)
705 self.mreadpropdef
= mreadpropdef
706 modelbuilder
.mpropdef2npropdef
[mreadpropdef
] = self
707 mreadpropdef
.mdoc
= mpropdef
.mdoc
709 var writename
= name
+ "="
710 var nwritable
= self.n_writable
711 var atwritable
= self.get_single_annotation
("writable", modelbuilder
)
712 var mwriteprop
= modelbuilder
.try_get_mproperty_by_name
(nid2
, mclassdef
, writename
).as(nullable MMethod)
713 var nwkwredef
: nullable Token = null
714 if nwritable
!= null then nwkwredef
= nwritable
.n_kwredef
715 if atwritable
!= null then nwkwredef
= atwritable
.n_kwredef
716 if mwriteprop
== null then
718 if nwritable
!= null then
719 mvisibility
= new_property_visibility
(modelbuilder
, mclassdef
, nwritable
.n_visibility
)
720 else if atwritable
!= null then
721 mvisibility
= new_property_visibility
(modelbuilder
, mclassdef
, atwritable
.n_visibility
)
723 mvisibility
= private_visibility
725 mwriteprop
= new MMethod(mclassdef
, writename
, mvisibility
)
726 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, nwkwredef
, false, mwriteprop
) then return
728 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, nwkwredef
or else n_kwredef
, true, mwriteprop
) then return
729 if nwritable
!= null then
730 check_redef_property_visibility
(modelbuilder
, nwritable
.n_visibility
, mwriteprop
)
731 else if atwritable
!= null then
732 check_redef_property_visibility
(modelbuilder
, atwritable
.n_visibility
, mwriteprop
)
735 mclassdef
.mprop2npropdef
[mwriteprop
] = self
737 var mwritepropdef
= new MMethodDef(mclassdef
, mwriteprop
, self.location
)
738 self.mwritepropdef
= mwritepropdef
739 modelbuilder
.mpropdef2npropdef
[mwritepropdef
] = self
740 mwritepropdef
.mdoc
= mpropdef
.mdoc
744 redef fun build_signature
(modelbuilder
)
746 var mpropdef
= self.mpropdef
747 if mpropdef
== null then return # Error thus skiped
748 var mclassdef
= mpropdef
.mclassdef
749 var mmodule
= mclassdef
.mmodule
750 var mtype
: nullable MType = null
752 var mreadpropdef
= self.mreadpropdef
754 var ntype
= self.n_type
755 if ntype
!= null then
756 mtype
= modelbuilder
.resolve_mtype
(mmodule
, mclassdef
, ntype
)
757 if mtype
== null then return
760 # Inherit the type from the getter (usually an abstact getter)
761 if mtype
== null and mreadpropdef
!= null and not mreadpropdef
.is_intro
then
762 var msignature
= mreadpropdef
.mproperty
.intro
.msignature
763 if msignature
== null then return # Error, thus skiped
764 mtype
= msignature
.return_mtype
767 var nexpr
= self.n_expr
768 if mtype
== null then
769 if nexpr
!= null then
770 if nexpr
isa ANewExpr then
771 mtype
= modelbuilder
.resolve_mtype
(mmodule
, mclassdef
, nexpr
.n_type
)
772 else if nexpr
isa AIntExpr then
773 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Int")
774 if cla
!= null then mtype
= cla
.mclass_type
775 else if nexpr
isa AFloatExpr then
776 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Float")
777 if cla
!= null then mtype
= cla
.mclass_type
778 else if nexpr
isa ACharExpr then
779 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Char")
780 if cla
!= null then mtype
= cla
.mclass_type
781 else if nexpr
isa ABoolExpr then
782 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Bool")
783 if cla
!= null then mtype
= cla
.mclass_type
784 else if nexpr
isa ASuperstringExpr then
785 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "String")
786 if cla
!= null then mtype
= cla
.mclass_type
787 else if nexpr
isa AStringFormExpr then
788 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "String")
789 if cla
!= null then mtype
= cla
.mclass_type
791 modelbuilder
.error
(self, "Error: Untyped attribute {mpropdef}. Implicit typing allowed only for literals and new.")
794 if mtype
== null then return
796 else if ntype
!= null then
797 if nexpr
isa ANewExpr then
798 var xmtype
= modelbuilder
.resolve_mtype
(mmodule
, mclassdef
, nexpr
.n_type
)
799 if xmtype
== mtype
and modelbuilder
.toolcontext
.opt_warn
.value
>= 2 then
800 modelbuilder
.warning
(ntype
, "Warning: useless type definition")
805 if mtype
== null then
806 modelbuilder
.error
(self, "Error: Untyped attribute {mpropdef}")
810 mpropdef
.static_mtype
= mtype
812 if mreadpropdef
!= null then
813 var msignature
= new MSignature(new Array[MParameter], mtype
)
814 mreadpropdef
.msignature
= msignature
817 var msritepropdef
= self.mwritepropdef
818 if mwritepropdef
!= null then
821 name
= n_id
.text
.substring_from
(1)
825 var mparameter
= new MParameter(name
, mtype
, false)
826 var msignature
= new MSignature([mparameter
], null)
827 mwritepropdef
.msignature
= msignature
831 redef fun check_signature
(modelbuilder
)
833 var mpropdef
= self.mpropdef
834 if mpropdef
== null then return # Error thus skiped
835 var mclassdef
= mpropdef
.mclassdef
836 var mmodule
= mclassdef
.mmodule
837 var ntype
= self.n_type
838 var mtype
= self.mpropdef
.static_mtype
839 if mtype
== null then return # Error thus skiped
841 # Lookup for signature in the precursor
842 # FIXME all precursors should be considered
843 if not mpropdef
.is_intro
then
844 var precursor_type
= mpropdef
.mproperty
.intro
.static_mtype
845 if precursor_type
== null then return
847 if mtype
!= precursor_type
then
848 modelbuilder
.error
(ntype
.as(not null), "Redef Error: Wrong static type. found {mtype}, expected {precursor_type}.")
853 # Check getter and setter
854 var meth
= self.mreadpropdef
856 self.check_method_signature
(modelbuilder
, meth
)
857 var node
: nullable ANode = ntype
858 if node
== null then node
= self
859 modelbuilder
.check_visibility
(node
, mtype
, meth
)
861 meth
= self.mwritepropdef
863 self.check_method_signature
(modelbuilder
, meth
)
864 var node
: nullable ANode = ntype
865 if node
== null then node
= self
866 modelbuilder
.check_visibility
(node
, mtype
, meth
)
870 private fun check_method_signature
(modelbuilder
: ModelBuilder, mpropdef
: MMethodDef)
872 var mclassdef
= mpropdef
.mclassdef
873 var mmodule
= mclassdef
.mmodule
874 var nsig
= self.n_type
875 var mysignature
= mpropdef
.msignature
876 if mysignature
== null then return # Error thus skiped
878 # Lookup for signature in the precursor
879 # FIXME all precursors should be considered
880 if not mpropdef
.is_intro
then
881 var msignature
= mpropdef
.mproperty
.intro
.msignature
882 if msignature
== null then return
884 if mysignature
.arity
!= msignature
.arity
then
886 if nsig
!= null then node
= nsig
else node
= self
887 modelbuilder
.error
(node
, "Redef Error: {mysignature.arity} parameters found, {msignature.arity} expected. Signature is {mpropdef}{msignature}")
890 var precursor_ret_type
= msignature
.return_mtype
891 var ret_type
= mysignature
.return_mtype
892 if ret_type
!= null and precursor_ret_type
== null then
894 if nsig
!= null then node
= nsig
else node
= self
895 modelbuilder
.error
(node
, "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
899 if mysignature
.arity
> 0 then
900 # Check parameters types
901 for i
in [0..mysignature
.arity
[ do
902 var myt
= mysignature
.mparameters
[i
].mtype
903 var prt
= msignature
.mparameters
[i
].mtype
904 if not myt
.is_subtype
(mmodule
, mclassdef
.bound_mtype
, prt
) or
905 not prt
.is_subtype
(mmodule
, mclassdef
.bound_mtype
, myt
) then
907 if nsig
!= null then node
= nsig
else node
= self
908 modelbuilder
.error
(node
, "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
912 if precursor_ret_type
!= null then
913 if ret_type
== null then
914 # Inherit the return type
915 ret_type
= precursor_ret_type
916 else if not ret_type
.is_subtype
(mmodule
, mclassdef
.bound_mtype
, precursor_ret_type
) then
918 if nsig
!= null then node
= nsig
else node
= self
919 modelbuilder
.error
(node
, "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type}.")
926 redef class ATypePropdef
927 redef type MPROPDEF: MVirtualTypeDef
929 redef fun build_property
(modelbuilder
, mclassdef
)
931 var name
= self.n_id
.text
932 var mprop
= modelbuilder
.try_get_mproperty_by_name
(self.n_id
, mclassdef
, name
)
933 if mprop
== null then
934 var mvisibility
= new_property_visibility
(modelbuilder
, mclassdef
, self.n_visibility
)
935 mprop
= new MVirtualTypeProp(mclassdef
, name
, mvisibility
)
936 for c
in name
.chars
do if c
>= 'a' and c
<= 'z' then
937 modelbuilder
.warning
(n_id
, "Warning: lowercase in the virtual type {name}")
940 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, self.n_kwredef
, false, mprop
) then return
942 if not self.check_redef_keyword
(modelbuilder
, mclassdef
, self.n_kwredef
, true, mprop
) then return
943 assert mprop
isa MVirtualTypeProp
944 check_redef_property_visibility
(modelbuilder
, self.n_visibility
, mprop
)
946 mclassdef
.mprop2npropdef
[mprop
] = self
948 var mpropdef
= new MVirtualTypeDef(mclassdef
, mprop
, self.location
)
949 self.mpropdef
= mpropdef
950 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
954 redef fun build_signature
(modelbuilder
)
956 var mpropdef
= self.mpropdef
957 if mpropdef
== null then return # Error thus skiped
958 var mclassdef
= mpropdef
.mclassdef
959 var mmodule
= mclassdef
.mmodule
960 var mtype
: nullable MType = null
962 var ntype
= self.n_type
963 mtype
= modelbuilder
.resolve_mtype
(mmodule
, mclassdef
, ntype
)
964 if mtype
== null then return
966 mpropdef
.bound
= mtype
967 # print "{mpropdef}: {mtype}"
970 redef fun check_signature
(modelbuilder
)
972 var mpropdef
= self.mpropdef
973 if mpropdef
== null then return # Error thus skiped
975 var bound
= self.mpropdef
.bound
976 if bound
== null then return # Error thus skiped
978 modelbuilder
.check_visibility
(n_type
, bound
, mpropdef
)
980 # Fast case: the bound is not a formal type
981 if not bound
isa MVirtualType then return
983 var mclassdef
= mpropdef
.mclassdef
984 var mmodule
= mclassdef
.mmodule
985 var anchor
= mclassdef
.bound_mtype
987 # Slow case: progress on each resolution until: (i) we loop, or (ii) we found a non formal type
988 var seen
= [self.mpropdef
.mproperty
.mvirtualtype
]
990 if seen
.has
(bound
) then
992 modelbuilder
.error
(self, "Error: circularity of virtual type definition: {seen.join(" -> ")}")
996 var next
= bound
.lookup_bound
(mmodule
, anchor
)
997 if not next
isa MVirtualType then break