Skip to content

Commit

Permalink
modelize_property: Split model build of AAttrPropdef
Browse files Browse the repository at this point in the history
Split the build method of AAttrPropdef

Signed-off-by: Florian Deljarry <[email protected]>
  • Loading branch information
Delja committed Aug 16, 2020
1 parent 22fd41c commit f6e2314
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 99 deletions.
2 changes: 0 additions & 2 deletions src/frontend/serialization_model_phase.nit
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
256 changes: 159 additions & 97 deletions src/modelize/modelize_property.nit
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand All @@ -1304,40 +1253,123 @@ 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
if not atwritable.n_args.is_empty then
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
var mvisibility
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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down

0 comments on commit f6e2314

Please sign in to comment.