/// <summary> /// Initialize a new instance of <see cref="BlockInterpreter"/> /// </summary> /// <param name="statements">the list of statements to interpret</param> /// <param name="debugMode">defines is the debug mode is enabled or not</param> /// <param name="parentProgramInterpreter">the parent program interpreter</param> /// <param name="parentMethodInterpreter">the parent method interpreter</param> /// <param name="parentBlockInterpreter">the parent block interpreter</param> /// <param name="parentClassInterpreter">the parent class interpreter</param> internal BlockInterpreter(AlgorithmStatementCollection statements, bool debugMode, ProgramInterpreter parentProgramInterpreter, MethodInterpreter parentMethodInterpreter, BlockInterpreter parentBlockInterpreter, ClassInterpreter parentClassInterpreter) : base(debugMode) { ParentProgramInterpreter = parentProgramInterpreter; ParentMethodInterpreter = parentMethodInterpreter; ParentBlockInterpreter = parentBlockInterpreter; ParentClassInterpreter = parentClassInterpreter; Statements = statements; }
/// <summary> /// Execute a method in the current thread /// </summary> /// <param name="argumentValues">the list of argument values</param> /// <param name="stackTraceId">the user stack trace id</param> /// <param name="mustClearStackAtTheEnd">defines if the user call stack must be cleared at the end of this call</param> private void RunSync(IReadOnlyList <object> argumentValues, Guid stackTraceId, bool mustClearStackAtTheEnd) { if (_callStackService.StackTraceCallCount.ContainsKey(stackTraceId)) { if (_callStackService.StackTraceCallCount[stackTraceId] > Consts.CallStackSize) { ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(new StackOverflowException($"You called too many (more than {Consts.CallStackSize}) methods in the same thread.")), GetParentInterpreter().GetDebugInfo())); return; } ++_callStackService.StackTraceCallCount[stackTraceId]; } else { _callStackService.StackTraceCallCount.Add(stackTraceId, 0); if (DebugMode) { _callStackService.CallStacks.Add(new CallStack(stackTraceId)); } } StacktraceId = stackTraceId; if (DebugMode) { var classReference = new AlgorithmClassReferenceExpression(ParentClassInterpreter.ClassDeclaration.Name.ToString()); var callStack = _callStackService.CallStacks.Single(cs => cs.TaceId == stackTraceId); var arguments = new List <AlgorithmExpression>(); foreach (var argumentValue in argumentValues) { arguments.Add(new AlgorithmPrimitiveExpression(argumentValue)); } var call = new Call(classReference, new AlgorithmInvokeMethodExpression(classReference, MethodDeclaration._name.ToString(), arguments.ToArray())); callStack.Stack.Push(call); } var block = new BlockInterpreter(MethodDeclaration._statements, DebugMode, ParentProgramInterpreter, this, null, ParentClassInterpreter); block.OnGetParentInterpreter += new Func <MethodInterpreter>(() => this); block.StateChanged += ChangeState; block.Initialize(); for (var i = 0; i < MethodDeclaration._arguments.Count; i++) { var argDecl = MethodDeclaration._arguments[i]; var argValue = argumentValues[i]; if (!(argValue is string) && argValue is IList && !argDecl.IsArray) { ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(new BadArgumentException(argDecl.Name.ToString(), $"The argument's value '{argDecl.Name}' must not be an array of values."), MethodDeclaration), GetParentInterpreter().GetDebugInfo())); return; } if ((!(argValue is IList) || argValue is string) && argDecl.IsArray) { ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(new BadArgumentException(argDecl.Name.ToString(), $"The argument's value '{argDecl.Name}' must be an array of values."), MethodDeclaration), GetParentInterpreter().GetDebugInfo())); return; } block.AddVariable(argDecl, argValue, true); } if (FailedOrStop) { return; } // try // { block.Run(); // } // catch (Exception ex) // { // ChangeState(this, new AlgorithmInterpreterStateEventArgs(new Error(ex, MethodDeclaration), GetDebugInfo())); // return; // } // finally // { block.StateChanged -= ChangeState; block.Dispose(); // } if (mustClearStackAtTheEnd) { _callStackService.StackTraceCallCount.Remove(stackTraceId); } if (DebugMode && !Failed) { if (mustClearStackAtTheEnd) { _callStackService.CallStacks.Remove(_callStackService.CallStacks.Single(callStack => callStack.TaceId == stackTraceId)); } else { _callStackService.CallStacks.Single(callStack => callStack.TaceId == stackTraceId).Stack.Pop(); } } Done = true; OnDone(this); }