# Is `self` use restricted?
# * no explicit `self`
# * method called on the implicit self must be top-level
+ # Currently only used for `new` factory since there is no valid receiver inside
var is_toplevel_context = false
init
selfvariable.declared_type = mclass.mclass_type
var mprop = mpropdef.mproperty
- if mprop isa MMethod and (mprop.is_toplevel or mprop.is_new) then
+ if mprop isa MMethod and mprop.is_new then
is_toplevel_context = true
end
end
fun get_mclass(node: ANode, name: String): nullable MClass
do
- var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
- if mclass == null then
- self.modelbuilder.error(node, "Type Error: missing primitive class `{name}'.")
- end
+ var mclass = modelbuilder.get_mclass_by_name(node, mmodule, name)
return mclass
end
if recvtype isa MNullType then
# `null` only accepts some methods of object.
if name == "==" or name == "!=" or name == "is_same_instance" then
- unsafe_type = mmodule.object_type.as_nullable
+ var objclass = get_mclass(node, "Object")
+ if objclass == null then return null # Forward error
+ unsafe_type = objclass.mclass_type
else
self.error(node, "Error: Method '{name}' call on 'null'.")
return null
end
- var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
+ var msignature = mpropdef.new_msignature or else mpropdef.msignature
+ if msignature == null then return null # skip error
msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
var erasure_cast = false
var nblock = self.n_block
if nblock == null then return
- var mpropdef = self.mpropdef.as(not null)
+ var mpropdef = self.mpropdef
+ if mpropdef == null then return # skip error
+
var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var mmethoddef = self.mpropdef.as(not null)
- for i in [0..mmethoddef.msignature.arity[ do
- var mtype = mmethoddef.msignature.mparameters[i].mtype
- if mmethoddef.msignature.vararg_rank == i then
+ var msignature = mmethoddef.msignature
+ if msignature == null then return # skip error
+ for i in [0..msignature.arity[ do
+ var mtype = msignature.mparameters[i].mtype
+ if msignature.vararg_rank == i then
var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
if arrayclass == null then return # Skip error
mtype = arrayclass.get_mtype([mtype])
end
v.visit_stmt(nblock)
- if not nblock.after_flow_context.is_unreachable and mmethoddef.msignature.return_mtype != null then
+ if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then
# We reach the end of the function without having a return, it is bad
v.error(self, "Control error: Reached end of function (a 'return' with a value was expected).")
end
do
if not has_value then return
- var mpropdef = self.mpropdef.as(not null)
+ var mpropdef = self.mpropdef
+ if mpropdef == null then return # skip error
+
var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var decltype = mtype
if mtype == null or mtype isa MNullType then
- decltype = v.get_mclass(self, "Object").mclass_type.as_nullable
+ var objclass = v.get_mclass(self, "Object")
+ if objclass == null then return # skip error
+ decltype = objclass.mclass_type.as_nullable
if mtype == null then mtype = decltype
end
#debug("var {variable}: {mtype}")
+ self.mtype = mtype
self.is_typed = true
end
end
end
end
+redef class AWithExpr
+ var method_start: nullable CallSite
+ var method_finish: nullable CallSite
+
+ redef fun accept_typing(v: TypeVisitor)
+ do
+ var mtype = v.visit_expr(n_expr)
+ if mtype == null then return
+
+ method_start = v.get_method(self, mtype, "start", n_expr isa ASelfExpr)
+ method_finish = v.get_method(self, mtype, "finish", n_expr isa ASelfExpr)
+
+ v.visit_stmt(n_block)
+ self.mtype = n_block.mtype
+ self.is_typed = true
+ end
+end
+
redef class AAssertExpr
redef fun accept_typing(v)
do
var t = v.merge_types(self, [t1, t2])
if t == null then
- t = v.mmodule.object_type
+ var c = v.get_mclass(self, "Object")
+ if c == null then return # forward error
+ t = c.mclass_type
if v.can_be_null(t2) then
t = t.as_nullable
end
var mclass = v.get_mclass(self, "String")
if mclass == null then return # Forward error
self.mtype = mclass.mclass_type
+ var objclass = v.get_mclass(self, "Object")
+ if objclass == null then return # Forward error
+ var objtype = objclass.mclass_type
for nexpr in self.n_exprs do
- v.visit_expr_subtype(nexpr, v.mmodule.object_type)
+ v.visit_expr_subtype(nexpr, objtype)
end
end
end
end
end
+redef class AImplicitSelfExpr
+ # Is the implicit receiver `sys`?
+ #
+ # By default, the implicit receiver is `self`.
+ # But when there is not method for `self`, `sys` is used as a fall-back.
+ # Is this case this flag is set to `true`.
+ var is_sys = false
+end
+
## MESSAGE SENDING AND PROPERTY
redef class ASendExpr
redef fun accept_typing(v)
do
- var recvtype = v.visit_expr(self.n_expr)
+ var nrecv = self.n_expr
+ var recvtype = v.visit_expr(nrecv)
var name = self.property_name
if recvtype == null then return # Forward error
- var callsite = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr)
- if callsite == null then return
+ var callsite = null
+ var unsafe_type = v.anchor_to(recvtype)
+ var mproperty = v.try_get_mproperty_by_name2(self, unsafe_type, name)
+ if mproperty == null and nrecv isa AImplicitSelfExpr then
+ # Special fall-back search in `sys` when noting found in the implicit receiver.
+ var sysclass = v.try_get_mclass(self, "Sys")
+ if sysclass != null then
+ var systype = sysclass.mclass_type
+ mproperty = v.try_get_mproperty_by_name2(self, systype, name)
+ if mproperty != null then
+ callsite = v.get_method(self, systype, name, false)
+ if callsite == null then return # Forward error
+ # Update information, we are looking at `sys` now, not `self`
+ nrecv.is_sys = true
+ nrecv.its_variable = null
+ nrecv.mtype = systype
+ recvtype = systype
+ end
+ end
+ end
+ if callsite == null then
+ # If still nothing, just exit
+ callsite = v.get_method(self, recvtype, name, nrecv isa ASelfExpr)
+ if callsite == null then return
+ end
+
self.callsite = callsite
var msignature = callsite.msignature
var mpropdefs = mproperty.lookup_definitions(v.mmodule, unsafe_type)
assert mpropdefs.length == 1
var mpropdef = mpropdefs.first
- var attr_type = mpropdef.static_mtype.as(not null)
+ var attr_type = mpropdef.static_mtype
+ if attr_type == null then return # skip error
attr_type = v.resolve_for(attr_type, recvtype, self.n_expr isa ASelfExpr)
self.attr_type = attr_type
end