private class TypeVisitor
var modelbuilder: ModelBuilder
- var nclassdef: AClassdef
# The module of the analysis
# Used to correctly query the model
# Mainly used for type tests and type resolutions
var anchor: nullable MClassType
+ # The analyzed mclassdef
+ var mclassdef: nullable MClassDef
+
# The analyzed property
var mpropdef: nullable MPropDef
var selfvariable: Variable = new Variable("self")
- init(modelbuilder: ModelBuilder, nclassdef: AClassdef, mpropdef: MPropDef)
+ # Is `self` use restricted?
+ # * no explicit `self`
+ # * method called on the implicit self must be top-level
+ var is_toplevel_context = false
+
+ init(modelbuilder: ModelBuilder, mmodule: MModule, mpropdef: nullable MPropDef)
do
self.modelbuilder = modelbuilder
- self.nclassdef = nclassdef
- self.mpropdef = mpropdef
- var mclassdef = mpropdef.mclassdef
+ self.mmodule = mmodule
+
+ if mpropdef != null then
+ self.mpropdef = mpropdef
+ var mclassdef = mpropdef.mclassdef
+ self.mclassdef = mclassdef
+ self.anchor = mclassdef.bound_mtype
- self.mmodule = mclassdef.mmodule
- self.anchor = mclassdef.bound_mtype
+ var mclass = mclassdef.mclass
- var mclass = mclassdef.mclass
+ var selfvariable = new Variable("self")
+ self.selfvariable = selfvariable
+ selfvariable.declared_type = mclass.mclass_type
- var selfvariable = new Variable("self")
- self.selfvariable = selfvariable
- selfvariable.declared_type = mclass.mclass_type
+ var mprop = mpropdef.mproperty
+ if mprop isa MMethod and mprop.is_toplevel then
+ is_toplevel_context = true
+ end
+ end
end
fun anchor_to(mtype: MType): MType
fun resolve_mtype(node: AType): nullable MType
do
- return self.modelbuilder.resolve_mtype(mmodule, mpropdef.mclassdef, node)
+ return self.modelbuilder.resolve_mtype(mmodule, mclassdef, node)
end
fun try_get_mclass(node: ANode, name: String): nullable MClass
end
assert mproperty isa MMethod
+
+ if is_toplevel_context and recv_is_self and not mproperty.is_toplevel and name != "sys" and name != "exit" and name != "args" then
+ # FIXME named methods are here as a workaround
+ error(node, "Error: '{name}' is not a top-level method, thus need a receiver.")
+ end
+ if not recv_is_self and mproperty.is_toplevel then
+ error(node, "Error: cannot call '{name}', a top-level method, with a receiver.")
+ end
+
if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility and not modelbuilder.toolcontext.opt_ignore_visibility.value then
self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self.")
return null
var nblock = self.n_block
if nblock == null then return
- var nclassdef = self.parent.as(AClassdef)
var mpropdef = self.mpropdef.as(not null)
- var v = new TypeVisitor(modelbuilder, nclassdef, mpropdef)
+ var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var mmethoddef = self.mpropdef.as(not null)
redef class AAttrPropdef
redef fun do_typing(modelbuilder: ModelBuilder)
do
- var nclassdef = self.parent.as(AClassdef)
- var v = new TypeVisitor(modelbuilder, nclassdef, self.mpropdef.as(not null))
+ var mpropdef = self.mpropdef.as(not null)
+ var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var nexpr = self.n_expr
if objcla == null then return
# check iterator method
- var itdef = v.get_method(self, mtype, "iterator", true)
+ var itdef = v.get_method(self, mtype, "iterator", n_expr isa ASelfExpr)
if itdef == null then
v.error(self, "Type Error: 'for' expects a type providing 'iterator' method, got '{mtype}'.")
return
redef var its_variable: nullable Variable
redef fun accept_typing(v)
do
+ if v.is_toplevel_context and not self isa AImplicitSelfExpr then
+ v.error(self, "Error: self cannot be used in top-level method.")
+ end
var variable = v.selfvariable
self.its_variable = variable
self.mtype = v.get_variable(self, variable)