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
22 redef class ToolContext
23 var modelize_property_phase
: Phase = new ModelizePropertyPhase(self, [modelize_class_phase
])
26 private class ModelizePropertyPhase
28 redef fun process_nmodule
(nmodule
)
30 for nclassdef
in nmodule
.n_classdefs
do
31 toolcontext
.modelbuilder
.build_properties
(nclassdef
)
36 redef class ModelBuilder
37 # Register the npropdef associated to each mpropdef
38 # FIXME: why not refine the `MPropDef` class with a nullable attribute?
39 var mpropdef2npropdef
: HashMap[MPropDef, APropdef] = new HashMap[MPropDef, APropdef]
41 # Build the properties of `nclassdef`.
42 # REQUIRE: all superclasses are built.
43 private fun build_properties
(nclassdef
: AClassdef)
45 # Force building recursively
46 if nclassdef
.build_properties_is_done
then return
47 nclassdef
.build_properties_is_done
= true
48 var mclassdef
= nclassdef
.mclassdef
.as(not null)
49 if mclassdef
.in_hierarchy
== null then return # Skip error
50 for superclassdef
in mclassdef
.in_hierarchy
.direct_greaters
do
51 build_properties
(mclassdef2nclassdef
[superclassdef
])
54 for npropdef
in nclassdef
.n_propdefs
do
55 npropdef
.build_property
(self, nclassdef
)
57 for npropdef
in nclassdef
.n_propdefs
do
58 npropdef
.build_signature
(self, nclassdef
)
60 for npropdef
in nclassdef
.n_propdefs
do
61 npropdef
.check_signature
(self, nclassdef
)
63 process_default_constructors
(nclassdef
)
66 # Introduce or inherit default constructor
67 # This is the last part of `build_properties`.
68 private fun process_default_constructors
(nclassdef
: AClassdef)
70 var mclassdef
= nclassdef
.mclassdef
.as(not null)
73 if not mclassdef
.is_intro
then return
75 # Is the class forbid constructors?
76 if not mclassdef
.mclass
.kind
.need_init
then return
78 # Is there already a constructor defined?
79 for mpropdef
in mclassdef
.mpropdefs
do
80 if not mpropdef
isa MMethodDef then continue
81 if mpropdef
.mproperty
.is_init
then return
84 if not nclassdef
isa AStdClassdef then return
86 var mmodule
= nclassdef
.mclassdef
.mmodule
87 # Do we inherit for a constructor?
88 var combine
= new Array[MMethod]
89 var inhc
: nullable MClass = null
90 for st
in mclassdef
.supertypes
do
92 if not c
.kind
.need_init
then continue
93 st
= st
.anchor_to
(mmodule
, nclassdef
.mclassdef
.bound_mtype
)
94 var candidate
= self.try_get_mproperty_by_name2
(nclassdef
, mmodule
, st
, "init").as(nullable MMethod)
95 if candidate
!= null and candidate
.intro
.msignature
.arity
== 0 then
96 combine
.add
(candidate
)
99 var inhc2
= c
.inherit_init_from
100 if inhc2
== null then inhc2
= c
101 if inhc2
== inhc
then continue
103 self.error
(nclassdef
, "Error: Cannot provide a defaut constructor: conflict for {inhc} and {c}")
108 if combine
.is_empty
and inhc
!= null then
109 # TODO: actively inherit the consturctor
110 self.toolcontext
.info
("{mclassdef} inherits all constructors from {inhc}", 3)
111 mclassdef
.mclass
.inherit_init_from
= inhc
114 if not combine
.is_empty
and inhc
!= null then
115 self.error
(nclassdef
, "Error: Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}")
119 if not combine
.is_empty
then
120 nclassdef
.super_inits
= combine
121 var mprop
= new MMethod(mclassdef
, "init", mclassdef
.mclass
.visibility
)
122 var mpropdef
= new MMethodDef(mclassdef
, mprop
, nclassdef
.location
)
123 var mparameters
= new Array[MParameter]
124 var msignature
= new MSignature(mparameters
, null)
125 mpropdef
.msignature
= msignature
127 nclassdef
.mfree_init
= mpropdef
128 self.toolcontext
.info
("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3)
132 # Collect undefined attributes
133 var mparameters
= new Array[MParameter]
134 for npropdef
in nclassdef
.n_propdefs
do
135 if npropdef
isa AAttrPropdef and npropdef
.n_expr
== null then
136 if npropdef
.mpropdef
== null then return # Skip broken attribute
137 var paramname
= npropdef
.mpropdef
.mproperty
.name
.substring_from
(1)
138 var ret_type
= npropdef
.mpropdef
.static_mtype
139 if ret_type
== null then return
140 var mparameter
= new MParameter(paramname
, ret_type
, false)
141 mparameters
.add
(mparameter
)
145 var mprop
= new MMethod(mclassdef
, "init", mclassdef
.mclass
.visibility
)
146 var mpropdef
= new MMethodDef(mclassdef
, mprop
, nclassdef
.location
)
147 var msignature
= new MSignature(mparameters
, null)
148 mpropdef
.msignature
= msignature
150 nclassdef
.mfree_init
= mpropdef
151 self.toolcontext
.info
("{mclassdef} gets a free constructor for attributes {mpropdef}{msignature}", 3)
154 # Check the visibility of `mtype` as an element of the signature of `mpropdef`.
155 fun check_visibility
(node
: ANode, mtype
: MType, mpropdef
: MPropDef)
157 var mmodule
= mpropdef
.mclassdef
.mmodule
158 var mproperty
= mpropdef
.mproperty
160 # Extract visibility information of the main part of `mtype`
161 # It is a case-by case
162 var vis_type
: nullable MVisibility = null # The own visibility of the type
163 var mmodule_type
: nullable MModule = null # The origial module of the type
164 if mtype
isa MNullableType then mtype
= mtype
.mtype
165 if mtype
isa MClassType then
166 vis_type
= mtype
.mclass
.visibility
167 mmodule_type
= mtype
.mclass
.intro
.mmodule
168 else if mtype
isa MVirtualType then
169 vis_type
= mtype
.mproperty
.visibility
170 mmodule_type
= mtype
.mproperty
.intro_mclassdef
.mmodule
171 else if mtype
isa MParameterType then
172 # nothing, always visible
174 node
.debug
"Unexpected type {mtype}"
178 if vis_type
!= null then
179 assert mmodule_type
!= null
180 var vis_module_type
= mmodule
.visibility_for
(mmodule_type
) # the visibility of the original module
181 if mproperty
.visibility
> vis_type
then
182 error
(node
, "Error: The {mproperty.visibility} property `{mproperty}` cannot contain the {vis_type} type `{mtype}`")
184 else if mproperty
.visibility
> vis_module_type
then
185 error
(node
, "Error: The {mproperty.visibility} property `{mproperty}` cannot contain the type `{mtype}` from the {vis_module_type} module `{mmodule_type}`")
190 # No error, try to go deeper in generic types
191 if node
isa AType then
192 for a
in node
.n_types
do check_visibility
(a
, a
.mtype
.as(not null), mpropdef
)
193 else if mtype
isa MGenericType then
194 for t
in mtype
.arguments
do check_visibility
(node
, t
, mpropdef
)
200 # The class whose self inherit all the constructors.
201 # 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
202 var inherit_init_from
: nullable MClass = null
205 redef class MClassDef
206 private var propdef_names
= new HashSet[String]
210 # Does the MPropDef contains a call to super or a call of a super-constructor?
211 # Subsequent phases of the frontend (esp. typing) set it if required
212 var has_supercall
: Bool writable = false
215 redef class AClassdef
216 var build_properties_is_done
: Bool = false
217 # The list of super-constructor to call at the start of the free constructor
218 # 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
219 var super_inits
: nullable Collection[MMethod] = null
221 # The free init (implicitely constructed by the class if required)
222 var mfree_init
: nullable MMethodDef = null
224 # What is the `APropdef` associated to a `MProperty`?
225 # Used to check multiple definition of a property.
226 var mprop2npropdef
: Map[MProperty, APropdef] = new HashMap[MProperty, APropdef]
230 # Join the text of all tokens
231 # Used to get the 'real name' of method definitions.
232 fun collect_text
: String
234 var v
= new TextCollectorVisitor
241 private class TextCollectorVisitor
243 var text
: String = ""
246 if n
isa Token then text
+= n
.text
252 # The associated main model entity
253 type MPROPDEF: MPropDef
255 # The associated propdef once build by a `ModelBuilder`
256 var mpropdef
: nullable MPROPDEF writable
258 private fun build_property
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef) is abstract
259 private fun build_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef) is abstract
260 private fun check_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef) is abstract
261 private fun new_property_visibility
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, nvisibility
: nullable AVisibility): MVisibility
263 var mvisibility
= public_visibility
264 if nvisibility
!= null then
265 mvisibility
= nvisibility
.mvisibility
266 if mvisibility
== intrude_visibility
then
267 modelbuilder
.error
(nvisibility
, "Error: intrude is not a legal visibility for properties.")
268 mvisibility
= public_visibility
271 if nclassdef
.mclassdef
.mclass
.visibility
== private_visibility
then
272 if mvisibility
== protected_visibility
then
273 assert nvisibility
!= null
274 modelbuilder
.error
(nvisibility
, "Error: The only legal visibility for properties in a private class is private.")
275 else if mvisibility
== private_visibility
then
276 assert nvisibility
!= null
278 # modelbuilder.warning(nvisibility, "Warning: private is unrequired since the only legal visibility for properties in a private class is private.")
280 mvisibility
= private_visibility
285 private fun set_doc
(mpropdef
: MPropDef)
287 var ndoc
= self.n_doc
288 if ndoc
!= null then mpropdef
.mdoc
= ndoc
.to_mdoc
291 private fun check_redef_property_visibility
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, nvisibility
: nullable AVisibility, mprop
: MProperty)
293 if nvisibility
== null then return
294 var mvisibility
= nvisibility
.mvisibility
295 if mvisibility
!= mprop
.visibility
and mvisibility
!= public_visibility
then
296 modelbuilder
.error
(nvisibility
, "Error: redefinition changed the visibility from a {mprop.visibility} to a {mvisibility}")
300 private fun check_redef_keyword
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, kwredef
: nullable Token, need_redef
: Bool, mprop
: MProperty): Bool
302 if nclassdef
.mprop2npropdef
.has_key
(mprop
) then
303 modelbuilder
.error
(self, "Error: A property {mprop} is already defined in class {nclassdef.mclassdef.mclass}.")
306 if kwredef
== null then
308 modelbuilder
.error
(self, "Redef error: {nclassdef.mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.")
312 if not need_redef
then
313 modelbuilder
.error
(self, "Error: No property {nclassdef.mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.")
322 redef class ASignature
323 # Is the model builder has correctly visited the signature
324 var is_visited
= false
325 # Names of parameters from the AST
326 # REQUIRE: is_visited
327 var param_names
= new Array[String]
328 # Types of parameters from the AST
329 # REQUIRE: is_visited
330 var param_types
= new Array[MType]
331 # Rank of the vararg (of -1 if none)
332 # REQUIRE: is_visited
333 var vararg_rank
: Int = -1
335 var ret_type
: nullable MType = null
337 # Visit and fill information about a signature
338 private fun visit_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef): Bool
340 var param_names
= self.param_names
341 var param_types
= self.param_types
342 for np
in self.n_params
do
343 param_names
.add
(np
.n_id
.text
)
344 var ntype
= np
.n_type
345 if ntype
!= null then
346 var mtype
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
347 if mtype
== null then return false # Skip error
348 for i
in [0..param_names
.length-param_types
.length
[ do
349 param_types
.add
(mtype
)
351 if np
.n_dotdotdot
!= null then
352 if self.vararg_rank
!= -1 then
353 modelbuilder
.error
(np
, "Error: {param_names[self.vararg_rank]} is already a vararg")
356 self.vararg_rank
= param_names
.length
- 1
361 var ntype
= self.n_type
362 if ntype
!= null then
363 self.ret_type
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
364 if self.ret_type
== null then return false # Skip errir
367 self.is_visited
= true
371 # Build a visited signature
372 fun build_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef): nullable MSignature
374 if param_names
.length
!= param_types
.length
then
375 # Some parameters are typed, other parameters are not typed.
376 modelbuilder
.error
(self.n_params
[param_types
.length
], "Error: Untyped parameter `{param_names[param_types.length]}'.")
380 var mparameters
= new Array[MParameter]
381 for i
in [0..param_names
.length
[ do
382 var mparameter
= new MParameter(param_names
[i
], param_types
[i
], i
== vararg_rank
)
383 self.n_params
[i
].mparameter
= mparameter
384 mparameters
.add
(mparameter
)
387 var msignature
= new MSignature(mparameters
, ret_type
)
393 # The associated mparameter if any
394 var mparameter
: nullable MParameter = null
397 redef class AMethPropdef
398 redef type MPROPDEF: MMethodDef
400 redef fun build_property
(modelbuilder
, nclassdef
)
402 var is_init
= self isa AInitPropdef
403 var mclassdef
= nclassdef
.mclassdef
.as(not null)
405 var amethodid
= self.n_methid
407 if amethodid
== null then
408 if self isa AMainMethPropdef then
411 else if self isa AConcreteInitPropdef then
413 name_node
= self.n_kwinit
414 else if self isa AExternInitPropdef then
416 name_node
= self.n_kwnew
420 else if amethodid
isa AIdMethid then
421 name
= amethodid
.n_id
.text
422 name_node
= amethodid
424 # operator, bracket or assign
425 name
= amethodid
.collect_text
426 name_node
= amethodid
428 if name
== "-" and self.n_signature
.n_params
.length
== 0 then
433 var mprop
: nullable MMethod = null
434 if not is_init
or n_kwredef
!= null then mprop
= modelbuilder
.try_get_mproperty_by_name
(name_node
, mclassdef
, name
).as(nullable MMethod)
435 if mprop
== null then
436 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
437 mprop
= new MMethod(mclassdef
, name
, mvisibility
)
438 mprop
.is_init
= is_init
439 mprop
.is_new
= self isa AExternInitPropdef
440 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, false, mprop
) then return
442 if n_kwredef
== null then
443 if self isa AMainMethPropdef then
446 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, true, mprop
) then return
449 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
451 nclassdef
.mprop2npropdef
[mprop
] = self
453 var mpropdef
= new MMethodDef(mclassdef
, mprop
, self.location
)
455 if mclassdef
.propdef_names
.has
(mprop
.name
) then
456 var loc
: nullable Location = null
457 for i
in mclassdef
.mpropdefs
do
458 if i
.mproperty
.name
== mprop
.name
then
463 if loc
== null then abort
464 modelbuilder
.error
(self, "Error: a property {mprop} is already defined in class {mclassdef.mclass} at {loc}")
467 mclassdef
.propdef_names
.add
(mpropdef
.mproperty
.name
)
471 self.mpropdef
= mpropdef
472 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
473 if mpropdef
.is_intro
then
474 modelbuilder
.toolcontext
.info
("{mpropdef} introduces new method {mprop.full_name}", 3)
476 modelbuilder
.toolcontext
.info
("{mpropdef} redefines method {mprop.full_name}", 3)
480 redef fun build_signature
(modelbuilder
, nclassdef
)
482 var mpropdef
= self.mpropdef
483 if mpropdef
== null then return # Error thus skiped
484 var mmodule
= mpropdef
.mclassdef
.mmodule
485 var nsig
= self.n_signature
487 # Retrieve info from the signature AST
488 var param_names
= new Array[String] # Names of parameters from the AST
489 var param_types
= new Array[MType] # Types of parameters from the AST
491 var ret_type
: nullable MType = null # Return type from the AST
493 if not nsig
.visit_signature
(modelbuilder
, nclassdef
) then return
494 param_names
= nsig
.param_names
495 param_types
= nsig
.param_types
496 vararg_rank
= nsig
.vararg_rank
497 ret_type
= nsig
.ret_type
500 # Look for some signature to inherit
501 # FIXME: do not inherit from the intro, but from the most specific
502 var msignature
: nullable MSignature = null
503 if not mpropdef
.is_intro
then
504 msignature
= mpropdef
.mproperty
.intro
.msignature
505 if msignature
== null then return # Skip error
507 # Check inherited signature arity
508 if param_names
.length
!= msignature
.arity
then
510 if nsig
!= null then node
= nsig
else node
= self
511 modelbuilder
.error
(node
, "Redef error: {mpropdef} redefines {mpropdef.mproperty.intro} with {param_names.length} parameter(s), {msignature.arity} expected. Signature is {mpropdef}{msignature}")
514 else if mpropdef
.mproperty
.is_init
then
515 # FIXME UGLY: inherit signature from a super-constructor
516 for msupertype
in nclassdef
.mclassdef
.supertypes
do
517 msupertype
= msupertype
.anchor_to
(mmodule
, nclassdef
.mclassdef
.bound_mtype
)
518 var candidate
= modelbuilder
.try_get_mproperty_by_name2
(self, mmodule
, msupertype
, mpropdef
.mproperty
.name
)
519 if candidate
!= null then
520 if msignature
== null then
521 msignature
= candidate
.intro
.as(MMethodDef).msignature
528 # Inherit the signature
529 if msignature
!= null and param_names
.length
!= param_types
.length
and param_names
.length
== msignature
.arity
and param_types
.length
== 0 then
530 # Parameters are untyped, thus inherit them
531 param_types
= new Array[MType]
532 for mparameter
in msignature
.mparameters
do
533 param_types
.add
(mparameter
.mtype
)
535 vararg_rank
= msignature
.vararg_rank
537 if msignature
!= null and ret_type
== null then
538 ret_type
= msignature
.return_mtype
541 if param_names
.length
!= param_types
.length
then
542 # Some parameters are typed, other parameters are not typed.
543 modelbuilder
.error
(nsig
.n_params
[param_types
.length
], "Error: Untyped parameter `{param_names[param_types.length]}'.")
547 var mparameters
= new Array[MParameter]
548 for i
in [0..param_names
.length
[ do
549 var mparameter
= new MParameter(param_names
[i
], param_types
[i
], i
== vararg_rank
)
550 if nsig
!= null then nsig
.n_params
[i
].mparameter
= mparameter
551 mparameters
.add
(mparameter
)
554 msignature
= new MSignature(mparameters
, ret_type
)
555 mpropdef
.msignature
= msignature
556 mpropdef
.is_abstract
= self isa ADeferredMethPropdef
557 mpropdef
.is_intern
= self isa AInternMethPropdef
560 redef fun check_signature
(modelbuilder
, nclassdef
)
562 var mpropdef
= self.mpropdef
563 if mpropdef
== null then return # Error thus skiped
564 var mmodule
= mpropdef
.mclassdef
.mmodule
565 var nsig
= self.n_signature
566 var mysignature
= self.mpropdef
.msignature
567 if mysignature
== null then return # Error thus skiped
569 # Lookup for signature in the precursor
570 # FIXME all precursors should be considered
571 if not mpropdef
.is_intro
then
572 var msignature
= mpropdef
.mproperty
.intro
.msignature
573 if msignature
== null then return
575 var precursor_ret_type
= msignature
.return_mtype
576 var ret_type
= mysignature
.return_mtype
577 if ret_type
!= null and precursor_ret_type
== null then
578 modelbuilder
.error
(nsig
.n_type
.as(not null), "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
582 if mysignature
.arity
> 0 then
583 # Check parameters types
584 for i
in [0..mysignature
.arity
[ do
585 var myt
= mysignature
.mparameters
[i
].mtype
586 var prt
= msignature
.mparameters
[i
].mtype
587 if not myt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, prt
) or
588 not prt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, myt
) then
589 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}.")
593 if precursor_ret_type
!= null then
594 if ret_type
== null then
595 # Inherit the return type
596 ret_type
= precursor_ret_type
597 else if not ret_type
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, precursor_ret_type
) then
598 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}.")
603 if mysignature
.arity
> 0 then
604 # Check parameters visibility
605 for i
in [0..mysignature
.arity
[ do
606 var nt
= nsig
.n_params
[i
].n_type
607 if nt
!= null then modelbuilder
.check_visibility
(nt
, nt
.mtype
.as(not null), mpropdef
)
610 if nt
!= null then modelbuilder
.check_visibility
(nt
, nt
.mtype
.as(not null), mpropdef
)
615 redef class AAttrPropdef
616 redef type MPROPDEF: MAttributeDef
618 # The associated getter (read accessor) if any
619 var mreadpropdef
: nullable MMethodDef writable
620 # The associated setter (write accessor) if any
621 var mwritepropdef
: nullable MMethodDef writable
622 redef fun build_property
(modelbuilder
, nclassdef
)
624 var mclassdef
= nclassdef
.mclassdef
.as(not null)
625 var mclass
= mclassdef
.mclass
628 if self.n_id
!= null then
629 name
= self.n_id
.text
631 name
= self.n_id2
.text
634 if mclass
.kind
== interface_kind
or mclassdef
.mclass
.kind
== enum_kind
then
635 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the interface {mclass}.")
636 else if mclass
.kind
== enum_kind
then
637 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the enum class {mclass}.")
638 else if mclass
.kind
== extern_kind
then
639 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the extern class {mclass}.")
644 # Old attribute style
645 var mprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, name
)
646 if mprop
== null then
647 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
648 mprop
= new MAttribute(mclassdef
, name
, mvisibility
)
649 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, false, mprop
) then return
651 assert mprop
isa MAttribute
652 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
653 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, true, mprop
) then return
655 nclassdef
.mprop2npropdef
[mprop
] = self
657 var mpropdef
= new MAttributeDef(mclassdef
, mprop
, self.location
)
658 self.mpropdef
= mpropdef
659 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
662 var nreadable
= self.n_readable
663 if nreadable
!= null then
664 var readname
= name
.substring_from
(1)
665 var mreadprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, readname
).as(nullable MMethod)
666 if mreadprop
== null then
667 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nreadable
.n_visibility
)
668 mreadprop
= new MMethod(mclassdef
, readname
, mvisibility
)
669 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nreadable
.n_kwredef
, false, mreadprop
) then return
671 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nreadable
.n_kwredef
, true, mreadprop
) then return
672 check_redef_property_visibility
(modelbuilder
, nclassdef
, nreadable
.n_visibility
, mreadprop
)
674 nclassdef
.mprop2npropdef
[mreadprop
] = self
676 var mreadpropdef
= new MMethodDef(mclassdef
, mreadprop
, self.location
)
677 self.mreadpropdef
= mreadpropdef
678 modelbuilder
.mpropdef2npropdef
[mreadpropdef
] = self
679 mreadpropdef
.mdoc
= mpropdef
.mdoc
682 var nwritable
= self.n_writable
683 if nwritable
!= null then
684 var writename
= name
.substring_from
(1) + "="
685 var mwriteprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, writename
).as(nullable MMethod)
686 if mwriteprop
== null then
687 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
)
688 mwriteprop
= new MMethod(mclassdef
, writename
, mvisibility
)
689 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwritable
.n_kwredef
, false, mwriteprop
) then return
691 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwritable
.n_kwredef
, true, mwriteprop
) then return
692 check_redef_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
, mwriteprop
)
694 nclassdef
.mprop2npropdef
[mwriteprop
] = self
696 var mwritepropdef
= new MMethodDef(mclassdef
, mwriteprop
, self.location
)
697 self.mwritepropdef
= mwritepropdef
698 modelbuilder
.mpropdef2npropdef
[mwritepropdef
] = self
699 mwritepropdef
.mdoc
= mpropdef
.mdoc
702 # New attribute style
703 var nid2
= self.n_id2
.as(not null)
704 var mprop
= new MAttribute(mclassdef
, "@" + name
, none_visibility
)
705 var mpropdef
= new MAttributeDef(mclassdef
, mprop
, self.location
)
706 self.mpropdef
= mpropdef
707 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
711 var mreadprop
= modelbuilder
.try_get_mproperty_by_name
(nid2
, mclassdef
, readname
).as(nullable MMethod)
712 if mreadprop
== null then
713 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
714 mreadprop
= new MMethod(mclassdef
, readname
, mvisibility
)
715 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, false, mreadprop
) then return
717 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, true, mreadprop
) then return
718 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mreadprop
)
720 nclassdef
.mprop2npropdef
[mreadprop
] = self
722 var mreadpropdef
= new MMethodDef(mclassdef
, mreadprop
, self.location
)
723 self.mreadpropdef
= mreadpropdef
724 modelbuilder
.mpropdef2npropdef
[mreadpropdef
] = self
725 mreadpropdef
.mdoc
= mpropdef
.mdoc
727 var writename
= name
+ "="
728 var nwritable
= self.n_writable
729 var mwriteprop
= modelbuilder
.try_get_mproperty_by_name
(nid2
, mclassdef
, writename
).as(nullable MMethod)
730 var nwkwredef
: nullable Token = null
731 if nwritable
!= null then nwkwredef
= nwritable
.n_kwredef
732 if mwriteprop
== null then
734 if nwritable
!= null then
735 mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
)
737 mvisibility
= private_visibility
739 mwriteprop
= new MMethod(mclassdef
, writename
, mvisibility
)
740 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwkwredef
, false, mwriteprop
) then return
742 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwkwredef
, true, mwriteprop
) then return
743 if nwritable
!= null then
744 check_redef_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
, mwriteprop
)
747 nclassdef
.mprop2npropdef
[mwriteprop
] = self
749 var mwritepropdef
= new MMethodDef(mclassdef
, mwriteprop
, self.location
)
750 self.mwritepropdef
= mwritepropdef
751 modelbuilder
.mpropdef2npropdef
[mwritepropdef
] = self
752 mwritepropdef
.mdoc
= mpropdef
.mdoc
756 redef fun build_signature
(modelbuilder
, nclassdef
)
758 var mpropdef
= self.mpropdef
759 if mpropdef
== null then return # Error thus skiped
760 var mmodule
= mpropdef
.mclassdef
.mmodule
761 var mtype
: nullable MType = null
763 var ntype
= self.n_type
764 if ntype
!= null then
765 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
766 if mtype
== null then return
769 var nexpr
= self.n_expr
770 if mtype
== null then
771 if nexpr
!= null then
772 if nexpr
isa ANewExpr then
773 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, nexpr
.n_type
)
774 else if nexpr
isa AIntExpr then
775 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Int")
776 if cla
!= null then mtype
= cla
.mclass_type
777 else if nexpr
isa AFloatExpr then
778 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Float")
779 if cla
!= null then mtype
= cla
.mclass_type
780 else if nexpr
isa ACharExpr then
781 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Char")
782 if cla
!= null then mtype
= cla
.mclass_type
783 else if nexpr
isa ABoolExpr then
784 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Bool")
785 if cla
!= null then mtype
= cla
.mclass_type
786 else if nexpr
isa ASuperstringExpr then
787 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "String")
788 if cla
!= null then mtype
= cla
.mclass_type
789 else if nexpr
isa AStringFormExpr then
790 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "String")
791 if cla
!= null then mtype
= cla
.mclass_type
793 modelbuilder
.error
(self, "Error: Untyped attribute {mpropdef}. Implicit typing allowed only for literals and new.")
797 modelbuilder
.error
(self, "Error: Untyped attribute {mpropdef}")
801 if nexpr
isa ANewExpr then
802 var xmtype
= modelbuilder
.resolve_mtype
(nclassdef
, nexpr
.n_type
)
803 if xmtype
== mtype
and modelbuilder
.toolcontext
.opt_warn
.value
>= 2 then
804 modelbuilder
.warning
(ntype
, "Warning: useless type definition")
809 if mtype
== null then return
811 mpropdef
.static_mtype
= mtype
813 var mreadpropdef
= self.mreadpropdef
814 if mreadpropdef
!= null then
815 var msignature
= new MSignature(new Array[MParameter], mtype
)
816 mreadpropdef
.msignature
= msignature
819 var msritepropdef
= self.mwritepropdef
820 if mwritepropdef
!= null then
823 name
= n_id
.text
.substring_from
(1)
827 var mparameter
= new MParameter(name
, mtype
, false)
828 var msignature
= new MSignature([mparameter
], null)
829 mwritepropdef
.msignature
= msignature
833 redef fun check_signature
(modelbuilder
, nclassdef
)
835 var mpropdef
= self.mpropdef
836 if mpropdef
== null then return # Error thus skiped
837 var mmodule
= mpropdef
.mclassdef
.mmodule
838 var ntype
= self.n_type
839 var mtype
= self.mpropdef
.static_mtype
840 if mtype
== null then return # Error thus skiped
842 # Lookup for signature in the precursor
843 # FIXME all precursors should be considered
844 if not mpropdef
.is_intro
then
845 var precursor_type
= mpropdef
.mproperty
.intro
.static_mtype
846 if precursor_type
== null then return
848 if mtype
!= precursor_type
then
849 modelbuilder
.error
(ntype
.as(not null), "Redef Error: Wrong static type. found {mtype}, expected {precursor_type}.")
854 # Check getter and setter
855 var meth
= self.mreadpropdef
857 self.check_method_signature
(modelbuilder
, nclassdef
, meth
)
858 var node
: nullable ANode = ntype
859 if node
== null then node
= self
860 modelbuilder
.check_visibility
(node
, mtype
, meth
)
862 meth
= self.mwritepropdef
864 self.check_method_signature
(modelbuilder
, nclassdef
, meth
)
865 var node
: nullable ANode = ntype
866 if node
== null then node
= self
867 modelbuilder
.check_visibility
(node
, mtype
, meth
)
871 private fun check_method_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, mpropdef
: MMethodDef)
873 var mmodule
= mpropdef
.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
, nclassdef
.mclassdef
.bound_mtype
, prt
) and
905 not prt
.is_subtype
(mmodule
, nclassdef
.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
, nclassdef
.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
, nclassdef
)
931 var mclassdef
= nclassdef
.mclassdef
.as(not null)
932 var name
= self.n_id
.text
933 var mprop
= modelbuilder
.try_get_mproperty_by_name
(self.n_id
, mclassdef
, name
)
934 if mprop
== null then
935 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
936 mprop
= new MVirtualTypeProp(mclassdef
, name
, mvisibility
)
937 for c
in name
do if c
>= 'a' and c
<= 'z' then
938 modelbuilder
.warning
(n_id
, "Warning: lowercase in the virtual type {name}")
941 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, false, mprop
) then return
943 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, true, mprop
) then return
944 assert mprop
isa MVirtualTypeProp
945 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
947 nclassdef
.mprop2npropdef
[mprop
] = self
949 var mpropdef
= new MVirtualTypeDef(mclassdef
, mprop
, self.location
)
950 self.mpropdef
= mpropdef
954 redef fun build_signature
(modelbuilder
, nclassdef
)
956 var mpropdef
= self.mpropdef
957 if mpropdef
== null then return # Error thus skiped
958 var mmodule
= mpropdef
.mclassdef
.mmodule
959 var mtype
: nullable MType = null
961 var ntype
= self.n_type
962 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
963 if mtype
== null then return
965 mpropdef
.bound
= mtype
966 # print "{mpropdef}: {mtype}"
969 redef fun check_signature
(modelbuilder
, nclassdef
)
971 var mpropdef
= self.mpropdef
972 if mpropdef
== null then return # Error thus skiped
974 var bound
= self.mpropdef
.bound
975 if bound
== null then return # Error thus skiped
977 modelbuilder
.check_visibility
(n_type
.as(not null), bound
, mpropdef
)
979 # Fast case: the bound is not a formal type
980 if not bound
isa MVirtualType then return
982 var mmodule
= nclassdef
.mclassdef
.mmodule
983 var anchor
= nclassdef
.mclassdef
.bound_mtype
985 # Slow case: progress on each resolution until: (i) we loop, or (ii) we found a non formal type
986 var seen
= [self.mpropdef
.mproperty
.mvirtualtype
]
988 if seen
.has
(bound
) then
990 modelbuilder
.error
(self, "Error: circularity of virtual type definition: {seen.join(" -> ")}")
994 var next
= bound
.lookup_bound
(mmodule
, anchor
)
995 if not next
isa MVirtualType then break