From 0bf1b73a30445ef21d73b5de31cf2da6f2a533ee Mon Sep 17 00:00:00 2001 From: Florian Deljarry Date: Thu, 30 Jan 2020 19:59:11 -0500 Subject: [PATCH] modelize_property: Split model build of AAttrPropdef Split the build method of AAttrPropdef Signed-off-by: Florian Deljarry --- src/frontend/serialization_model_phase.nit | 2 - src/modelize/modelize_property.nit | 256 +++++++++++++++++----------- 2 files changed, 159 insertions(+), 99 deletions(-) diff --git a/src/frontend/serialization_model_phase.nit b/src/frontend/serialization_model_phase.nit index 7e9a506..a44833d 100644 --- a/src/frontend/serialization_model_phase.nit +++ b/src/frontend/serialization_model_phase.nit @@ -267,8 +267,6 @@ redef init from_deserializer(v) do abort""" end redef class AAttrPropdef - private fun name: String do return n_id2.text - # Name of this attribute in the serialized format private var serialize_name: String = name is lazy end diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index beb9068..7aeffe8 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -1181,6 +1181,10 @@ redef class AAttrPropdef # Could be through `n_expr`, `n_block` or `is_lazy` var has_value = false + # The name of the attribute + # Note: The name of the attribute is in reality the name of the mreadpropdef + var name: String = n_id2.text is lazy + # The guard associated to a lazy attribute. # Because some engines does not have a working `isset`, # this additional attribute is used to guard the lazy initialization. @@ -1195,48 +1199,14 @@ redef class AAttrPropdef redef fun build_property(modelbuilder, mclassdef) do var mclass = mclassdef.mclass - var nid2 = n_id2 - var name = nid2.text var atabstract = self.get_single_annotation("abstract", modelbuilder) - if atabstract == null then - if not mclass.kind.need_init then - modelbuilder.error(self, "Error: attempt to define attribute `{name}` in the {mclass.kind} `{mclass}`.") - end - var mprop = new MAttribute(mclassdef, "_" + name, self.location, private_visibility) - var mpropdef = new MAttributeDef(mclassdef, mprop, self.location) - self.mpropdef = mpropdef - modelbuilder.mpropdef2npropdef[mpropdef] = self - end + if atabstract == null then build_attribute_property(modelbuilder, mclassdef) - var readname = name - var mreadprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, readname).as(nullable MMethod) - if mreadprop == null then - var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) - mreadprop = new MMethod(mclassdef, readname, self.location, mvisibility) - if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then - mreadprop.is_broken = true - return - end - else - if mreadprop.is_broken then return - if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, true, mreadprop) then return - check_redef_property_visibility(modelbuilder, self.n_visibility, mreadprop) - end - mclassdef.mprop2npropdef[mreadprop] = self - - var attr_mpropdef = mpropdef - if attr_mpropdef != null then - mreadprop.getter_for = attr_mpropdef.mproperty - attr_mpropdef.mproperty.getter = mreadprop - end + # Construction of the read property. If it's not correctly built just return. + if not build_read_property(modelbuilder, mclassdef) then return - var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location) - self.mreadpropdef = mreadpropdef - modelbuilder.mpropdef2npropdef[mreadpropdef] = self - set_doc(mreadpropdef, modelbuilder) - if mpropdef != null then mpropdef.mdoc = mreadpropdef.mdoc if atabstract != null then mreadpropdef.is_abstract = true has_value = n_expr != null or n_block != null @@ -1259,29 +1229,8 @@ redef class AAttrPropdef end end - var atlazy = self.get_single_annotation("lazy", modelbuilder) - var atlateinit = self.get_single_annotation("lateinit", modelbuilder) - if atlazy != null or atlateinit != null then - if atlazy != null and atlateinit != null then - modelbuilder.error(atlazy, "Error: `lazy` incompatible with `lateinit`.") - return - end - if not has_value then - if atlazy != null then - modelbuilder.error(atlazy, "Error: `lazy` attributes need a value.") - else if atlateinit != null then - modelbuilder.error(atlateinit, "Error: `lateinit` attributes need a value.") - end - has_value = true - return - end - is_lazy = true - var mlazyprop = new MAttribute(mclassdef, "lazy _" + name, self.location, none_visibility) - mlazyprop.is_fictive = true - var mlazypropdef = new MAttributeDef(mclassdef, mlazyprop, self.location) - mlazypropdef.is_fictive = true - self.mlazypropdef = mlazypropdef - end + # Construction of the read property. If it's not correctly built just return. + if not build_lazy_property(modelbuilder, mclassdef) then return var atoptional = self.get_single_annotation("optional", modelbuilder) if atoptional != null then @@ -1304,6 +1253,88 @@ redef class AAttrPropdef modelbuilder.advice(self, "attr-in-refinement", "Warning: attributes in refinement need a value or `noautoinit`.") end + # Construction of the read property. If it's not correctly built just return. + if not build_write_property(modelbuilder, mclassdef, false) then return + + if atabstract != null then mwritepropdef.is_abstract = true + + var atautoinit = self.get_single_annotation("autoinit", modelbuilder) + if atautoinit != null then + if has_value then + modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot have an initial value.") + else if not mwritepropdef.is_intro then + modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot be set on redefinitions.") + else if not mclassdef.is_intro then + modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot be used in class refinements.") + else if atabstract == null then + modelbuilder.warning(atautoinit, "useless-autoinit", "Warning: superfluous `autoinit` on attribute.") + end + else if atabstract != null then + # By default, abstract attribute are not autoinit + noinit = true + end + end + + # Build the attribute property + fun build_attribute_property(modelbuilder: ModelBuilder, mclassdef: MClassDef) + do + var mclass = mclassdef.mclass + var attribute_name = "_" + name + + if not mclass.kind.need_init then + modelbuilder.error(self, "Error: attempt to define attribute `{name}` in the {mclass.kind} `{mclass}`.") + end + var mprop = new MAttribute(mclassdef, "_" + name, self.location, private_visibility) + var mpropdef = new MAttributeDef(mclassdef, mprop, self.location) + self.mpropdef = mpropdef + modelbuilder.mpropdef2npropdef[mpropdef] = self + end + + # Build the read method property to get the value of the attribute + # Return `true` if the property was correctly created else return `false`. + # Warning the signature of the property is not set. This step is done by `build_signature`. + fun build_read_property(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool + do + var mclass = mclassdef.mclass + + var readname = name + var mreadprop = modelbuilder.try_get_mproperty_by_name(self, mclassdef, readname).as(nullable MMethod) + if mreadprop == null then + var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) + mreadprop = new MMethod(mclassdef, readname, self.location, mvisibility) + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then + mreadprop.is_broken = true + return false + end + else + if mreadprop.is_broken then return false + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, true, mreadprop) then return false + check_redef_property_visibility(modelbuilder, self.n_visibility, mreadprop) + end + mclassdef.mprop2npropdef[mreadprop] = self + + var attr_mpropdef = mpropdef + if attr_mpropdef != null then + mreadprop.getter_for = attr_mpropdef.mproperty + attr_mpropdef.mproperty.getter = mreadprop + end + + var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location) + self.mreadpropdef = mreadpropdef + modelbuilder.mpropdef2npropdef[mreadpropdef] = self + set_doc(mreadpropdef, modelbuilder) + if mpropdef != null then mpropdef.mdoc = mreadpropdef.mdoc + + return true + end + + # Build the write method property to set the attribute value + # Return `true` if the property was correctly created else return `false`. + # Warning the signature of the property is not set. + fun build_write_property(modelbuilder: ModelBuilder, mclassdef: MClassDef, is_same_visibility: Bool): Bool + do + var mclass = mclassdef.mclass + var writename = name + "=" var atwritable = self.get_single_annotation("writable", modelbuilder) if atwritable != null then @@ -1311,7 +1342,7 @@ redef class AAttrPropdef writename = atwritable.arg_as_id(modelbuilder) or else writename end end - var mwriteprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, writename).as(nullable MMethod) + var mwriteprop = modelbuilder.try_get_mproperty_by_name(self, mclassdef, writename).as(nullable MMethod) var nwkwredef: nullable Token = null if atwritable != null then nwkwredef = atwritable.n_kwredef if mwriteprop == null then @@ -1319,25 +1350,26 @@ redef class AAttrPropdef if atwritable != null then mvisibility = new_property_visibility(modelbuilder, mclassdef, atwritable.n_visibility) else - mvisibility = mreadprop.visibility + mvisibility = mreadpropdef.mproperty.visibility # By default, use protected visibility at most - if mvisibility > protected_visibility then mvisibility = protected_visibility + if mvisibility > protected_visibility and not is_same_visibility then mvisibility = protected_visibility end mwriteprop = new MMethod(mclassdef, writename, self.location, mvisibility) if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then mwriteprop.is_broken = true - return + return false end - mwriteprop.deprecation = mreadprop.deprecation + mwriteprop.deprecation = mreadpropdef.mproperty.deprecation else - if mwriteprop.is_broken then return - if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef or else n_kwredef, true, mwriteprop) then return + if mwriteprop.is_broken then return false + if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef or else n_kwredef, true, mwriteprop) then return false if atwritable != null then check_redef_property_visibility(modelbuilder, atwritable.n_visibility, mwriteprop) end end mclassdef.mprop2npropdef[mwriteprop] = self + var attr_mpropdef = mpropdef if attr_mpropdef != null then mwriteprop.setter_for = attr_mpropdef.mproperty attr_mpropdef.mproperty.setter = mwriteprop @@ -1347,23 +1379,40 @@ redef class AAttrPropdef self.mwritepropdef = mwritepropdef modelbuilder.mpropdef2npropdef[mwritepropdef] = self mwritepropdef.mdoc = mreadpropdef.mdoc - if atabstract != null then mwritepropdef.is_abstract = true - var atautoinit = self.get_single_annotation("autoinit", modelbuilder) - if atautoinit != null then - if has_value then - modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot have an initial value.") - else if not mwritepropdef.is_intro then - modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot be set on redefinitions.") - else if not mclassdef.is_intro then - modelbuilder.error(atautoinit, "Error: `autoinit` attributes cannot be used in class refinements.") - else if atabstract == null then - modelbuilder.warning(atautoinit, "useless-autoinit", "Warning: superfluous `autoinit` on attribute.") + return true + end + + # Build the lazy attribute property + # Return `true` if the property was correctly created else return `false`. + fun build_lazy_property(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool + do + var mclass = mclassdef.mclass + + var atlazy = self.get_single_annotation("lazy", modelbuilder) + var atlateinit = self.get_single_annotation("lateinit", modelbuilder) + if atlazy != null or atlateinit != null then + if atlazy != null and atlateinit != null then + modelbuilder.error(atlazy, "Error: `lazy` incompatible with `lateinit`.") + return false end - else if atabstract != null then - # By default, abstract attribute are not autoinit - noinit = true + if not has_value then + if atlazy != null then + modelbuilder.error(atlazy, "Error: `lazy` attributes need a value.") + else if atlateinit != null then + modelbuilder.error(atlateinit, "Error: `lateinit` attributes need a value.") + end + has_value = true + return false + end + is_lazy = true + var mlazyprop = new MAttribute(mclassdef, "lazy _" + name, self.location, none_visibility) + mlazyprop.is_fictive = true + var mlazypropdef = new MAttributeDef(mclassdef, mlazyprop, self.location) + mlazypropdef.is_fictive = true + self.mlazypropdef = mlazypropdef end + return true end redef fun build_signature(modelbuilder) @@ -1421,23 +1470,9 @@ redef class AAttrPropdef mpropdef.static_mtype = mtype end - do - var msignature = new MSignature(new Array[MParameter], mtype) - mreadpropdef.msignature = msignature - end + build_read_signature - var mwritepropdef = self.mwritepropdef - if mwritepropdef != null then - var mwritetype = mtype - if is_optional then - mwritetype = mwritetype.as_nullable - end - var name: String - name = n_id2.text - var mparameter = new MParameter(name, mwritetype, false) - var msignature = new MSignature([mparameter], null) - mwritepropdef.msignature = msignature - end + if self.mwritepropdef != null then build_write_signature var mlazypropdef = self.mlazypropdef if mlazypropdef != null then @@ -1446,6 +1481,33 @@ redef class AAttrPropdef check_repeated_types(modelbuilder) end + # Build the read method signature + # `except`: mreadpropdef != null + # `expect`: mtype != null + fun build_read_signature + is + expect(mreadpropdef != null and mtype != null) + do + var msignature = new MSignature(new Array[MParameter], mtype) + mreadpropdef.msignature = msignature + end + + # Build the write method signature + # `except`: mwritepropdef != null + # `expect`: mtype != null + fun build_write_signature + is + expect(mwritepropdef != null and mtype != null) + do + var mwritetype = mtype.as(not null) + if is_optional then + mwritetype = mwritetype.as_nullable + end + var mparameter = new MParameter(name, mwritetype, false) + var msignature = new MSignature([mparameter], null) + mwritepropdef.msignature = msignature + end + # Detect the static type from the value assigned to the attribute `self` # # Return the static type if it can be safely inferred. -- 1.7.9.5