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 for nclosure
in self.n_closure_decls
do
308 if not nclosure
.n_signature
.visit_signature
(modelbuilder
, nclassdef
) then return false
311 self.is_visited
= true
315 # Build a visited signature
316 fun build_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef): nullable MSignature
318 if param_names
.length
!= param_types
.length
then
319 # Some parameters are typed, other parameters are not typed.
320 modelbuilder
.error
(self.n_params
[param_types
.length
], "Error: Untyped parameter `{param_names[param_types.length]}'.")
324 var mparameters
= new Array[MParameter]
325 for i
in [0..param_names
.length
[ do
326 var mparameter
= new MParameter(param_names
[i
], param_types
[i
], i
== vararg_rank
)
327 self.n_params
[i
].mparameter
= mparameter
328 mparameters
.add
(mparameter
)
331 var msignature
= new MSignature(mparameters
, ret_type
)
337 # The associated mparameter if any
338 var mparameter
: nullable MParameter = null
341 redef class AMethPropdef
342 redef type MPROPDEF: MMethodDef
344 redef fun build_property
(modelbuilder
, nclassdef
)
346 var is_init
= self isa AInitPropdef
347 var mclassdef
= nclassdef
.mclassdef
.as(not null)
349 var amethodid
= self.n_methid
351 if amethodid
== null then
352 if self isa AMainMethPropdef then
355 else if self isa AConcreteInitPropdef then
357 name_node
= self.n_kwinit
358 else if self isa AExternInitPropdef then
360 name_node
= self.n_kwnew
364 else if amethodid
isa AIdMethid then
365 name
= amethodid
.n_id
.text
366 name_node
= amethodid
368 # operator, bracket or assign
369 name
= amethodid
.collect_text
370 name_node
= amethodid
372 if name
== "-" and self.n_signature
.n_params
.length
== 0 then
377 var mprop
: nullable MMethod = null
378 if not is_init
or n_kwredef
!= null then mprop
= modelbuilder
.try_get_mproperty_by_name
(name_node
, mclassdef
, name
).as(nullable MMethod)
379 if mprop
== null then
380 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
381 mprop
= new MMethod(mclassdef
, name
, mvisibility
)
382 mprop
.is_init
= is_init
383 mprop
.is_new
= self isa AExternInitPropdef
384 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, false, mprop
) then return
386 if n_kwredef
== null then
387 if self isa AMainMethPropdef then
390 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, true, mprop
) then return
393 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
395 nclassdef
.mprop2npropdef
[mprop
] = self
397 var mpropdef
= new MMethodDef(mclassdef
, mprop
, self.location
)
399 self.mpropdef
= mpropdef
400 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
401 if mpropdef
.is_intro
then
402 modelbuilder
.toolcontext
.info
("{mpropdef} introduces new method {mprop.full_name}", 3)
404 modelbuilder
.toolcontext
.info
("{mpropdef} redefines method {mprop.full_name}", 3)
408 redef fun build_signature
(modelbuilder
, nclassdef
)
410 var mpropdef
= self.mpropdef
411 if mpropdef
== null then return # Error thus skiped
412 var mmodule
= mpropdef
.mclassdef
.mmodule
413 var nsig
= self.n_signature
415 # Retrieve info from the signature AST
416 var param_names
= new Array[String] # Names of parameters from the AST
417 var param_types
= new Array[MType] # Types of parameters from the AST
419 var ret_type
: nullable MType = null # Return type from the AST
421 if not nsig
.visit_signature
(modelbuilder
, nclassdef
) then return
422 param_names
= nsig
.param_names
423 param_types
= nsig
.param_types
424 vararg_rank
= nsig
.vararg_rank
425 ret_type
= nsig
.ret_type
428 # Look for some signature to inherit
429 # FIXME: do not inherit from the intro, but from the most specific
430 var msignature
: nullable MSignature = null
431 if not mpropdef
.is_intro
then
432 msignature
= mpropdef
.mproperty
.intro
.msignature
433 if msignature
== null then return # Skip error
435 # Check inherited signature arity
436 if param_names
.length
!= msignature
.arity
then
438 if nsig
!= null then node
= nsig
else node
= self
439 modelbuilder
.error
(node
, "Redef error: {mpropdef} redefines {mpropdef.mproperty.intro} with {param_names.length} parameter(s), {msignature.arity} expected. Signature is {mpropdef}{msignature}")
442 else if mpropdef
.mproperty
.is_init
then
443 # FIXME UGLY: inherit signature from a super-constructor
444 for msupertype
in nclassdef
.mclassdef
.supertypes
do
445 msupertype
= msupertype
.anchor_to
(mmodule
, nclassdef
.mclassdef
.bound_mtype
)
446 var candidate
= modelbuilder
.try_get_mproperty_by_name2
(self, mmodule
, msupertype
, mpropdef
.mproperty
.name
)
447 if candidate
!= null then
448 if msignature
== null then
449 msignature
= candidate
.intro
.as(MMethodDef).msignature
456 # Inherit the signature
457 if msignature
!= null and param_names
.length
!= param_types
.length
and param_names
.length
== msignature
.arity
and param_types
.length
== 0 then
458 # Parameters are untyped, thus inherit them
459 param_types
= new Array[MType]
460 for mparameter
in msignature
.mparameters
do
461 param_types
.add
(mparameter
.mtype
)
463 vararg_rank
= msignature
.vararg_rank
465 if msignature
!= null and ret_type
== null then
466 ret_type
= msignature
.return_mtype
469 if param_names
.length
!= param_types
.length
then
470 # Some parameters are typed, other parameters are not typed.
471 modelbuilder
.error
(nsig
.n_params
[param_types
.length
], "Error: Untyped parameter `{param_names[param_types.length]}'.")
475 var mparameters
= new Array[MParameter]
476 for i
in [0..param_names
.length
[ do
477 var mparameter
= new MParameter(param_names
[i
], param_types
[i
], i
== vararg_rank
)
478 if nsig
!= null then nsig
.n_params
[i
].mparameter
= mparameter
479 mparameters
.add
(mparameter
)
482 msignature
= new MSignature(mparameters
, ret_type
)
483 mpropdef
.msignature
= msignature
484 mpropdef
.is_abstract
= self isa ADeferredMethPropdef
487 for nclosure
in nsig
.n_closure_decls
do
488 var clos_signature
= nclosure
.n_signature
.build_signature
(modelbuilder
, nclassdef
)
489 if clos_signature
== null then return
490 var mparameter
= new MParameter(nclosure
.n_id
.text
, clos_signature
, false)
491 msignature
.mclosures
.add
(mparameter
)
497 redef fun check_signature
(modelbuilder
, nclassdef
)
499 var mpropdef
= self.mpropdef
500 if mpropdef
== null then return # Error thus skiped
501 var mmodule
= mpropdef
.mclassdef
.mmodule
502 var nsig
= self.n_signature
503 var mysignature
= self.mpropdef
.msignature
504 if mysignature
== null then return # Error thus skiped
506 # Lookup for signature in the precursor
507 # FIXME all precursors should be considered
508 if not mpropdef
.is_intro
then
509 var msignature
= mpropdef
.mproperty
.intro
.msignature
510 if msignature
== null then return
512 var precursor_ret_type
= msignature
.return_mtype
513 var ret_type
= mysignature
.return_mtype
514 if ret_type
!= null and precursor_ret_type
== null then
515 modelbuilder
.error
(nsig
.n_type
.as(not null), "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
519 if mysignature
.arity
> 0 then
520 # Check parameters types
521 for i
in [0..mysignature
.arity
[ do
522 var myt
= mysignature
.mparameters
[i
].mtype
523 var prt
= msignature
.mparameters
[i
].mtype
524 if not myt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, prt
) and
525 not prt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, myt
) then
526 modelbuilder
.error
(nsig
.n_params
[i
], "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
530 if precursor_ret_type
!= null then
531 if ret_type
== null then
532 # Inherit the return type
533 ret_type
= precursor_ret_type
534 else if not ret_type
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, precursor_ret_type
) then
535 modelbuilder
.error
(nsig
.n_type
.as(not null), "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type}.")
542 redef class AAttrPropdef
543 redef type MPROPDEF: MAttributeDef
545 # The associated getter (read accessor) if any
546 var mreadpropdef
: nullable MMethodDef writable
547 # The associated setter (write accessor) if any
548 var mwritepropdef
: nullable MMethodDef writable
549 redef fun build_property
(modelbuilder
, nclassdef
)
551 var mclassdef
= nclassdef
.mclassdef
.as(not null)
552 var mclass
= mclassdef
.mclass
555 if self.n_id
!= null then
556 name
= self.n_id
.text
558 name
= self.n_id2
.text
561 if mclass
.kind
== interface_kind
or mclassdef
.mclass
.kind
== enum_kind
then
562 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the interface {mclass}.")
563 else if mclass
.kind
== enum_kind
then
564 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the enum class {mclass}.")
565 else if mclass
.kind
== extern_kind
then
566 modelbuilder
.error
(self, "Error: Attempt to define attribute {name} in the extern class {mclass}.")
571 # Old attribute style
572 var mprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, name
)
573 if mprop
== null then
574 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
575 mprop
= new MAttribute(mclassdef
, name
, mvisibility
)
576 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, false, mprop
) then return
578 assert mprop
isa MAttribute
579 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
580 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, true, mprop
) then return
582 nclassdef
.mprop2npropdef
[mprop
] = self
584 var mpropdef
= new MAttributeDef(mclassdef
, mprop
, self.location
)
585 self.mpropdef
= mpropdef
586 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
588 var nreadable
= self.n_readable
589 if nreadable
!= null then
590 var readname
= name
.substring_from
(1)
591 var mreadprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, readname
).as(nullable MMethod)
592 if mreadprop
== null then
593 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nreadable
.n_visibility
)
594 mreadprop
= new MMethod(mclassdef
, readname
, mvisibility
)
595 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nreadable
.n_kwredef
, false, mreadprop
) then return
597 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nreadable
.n_kwredef
, true, mreadprop
) then return
598 check_redef_property_visibility
(modelbuilder
, nclassdef
, nreadable
.n_visibility
, mreadprop
)
600 nclassdef
.mprop2npropdef
[mreadprop
] = self
602 var mreadpropdef
= new MMethodDef(mclassdef
, mreadprop
, self.location
)
603 self.mreadpropdef
= mreadpropdef
604 modelbuilder
.mpropdef2npropdef
[mreadpropdef
] = self
607 var nwritable
= self.n_writable
608 if nwritable
!= null then
609 var writename
= name
.substring_from
(1) + "="
610 var mwriteprop
= modelbuilder
.try_get_mproperty_by_name
(nid
, mclassdef
, writename
).as(nullable MMethod)
611 if mwriteprop
== null then
612 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
)
613 mwriteprop
= new MMethod(mclassdef
, writename
, mvisibility
)
614 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwritable
.n_kwredef
, false, mwriteprop
) then return
616 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwritable
.n_kwredef
, true, mwriteprop
) then return
617 check_redef_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
, mwriteprop
)
619 nclassdef
.mprop2npropdef
[mwriteprop
] = self
621 var mwritepropdef
= new MMethodDef(mclassdef
, mwriteprop
, self.location
)
622 self.mwritepropdef
= mwritepropdef
623 modelbuilder
.mpropdef2npropdef
[mwritepropdef
] = self
626 # New attribute style
627 var nid2
= self.n_id2
.as(not null)
628 var mprop
= new MAttribute(mclassdef
, "@" + name
, none_visibility
)
629 var mpropdef
= new MAttributeDef(mclassdef
, mprop
, self.location
)
630 self.mpropdef
= mpropdef
631 modelbuilder
.mpropdef2npropdef
[mpropdef
] = self
634 var mreadprop
= modelbuilder
.try_get_mproperty_by_name
(nid2
, mclassdef
, readname
).as(nullable MMethod)
635 if mreadprop
== null then
636 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
637 mreadprop
= new MMethod(mclassdef
, readname
, mvisibility
)
638 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, false, mreadprop
) then return
640 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, n_kwredef
, true, mreadprop
) then return
641 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mreadprop
)
643 nclassdef
.mprop2npropdef
[mreadprop
] = self
645 var mreadpropdef
= new MMethodDef(mclassdef
, mreadprop
, self.location
)
646 self.mreadpropdef
= mreadpropdef
647 modelbuilder
.mpropdef2npropdef
[mreadpropdef
] = self
649 var writename
= name
+ "="
650 var nwritable
= self.n_writable
651 var mwriteprop
= modelbuilder
.try_get_mproperty_by_name
(nid2
, mclassdef
, writename
).as(nullable MMethod)
652 var nwkwredef
: nullable Token = null
653 if nwritable
!= null then nwkwredef
= nwritable
.n_kwredef
654 if mwriteprop
== null then
656 if nwritable
!= null then
657 mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
)
659 mvisibility
= private_visibility
661 mwriteprop
= new MMethod(mclassdef
, writename
, mvisibility
)
662 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwkwredef
, false, mwriteprop
) then return
664 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, nwkwredef
, true, mwriteprop
) then return
665 if nwritable
!= null then
666 check_redef_property_visibility
(modelbuilder
, nclassdef
, nwritable
.n_visibility
, mwriteprop
)
669 nclassdef
.mprop2npropdef
[mwriteprop
] = self
671 var mwritepropdef
= new MMethodDef(mclassdef
, mwriteprop
, self.location
)
672 self.mwritepropdef
= mwritepropdef
673 modelbuilder
.mpropdef2npropdef
[mwritepropdef
] = self
677 redef fun build_signature
(modelbuilder
, nclassdef
)
679 var mpropdef
= self.mpropdef
680 if mpropdef
== null then return # Error thus skiped
681 var mmodule
= mpropdef
.mclassdef
.mmodule
682 var mtype
: nullable MType = null
684 var ntype
= self.n_type
685 if ntype
!= null then
686 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
687 if mtype
== null then return
690 var nexpr
= self.n_expr
691 if mtype
== null then
692 if nexpr
!= null then
693 if nexpr
isa ANewExpr then
694 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, nexpr
.n_type
)
695 else if nexpr
isa AIntExpr then
696 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Int")
697 if cla
!= null then mtype
= cla
.mclass_type
698 else if nexpr
isa AFloatExpr then
699 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Float")
700 if cla
!= null then mtype
= cla
.mclass_type
701 else if nexpr
isa ACharExpr then
702 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Char")
703 if cla
!= null then mtype
= cla
.mclass_type
704 else if nexpr
isa ABoolExpr then
705 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "Bool")
706 if cla
!= null then mtype
= cla
.mclass_type
707 else if nexpr
isa ASuperstringExpr then
708 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "String")
709 if cla
!= null then mtype
= cla
.mclass_type
710 else if nexpr
isa AStringFormExpr then
711 var cla
= modelbuilder
.try_get_mclass_by_name
(nexpr
, mmodule
, "String")
712 if cla
!= null then mtype
= cla
.mclass_type
714 modelbuilder
.error
(self, "Error: Untyped attribute {mpropdef}. Implicit typing allowed only for literals and new.")
718 modelbuilder
.error
(self, "Error: Untyped attribute {mpropdef}")
722 if nexpr
isa ANewExpr then
723 var xmtype
= modelbuilder
.resolve_mtype
(nclassdef
, nexpr
.n_type
)
724 if xmtype
== mtype
and modelbuilder
.toolcontext
.opt_warn
.value
>= 2 then
725 modelbuilder
.warning
(ntype
, "Warning: useless type definition")
730 if mtype
== null then return
732 mpropdef
.static_mtype
= mtype
734 var mreadpropdef
= self.mreadpropdef
735 if mreadpropdef
!= null then
736 var msignature
= new MSignature(new Array[MParameter], mtype
)
737 mreadpropdef
.msignature
= msignature
740 var msritepropdef
= self.mwritepropdef
741 if mwritepropdef
!= null then
744 name
= n_id
.text
.substring_from
(1)
748 var mparameter
= new MParameter(name
, mtype
, false)
749 var msignature
= new MSignature([mparameter
], null)
750 mwritepropdef
.msignature
= msignature
754 redef fun check_signature
(modelbuilder
, nclassdef
)
756 var mpropdef
= self.mpropdef
757 if mpropdef
== null then return # Error thus skiped
758 var mmodule
= mpropdef
.mclassdef
.mmodule
759 var ntype
= self.n_type
760 var mtype
= self.mpropdef
.static_mtype
761 if mtype
== null then return # Error thus skiped
763 # Lookup for signature in the precursor
764 # FIXME all precursors should be considered
765 if not mpropdef
.is_intro
then
766 var precursor_type
= mpropdef
.mproperty
.intro
.static_mtype
767 if precursor_type
== null then return
769 if mtype
!= precursor_type
then
770 modelbuilder
.error
(ntype
.as(not null), "Redef Error: Wrong static type. found {mtype}, expected {precursor_type}.")
775 # Check getter and setter
776 var meth
= self.mreadpropdef
777 if meth
!= null then self.check_method_signature
(modelbuilder
, nclassdef
, meth
)
778 meth
= self.mwritepropdef
779 if meth
!= null then self.check_method_signature
(modelbuilder
, nclassdef
, meth
)
782 private fun check_method_signature
(modelbuilder
: ModelBuilder, nclassdef
: AClassdef, mpropdef
: MMethodDef)
784 var mmodule
= mpropdef
.mclassdef
.mmodule
785 var nsig
= self.n_type
786 var mysignature
= mpropdef
.msignature
787 if mysignature
== null then return # Error thus skiped
789 # Lookup for signature in the precursor
790 # FIXME all precursors should be considered
791 if not mpropdef
.is_intro
then
792 var msignature
= mpropdef
.mproperty
.intro
.msignature
793 if msignature
== null then return
795 if mysignature
.arity
!= msignature
.arity
then
797 if nsig
!= null then node
= nsig
else node
= self
798 modelbuilder
.error
(node
, "Redef Error: {mysignature.arity} parameters found, {msignature.arity} expected. Signature is {mpropdef}{msignature}")
801 var precursor_ret_type
= msignature
.return_mtype
802 var ret_type
= mysignature
.return_mtype
803 if ret_type
!= null and precursor_ret_type
== null then
805 if nsig
!= null then node
= nsig
else node
= self
806 modelbuilder
.error
(node
, "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
810 if mysignature
.arity
> 0 then
811 # Check parameters types
812 for i
in [0..mysignature
.arity
[ do
813 var myt
= mysignature
.mparameters
[i
].mtype
814 var prt
= msignature
.mparameters
[i
].mtype
815 if not myt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, prt
) and
816 not prt
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, myt
) then
818 if nsig
!= null then node
= nsig
else node
= self
819 modelbuilder
.error
(node
, "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
823 if precursor_ret_type
!= null then
824 if ret_type
== null then
825 # Inherit the return type
826 ret_type
= precursor_ret_type
827 else if not ret_type
.is_subtype
(mmodule
, nclassdef
.mclassdef
.bound_mtype
, precursor_ret_type
) then
829 if nsig
!= null then node
= nsig
else node
= self
830 modelbuilder
.error
(node
, "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type}.")
837 redef class ATypePropdef
838 redef type MPROPDEF: MVirtualTypeDef
840 redef fun build_property
(modelbuilder
, nclassdef
)
842 var mclassdef
= nclassdef
.mclassdef
.as(not null)
843 var name
= self.n_id
.text
844 var mprop
= modelbuilder
.try_get_mproperty_by_name
(self.n_id
, mclassdef
, name
)
845 if mprop
== null then
846 var mvisibility
= new_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
)
847 mprop
= new MVirtualTypeProp(mclassdef
, name
, mvisibility
)
848 for c
in name
do if c
>= 'a' and c
<= 'z' then
849 modelbuilder
.warning
(n_id
, "Warning: lowercase in the virtual type {name}")
852 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, false, mprop
) then return
854 if not self.check_redef_keyword
(modelbuilder
, nclassdef
, self.n_kwredef
, true, mprop
) then return
855 assert mprop
isa MVirtualTypeProp
856 check_redef_property_visibility
(modelbuilder
, nclassdef
, self.n_visibility
, mprop
)
858 nclassdef
.mprop2npropdef
[mprop
] = self
860 var mpropdef
= new MVirtualTypeDef(mclassdef
, mprop
, self.location
)
861 self.mpropdef
= mpropdef
864 redef fun build_signature
(modelbuilder
, nclassdef
)
866 var mpropdef
= self.mpropdef
867 if mpropdef
== null then return # Error thus skiped
868 var mmodule
= mpropdef
.mclassdef
.mmodule
869 var mtype
: nullable MType = null
871 var ntype
= self.n_type
872 mtype
= modelbuilder
.resolve_mtype
(nclassdef
, ntype
)
873 if mtype
== null then return
875 mpropdef
.bound
= mtype
876 # print "{mpropdef}: {mtype}"
879 redef fun check_signature
(modelbuilder
, nclassdef
)
881 var bound
= self.mpropdef
.bound
883 # Fast case: the bound is not a formal type
884 if not bound
isa MVirtualType then return
886 var mmodule
= nclassdef
.mclassdef
.mmodule
887 var anchor
= nclassdef
.mclassdef
.bound_mtype
889 # Slow case: progress on each resolution until: (i) we loop, or (ii) we found a non formal type
890 var seen
= [self.mpropdef
.mproperty
.mvirtualtype
]
892 if seen
.has
(bound
) then
894 modelbuilder
.error
(self, "Error: circularity of virtual type definition: {seen.join(" -> ")}")
898 var next
= bound
.lookup_bound
(mmodule
, anchor
)
899 if not next
isa MVirtualType then return