/// <summary> /// Initialize, after the constructor, the other properties /// </summary> internal override void Initialize() { Variables = new Collection <Variable>(); ParentProgramInterpreter = (ProgramInterpreter)GetFirstNextParentInterpreter(InterpreterType.ProgramInterpreter); ParentClassInterpreter = (ClassInterpreter)GetFirstNextParentInterpreter(InterpreterType.ClassInterpreter); _callStackService = ParentProgramInterpreter.DebugInfo.CallStackService; }
/// <summary> /// Initialize a new instance of <see cref="DebugInfo"/> /// </summary> internal DebugInfo() { CallStackService = new CallStackService(); }
/// <summary> /// Invoke a method in a new thread to avoid a stack overflow exception /// </summary> /// <param name="referenceClass">The class reference</param> /// <param name="argumentValues">The arguments values</param> /// <param name="callerMethod">The method from which we do the call</param> /// <param name="callStackService">The user call stack service</param> /// <returns></returns> private async Task CallMethodNewThread(ClassInterpreter referenceClass, Collection <object> argumentValues, MethodInterpreter callerMethod, CallStackService callStackService) { await ThreadPool.RunAsync(delegate { _result = referenceClass.InvokeMethod(ParentInterpreter, Expression, argumentValues, callerMethod, callStackService); }); }
/// <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); }