/// <summary> /// Invoke a public method accessible from outside of the interpreter (EXTERN FUNCTION). /// </summary> /// <param name="executionFlowId">A GUID that defines in which callstack is linked.</param> /// <param name="methodName">The name of the method.</param> /// <param name="awaitIfAsync">Await if the method is maked as asynchronous.</param> /// <param name="args">The arguments to pass to the method.</param> /// <returns>Returns the result of the invocation (a <see cref="Task"/> in the case of a not awaited asynchronous method, or the value returned by the method).</returns> internal object InvokeMethod(Guid executionFlowId, string methodName, bool awaitIfAsync, Code.AbstractSyntaxTree.Expression[] args) { InitializeGlobalState(); BaZicInterpreter.CheckState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); var invokeExpression = new InvokeMethodExpression(methodName, awaitIfAsync).WithParameters(args); BaZicInterpreter.ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); return(new InvokeMethodInterpreter(BaZicInterpreter, this, invokeExpression, executionFlowId, true).Run()); }
internal void Start(object[] args) { BaZicInterpreter.CheckState(BaZicInterpreterState.Preparing); InitializeGlobalState(); var entryPoint = GetEntryPointMethod(); if (IsAborted) { return; } if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.ProgramInterpreter.EntryPointDetected); } BaZicInterpreter.ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); var argsExpressions = new List <Code.AbstractSyntaxTree.Expression>(); if (args != null) { foreach (var argument in args) { argsExpressions.Add(new PrimitiveExpression(argument)); } } var entryPointInvocation = new InvokeMethodExpression(Consts.EntryPointMethodName, false).WithParameters(new ArrayCreationExpression().WithValues(argsExpressions.ToArray())); var entryPointInterpreter = new MethodInterpreter(BaZicInterpreter, this, entryPoint, entryPointInvocation, ExecutionFlowId); ProgramResult = entryPointInterpreter.Invoke(); if (IsAborted) { return; } if (_uiProgram != null && ProgramResult == null) { Exception eventException = null; ThreadHelper.RunOnStaThread(() => { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.ProgramInterpreter.LoadingUi); } _uiThread = Thread.CurrentThread; LoadUserInterface(); if (UserInterface == null) { BaZicInterpreter.ChangeState(this, new UiException(L.BaZic.Parser.XamlUnknownParsingError)); return; } UIDispatcher = UserInterface.Dispatcher; if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.ProgramInterpreter.DeclaringEvents); } foreach (var uiEvent in _uiProgram.UiEvents) { var targetObject = UserInterface.FindName(uiEvent.ControlName); if (targetObject == null) { BaZicInterpreter.ChangeState(this, new UiException($"Unable to find the control named '{uiEvent.ControlName}'.")); return; } var action = new Action(() => { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.ProgramInterpreter.EventRaised); } BaZicInterpreter.ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); var eventMethodDeclaration = _uiProgram.Methods.Single(m => m.Id == uiEvent.MethodId); var eventInvocation = new InvokeMethodExpression(eventMethodDeclaration.Name.Identifier, false); var eventMethodInterpreter = new MethodInterpreter(BaZicInterpreter, this, eventMethodDeclaration, eventInvocation, ExecutionFlowId); if (targetObject is Window && uiEvent.ControlEventName == nameof(Window.Closed)) { ProgramResult = eventMethodInterpreter.Invoke(); } else { eventMethodInterpreter.Invoke(); } BaZicInterpreter.RunningStateManager.SetIsRunningMainFunction(false); // In all cases, at this point, the main function is done. The UI is running. Idle state must be able to be setted. BaZicInterpreter.RunningStateManager.UpdateState(); }); BaZicInterpreter.Reflection.SubscribeEvent(targetObject, uiEvent.ControlEventName, action); } if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.ProgramInterpreter.DeclaringBindings); } foreach (var controlAccessor in _uiProgram.UiControlAccessors) { AddVariable(controlAccessor); } if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.ProgramInterpreter.ShowUi); } var window = UserInterface as Window; try { if (window != null) { window.Closed += (sender, e) => { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.ProgramInterpreter.CloseUi); } UserInterface?.Dispatcher?.InvokeShutdown(); }; } BaZicInterpreter.ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Idle)); window?.Show(); Dispatcher.Run(); } catch (Exception exception) { CoreHelper.ReportException(exception); eventException = exception; } finally { try { window?.Close(); } catch (Exception exception) { CoreHelper.ReportException(exception); } finally { RuntimeResourceManager.DeleteResources(ExecutionFlowId.ToString()); foreach (var variable in Variables) { variable.Dispose(); } BaZicInterpreter.Reflection.UnsubscribeAllEvents(); UserInterface = null; } } }); if (eventException != null) { throw eventException; } } }