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)
156 # The class whose self inherit all the constructors.
157 # 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
158 var inherit_init_from
: nullable MClass = null
161 redef class AClassdef
162 var build_properties_is_done
: Bool = false
163 # The list of super-constructor to call at the start of the free constructor
164 # 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
165 var super_inits
: nullable Collection[MMethod] = null
167 # The free init (implicitely constructed by the class if required)
168 var mfree_init
: nullable MMethodDef = null
170 # What is the `APropdef` associated to a `MProperty`?
171 # Used to check multiple definition of a property.
172 var mprop2npropdef
: Map[MProperty, APropdef] = new HashMap[MProperty, APropdef]
176 # Join the text of all tokens
177 # Used to get the 'real name' of method definitions.
178 fun collect_text
: String
180 var v
= new TextCollectorVisitor
187 private class TextCollectorVisitor
189 var text
: String = ""
192 if n
isa Token then text
+= n
.text
198 # The associated main model entity
199 type MPROPDEF: MPropDef
201 # The associated propdef once build by a `ModelBuilder`
202 var mpropdef
: nullable MPROPDEF writable
204 private fun build_property
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef) is abstract
205 private fun build_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef) is abstract
206 private fun check_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef) is abstract
207 private fun new_property_visibility
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, nvisibility
: nullable AVisibility): MVisibility
209 var mvisibility
= public_visibility
210 if nvisibility
!= null then
211 mvisibility
= nvisibility
.mvisibility
212 if mvisibility
== intrude_visibility
then
213 modelbuilder
.error
(nvisibility
, "Error: intrude is not a legal visibility for properties.")
214 mvisibility
= public_visibility
217 if nclassdef
.mclassdef
.mclass
.visibility
== private_visibility
then
218 if mvisibility
== protected_visibility
then
219 assert nvisibility
!= null
220 modelbuilder
.error
(nvisibility
, "Error: The only legal visibility for properties in a private class is private.")
221 else if mvisibility
== private_visibility
then
222 assert nvisibility
!= null
224 # modelbuilder.warning(nvisibility, "Warning: private is unrequired since the only legal visibility for properties in a private class is private.")
226 mvisibility
= private_visibility
231 private fun check_redef_property_visibility
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, nvisibility
: nullable AVisibility, mprop
: MProperty)
233 if nvisibility
== null then return
234 var mvisibility
= nvisibility
.mvisibility
235 if mvisibility
!= mprop
.visibility
and mvisibility
!= public_visibility
then
236 modelbuilder
.error
(nvisibility
, "Error: redefinition changed the visibility from a {mprop.visibility} to a {mvisibility}")
240 private fun check_redef_keyword
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, kwredef
: nullable Token, need_redef
: Bool, mprop
: MProperty): Bool
242 if nclassdef
.mprop2npropdef
.has_key
(mprop
) then
243 modelbuilder
.error
(self, "Error: A property {mprop} is already defined in class {nclassdef.mclassdef.mclass}.")
246 if kwredef
== null then
248 modelbuilder
.error
(self, "Redef error: {nclassdef.mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.")
252 if not need_redef
then
253 modelbuilder
.error
(self, "Error: No property {nclassdef.mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.")
262 redef class ASignature
263 # Is the model builder has correctly visited the signature
264 var is_visited
= false
265 # Names of parameters from the AST
266 # REQUIRE: is_visited
267 var param_names
= new Array[String]
268 # Types of parameters from the AST
269 # REQUIRE: is_visited
270 var param_types
= new Array[MType]
271 # Rank of the vararg (of -1 if none)
272 # REQUIRE: is_visited
273 var vararg_rank
: Int = -1
275 var ret_type
: nullable MType = null
277 # Visit and fill information about a signature
278 private fun visit_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef): Bool
280 var param_names
= self.param_names
281 var param_types
= self.param_types
282 for np
in self.n_params
do
283 param_names
.add
(np
.n_id
.text
)
284 var ntype
= np
.n_type
285 if ntype
!= null then
286 var mtype
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
287 if mtype
== null then return false # Skip error
288 for i
in [0..param_names
.length-param_types
.length
[ do
289 param_types
.add
(mtype
)
291 if np
.n_dotdotdot
!= null then
292 if self.vararg_rank
!= -1 then
293 modelbuilder
.error
(np
, "Error: {param_names[self.vararg_rank]} is already a vararg")
296 self.vararg_rank
= param_names
.length
- 1
301 var ntype
= self.n_type
302 if ntype
!= null then
303 self.ret_type
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
304 if self.ret_type
== null then return false # Skip errir
307 self.is_visited
= true
311 # Build a visited signature
312 fun build_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef): nullable MSignature
314 if param_names
.length
!= param_types
.length
then
315 # Some parameters are typed, other parameters are not typed.
316 modelbuilder
.error
(self.n_params
[param_types
.length
], "Error: Untyped parameter `{param_names[param_types.length]}'.")
320 var mparameters
= new Array[MParameter]
321 for i
in [0..param_names
.length
[ do
322 var mparameter
= new MParameter(param_names
[i
], param_types
[i
], i
== vararg_rank
)
323 self.n_params
[i
].mparameter
= mparameter
324 mparameters
.add
(mparameter
)
327 var msignature
= new MSignature(mparameters
, ret_type
)
333 # The associated mparameter if any
334 var mparameter
: nullable MParameter = null
337 redef class AMethPropdef
338 redef type MPROPDEF: MMethodDef
340 redef fun build_property
(modelbuilder
, nclassdef
)
342 var is_init
= self isa AInitPropdef
343 var mclassdef
= nclassdef
.mclassdef
.as(not null)
345 var amethodid
= self.n_methid
347 if amethodid
== null then
348 if self isa AMainMethPropdef then
351 else if self isa AConcreteInitPropdef then
353 name_node
= self.n_kwinit
354 else if self isa AExternInitPropdef then
356 name_node
= self.n_kwnew
360 else if amethodid
isa AIdMethid then
361 name
= amethodid
.n_id
.text
362 name_node
= amethodid
364 # operator, bracket or assign
365 name
= amethodid
.collect_text
366 name_node
= amethodid
368 if name
== "-" and self.n_signature
.n_params
.length
== 0 then
373 var mprop
: nullable MMethod = null
374 if not is_init
or n_kwredef
!= null then mprop
= modelbuilder
.try_get_mproperty_by_name
(name_node
, mclassdef
, name
).as(nullable MMethod)
375 if mprop
== null then
376 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
377 mprop
= new MMethod(mclassdef
, name
, mvisibility
)
378 mprop
.is_init
= is_init
379 mprop
.is_new
= self isa AExternInitPropdef
380 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, false, mprop
) then return
382 if n_kwredef
== null then
383 if self isa AMainMethPropdef then
386 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, true, mprop
) then return
389 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
391 nclassdef
.mprop2npropdef
[mprop
] = self
393 var mpropdef
= new MMethodDef(mclassdef
, mprop
, self.location
)
395 self.mpropdef
= mpropdef
396 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
397 if mpropdef
.is_intro
then
398 modelbuilder
.toolcontext
.info
("{mpropdef} introduces new method {mprop.full_name}", 3)
400 modelbuilder
.toolcontext
.info
("{mpropdef} redefines method {mprop.full_name}", 3)
404 redef fun build_signature
(modelbuilder
, nclassdef
)
406 var mpropdef
= self.mpropdef
407 if mpropdef
== null then return # Error thus skiped
408 var mmodule
= mpropdef
.mclassdef
.mmodule
409 var nsig
= self.n_signature
411 # Retrieve info from the signature AST
412 var param_names
= new Array[String] # Names of parameters from the AST
413 var param_types
= new Array[MType] # Types of parameters from the AST
415 var ret_type
: nullable MType = null # Return type from the AST
417 if not nsig
.visit_signature
(modelbuilder
, nclassdef
) then return
418 param_names
= nsig
.param_names
419 param_types
= nsig
.param_types
420 vararg_rank
= nsig
.vararg_rank
421 ret_type
= nsig
.ret_type
424 # Look for some signature to inherit
425 # FIXME: do not inherit from the intro, but from the most specific
426 var msignature
: nullable MSignature = null
427 if not mpropdef
.is_intro
then
428 msignature
= mpropdef
.mproperty
.intro
.msignature
429 if msignature
== null then return # Skip error
431 # Check inherited signature arity
432 if param_names
.length
!= msignature
.arity
then
434 if nsig
!= null then node
= nsig
else node
= self
435 modelbuilder
.error
(node
, "Redef error: {mpropdef} redefines {mpropdef.mproperty.intro} with {param_names.length} parameter(s), {msignature.arity} expected. Signature is {mpropdef}{msignature}")
438 else if mpropdef
.mproperty
.is_init
then
439 # FIXME UGLY: inherit signature from a super-constructor
440 for msupertype
in nclassdef
.mclassdef
.supertypes
do
441 msupertype
= msupertype
.anchor_to
(mmodule
, nclassdef
.mclassdef
.bound_mtype
)
442 var candidate
= modelbuilder
.try_get_mproperty_by_name2
(self, mmodule
, msupertype
, mpropdef
.mproperty
.name
)
443 if candidate
!= null then
444 if msignature
== null then
445 msignature
= candidate
.intro
.as(MMethodDef).msignature
452 # Inherit the signature
453 if msignature
!= null and param_names
.length
!= param_types
.length
and param_names
.length
== msignature
.arity
and param_types
.length
== 0 then
454 # Parameters are untyped, thus inherit them
455 param_types
= new Array[MType]
456 for mparameter
in msignature
.mparameters
do
457 param_types
.add
(mparameter
.mtype
)
459 vararg_rank
= msignature
.vararg_rank
461 if msignature
!= null and ret_type
== null then
462 ret_type
= msignature
.return_mtype
465 if param_names
.length
!= param_types
.length
then
466 # Some parameters are typed, other parameters are not typed.
467 modelbuilder
.error
(nsig
.n_params
[param_types
.length
], "Error: Untyped parameter `{param_names[param_types.length]}'.")
471 var mparameters
= new Array[MParameter]
472 for i
in [0..param_names
.length
[ do
473 var mparameter
= new MParameter(param_names
[i
], param_types
[i
], i
== vararg_rank
)
474 if nsig
!= null then nsig
.n_params
[i
].mparameter
= mparameter
475 mparameters
.add
(mparameter
)
478 msignature
= new MSignature(mparameters
, ret_type
)
479 mpropdef
.msignature
= msignature
480 mpropdef
.is_abstract
= self isa ADeferredMethPropdef
483 redef fun check_signature
(modelbuilder
, nclassdef
)
485 var mpropdef
= self.mpropdef
486 if mpropdef
== null then return # Error thus skiped
487 var mmodule
= mpropdef
.mclassdef
.mmodule
488 var nsig
= self.n_signature
489 var mysignature
= self.mpropdef
.msignature
490 if mysignature
== null then return # Error thus skiped
492 # Lookup for signature in the precursor
493 # FIXME all precursors should be considered
494 if not mpropdef
.is_intro
then
495 var msignature
= mpropdef
.mproperty
.intro
.msignature
496 if msignature
== null then return
498 var precursor_ret_type
= msignature
.return_mtype
499 var ret_type
= mysignature
.return_mtype
500 if ret_type
!= null and precursor_ret_type
== null then
501 modelbuilder
.error
(nsig
.n_type
.as(not null), "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
505 if mysignature
.arity
> 0 then
506 # Check parameters types
507 for i
in [0..mysignature
.arity
[ do
508 var myt
= mysignature
.mparameters
[i
].mtype
509 var prt
= msignature
.mparameters
[i
].mtype
510 if not myt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, prt
) or
511 not prt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, myt
) then
512 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}.")
516 if precursor_ret_type
!= null then
517 if ret_type
== null then
518 # Inherit the return type
519 ret_type
= precursor_ret_type
520 else if not ret_type
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, precursor_ret_type
) then
521 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}.")
528 redef class AAttrPropdef
529 redef type MPROPDEF: MAttributeDef
531 # The associated getter (read accessor) if any
532 var mreadpropdef
: nullable MMethodDef writable
533 # The associated setter (write accessor) if any
534 var mwritepropdef
: nullable MMethodDef writable
535 redef fun build_property
(modelbuilder
, nclassdef
)
537 var mclassdef
= nclassdef
.mclassdef
.as(not null)
538 var mclass
= mclassdef
.mclass
541 if self.n_id
!= null then
542 name
= self.n_id
.text
544 name
= self.n_id2
.text
547 if mclass
.kind
== interface_kind
or mclassdef
.mclass
.kind
== enum_kind
then
548 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the interface {mclass}.")
549 else if mclass
.kind
== enum_kind
then
550 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the enum class {mclass}.")
551 else if mclass
.kind
== extern_kind
then
552 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the extern class {mclass}.")
557 # Old attribute style
558 var mprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, name
)
559 if mprop
== null then
560 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
561 mprop
= new MAttribute(mclassdef
, name
, mvisibility
)
562 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, false, mprop
) then return
564 assert mprop
isa MAttribute
565 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
566 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, true, mprop
) then return
568 nclassdef
.mprop2npropdef
[mprop
] = self
570 var mpropdef
= new MAttributeDef(mclassdef
, mprop
, self.location
)
571 self.mpropdef
= mpropdef
572 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
574 var nreadable
= self.n_readable
575 if nreadable
!= null then
576 var readname
= name
.substring_from
(1)
577 var mreadprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, readname
).as(nullable MMethod)
578 if mreadprop
== null then
579 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nreadable
.n_visibility
)
580 mreadprop
= new MMethod(mclassdef
, readname
, mvisibility
)
581 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nreadable
.n_kwredef
, false, mreadprop
) then return
583 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nreadable
.n_kwredef
, true, mreadprop
) then return
584 check_redef_property_visibility
(modelbuilder
, nclassdef
, nreadable
.n_visibility
, mreadprop
)
586 nclassdef
.mprop2npropdef
[mreadprop
] = self
588 var mreadpropdef
= new MMethodDef(mclassdef
, mreadprop
, self.location
)
589 self.mreadpropdef
= mreadpropdef
590 modelbuilder
.mpropdef2npropdef
[mreadpropdef
] = self
593 var nwritable
= self.n_writable
594 if nwritable
!= null then
595 var writename
= name
.substring_from
(1) + "="
596 var mwriteprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, writename
).as(nullable MMethod)
597 if mwriteprop
== null then
598 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
)
599 mwriteprop
= new MMethod(mclassdef
, writename
, mvisibility
)
600 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwritable
.n_kwredef
, false, mwriteprop
) then return
602 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwritable
.n_kwredef
, true, mwriteprop
) then return
603 check_redef_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
, mwriteprop
)
605 nclassdef
.mprop2npropdef
[mwriteprop
] = self
607 var mwritepropdef
= new MMethodDef(mclassdef
, mwriteprop
, self.location
)
608 self.mwritepropdef
= mwritepropdef
609 modelbuilder
.mpropdef2npropdef
[mwritepropdef
] = self
612 # New attribute style
613 var nid2
= self.n_id2
.as(not null)
614 var mprop
= new MAttribute(mclassdef
, "@" + name
, none_visibility
)
615 var mpropdef
= new MAttributeDef(mclassdef
, mprop
, self.location
)
616 self.mpropdef
= mpropdef
617 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
620 var mreadprop
= modelbuilder
.try_get_mproperty_by_name
(nid2
, mclassdef
, readname
).as(nullable MMethod)
621 if mreadprop
== null then
622 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
623 mreadprop
= new MMethod(mclassdef
, readname
, mvisibility
)
624 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, false, mreadprop
) then return
626 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, true, mreadprop
) then return
627 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mreadprop
)
629 nclassdef
.mprop2npropdef
[mreadprop
] = self
631 var mreadpropdef
= new MMethodDef(mclassdef
, mreadprop
, self.location
)
632 self.mreadpropdef
= mreadpropdef
633 modelbuilder
.mpropdef2npropdef
[mreadpropdef
] = self
635 var writename
= name
+ "="
636 var nwritable
= self.n_writable
637 var mwriteprop
= modelbuilder
.try_get_mproperty_by_name
(nid2
, mclassdef
, writename
).as(nullable MMethod)
638 var nwkwredef
: nullable Token = null
639 if nwritable
!= null then nwkwredef
= nwritable
.n_kwredef
640 if mwriteprop
== null then
642 if nwritable
!= null then
643 mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
)
645 mvisibility
= private_visibility
647 mwriteprop
= new MMethod(mclassdef
, writename
, mvisibility
)
648 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwkwredef
, false, mwriteprop
) then return
650 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwkwredef
, true, mwriteprop
) then return
651 if nwritable
!= null then
652 check_redef_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
, mwriteprop
)
655 nclassdef
.mprop2npropdef
[mwriteprop
] = self
657 var mwritepropdef
= new MMethodDef(mclassdef
, mwriteprop
, self.location
)
658 self.mwritepropdef
= mwritepropdef
659 modelbuilder
.mpropdef2npropdef
[mwritepropdef
] = self
663 redef fun build_signature
(modelbuilder
, nclassdef
)
665 var mpropdef
= self.mpropdef
666 if mpropdef
== null then return # Error thus skiped
667 var mmodule
= mpropdef
.mclassdef
.mmodule
668 var mtype
: nullable MType = null
670 var ntype
= self.n_type
671 if ntype
!= null then
672 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
673 if mtype
== null then return
676 var nexpr
= self.n_expr
677 if mtype
== null then
678 if nexpr
!= null then
679 if nexpr
isa ANewExpr then
680 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, nexpr
.n_type
)
681 else if nexpr
isa AIntExpr then
682 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Int")
683 if cla
!= null then mtype
= cla
.mclass_type
684 else if nexpr
isa AFloatExpr then
685 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Float")
686 if cla
!= null then mtype
= cla
.mclass_type
687 else if nexpr
isa ACharExpr then
688 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Char")
689 if cla
!= null then mtype
= cla
.mclass_type
690 else if nexpr
isa ABoolExpr then
691 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Bool")
692 if cla
!= null then mtype
= cla
.mclass_type
693 else if nexpr
isa ASuperstringExpr then
694 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "String")
695 if cla
!= null then mtype
= cla
.mclass_type
696 else if nexpr
isa AStringFormExpr then
697 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "String")
698 if cla
!= null then mtype
= cla
.mclass_type
700 modelbuilder
.error
(self, "Error: Untyped attribute {mpropdef}. Implicit typing allowed only for literals and new.")
704 modelbuilder
.error
(self, "Error: Untyped attribute {mpropdef}")
708 if nexpr
isa ANewExpr then
709 var xmtype
= modelbuilder
.resolve_mtype
(nclassdef
, nexpr
.n_type
)
710 if xmtype
== mtype
and modelbuilder
.toolcontext
.opt_warn
.value
>= 2 then
711 modelbuilder
.warning
(ntype
, "Warning: useless type definition")
716 if mtype
== null then return
718 mpropdef
.static_mtype
= mtype
720 var mreadpropdef
= self.mreadpropdef
721 if mreadpropdef
!= null then
722 var msignature
= new MSignature(new Array[MParameter], mtype
)
723 mreadpropdef
.msignature
= msignature
726 var msritepropdef
= self.mwritepropdef
727 if mwritepropdef
!= null then
730 name
= n_id
.text
.substring_from
(1)
734 var mparameter
= new MParameter(name
, mtype
, false)
735 var msignature
= new MSignature([mparameter
], null)
736 mwritepropdef
.msignature
= msignature
740 redef fun check_signature
(modelbuilder
, nclassdef
)
742 var mpropdef
= self.mpropdef
743 if mpropdef
== null then return # Error thus skiped
744 var mmodule
= mpropdef
.mclassdef
.mmodule
745 var ntype
= self.n_type
746 var mtype
= self.mpropdef
.static_mtype
747 if mtype
== null then return # Error thus skiped
749 # Lookup for signature in the precursor
750 # FIXME all precursors should be considered
751 if not mpropdef
.is_intro
then
752 var precursor_type
= mpropdef
.mproperty
.intro
.static_mtype
753 if precursor_type
== null then return
755 if mtype
!= precursor_type
then
756 modelbuilder
.error
(ntype
.as(not null), "Redef Error: Wrong static type. found {mtype}, expected {precursor_type}.")
761 # Check getter and setter
762 var meth
= self.mreadpropdef
763 if meth
!= null then self.check_method_signature
(modelbuilder
, nclassdef
, meth
)
764 meth
= self.mwritepropdef
765 if meth
!= null then self.check_method_signature
(modelbuilder
, nclassdef
, meth
)
768 private fun check_method_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, mpropdef
: MMethodDef)
770 var mmodule
= mpropdef
.mclassdef
.mmodule
771 var nsig
= self.n_type
772 var mysignature
= mpropdef
.msignature
773 if mysignature
== null then return # Error thus skiped
775 # Lookup for signature in the precursor
776 # FIXME all precursors should be considered
777 if not mpropdef
.is_intro
then
778 var msignature
= mpropdef
.mproperty
.intro
.msignature
779 if msignature
== null then return
781 if mysignature
.arity
!= msignature
.arity
then
783 if nsig
!= null then node
= nsig
else node
= self
784 modelbuilder
.error
(node
, "Redef Error: {mysignature.arity} parameters found, {msignature.arity} expected. Signature is {mpropdef}{msignature}")
787 var precursor_ret_type
= msignature
.return_mtype
788 var ret_type
= mysignature
.return_mtype
789 if ret_type
!= null and precursor_ret_type
== null then
791 if nsig
!= null then node
= nsig
else node
= self
792 modelbuilder
.error
(node
, "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
796 if mysignature
.arity
> 0 then
797 # Check parameters types
798 for i
in [0..mysignature
.arity
[ do
799 var myt
= mysignature
.mparameters
[i
].mtype
800 var prt
= msignature
.mparameters
[i
].mtype
801 if not myt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, prt
) and
802 not prt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, myt
) then
804 if nsig
!= null then node
= nsig
else node
= self
805 modelbuilder
.error
(node
, "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
809 if precursor_ret_type
!= null then
810 if ret_type
== null then
811 # Inherit the return type
812 ret_type
= precursor_ret_type
813 else if not ret_type
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, precursor_ret_type
) then
815 if nsig
!= null then node
= nsig
else node
= self
816 modelbuilder
.error
(node
, "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type}.")
823 redef class ATypePropdef
824 redef type MPROPDEF: MVirtualTypeDef
826 redef fun build_property
(modelbuilder
, nclassdef
)
828 var mclassdef
= nclassdef
.mclassdef
.as(not null)
829 var name
= self.n_id
.text
830 var mprop
= modelbuilder
.try_get_mproperty_by_name
(self.n_id
, mclassdef
, name
)
831 if mprop
== null then
832 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
833 mprop
= new MVirtualTypeProp(mclassdef
, name
, mvisibility
)
834 for c
in name
do if c
>= 'a' and c
<= 'z' then
835 modelbuilder
.warning
(n_id
, "Warning: lowercase in the virtual type {name}")
838 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, false, mprop
) then return
840 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, true, mprop
) then return
841 assert mprop
isa MVirtualTypeProp
842 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
844 nclassdef
.mprop2npropdef
[mprop
] = self
846 var mpropdef
= new MVirtualTypeDef(mclassdef
, mprop
, self.location
)
847 self.mpropdef
= mpropdef
850 redef fun build_signature
(modelbuilder
, nclassdef
)
852 var mpropdef
= self.mpropdef
853 if mpropdef
== null then return # Error thus skiped
854 var mmodule
= mpropdef
.mclassdef
.mmodule
855 var mtype
: nullable MType = null
857 var ntype
= self.n_type
858 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
859 if mtype
== null then return
861 mpropdef
.bound
= mtype
862 # print "{mpropdef}: {mtype}"
865 redef fun check_signature
(modelbuilder
, nclassdef
)
867 var bound
= self.mpropdef
.bound
869 # Fast case: the bound is not a formal type
870 if not bound
isa MVirtualType then return
872 var mmodule
= nclassdef
.mclassdef
.mmodule
873 var anchor
= nclassdef
.mclassdef
.bound_mtype
875 # Slow case: progress on each resolution until: (i) we loop, or (ii) we found a non formal type
876 var seen
= [self.mpropdef
.mproperty
.mvirtualtype
]
878 if seen
.has
(bound
) then
880 modelbuilder
.error
(self, "Error: circularity of virtual type definition: {seen.join(" -> ")}")
884 var next
= bound
.lookup_bound
(mmodule
, anchor
)
885 if not next
isa MVirtualType then return