The client has 3 steps to do:
collect
to initialize the attributes.propagate
to propagate the variance constraints.print_stats
to print the results.nitc :: DetectVarianceConstraints :: _contravar_classes
The set of generic types found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: _contravar_pt
The set of formal parameters found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: _covar_classes
The set of generic types found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: _covar_pt
The set of formal parameters found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: _cpt_class
Classes by number of formal parametersnitc :: DetectVarianceConstraints :: _exclude_private
Does the collect exclude private properties?nitc :: DetectVarianceConstraints :: _pts
The set of all collected formal parametersnitc :: DetectVarianceConstraints :: collect
Collect all types used in covariant and contravariant positions.nitc :: DetectVarianceConstraints :: contravar_classes
The set of generic types found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: contravar_classes=
The set of generic types found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: contravar_pt
The set of formal parameters found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: contravar_pt=
The set of formal parameters found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: covar_classes
The set of generic types found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: covar_classes=
The set of generic types found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: covar_pt
The set of formal parameters found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: covar_pt=
The set of formal parameters found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: cpt_class=
Classes by number of formal parametersnitc :: DetectVarianceConstraints :: exclude_private
Does the collect exclude private properties?nitc :: DetectVarianceConstraints :: exclude_private=
Does the collect exclude private properties?nitc :: DetectVarianceConstraints :: print_stats
Print the final stats on the screennitc :: DetectVarianceConstraints :: propagate
Propagate the variance constraints oncovar_classes
, covar_pt
, contravar_classes
and contravar_pt
nitc :: DetectVarianceConstraints :: pts
The set of all collected formal parametersnitc :: DetectVarianceConstraints :: pts=
The set of all collected formal parametersnitc $ DetectVarianceConstraints :: SELF
Type of this instance, automatically specialized in every classnitc :: DetectVarianceConstraints :: _contravar_classes
The set of generic types found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: _contravar_pt
The set of formal parameters found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: _covar_classes
The set of generic types found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: _covar_pt
The set of formal parameters found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: _cpt_class
Classes by number of formal parametersnitc :: DetectVarianceConstraints :: _exclude_private
Does the collect exclude private properties?nitc :: DetectVarianceConstraints :: _pts
The set of all collected formal parameterscore :: Object :: class_factory
Implementation used byget_class
to create the specific class.
nitc :: DetectVarianceConstraints :: collect
Collect all types used in covariant and contravariant positions.nitc :: DetectVarianceConstraints :: contravar_classes
The set of generic types found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: contravar_classes=
The set of generic types found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: contravar_pt
The set of formal parameters found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: contravar_pt=
The set of formal parameters found in a contravariant (and invariant) positionnitc :: DetectVarianceConstraints :: covar_classes
The set of generic types found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: covar_classes=
The set of generic types found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: covar_pt
The set of formal parameters found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: covar_pt=
The set of formal parameters found in a covariant (and invariant) positionnitc :: DetectVarianceConstraints :: cpt_class=
Classes by number of formal parameterscore :: Object :: defaultinit
nitc :: DetectVarianceConstraints :: exclude_private
Does the collect exclude private properties?nitc :: DetectVarianceConstraints :: exclude_private=
Does the collect exclude private properties?core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
core :: Object :: native_class_name
The class name of the object in CString format.core :: Object :: output_class_name
Display class name on stdout (debug only).nitc :: DetectVarianceConstraints :: print_stats
Print the final stats on the screennitc :: DetectVarianceConstraints :: propagate
Propagate the variance constraints oncovar_classes
, covar_pt
, contravar_classes
and contravar_pt
nitc :: DetectVarianceConstraints :: pts
The set of all collected formal parametersnitc :: DetectVarianceConstraints :: pts=
The set of all collected formal parameters
# A specific analysis that detects the variance constraints of formal parameters.
#
# The client has 3 steps to do:
#
# * call `collect` to initialize the attributes.
# * call `propagate` to propagate the variance constraints.
# * call `print_stats` to print the results.
class DetectVarianceConstraints
# Collect all types used in covariant and contravariant positions.
#
# The collect visits all classes and properties of `mainmodule` and its imported modules.
#
# After the visit, the attributes of `self` are filled.
fun collect(mainmodule: MModule)
do
for m in mainmodule.in_importation.greaters do
for cd in m.mclassdefs do
if cd.is_intro then
pts.add_all(cd.mclass.mparameters)
var a = cd.mclass.arity
if a == 0 then
cpt_class.inc("non generic")
else if a == 1 then
cpt_class.inc("with 1 formal type parameter")
else
cpt_class.inc("with {a} formal type parameters")
end
end
for t in cd.supertypes do
# Supertype (covariant)
if t.need_anchor then covar_classes.add(t)
end
for pd in cd.mpropdefs do
if exclude_private and pd.mproperty.visibility <= private_visibility then continue
if pd isa MMethodDef then
# Parameters (contravariant)
for p in pd.msignature.mparameters do
var t = p.mtype.undecorate
if not t.need_anchor then
# OK
else if t isa MParameterType then
contravar_pt.add(t)
else if t isa MVirtualType then
# TODO?
else if t isa MClassType then
contravar_classes.add(t)
else
abort
end
end
# Return (covariant)
var t = pd.msignature.return_mtype
if t != null and t.need_anchor then
t = t.undecorate
if t isa MParameterType then
covar_pt.add(t)
else if t isa MVirtualType then
# TODO?
else if t isa MClassType then
covar_classes.add(t)
else
abort
end
end
else if pd isa MAttributeDef then
# Attribute (invariant)
var t = pd.static_mtype
if t != null and t.need_anchor then
t = t.undecorate
if t isa MParameterType then
covar_pt.add t
contravar_pt.add t
else if t isa MVirtualType then
# TODO?
else if t isa MClassType then
covar_classes.add(t)
contravar_classes.add(t)
else
abort
end
end
else if pd isa MVirtualTypeDef then
# Virtual type bound (covariant)
var t = pd.bound
if t != null and t.need_anchor then
t = t.undecorate
if t isa MParameterType then
covar_pt.add t
else if t isa MVirtualType then
# TODO?
else if t isa MClassType then
covar_classes.add(t)
else
abort
end
end
end
end
end
end
end
# The set of all collected formal parameters
var pts = new HashSet[MParameterType]
# The set of generic types found in a covariant (and invariant) position
var covar_classes = new HashSet[MClassType]
# The set of formal parameters found in a covariant (and invariant) position
var covar_pt = new HashSet[MParameterType]
# The set of generic types found in a contravariant (and invariant) position
var contravar_classes = new HashSet[MClassType]
# The set of formal parameters found in a contravariant (and invariant) position
var contravar_pt = new HashSet[MParameterType]
# Classes by number of formal parameters
var cpt_class = new Counter[String]
# Does the collect exclude private properties?
# Default is `false`
var exclude_private = false
# Propagate the variance constraints on `covar_classes`, `covar_pt`, `contravar_classes` and `contravar_pt`
#
# The algorithm uses a fixed-point approach on the covariance/contravariance rules.
fun propagate
do
# Classes to add to the `covar_classes` set at the end of an iteration
var new_covar = new Array[MClassType]
# Classes to add to the `contravar_classes` set at the end of an iteration
var new_contravar = new Array[MClassType]
# Does a modification occurred, so that another iteration is needed?
var dirty = true
# Total number of iterations
var cpt = 0
while dirty do
cpt += 1
dirty = false
new_covar.clear
new_contravar.clear
# Process the generic types in a covariant position
for c in covar_classes do for i in [0..c.mclass.arity[ do
# The type used in the argument
var ta = c.arguments[i].undecorate
# The associated formal parameter
var tp = c.mclass.mparameters[i]
if not ta.need_anchor then
# Nothing to do
else if ta isa MParameterType then
# COVAR * COVAR = COVAR
if covar_pt.has(tp) and not covar_pt.has(ta) then
covar_pt.add(ta)
dirty = true
end
# COVAR * CONTRAVAR = CONTRAVAR
if contravar_pt.has(tp) and not contravar_pt.has(ta) then
contravar_pt.add(ta)
dirty = true
end
else if ta isa MVirtualType then
# TODO?
else if ta isa MClassType then
# COVAR * COVAR = COVAR
if covar_pt.has(tp) and not covar_classes.has(ta) then
new_covar.add ta
dirty = true
end
# COVAR * CONTRAVAR = CONTRAVAR
if contravar_pt.has(tp) and not contravar_classes.has(ta) then
new_contravar.add ta
dirty = true
end
end
end
# Process the generic types in a contravariant position
for c in contravar_classes do for i in [0..c.mclass.arity[ do
# The type used in the argument
var ta = c.arguments[i].undecorate
# The associated formal parameter
var tp = c.mclass.mparameters[i]
if not ta.need_anchor then
# Nothing to do
else if ta isa MParameterType then
# CONTRAVAR * CONTRAVAR = COVAR
if contravar_pt.has(tp) and not covar_pt.has(ta) then
covar_pt.add(ta)
dirty = true
end
# CONTRAVAR * COVAR = CONTRAVAR
if covar_pt.has(tp) and not contravar_pt.has(ta) then
contravar_pt.add(ta)
dirty = true
end
else if ta isa MVirtualType then
# TODO?
else if ta isa MClassType then
# CONTRAVAR * CONTRAVAR = COVAR
if contravar_pt.has(tp) and not covar_classes.has(ta) then
new_covar.add ta
dirty = true
end
# CONTRAVAR * COVAR = CONTRAVAR
if covar_pt.has(tp) and not contravar_classes.has(ta) then
new_contravar.add ta
dirty = true
end
end
end
covar_classes.add_all(new_covar)
contravar_classes.add_all(new_contravar)
end
end
# Print the final stats on the screen
fun print_stats
do
var nb_cov = 0
var nb_con = 0
var nb_inv = 0
var nb_biv = 0
for pt in pts do
if covar_pt.has(pt) then
if contravar_pt.has(pt) then
nb_inv += 1
else
nb_cov += 1
#print "covar: {pt.full_name}"
end
else
if contravar_pt.has(pt) then
nb_con += 1
#print "contravar: {pt.full_name}"
else
nb_biv += 1
#print "bivar: {pt.full_name}"
end
end
end
print " covariants: {nb_cov} ({div(nb_cov*100, pts.length)}%)"
print " contravariants: {nb_con} ({div(nb_con*100, pts.length)}%)"
print " bivariants: {nb_biv} ({div(nb_biv*100, pts.length)}%)"
print " invariants: {nb_inv} ({div(nb_inv*100, pts.length)}%)"
print " total: {pts.length}"
end
end
src/metrics/detect_variance_constraints.nit:79,1--333,3