import modelize
import local_var_init
+import literal
redef class ToolContext
var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
end
end
- var callsite = new CallSite(node, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
+ var callsite = new CallSite(node.hot_location, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
return callsite
end
return null
end
else if args.length != msignature.arity then
- if msignature.arity == msignature.min_arity then
- modelbuilder.error(node, "Error: expected {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
- return null
- end
+ # Too much argument
if args.length > msignature.arity then
- modelbuilder.error(node, "Error: expected at most {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
- return null
- end
- if args.length < msignature.min_arity then
- modelbuilder.error(node, "Error: expected at least {msignature.min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
+ modelbuilder.error(node, "Error: expected {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
return null
end
+ # Other cases are managed later
end
+
#debug("CALL {unsafe_type}.{msignature}")
# Associate each parameter to a position in the arguments
var map = new SignatureMap
- var setted = args.length - msignature.min_arity
+ # Special case for the isolated last argument
+ # TODO: reify this method characteristics (where? the param, the signature, the method?)
+ var last_is_padded = mproperty.name.chars.last == '='
+ var nbargs = args.length
+ if last_is_padded then
+ nbargs -= 1
+ assert not args.last isa ANamedargExpr
+ map.map[msignature.arity - 1] = args.length - 1
+ self.visit_expr_subtype(args.last, msignature.mparameters.last.mtype)
+ end
# First, handle named arguments
for i in [0..args.length[ do
modelbuilder.error(e.n_id, "Error: no parameter `{name}` for `{mproperty}{msignature}`.")
return null
end
- if not param.is_default then
- modelbuilder.error(e, "Error: parameter `{name}` is not optional for `{mproperty}{msignature}`.")
- return null
- end
var idx = msignature.mparameters.index_of(param)
var prev = map.map.get_or_null(idx)
if prev != null then
return null
end
map.map[idx] = i
- setted -= 1
e.mtype = self.visit_expr_subtype(e.n_expr, param.mtype)
end
+ # Number of minimum mandatory remaining parameters
+ var min_arity = 0
+
# Second, associate remaining parameters
var vararg_decl = args.length - msignature.arity
var j = 0
if map.map.has_key(i) then continue
var param = msignature.mparameters[i]
- if param.is_default then
- if setted > 0 then
- setted -= 1
- else
- continue
- end
- end
# Search the next free argument: skip named arguments since they are already associated
- while args[j] isa ANamedargExpr do j += 1
+ while j < nbargs and args[j] isa ANamedargExpr do j += 1
+ if j >= nbargs then
+ if not param.mtype isa MNullableType then
+ min_arity = j + 1
+ end
+ j += 1
+ continue
+ end
var arg = args[j]
map.map[i] = j
j += 1
self.visit_expr_subtype(arg, paramtype)
end
+ if min_arity > 0 then
+ if last_is_padded then min_arity += 1
+ if min_arity < msignature.arity then
+ modelbuilder.error(node, "Error: expected at least {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
+ else
+ modelbuilder.error(node, "Error: expected {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
+ end
+ return null
+ end
+
# Third, check varargs
if vararg_rank >= 0 then
var paramtype = msignature.mparameters[vararg_rank].mtype
# A specific method call site with its associated informations.
class CallSite
- # The associated node for location
- var node: ANode
+ # The associated location of the callsite
+ var location: Location
# The static type of the receiver (possibly unresolved)
var recv: MType
# If null then no specific association is required.
var signaturemap: nullable SignatureMap = null
- private fun check_signature(v: TypeVisitor, args: Array[AExpr]): Bool
+ private fun check_signature(v: TypeVisitor, node: ANode, args: Array[AExpr]): Bool
do
- var map = v.check_signature(self.node, args, self.mproperty, self.msignature)
+ var map = v.check_signature(node, args, self.mproperty, self.msignature)
signaturemap = map
return map == null
end
end
end
-redef class AIntExpr
+redef class AIntegerExpr
redef fun accept_typing(v)
do
- var mclass = v.get_mclass(self, "Int")
- if mclass == null then return # Forward error
- self.mtype = mclass.mclass_type
- end
-end
-
-redef class AByteExpr
- redef fun accept_typing(v)
- do
- var mclass = v.get_mclass(self, "Byte")
+ var mclass: nullable MClass = null
+ if value isa Byte then
+ mclass = v.get_mclass(self, "Byte")
+ else if value isa Int then
+ mclass = v.get_mclass(self, "Int")
+ else if value isa Int8 then
+ mclass = v.get_mclass(self, "Int8")
+ else if value isa Int16 then
+ mclass = v.get_mclass(self, "Int16")
+ else if value isa UInt16 then
+ mclass = v.get_mclass(self, "UInt16")
+ else if value isa Int32 then
+ mclass = v.get_mclass(self, "Int32")
+ else if value isa UInt32 then
+ mclass = v.get_mclass(self, "UInt32")
+ end
if mclass == null then return # Forward error
self.mtype = mclass.mclass_type
end
var args = compute_raw_arguments
- callsite.check_signature(v, args)
+ callsite.check_signature(v, node, args)
if callsite.mproperty.is_init then
var vmpropdef = v.mpropdef
redef class ACallExpr
- redef fun property_name do return n_id.text
- redef fun property_node do return n_id
+ redef fun property_name do return n_qid.n_id.text
+ redef fun property_node do return n_qid
redef fun compute_raw_arguments do return n_args.to_a
end
redef class ACallAssignExpr
- redef fun property_name do return n_id.text + "="
- redef fun property_node do return n_id
+ redef fun property_name do return n_qid.n_id.text + "="
+ redef fun property_node do return n_qid
redef fun compute_raw_arguments
do
var res = n_args.to_a
var args = compute_raw_arguments
- callsite.check_signature(v, args)
+ callsite.check_signature(v, node, args)
var readtype = callsite.msignature.return_mtype
if readtype == null then
args = args.to_a # duplicate so raw_arguments keeps only the getter args
args.add(self.n_value)
- wcallsite.check_signature(v, args)
+ wcallsite.check_signature(v, node, args)
self.is_typed = true
end
end
redef class ACallReassignExpr
- redef fun property_name do return n_id.text
- redef fun property_node do return n_id
+ redef fun property_name do return n_qid.n_id.text
+ redef fun property_node do return n_qid.n_id
redef fun compute_raw_arguments do return n_args.to_a
end
var msignature = superprop.new_msignature or else superprop.msignature.as(not null)
msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
- var callsite = new CallSite(self, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
+ var callsite = new CallSite(hot_location, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
self.callsite = callsite
var args = self.n_args.to_a
if args.length > 0 then
- callsite.check_signature(v, args)
+ callsite.check_signature(v, self, args)
else
# Check there is at least enough parameters
if mpropdef.msignature.arity < msignature.arity then
var kind = recvtype.mclass.kind
var name: String
- var nid = self.n_id
+ var nqid = self.n_qid
var node: ANode
- if nid != null then
- name = nid.text
- node = nid
+ if nqid != null then
+ name = nqid.n_id.text
+ node = nqid
else
name = "new"
node = self.n_kwnew
end
var args = n_args.to_a
- callsite.check_signature(v, args)
+ callsite.check_signature(v, node, args)
end
end