module typing
import flow
-import modelbuilder
+import modelize_property
+import phase
+import local_var_init
+
+redef class ToolContext
+ var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
+end
+
+private class TypingPhase
+ super Phase
+ redef fun process_npropdef(npropdef) do npropdef.do_typing(toolcontext.modelbuilder)
+end
private class TypeVisitor
var modelbuilder: ModelBuilder
end
var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
+ var mpropdef
if propdefs.length == 0 then
self.modelbuilder.error(node, "Type error: no definition found for property {name} in {unsafe_type}")
return null
- else if propdefs.length > 1 then
- self.modelbuilder.error(node, "Error: confliting property definitions for property {name} in {unsafe_type}: {propdefs.join(" ")}")
- return null
+ else if propdefs.length == 1 then
+ mpropdef = propdefs.first
+ else
+ self.modelbuilder.warning(node, "Warning: confliting property definitions for property {name} in {unsafe_type}: {propdefs.join(" ")}")
+ mpropdef = mproperty.intro
end
- var mpropdef = propdefs.first
var msignature = self.resolve_signature_for(mpropdef, recvtype, recv_is_self)
- var callsite = new CallSite(node, recvtype, recv_is_self, mproperty, mpropdef, msignature)
+ var erasure_cast = false
+ var rettype = mpropdef.msignature.return_mtype
+ if not recv_is_self and rettype != null then
+ if rettype isa MNullableType then rettype = rettype.mtype
+ if rettype isa MParameterType then
+ var erased_rettype = msignature.return_mtype
+ assert erased_rettype != null
+ #node.debug("Erasure cast: Really a {rettype} but unsafely a {erased_rettype}")
+ erasure_cast = true
+ end
+ end
+
+ var callsite = new CallSite(node, recvtype, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
return callsite
end
# The resolved signature for the receiver
var msignature: MSignature
+ # Is a implicit cast required on erasure typing policy?
+ var erasure_cast: Bool
+
private fun check_signature(v: TypeVisitor, args: Array[AExpr]): Bool
do
return v.check_signature(self.node, args, self.mproperty.name, self.msignature)
end
end
- if mtype == null then
- mtype = v.get_mclass(self, "Object").mclass_type.as_nullable
+ var decltype = mtype
+ if mtype == null or mtype isa MNullType then
+ decltype = v.get_mclass(self, "Object").mclass_type.as_nullable
+ if mtype == null then mtype = decltype
end
- variable.declared_type = mtype
+ variable.declared_type = decltype
v.set_variable(self, variable, mtype)
#debug("var {variable}: {mtype}")
end
redef class AReassignFormExpr
+ # @depreciated use `reassign_callsite`
+ fun reassign_property: nullable MMethodDef do return self.reassign_callsite.mpropdef
+
# The method designed by the reassign operator.
- var reassign_property: nullable MMethodDef = null
+ var reassign_callsite: nullable CallSite
var read_type: nullable MType = null
var callsite = v.get_method(self, readtype, reassign_name, false)
if callsite == null then return null # Skip error
- var mpropdef = callsite.mpropdef
-
- self.reassign_property = mpropdef
+ self.reassign_callsite = callsite
var msignature = callsite.msignature
var rettype = msignature.return_mtype
## MESSAGE SENDING AND PROPERTY
redef class ASendExpr
+ # @depreciated: use `callsite`
+ fun mproperty: nullable MMethod do return callsite.mproperty
+
# The property invoked by the send.
- var mproperty: nullable MMethod
+ var callsite: nullable CallSite
redef fun accept_typing(v)
do
var callsite = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr)
if callsite == null then return
- var mproperty = callsite.mproperty
- self.mproperty = mproperty
+ self.callsite = callsite
var msignature = callsite.msignature
var args = compute_raw_arguments
callsite.check_signature(v, args)
- if mproperty.is_init then
+ if callsite.mproperty.is_init then
var vmpropdef = v.mpropdef
if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then
v.error(self, "Can call a init only in another init")
end
redef class ASendReassignFormExpr
+ # @depreciated use `write_callsite`
+ fun write_mproperty: nullable MMethod do return write_callsite.mproperty
+
# The property invoked for the writing
- var write_mproperty: nullable MMethod = null
+ var write_callsite: nullable CallSite
redef fun accept_typing(v)
do
var callsite = v.get_method(self, recvtype, name, for_self)
if callsite == null then return
- var mproperty = callsite.mproperty
- self.mproperty = mproperty
+ self.callsite = callsite
var args = compute_raw_arguments
self.raw_arguments = args
var wcallsite = v.get_method(self, recvtype, name + "=", self.n_expr isa ASelfExpr)
if wcallsite == null then return
- var wmproperty = wcallsite.mproperty
- self.write_mproperty = wmproperty
+ self.write_callsite = wcallsite
var wtype = self.resolve_reassignment(v, readtype, wcallsite.msignature.mparameters.last.mtype)
if wtype == null then return
end
v.error(self, "Error: No super method to call for {mproperty}.")
return
- else if superprops.length > 1 then
- v.modelbuilder.warning(self, "Warning: NOT YET IMPLEMENTED: Conflicting super method to call for {mproperty}: {superprops.join(", ")}.")
- return
end
+ # FIXME: covariance of return type in linear extension?
var superprop = superprops.first
assert superprop isa MMethodDef
####
redef class ANewExpr
+ # @depreciated use `callsite`
+ fun mproperty: nullable MMethod do return self.callsite.mproperty
+
# The constructor invoked by the new.
- var mproperty: nullable MMethod
+ var callsite: nullable CallSite
redef fun accept_typing(v)
do
var callsite = v.get_method(self, recvtype, name, false)
if callsite == null then return
- self.mproperty = callsite.mproperty
+ self.callsite = callsite
if not callsite.mproperty.is_init_for(recvtype.mclass) then
v.error(self, "Error: {name} is not a constructor.")