/// <summary> /// A subcontext carries the variable state of the parent FrameContext but runs different /// code with it. This is used for things like functions defined inside functions. /// </summary> /// <param name="subFrames">The frame stack to use for the subcontext.</param> /// <returns>A new FrameContext that has this FrameContext's variable state but the /// new callstack based on rootFrame.</returns> public FrameContext CreateSubcontext(Stack<Frame> subFrames) { Stack<Frame> reverseStack = new Stack<Frame>(); foreach (var parentFrame in callStack) { reverseStack.Push(parentFrame); } foreach (var childFrame in subFrames) { reverseStack.Push(childFrame); } int subStartDepth = callStack.Count; FrameContext newContext = new FrameContext(reverseStack); newContext.StartDepth = subStartDepth; return newContext; }
public void Prepare(IInterpreter interpreter, FrameContext context, IScheduler scheduler) { Interpreter = interpreter; Context = context; Scheduler = scheduler; }
public Injector(IInterpreter interpreter, FrameContext context, IScheduler scheduler) { Prepare(interpreter, context, scheduler); }
public WrappedCodeObject(FrameContext context, MethodBase[] methodBases) { this.MethodBases = methodBases; Name = methodBases[0].Name; instance = null; }
public WrappedCodeObject(FrameContext context, string nameInsideInterpreter, MethodBase methodBase) : this(context, nameInsideInterpreter, new MethodBase[] { methodBase }) { AssertMethodBaseNotNull(methodBase); }
public WrappedCodeObject(FrameContext context, string nameInsideInterpreter, MethodBase[] methodBases) { this.MethodBases = methodBases; Name = nameInsideInterpreter; instance = null; }
public WrappedCodeObject(FrameContext context, MethodBase methodBase, object instance) : this(context, new MethodBase[] { methodBase }, instance) { AssertMethodBaseNotNull(methodBase); }
public WrappedCodeObject(FrameContext context, MethodBase[] methodBases, object instance) { this.MethodBases = methodBases; Name = methodBases[0].Name; this.instance = instance; }
public Task <object> Call(IInterpreter interpreter, FrameContext context, object[] args) { var methodBase = findBestMethodMatch(args); // Strip generic arguments (if any). // Note this is kind of hacky! We get a monomorphized generic method back whether or not // we started out that way already. Current hack is to see if we have more arguments than // the method needs. If we do, then we strip the excess in front since they were used to // monomorphize the generic. int numGenerics = 0; var noGenericArgs = args; int actualParametersLength = methodBase.IsExtensionMethod() ? methodBase.GetParameters().Length - 1 : methodBase.GetParameters().Length; if ((methodBase.ContainsGenericParameters || methodBase.IsGenericMethod) && args.Length > actualParametersLength) { if (methodBase.IsConstructor) { // If this is a constructor, then the class we're instantiating itself might be generic. The constructor // can't legally define additional arguments, so the generic arguments boil down to what the type itself // defines. var asConstructor = methodBase as ConstructorInfo; numGenerics = asConstructor.DeclaringType.GetGenericArguments().Length; } else { numGenerics = methodBase.GetGenericArguments().Length; noGenericArgs = new object[args.Length - numGenerics]; } } Array.Copy(args, numGenerics, noGenericArgs, 0, args.Length - numGenerics); // Inject internal types, convert .NET/Cloaca types. // Unit tests like to come in with a null interpreter so we have to test for it. var injector = new Injector(interpreter, context, interpreter != null ? interpreter.Scheduler : null); var injected_args = injector.Inject(methodBase, noGenericArgs, instance); object[] final_args = injected_args; // Little convenience here. We'll convert a non-task Task<object> type to a task. var asMethodInfo = methodBase as MethodInfo; if (asMethodInfo != null && asMethodInfo.ReturnType.IsGenericType && asMethodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task <>)) { // Task<object> is straightforward and we can just return it. Other return types need to go through // our helper. if (asMethodInfo.ReturnType == typeof(Task <object>)) { return((Task <object>)methodBase.Invoke(instance, final_args)); } else { return(InvokeAsTaskObject(final_args)); } } else { var asConstructor = methodBase as ConstructorInfo; if (asConstructor != null) { // Special handling for generic constructors. The generic arguments for generic constructors are part of the type, // not the constructor. if (asConstructor.ContainsGenericParameters) { Type[] generics = new Type[numGenerics]; var constructorParamIns = methodBase.GetParameters(); Type[] constructorInTypes = new Type[constructorParamIns.Length]; for (int param_i = 0; param_i < constructorInTypes.Length; ++param_i) { constructorInTypes[param_i] = constructorParamIns[param_i].ParameterType; } Array.Copy(args, 0, generics, 0, numGenerics); Type monomorphedConstructor = asConstructor.DeclaringType.MakeGenericType(generics); asConstructor = monomorphedConstructor.GetConstructor(constructorInTypes); } return(Task.FromResult(asConstructor.Invoke(final_args))); } else { return(Task.FromResult(methodBase.Invoke(instance, final_args))); } } }
public Task <object> Call(IInterpreter interpreter, FrameContext context, object[] args) { return(interpreter.CallInto(context, this, args)); }
public static Delegate Create(MethodInfo dotNetMethod, Type delegateType, IPyCallable callable, IInterpreter interpreter, FrameContext contextToUseForCall) { var proxy = new CallableDelegateProxy(callable, interpreter, contextToUseForCall); var dotNetMethodParamInfos = dotNetMethod.GetParameters(); if (dotNetMethodParamInfos.Length > 2) { throw new NotImplementedException("We have only created templates for generic wrappers up to 4 arguments"); } Delegate asDelegate; Type[] delegateArgs; MethodInfo genericWrapper; // An ugly amount of copypasta. If we have a return type, then we need an array one element longer to put in RetVal at the end. // We also need to find the method matching the name of the right return type and accommodate the existing of a return value into // the number of generic parameters required for the right binding. if (dotNetMethod.ReturnType == typeof(void)) { delegateArgs = new Type[dotNetMethodParamInfos.Length]; for (int i = 0; i < dotNetMethodParamInfos.Length; ++i) { delegateArgs[i] = dotNetMethodParamInfos[i].ParameterType; } genericWrapper = typeof(CallableDelegateProxy).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance) .Where(x => x.Name == "GenericWrapperVoid" && x.GetParameters().Length == delegateArgs.Length) .First(); } else { throw new Exception("Attempted to bind a callable to an event that requires a return type. We don't support this type of binding. " + "All our callables have to be async, and that meddles with signature of basic return values. Why are you using an event with " + "a return type anyways?"); } var monomorphizedWrapper = genericWrapper.MakeGenericMethod(delegateArgs); asDelegate = Delegate.CreateDelegate(delegateType, proxy, monomorphizedWrapper); return(asDelegate); }
private CallableDelegateProxy(IPyCallable callable, IInterpreter interpreter, FrameContext contextToUseForCall) { this.callable = callable; this.interpreter = interpreter; this.contextToUseForCall = contextToUseForCall; }
public ScheduledTaskRecord(FrameContext frame, ISubscheduledContinuation continuation, TaskEventRecord submitterReceipt) { Frame = frame; Continuation = continuation; SubmitterReceipt = submitterReceipt; }