public EarleStackFrameExecutor(EarleFunction function, EarleStackFrame parentFrame, int callerIp, EarleValue target, IEarleRuntimeScope superScope, EarleDictionary locals) : base(target) { Frame = parentFrame.SpawnChild(function, this, callerIp); Scopes.Push(new EarleRuntimeScope(superScope, locals)); }
public virtual bool SetValue(string name, EarleValue value) { if ((_superScope?.GetValue(name) ?? EarleValue.Undefined).HasValue) { return _superScope.SetValue(name, value); } if (CanAssignVariableInScope(name)) { _locals[name] = value; return true; } return false; }
public virtual IEarleStackFrameExecutor CreateFrameExecutor(EarleStackFrame parentFrame, int callerIp, EarleValue target, EarleValue[] arguments) { if (arguments == null) throw new ArgumentNullException(nameof(arguments)); var locals = new EarleDictionary(); var index = 0; if (Parameters == null) { throw new Exception("Parameters cannot be null in order for a EarleStackFrameExecutor to be created."); } foreach (var parameter in Parameters) { locals[parameter] = index >= arguments.Length ? EarleValue.Undefined : arguments[index]; index++; } return new EarleStackFrameExecutor(this, parentFrame, callerIp, target, File, locals); }
/// <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); }
public EarleValue? Invoke(EarleCompletionHandler completionHandler, EarleValue target, params EarleValue[] args) { var thread = new EarleThread(completionHandler); var rootFrame = new EarleStackFrame(File.Runtime, null, null, EarleStackFrame.RootFrameIP, null, thread); var frame = CreateFrameExecutor(rootFrame, EarleStackFrame.RootCallIP, target, args?.ToArray() ?? new EarleValue[0]); thread.AttachExecutor(frame); return thread.Run(); }
private static bool IsDefined(EarleValue value) { return value.Value != null; }
public virtual bool SetValue(string name, EarleValue value) { if (name == "self" || name == "thread") { Frame.Runtime.HandleWarning($"'{name}' cannot be set!"); return false; } return Scopes.Peek().SetValue(name, value); }
public EarleBaseStackFrameExecutor(EarleValue target) { Target = target; }
public void SetField(string name, EarleValue value) { // Values cannot be set. }
/// <summary> /// Runs the specified unary operator. /// </summary> /// <param name="operator">The operator to run.</param> /// <param name="value">The value.</param> /// <returns>The result of the operation.</returns> public EarleValue RunUnaryOperator(OpCode @operator, EarleValue value) { Func<EarleValue, EarleValue> func; return _unaryOperators.TryGetValue(new Tuple<OpCode, Type>(@operator, value.Value?.GetType()), out func) ? func(value) : EarleValue.Undefined; }
/// <summary> /// Runs the specified binary operator. /// </summary> /// <param name="operator">The operator to run.</param> /// <param name="left">The left value.</param> /// <param name="right">The right value.</param> /// <returns>The result of the operation.</returns> public EarleValue RunBinaryOperator(OpCode @operator, EarleValue left, EarleValue right) { Tuple<bool, Func<EarleValue, EarleValue, EarleValue>> op; if ( !_binaryOperators.TryGetValue( new Tuple<OpCode, Type, Type>(@operator, left.Value?.GetType(), right.Value?.GetType()), out op) && !_binaryOperators.TryGetValue(new Tuple<OpCode, Type, Type>(@operator, null, right.Value?.GetType()), out op) && !_binaryOperators.TryGetValue(new Tuple<OpCode, Type, Type>(@operator, left.Value?.GetType(), null), out op)) return EarleValue.Undefined; if (op.Item1) { var tmp = left; left = right; right = tmp; } return op.Item2(left, right); }
/// <summary> /// Initializes a new instance of the <see cref="EarleEventNotifyEventArgs" /> class. /// </summary> /// <param name="eventName">Name of the event.</param> /// <param name="firer">The firer of the event.</param> public EarleEventNotifyEventArgs(string eventName, EarleValue firer) { EventName = eventName; Firer = firer; }
private static void Notify(EarleStackFrame frame, string eventName, EarleValue[] optionals) { GetManager(frame, "notify") ?.Notify(eventName, optionals?.FirstOrDefault() ?? EarleValue.Undefined); }
/// <summary> /// Called when an event is fired. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="EarleEventNotifyEventArgs" /> instance containing the event data.</param> private void OnEventFired(object sender, EarleEventNotifyEventArgs e) { if (e.EventName == _eventName) { _hasFired = true; _firer = e.Firer; } }
/// <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; }