# 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`
end
# Check that `sub` is a subtype of `sup`.
- # If `sub` is not a valud suptype, then display an error on `node` an return null.
+ # If `sub` is not a valid suptype, then display an error on `node` an return null.
# If `sub` is a safe subtype of `sup` then return `sub`.
- # If `sub` is an insafe subtype (ie an imlicit cast is required), then return `sup`.
+ # If `sub` is an unsafe subtype (ie an implicit cast is required), then return `sup`.
#
# The point of the return type is to determinate the usable type on an expression:
# If the suptype is safe, then the return type is the one on the expression typed by `sub`.
do
if self.is_subtype(sub, sup) then return sub
if self.is_subtype(sub, self.anchor_to(sup)) then
- # FIXME workarround to the current unsafe typing policy. To remove once fixed virtual types exists.
+ # FIXME workaround to the current unsafe typing policy. To remove once fixed virtual types exists.
#node.debug("Unsafe typing: expected {sup}, got {sub}")
return sup
end
return callsite
end
- # Visit the expressions of args and cheik their conformity with the corresponding typi in signature
+ fun try_get_method(node: ANode, recvtype: MType, name: String, recv_is_self: Bool): nullable CallSite
+ do
+ var unsafe_type = self.anchor_to(recvtype)
+ var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
+ if mproperty == null then return null
+ return get_method(node, recvtype, name, recv_is_self)
+ end
+
+
+ # Visit the expressions of args and check their conformity with the corresponding type in signature
# The point of this method is to handle varargs correctly
# Note: The signature must be correctly adapted
fun check_signature(node: ANode, args: Array[AExpr], name: String, msignature: MSignature): Bool
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
# A specific method call site with its associated informations.
class CallSite
- # The assiciated node for location
+ # The associated node for location
var node: ANode
# The static type of the receiver (possibly unresolved)
var anchor: nullable MClassType
# Is the receiver self?
- # If "for_self", virtual types of the signature are keeped
+ # If "for_self", virtual types of the signature are kept
# If "not_for_self", virtual type are erased
var recv_is_self: Bool
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.
- # Warning2: sub-flow may have cached a unadapted variabial
+ # Warning2: sub-flow may have cached a unadapted variable
private fun set_var(variable: Variable, mtype: nullable MType)
do
self.vars[variable] = mtype
do
end
- # The variable associated to the reciever (if any)
+ # The variable associated to the receiver (if any)
var selfvariable: nullable Variable
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
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 method_item: nullable CallSite
var method_next: nullable CallSite
var method_key: nullable CallSite
+ var method_finish: nullable CallSite
private fun do_type_iterator(v: TypeVisitor, mtype: MType)
do
end
self.method_next = nextdef
+ self.method_finish = v.try_get_method(self, ittype, "finish", false)
+
if is_map then
var keydef = v.get_method(self, ittype, "key", false)
if keydef == null then
redef fun accept_typing(v)
do
+ var mtype: nullable MType = null
+ var ntype = self.n_type
+ if ntype != null then
+ mtype = v.resolve_mtype(ntype)
+ if mtype == null then return # Skip error
+ end
var mtypes = new Array[nullable MType]
+ var useless = false
for e in self.n_exprs.n_exprs do
var t = v.visit_expr(e)
if t == null then
return # Skip error
end
- mtypes.add(t)
+ if mtype != null then
+ if v.check_subtype(e, t, mtype) == null then return # Skip error
+ if t == mtype then useless = true
+ else
+ mtypes.add(t)
+ end
+ end
+ if mtype == null then
+ mtype = v.merge_types(self, mtypes)
end
- var mtype = v.merge_types(self, mtypes)
if mtype == null then
v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}")
return
end
+ if useless then
+ assert ntype != null
+ v.modelbuilder.warning(ntype, "useless-type", "Warning: useless type declaration `{mtype}` in literal Array since it can be inferred from the elements type.")
+ end
var mclass = v.get_mclass(self, "Array")
if mclass == null then return # Forward error
var array_mtype = mclass.get_mtype([mtype])
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
var errcount = v.modelbuilder.toolcontext.error_count
var candidate = v.try_get_mproperty_by_name2(self, msupertype, mproperty.name).as(nullable MMethod)
if candidate == null then
- if v.modelbuilder.toolcontext.error_count > errcount then return # Forard error
+ if v.modelbuilder.toolcontext.error_count > errcount then return # Forward error
continue # Try next super-class
end
if superprop != null and candidate.is_root_init then
candidatedefs.add(superprop)
end
if candidatedefs.length > 1 then
- v.error(self, "Error: confliting property definitions for property {mproperty} in {recvtype}: {candidatedefs.join(", ")}")
+ v.error(self, "Error: conflicting property definitions for property {mproperty} in {recvtype}: {candidatedefs.join(", ")}")
return
end
superprop = candidatedefs.first