protected override bool Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool defaultFallback) {
RubyModule currentDeclaringModule;
string currentMethodName;
var scope = args.Scope;
object target;
scope.GetSuperCallTarget(out currentDeclaringModule, out currentMethodName, out target);
var targetExpression = metaBuilder.GetTemporary(typeof(object), "#super-self");
metaBuilder.AddCondition(
Methods.IsSuperCallTarget.OpCall(
AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)),
AstUtils.Constant(currentDeclaringModule),
AstUtils.Constant(currentMethodName),
targetExpression
)
);
args.SetTarget(targetExpression, target);
Debug.Assert(currentDeclaringModule != null);
RubyMemberInfo method;
RubyMemberInfo methodMissing = null;
// we need to lock the hierarchy of the target class:
var targetClass = scope.RubyContext.GetImmediateClassOf(target);
using (targetClass.Context.ClassHierarchyLocker()) {
// initialize all methods in ancestors:
targetClass.InitializeMethodsNoLock();
// target is stored in a local, therefore it cannot be part of the restrictions:
metaBuilder.TreatRestrictionsAsConditions = true;
metaBuilder.AddTargetTypeTest(target, targetClass, targetExpression, args.MetaContext,
new[] { Symbols.MethodMissing } // currentMethodName is resolved for super, which cannot be an instance singleton
);
metaBuilder.TreatRestrictionsAsConditions = false;
method = targetClass.ResolveSuperMethodNoLock(currentMethodName, currentDeclaringModule).InvalidateSitesOnOverride().Info;
if (method == null) {
// MRI: method_missing is called for the targetClass, not for the super:
methodMissing = targetClass.ResolveMethodMissingForSite(currentMethodName, RubyMethodVisibility.None);
}
}
if (method != null) {
method.BuildSuperCall(metaBuilder, args, currentMethodName, currentDeclaringModule);
} else {
return RubyCallAction.BuildMethodMissingCall(metaBuilder, args, currentMethodName, methodMissing, RubyMethodVisibility.None, true, defaultFallback);
}
return true;
}