private object AccessOneByOne(object currentTarget, object previousTarget, List<Node> suffixes)
{
if (suffixes.Count == 0)
return currentTarget;
if (currentTarget == null)
throw ErrorFactory.CreateNullError("Object");
var currentSuffix = suffixes[0];
// bike function, .NET ctor or .NET delegate
if (currentSuffix is Arguments)
{
var arguments = (Arguments) currentSuffix;
// bike function
if (currentTarget is BikeFunction)
{
previousTarget = CallBikeFunction((BikeFunction)currentTarget,
previousTarget, arguments);
}
// ctor
else if (currentTarget is Type)
{
var argValues = GetArgumentValues(arguments);
previousTarget = CreateInstance((Type)currentTarget, argValues);
}
// delegate
else
{
var args = GetArgumentValues(arguments);
previousTarget = CallDelegate((Delegate)currentTarget, args);
}
return AccessOneByOne(previousTarget, currentTarget, suffixes.ExceptFirst());
}
if (currentSuffix is PropertyReferenceSuffix ||
currentSuffix is IndexSuffix ||
currentSuffix is TypeDescriptorSuffix)
{
if (currentTarget is BikeObject)
{
var currentSuffixStr = currentSuffix.SuffixValue(this);
previousTarget = ((BikeObject)currentTarget).Resolve(currentSuffixStr);
}
else if (currentTarget is Type) // Static context
{
var currentSuffixStr = currentSuffix.SuffixValue(this);
// Static generic call
if (suffixes.Count > 2 &&
suffixes[1] is TypeDescriptorSuffix &&
suffixes[2] is Arguments
)
{
var typeParams = (Type[])suffixes[1].Accept(this);
var args = GetArgumentValues((Arguments)suffixes[2]);
previousTarget = CallStaticFunction((Type)currentTarget, typeParams, currentSuffixStr, args);
suffixes = suffixes.ExceptFirst().ExceptFirst();
}
// Static method or delegate
else if (suffixes.Count > 1 && suffixes[1] is Arguments)
{
try
{
// delegate?
previousTarget = GetStaticProperty((Type)currentTarget, currentSuffixStr);
}
catch (BikeObject bo)
{
if (!ErrorFactory.IsClrError(bo))
throw;
// method? invoke immediately to avoid saving MethodInfo
var args = GetArgumentValues((Arguments)suffixes[1]);
previousTarget = CallStaticFunction((Type)currentTarget, currentSuffixStr, args);
suffixes = suffixes.ExceptFirst();
}
}
else // .NET static property, invoke immediately
{
previousTarget = GetStaticProperty((Type)currentTarget, currentSuffixStr);
}
}
// Must be .NET generic instance method
else if (suffixes.Count > 2 &&
suffixes[1] is TypeDescriptorSuffix &&
suffixes[2] is Arguments)
{
var currentSuffixStr = currentSuffix.SuffixValue(this);
var typeParams = (Type[])suffixes[1].Accept(this);
var args = GetArgumentValues((Arguments)suffixes[2]);
previousTarget = CallInstanceFunction(currentTarget, typeParams, currentSuffixStr, args);
suffixes = suffixes.ExceptFirst().ExceptFirst();
}
// .NET instance method or delegate
else if (suffixes.Count > 1 && suffixes[1] is Arguments)
{
try
{
// delegate?
var currentSuffixStr = currentSuffix.SuffixValue(this);
previousTarget = GetInstanceProperty(currentTarget, currentSuffixStr);
}
catch (BikeObject bo)
{
if (!ErrorFactory.IsClrError(bo))
throw;
// method?
var currentSuffixStr = currentSuffix.SuffixValue(this);
var args = GetArgumentValues((Arguments)suffixes[1]);
previousTarget = CallInstanceFunction(currentTarget, currentSuffixStr, args);
suffixes = suffixes.ExceptFirst();
}
}
// .NET instance property
else if (currentSuffix is PropertyReferenceSuffix)
{
var currentSuffixStr = currentSuffix.SuffixValue(this);
previousTarget = GetInstanceProperty(currentTarget, currentSuffixStr);
}
// .NET indexer
else
{
previousTarget = GetInstanceIndexer(currentTarget, currentSuffix.Arguments(this));
}
return AccessOneByOne(previousTarget, currentTarget, suffixes.ExceptFirst());
}
throw ErrorFactory.CreateError(string.Format("Invalid suffix type {0}", currentSuffix));
}