This method is used to check conformance among multiple expressions.
It is used to factorize code between AIfexprExpr, AArrayExpr and process_closure.
Tests are also updated to use the new error messages.
Signed-off-by: Jean Privat <jean@pryen.org>
if check_expr(n) then return check_conform(n, n.stype, stype) else return false
end
+ # Check conformance between multiple expressions and a static type
+ # Conformance is granted if among them there is a most general type
+ # Return the most general type if a conformance is found
+ # Display an error and return null if no conformance is found
+ # @param stype is a possible additional type (without node)
+ # Examples:
+ # Int, Int, Object => return Object
+ # Int, Float => display error, return null
+ meth check_conform_multiexpr(stype: MMType, nodes: Collection[PExpr]): MMType
+ do
+ var node: PExpr = null # candidate node
+ for n in nodes do
+ if not check_expr(n) then return null
+ var ntype = n.stype
+ if stype == null or (ntype != null and stype < ntype) then
+ stype = ntype
+ node = n
+ end
+ end
+ for n in nodes do
+ if not n.stype < stype then
+ if node == null then
+ error(n, "Type error: no most general type. Got {n.stype} and {stype}.")
+ else
+ error(n, "Type error: no most general type. Got {n.stype} and {stype} at {node.locate}.")
+ end
+ return null
+ end
+ end
+ return stype
+ end
protected init(tc: ToolContext, module: MMSrcModule)
do
v.check_conform_expr(n_expr, v.type_bool)
- if not v.check_expr(n_then) or not v.check_expr(n_else) then return
-
- var t = n_then.stype
- var te = n_else.stype
- if t < te then
- t = te
- else if not te < t then
- v.error(self, "Type error: {te} is not a subtype of {t}.")
- return
- end
-
- _stype = t
+ _stype = v.check_conform_multiexpr(null, [n_then, n_else])
end
end
redef meth after_typing(v)
do
- var stype: MMType = null
- for n in n_exprs do
- var ntype = n.stype
- if stype == null or (ntype != null and stype < ntype) then
- stype = ntype
- end
- end
- for n in n_exprs do
- v.check_conform_expr(n, stype)
- end
+ var stype = v.check_conform_multiexpr(null, n_exprs)
+ if stype == null then return
do_typing(v, stype)
end
# Check break type conformity
if break_list != null then
- for n in break_list do
- var ntype = n.stype
- if t == null or (t != null and t < ntype) then
- t = ntype
- end
- end
- for n in break_list do
- v.check_conform_expr(n, t)
- end
+ t = v.check_conform_multiexpr(t, break_list)
end
end
else if min_arity != 0 then
-alt/base_array_alt1.nit:27,15--18: Type error: expected Int, got Bool
+alt/base_array_alt1.nit:27,15--18: Type error: no most general type. Got Bool and Int at alt/base_array_alt1.nit:27,11--12.
-alt/base_closure5_alt2.nit:36,9--11: Type error: expected Int, got Char
+alt/base_closure5_alt2.nit:36,9--11: Type error: no most general type. Got Char and Int.
-./base_closure6.nit:55,25--25: Type error: expected U, got V
-./base_closure6.nit:65,8--8: Type error: expected U, got V
+./base_closure6.nit:55,25--25: Type error: no most general type. Got V and U.
+./base_closure6.nit:65,8--8: Type error: no most general type. Got V and U at ./base_closure6.nit:64,8--8.
alt/base_closure6_alt1.nit:53,5--25: Type error: expected U, got T
-alt/base_closure6_alt1.nit:55,25--25: Type error: expected U, got V
+alt/base_closure6_alt1.nit:55,25--25: Type error: no most general type. Got V and U.
alt/base_closure6_alt1.nit:57,5--61:8: Type error: expected U, got T
-alt/base_closure6_alt1.nit:65,8--8: Type error: expected U, got V
+alt/base_closure6_alt1.nit:65,8--8: Type error: no most general type. Got V and U at alt/base_closure6_alt1.nit:64,8--8.
-alt/base_if_expr_alt1.nit:39,11--35: Type error: Int is not a subtype of A.
+alt/base_if_expr_alt1.nit:39,35--35: Type error: no most general type. Got Int and A at alt/base_if_expr_alt1.nit:39,24--28.
-./error_array_ambig.nit:17,13--15: Type error: expected Int, got Char
+./error_array_ambig.nit:17,13--15: Type error: no most general type. Got Char and Int at ./error_array_ambig.nit:17,10--10.