+redef class ACallrefExpr
+ 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
+
+ redef fun accept_typing(v)
+ do
+ super # do the job as if it was a real call
+ var res = callsite.mproperty
+
+ var msignature = callsite.mpropdef.msignature
+ var recv = callsite.recv
+ assert msignature != null
+ var arity = msignature.mparameters.length
+
+ var routine_type_name = "ProcRef"
+ if msignature.return_mtype != null then
+ routine_type_name = "FunRef"
+ end
+
+ var target_routine_class = "{routine_type_name}{arity}"
+ var routine_mclass = v.get_mclass(self, target_routine_class)
+
+ if routine_mclass == null then
+ v.error(self, "Error: missing functional types, try `import functional`")
+ return
+ end
+
+ var types_list = new Array[MType]
+ for param in msignature.mparameters do
+ if param.is_vararg then
+ types_list.push(v.mmodule.array_type(param.mtype))
+ else
+ types_list.push(param.mtype)
+ end
+ end
+ if msignature.return_mtype != null then
+ types_list.push(msignature.return_mtype.as(not null))
+ end
+
+ # Why we need an anchor :
+ #
+ # ~~~~nitish
+ # class A[E]
+ # def toto(x: E) do print "{x}"
+ # end
+ #
+ # var a = new A[Int]
+ # var f = &a.toto # without anchor : ProcRef1[E]
+ # # with anchor : ProcRef[Int]
+ # ~~~~
+ # However, we can only anchor if we can resolve every formal
+ # parameter, here's an example where we can't.
+ # ~~~~nitish
+ # class A[E]
+ # fun bar: A[E] do return self
+ # fun foo: Fun0[A[E]] do return &bar # here we can't anchor
+ # end
+ # var f1 = a1.foo # when this expression will be evaluated,
+ # # `a1` will anchor `&bar` returned by `foo`.
+ # print f1.call
+ # ~~~~
+ var routine_type = routine_mclass.get_mtype(types_list)
+ if not recv.need_anchor then
+ routine_type = routine_type.anchor_to(v.mmodule, recv.as(MClassType))
+ end
+ is_typed = true
+ self.mtype = routine_type
+ end
+end
+