ClassDefinition CreateAdaptor(ICallableType to, ICallableType from)
{
BooClassBuilder adaptor = CodeBuilder.CreateClass("$adaptor$" + from.Name + "$" + to.Name + "$" + _adaptors.Count);
adaptor.AddBaseType(TypeSystemServices.ObjectType);
adaptor.Modifiers = TypeMemberModifiers.Final|TypeMemberModifiers.Internal;
Field callable = adaptor.AddField("$from", from);
BooMethodBuilder constructor = adaptor.AddConstructor();
ParameterDeclaration param = constructor.AddParameter("from", from);
constructor.Body.Add(
CodeBuilder.CreateSuperConstructorInvocation(TypeSystemServices.ObjectType));
constructor.Body.Add(
CodeBuilder.CreateAssignment(
CodeBuilder.CreateReference(callable),
CodeBuilder.CreateReference(param)));
CallableSignature signature = to.GetSignature();
BooMethodBuilder invoke = adaptor.AddMethod("Invoke", signature.ReturnType);
foreach (IParameter parameter in signature.Parameters)
{
invoke.AddParameter(parameter.Name, parameter.Type, parameter.IsByRef);
}
MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation(
CodeBuilder.CreateReference(callable),
GetInvokeMethod(from));
int fromParameterCount = from.GetSignature().Parameters.Length;
for (int i=0; i<fromParameterCount; ++i)
{
mie.Arguments.Add(
CodeBuilder.CreateReference(invoke.Parameters[i]));
}
if (signature.ReturnType != TypeSystemServices.VoidType &&
from.GetSignature().ReturnType != TypeSystemServices.VoidType)
{
invoke.Body.Add(new ReturnStatement(mie));
}
else
{
invoke.Body.Add(mie);
}
BooMethodBuilder adapt = adaptor.AddMethod("Adapt", to);
adapt.Modifiers = TypeMemberModifiers.Static|TypeMemberModifiers.Public;
param = adapt.AddParameter("from", from);
adapt.Body.Add(
new ReturnStatement(
CodeBuilder.CreateConstructorInvocation(
to.GetConstructors()[0],
CodeBuilder.CreateConstructorInvocation(
(IConstructor)constructor.Entity,
CodeBuilder.CreateReference(param)),
CodeBuilder.CreateAddressOfExpression(invoke.Entity))));
RegisterAdaptor(to, from, adaptor.ClassDefinition);
return adaptor.ClassDefinition;
}