/// <summary> /// Gets the event manager from the specified stack frame. If no manager could be found, a warning is sent to the /// runtime and null is returned. /// </summary> /// <param name="frame">The frame.</param> /// <param name="funcName">Name of the function.</param> /// <returns></returns> private static IEarleEventManager GetManager(EarleStackFrame frame, string funcName) { var manager = frame.Executor.Target.As<IEarleEventableObject>()?.EventManager; if (manager == null) frame.Runtime.HandleWarning($"A valid target must be specified when calling `{funcName}`"); return manager; }
/// <summary> /// This method is invoked when the instruction needs to be run. /// </summary> protected override void Handle() { // Create the thread and frame executor. var ip = Frame.Executor.CIP - 1; var thread = new EarleThread(null); var rootFrame = new EarleStackFrame(Frame.Runtime, Frame.Function, null, ip, Frame, thread); var frame = CreateFrameExecutor(rootFrame, EarleStackFrame.ThreadFrameIP); if (frame == null) return; // Attach the frame to the thread and put the thread in the runtime's threadpool. thread.AttachExecutor(frame); Frame.Runtime.EnqueueThread(thread); }
private static void EndOn(EarleStackFrame frame, string eventName) { var manager = GetManager(frame, "endon"); if (manager != null) { var thread = frame.Thread; manager.EventFired += (sender, e) => { if (e.EventName == eventName) { thread.Kill(); } }; } }
/// <summary> /// Creates the frame executor this instruction will invoke. /// </summary> /// <param name="superFrame">The super frame.</param> /// <param name="callerIp">The caller ip.</param> /// <returns>The newly created stack frame executor.</returns> protected virtual IEarleStackFrameExecutor CreateFrameExecutor(EarleStackFrame superFrame, int callerIp) { var argumentCount = GetInt32(); var funcValue = Pop(); // Pop the arguments of the stack. var args = new EarleValue[argumentCount]; for (var i = 0; i < argumentCount; i++) args[argumentCount - 1 - i] = Pop(); // Pop the call target of the stack. var target = HasTarget ? Pop() : EarleValue.Undefined; // Find the function to call. var function = funcValue.As<EarleFunctionCollection>()?.GetBestOverload(argumentCount) ?? funcValue.As<EarleFunction>(); // If no function was specified, show an error and push NULL onto the stack instead of the result. if (function == null) { // Throw a tailored warning. if (funcValue.As<EarleFunctionCollection>()?.Any() ?? false) Frame.Runtime.HandleWarning( $"No suitable overload can be found of `{funcValue.As<EarleFunctionCollection>().FirstOrDefault()?.Name}`."); else if (funcValue.As<EarleFunctionCollection>()?.Any() ?? false) Frame.Runtime.HandleWarning("No suitable overload can be found."); else if (!funcValue.HasValue) Frame.Runtime.HandleWarning("A null pointer cannot be invoked."); else Frame.Runtime.HandleWarning($"{funcValue.Value?.GetType()} cannot be invoked."); // Push NULL onto the stack to as the result. Push(EarleValue.Undefined); return null; } // Create the frame executor of the function. return function.CreateFrameExecutor(superFrame, callerIp, target, args); }
/// <summary> /// This method is invoked when the instruction needs to be run. /// </summary> /// <param name="frame">The frame which is running the instruction.</param> public void Handle(EarleStackFrame frame) { frame.Executor.CIP = frame.Function.PCode.Length; }
private static void WaitTill(EarleStackFrame frame, string eventName) { var manager = GetManager(frame, "waittill"); if (manager != null) frame.ChildFrame = new WaitTillStackFrameExecutor(frame, frame.Executor.Target, manager, eventName).Frame; }
private static void Notify(EarleStackFrame frame, string eventName, EarleValue[] optionals) { GetManager(frame, "notify") ?.Notify(eventName, optionals?.FirstOrDefault() ?? EarleValue.Undefined); }
/// <summary> /// Initializes a new instance of the <see cref="WaitTillStackFrameExecutor" /> class. /// </summary> /// <param name="parentFrame">The parent frame.</param> /// <param name="target">The target.</param> /// <param name="eventManager">The event manager.</param> /// <param name="eventName">Name of the event.</param> /// <exception cref="System.ArgumentNullException"> /// Thrown if <see cref="eventManager" /> or <see cref="eventName" /> is /// null. /// </exception> public WaitTillStackFrameExecutor(EarleStackFrame parentFrame, EarleValue target, IEarleEventManager eventManager, string eventName) : base(target) { if (eventManager == null) throw new ArgumentNullException(nameof(eventManager)); if (eventName == null) throw new ArgumentNullException(nameof(eventName)); Frame = parentFrame.SpawnChild(null, this, EarleStackFrame.SleepCallIP); _eventName = eventName; eventManager.EventFired += OnEventFired; }
/// <summary> /// This method is invoked when the instruction needs to be run. /// </summary> /// <param name="frame">The frame which is running the instruction.</param> public void Handle(EarleStackFrame frame) { }