/// <summary> /// Invoke the specified method /// </summary> /// <param name="callerInterpreter">The caller interpreter (usually a block)</param> /// <param name="invokeExpression">The invoke expression</param> /// <param name="argumentValues">The list of argument values</param> /// <param name="parentMethodInterpreter">The parent method interpret from where the invocation happened</param> /// <param name="callStackService">The user call stack service</param> /// <returns>Returns the result of the method</returns> internal object InvokeMethod(Interpret callerInterpreter, AlgorithmExpression invokeExpression, Collection <object> argumentValues, MethodInterpreter parentMethodInterpreter, CallStackService callStackService) { var methodName = invokeExpression._methodName.ToString(); var method = Methods.FirstOrDefault(m => m.MethodDeclaration._name.ToString() == methodName); if (method == null) { callerInterpreter.ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(new MethodNotFoundException(methodName, $"The method '{methodName}' does not exists in the current class or is not accessible."), ClassDeclaration), callerInterpreter.GetDebugInfo())); return(null); } if (!method.MethodDeclaration._isAsync && invokeExpression._await) { callerInterpreter.ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(new MethodNotAwaitableException(methodName), method.MethodDeclaration), callerInterpreter.GetDebugInfo())); return(null); } Guid stackTraceId; var isAsync = method.MethodDeclaration._isAsync; if (parentMethodInterpreter == null) { stackTraceId = Guid.Empty; } else { stackTraceId = parentMethodInterpreter.StacktraceId; if (DebugMode) { var callStack = callStackService.CallStacks.Single(cs => cs.TaceId == stackTraceId); var call = callStack.Stack.Pop(); if (call != null) { call.Variables = callerInterpreter.GetAllAccessibleVariable().DeepClone(); callStack.Stack.Push(call); } } } method = new MethodInterpreter(method.MethodDeclaration, DebugMode); method.StateChanged += ChangeState; method.OnGetParentInterpreter += new Func <ClassInterpreter>(() => this); method.OnDone += new Action <MethodInterpreter>((met) => { met.Dispose(); met.StateChanged -= ChangeState; }); method.Initialize(); method.Run(invokeExpression._await, argumentValues, stackTraceId); if (isAsync && !invokeExpression._await) { return(null); } return(method.ReturnedValue); }
/// <summary> /// Execute an expression /// </summary> /// <param name="expression">The expression to interpret</param> /// <returns>Returns the returned value of the expression</returns> internal object RunExpression(AlgorithmExpression expression) { object result = null; switch (expression.DomType) { case AlgorithmDomType.PrimitiveExpression: result = new PrimitiveValue(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.PropertyReferenceExpression: result = new PropertyReference(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.VariableReferenceExpression: result = new VariableReference(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.ClassReferenceExpression: result = new ClassReference(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.ThisReferenceExpression: result = new ThisReference(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.InstanciateExpression: result = new Instanciate(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.InvokeCoreMethodExpression: result = new InvokeCoreMethod(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.InvokeMethodExpression: result = new InvokeMethod(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.BinaryOperatorExpression: result = new BinaryOperator(DebugMode, this, expression).Execute(); break; case AlgorithmDomType.ArrayIndexerExpression: result = new ArrayIndexerExpression(DebugMode, this, expression).Execute(); break; default: ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(new InvalidCastException($"Unable to find an interpreter for this expression : '{expression.GetType().FullName}'"), expression), GetDebugInfo())); break; } return(FailedOrStop ? null : result); }
/// <summary> /// Returns the arguments values /// </summary> /// <returns>Returns a collection of object which represents the argument value</returns> internal static Collection <object> GetArgumentValues(AlgorithmExpression expression, BlockInterpreter parentInterpreter) { var argumentValues = new Collection <object>(); foreach (var arg in expression._argumentsExpression) { if (!parentInterpreter.FailedOrStop) { argumentValues.Add(parentInterpreter.RunExpression(arg)); } } return(argumentValues); }
/// <summary> /// Execute the condition /// </summary> /// <param name="parentInterpreter">The parent block interpreter</param> /// <param name="condition">The condition expression</param> /// <returns>Return true, false, or null in case of error</returns> internal static bool?RunCondition(BlockInterpreter parentInterpreter, AlgorithmExpression condition) { if (condition == null) { parentInterpreter.ChangeState(parentInterpreter, new AlgorithmInterpreterStateEventArgs(new Error(new NullReferenceException("A conditional expression is missing.")), parentInterpreter.GetDebugInfo())); return(null); } var conditionResult = parentInterpreter.RunExpression(condition); if (parentInterpreter.FailedOrStop) { return(null); } var boolResult = conditionResult as bool?; if (boolResult != null) { return(boolResult.Value); } var intResult = conditionResult as int?; if (intResult != null) { switch (intResult.Value) { case 1: return(true); case 0: return(false); default: parentInterpreter.ChangeState(parentInterpreter, new AlgorithmInterpreterStateEventArgs(new Error(new InvalidCastException("Unable to cast this number to a boolean."), condition), parentInterpreter.GetDebugInfo())); return(null); } } parentInterpreter.ChangeState(parentInterpreter, new AlgorithmInterpreterStateEventArgs(new Error(new InvalidCastException("Unable to perform a condition statement without a boolean value as conditional expression result."), condition), parentInterpreter.GetDebugInfo())); return(null); }
/// <summary> /// Initialize a new instance of <see cref="PropertyReference"/> /// </summary> /// <param name="debugMode">Defines if the debug mode is enabled</param> /// <param name="parentInterpreter">The parent block interpreter</param> /// <param name="expression">The algorithm expression</param> internal PropertyReference(bool debugMode, BlockInterpreter parentInterpreter, AlgorithmExpression expression) : base(debugMode, parentInterpreter, expression) { }
/// <summary> /// Initialize a new instance of <see cref="Instanciate"/> /// </summary> /// <param name="debugMode">Defines if the debug mode is enabled</param> /// <param name="parentInterpreter">The parent block interpreter</param> /// <param name="expression">The algorithm expression</param> internal Instanciate(bool debugMode, BlockInterpreter parentInterpreter, AlgorithmExpression expression) : base(debugMode, parentInterpreter, expression) { }
/// <summary> /// Initialize a new instance of <see cref="AlgorithmReturnStatement"/> /// </summary> /// <param name="expression">The expression to return</param> public AlgorithmReturnStatement(AlgorithmExpression expression) : base(expression) { }
/// <summary> /// Initialize a new instance of <see cref="InvokeMethod"/> /// </summary> /// <param name="debugMode">Defines if the debug mode is enabled</param> /// <param name="parentInterpreter">The parent block interpreter</param> /// <param name="expression">The algorithm expression</param> internal InvokeMethod(bool debugMode, BlockInterpreter parentInterpreter, AlgorithmExpression expression) : base(debugMode, parentInterpreter, expression) { }
/// <summary> /// Initialize a new instance of <see cref="InvokeCoreMethod"/> /// </summary> /// <param name="debugMode">Defines if the debug mode is enabled</param> /// <param name="parentInterpreter">The parent block interpreter</param> /// <param name="expression">The algorithm expression</param> internal InvokeCoreMethod(bool debugMode, BlockInterpreter parentInterpreter, AlgorithmExpression expression) : base(debugMode, parentInterpreter, expression) { _dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher; }
/// <summary> /// Initialize a new instance of <see cref="PrimitiveValue"/> /// </summary> /// <param name="debugMode">Defines if the debug mode is enabled</param> /// <param name="parentInterpreter">The parent block interpreter</param> /// <param name="expression">The algorithm expression</param> internal PrimitiveValue(bool debugMode, BlockInterpreter parentInterpreter, AlgorithmExpression expression) : base(debugMode, parentInterpreter, expression) { }
/// <summary> /// Initialize a new instance of <see cref="InterpretExpression"/> /// </summary> /// <param name="debugMode">Defines if the debug mode is enabled</param> /// <param name="parentInterpreter">the parent <see cref="BlockInterpreter"/></param> /// <param name="expression">the algorithm expression</param> internal InterpretExpression(bool debugMode, BlockInterpreter parentInterpreter, AlgorithmExpression expression) : base(debugMode) { ParentInterpreter = parentInterpreter; Expression = expression; }
/// <summary> /// Initialize a new instance of <see cref="BinaryOperator"/> /// </summary> /// <param name="debugMode">Defines if the debug mode is enabled</param> /// <param name="parentInterpreter">The parent block interpreter</param> /// <param name="expression">The algorithm expression</param> internal BinaryOperator(bool debugMode, BlockInterpreter parentInterpreter, AlgorithmExpression expression) : base(debugMode, parentInterpreter, expression) { }
/// <summary> /// Initialize a new instance of <see cref="ArrayIndexerExpression"/> /// </summary> /// <param name="debugMode">Defines if the debug mode is enabled</param> /// <param name="parentInterpreter">The parent block interpreter</param> /// <param name="expression">The algorithm expression</param> internal ArrayIndexerExpression(bool debugMode, BlockInterpreter parentInterpreter, AlgorithmExpression expression) : base(debugMode, parentInterpreter, expression) { }