X-Git-Url: http://nitlanguage.org diff --git a/src/semantize/typing.nit b/src/semantize/typing.nit index 1b53f65..b4599d0 100644 --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@ -117,6 +117,7 @@ private class TypeVisitor #node.debug("Unsafe typing: expected {sup}, got {sub}") return sup end + if sup isa MBottomType then return null # Skip error if sub.need_anchor then var u = anchor_to(sub) self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}: {u}`.") @@ -389,7 +390,7 @@ private class TypeVisitor 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 @@ -414,26 +415,30 @@ private class TypeVisitor 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 @@ -445,10 +450,6 @@ private class TypeVisitor 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 @@ -456,10 +457,12 @@ private class TypeVisitor 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 @@ -468,16 +471,16 @@ private class TypeVisitor 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 @@ -491,6 +494,16 @@ private class TypeVisitor 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 @@ -528,7 +541,7 @@ private class TypeVisitor fun error(node: ANode, message: String) do - self.modelbuilder.toolcontext.error(node.hot_location, message) + self.modelbuilder.error(node, message) end fun get_variable(node: AExpr, variable: Variable): nullable MType @@ -609,8 +622,10 @@ end # A specific method call site with its associated informations. class CallSite - # The associated node for location - var node: ANode + super MEntity + + # The associated location of the callsite + var location: Location # The static type of the receiver (possibly unresolved) var recv: MType @@ -643,10 +658,11 @@ class CallSite # 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 + if map == null then is_broken = true return map == null end end @@ -769,6 +785,9 @@ private class PostTypingVisitor redef fun visit(n) do n.visit_all(self) n.accept_post_typing(type_visitor) + if n isa AExpr and n.mtype == null and not n.is_typed then + n.is_broken = true + end end end @@ -1108,6 +1127,25 @@ redef class ALoopExpr end redef class AForExpr + redef fun accept_typing(v) + do + v.has_loop = true + + for g in n_groups do + var mtype = v.visit_expr(g.n_expr) + if mtype == null then return + g.do_type_iterator(v, mtype) + if g.is_broken then is_broken = true + end + + v.visit_stmt(n_block) + + self.mtype = n_block.mtype + self.is_typed = true + end +end + +redef class AForGroup var coltype: nullable MClassType var method_iterator: nullable CallSite @@ -1234,20 +1272,6 @@ redef class AForExpr self.method_successor = v.get_method(self, vtype, "successor", false) end end - - redef fun accept_typing(v) - do - v.has_loop = true - var mtype = v.visit_expr(n_expr) - if mtype == null then return - - self.do_type_iterator(v, mtype) - - v.visit_stmt(n_block) - - self.mtype = n_block.mtype - self.is_typed = true - end end redef class AWithExpr @@ -1377,6 +1401,16 @@ redef class AIntegerExpr 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 @@ -1698,7 +1732,7 @@ redef class ASendExpr 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 @@ -1766,14 +1800,14 @@ end 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 @@ -1817,7 +1851,7 @@ redef class ASendReassignFormExpr 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 @@ -1834,15 +1868,15 @@ redef class ASendReassignFormExpr 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 @@ -1955,12 +1989,12 @@ redef class ASuperExpr 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 @@ -2014,11 +2048,11 @@ redef class ANewExpr 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 @@ -2059,7 +2093,7 @@ redef class ANewExpr end var args = n_args.to_a - callsite.check_signature(v, args) + callsite.check_signature(v, node, args) end end