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)
end
var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
+ if name == "new" and mproperty == null then
+ name = "init"
+ mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
+ end
+
if mproperty == null then
#self.modelbuilder.error(node, "Type error: property {name} not found in {unsafe_type} (ie {recvtype})")
if recv_is_self then
self.visit_expr_subtype(args[j], paramtype)
end
if vararg_rank >= 0 then
- var varargs = new Array[AExpr]
var paramtype = msignature.mparameters[vararg_rank].mtype
- for j in [vararg_rank..vararg_rank+vararg_decl] do
- varargs.add(args[j])
- self.visit_expr_subtype(args[j], paramtype)
+ var first = args[vararg_rank]
+ if vararg_decl == 0 and first isa AVarargExpr then
+ var mclass = get_mclass(node, "Array")
+ if mclass == null then return false # Forward error
+ var array_mtype = mclass.get_mtype([paramtype])
+ self.visit_expr_subtype(first.n_expr, array_mtype)
+ first.mtype = first.n_expr.mtype
+ else
+ for j in [vararg_rank..vararg_rank+vararg_decl] do
+ self.visit_expr_subtype(args[j], paramtype)
+ end
end
end
return true
var method_key: nullable CallSite
var method_finish: nullable CallSite
+ var method_lt: nullable CallSite
+ var method_successor: nullable CallSite
+
private fun do_type_iterator(v: TypeVisitor, mtype: MType)
do
if mtype isa MNullType then
end
self.method_key = keydef
end
+
+ if self.variables.length == 1 and n_expr isa ARangeExpr then
+ var variable = variables.first
+ var vtype = variable.declared_type.as(not null)
+
+ if n_expr isa AOrangeExpr then
+ self.method_lt = v.get_method(self, vtype, "<", false)
+ else
+ self.method_lt = v.get_method(self, vtype, "<=", false)
+ end
+
+ self.method_successor = v.get_method(self, vtype, "successor", false)
+ end
end
redef fun accept_typing(v)
end
end
-redef class AProxyExpr
+redef class AParExpr
+ redef fun accept_typing(v)
+ do
+ self.mtype = v.visit_expr(self.n_expr)
+ end
+end
+
+redef class AOnceExpr
redef fun accept_typing(v)
do
self.mtype = v.visit_expr(self.n_expr)
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
# The constructor invoked by the new.
var callsite: nullable CallSite
+ # The designated type
+ var recvtype: nullable MClassType
+
redef fun accept_typing(v)
do
var recvtype = v.resolve_mtype(self.n_type)
if recvtype == null then return
- self.mtype = recvtype
if not recvtype isa MClassType then
if recvtype isa MNullableType then
end
end
+ self.recvtype = recvtype
+
var name: String
var nid = self.n_id
if nid != null then
name = nid.text
else
- name = "init"
+ name = "new"
end
var callsite = v.get_method(self, recvtype, name, false)
if callsite == null then return
+ if not callsite.mproperty.is_new then
+ self.mtype = recvtype
+ else
+ self.mtype = callsite.msignature.return_mtype
+ assert self.mtype != null
+ end
+
self.callsite = callsite
if not callsite.mproperty.is_init_for(recvtype.mclass) then
end
end
+redef class AVarargExpr
+ redef fun accept_typing(v)
+ do
+ # This kind of pseudo-expression can be only processed trough a signature
+ # See `check_signature`
+ # Other cases are a syntax error.
+ v.error(self, "Syntax error: unexpected `...`")
+ end
+end
+
###
redef class ADebugTypeExpr