# The analyzed property
var mpropdef: nullable MPropDef
- var selfvariable: Variable = new Variable("self")
+ var selfvariable = new Variable("self")
# Is `self` use restricted?
# * no explicit `self`
return sup
end
+ # Special verification on != and == for null
+ # Return true
+ fun null_test(anode: ABinopExpr)
+ do
+ var mtype = anode.n_expr.mtype
+ var mtype2 = anode.n_expr2.mtype
+
+ if mtype == null or mtype2 == null then return
+
+ if not mtype2 isa MNullType then return
+
+ # Check of useless null
+ if not mtype isa MNullableType then
+ if not anchor_to(mtype) isa MNullableType then
+ modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}`.")
+ end
+ return
+ end
+
+ # Check for type adaptation
+ var variable = anode.n_expr.its_variable
+ if variable == null then return
+
+ if anode isa AEqExpr then
+ anode.after_flow_context.when_true.set_var(variable, mtype2)
+ anode.after_flow_context.when_false.set_var(variable, mtype.mtype)
+ else if anode isa ANeExpr then
+ anode.after_flow_context.when_false.set_var(variable, mtype2)
+ anode.after_flow_context.when_true.set_var(variable, mtype.mtype)
+ else
+ abort
+ end
+ end
+
fun try_get_mproperty_by_name2(anode: ANode, mtype: MType, name: String): nullable MProperty
do
return self.modelbuilder.try_get_mproperty_by_name2(anode, mmodule, mtype, name)
fun merge_types(node: ANode, col: Array[nullable MType]): nullable MType
do
if col.length == 1 then return col.first
- var res = new Array[nullable MType]
for t1 in col do
if t1 == null then continue # return null
var found = true
redef class FlowContext
# Store changes of types because of type evolution
- private var vars: HashMap[Variable, nullable MType] = new HashMap[Variable, nullable MType]
- private var cache: HashMap[Variable, nullable Array[nullable MType]] = new HashMap[Variable, nullable Array[nullable MType]]
+ private var vars = new HashMap[Variable, nullable MType]
+ private var cache = new HashMap[Variable, nullable Array[nullable MType]]
# Adapt the variable to a static type
# Warning1: do not modify vars directly.
do
var nexpr = self.n_expr
if nexpr != null then
- var mtype = v.visit_expr(nexpr)
+ v.visit_expr(nexpr)
end
self.is_typed = true
end
do
var nexpr = self.n_expr
if nexpr != null then
- var mtype = v.visit_expr(nexpr)
+ v.visit_expr(nexpr)
end
self.is_typed = true
end
var ret_type = v.mpropdef.as(MMethodDef).msignature.return_mtype
if nexpr != null then
if ret_type != null then
- var mtype = v.visit_expr_subtype(nexpr, ret_type)
+ v.visit_expr_subtype(nexpr, ret_type)
else
- var mtype = v.visit_expr(nexpr)
+ v.visit_expr(nexpr)
v.error(self, "Error: Return with value in a procedure.")
end
else if ret_type != null then
var variable = self.n_expr.its_variable
if variable != null then
- var orig = self.n_expr.mtype
- var from = if orig != null then orig.to_s else "invalid"
- var to = if mtype != null then mtype.to_s else "invalid"
+ #var orig = self.n_expr.mtype
+ #var from = if orig != null then orig.to_s else "invalid"
+ #var to = if mtype != null then mtype.to_s else "invalid"
#debug("adapt {variable}: {from} -> {to}")
self.after_flow_context.when_true.set_var(variable, mtype)
end
redef fun accept_typing(v)
do
super
-
- var variable = self.n_expr.its_variable
- if variable == null then return
- var mtype = self.n_expr2.mtype
- if not mtype isa MNullType then return
- var vartype = v.get_variable(self, variable)
- if not vartype isa MNullableType then return
- self.after_flow_context.when_true.set_var(variable, mtype)
- self.after_flow_context.when_false.set_var(variable, vartype.mtype)
- #debug("adapt {variable}:{vartype} ; true->{mtype} false->{vartype.mtype}")
+ v.null_test(self)
end
end
redef class ANeExpr
redef fun accept_typing(v)
do
super
-
- var variable = self.n_expr.its_variable
- if variable == null then return
- var mtype = self.n_expr2.mtype
- if not mtype isa MNullType then return
- var vartype = v.get_variable(self, variable)
- if not vartype isa MNullableType then return
- self.after_flow_context.when_false.set_var(variable, mtype)
- self.after_flow_context.when_true.set_var(variable, vartype.mtype)
- #debug("adapt {variable}:{vartype} ; true->{vartype.mtype} false->{mtype}")
+ v.null_test(self)
end
end
redef class ALtExpr