private EntryPointMethod GetEntryPointMethod() { var entryPoints = _program.Methods.OfType <EntryPointMethod>().ToList(); if (entryPoints.Count == 0) { BaZicInterpreter.ChangeState(this, new MissingEntryPointMethodException()); return(null); } else if (entryPoints.Count > 1) { BaZicInterpreter.ChangeState(this, new SeveralEntryPointMethodException(), entryPoints.Last()); return(null); } var entryPoint = entryPoints.Single(); if (entryPoint.Arguments.Count != 1) { BaZicInterpreter.ChangeState(this, new BadArgumentException(L.BaZic.Parser.Statements.UniqueArgumentEntryPoint), entryPoint); return(null); } else if (!entryPoint.Arguments.Single().IsArray) { BaZicInterpreter.ChangeState(this, new BadArgumentException(L.BaZic.Parser.Statements.EntryPointArgumentArrayExpected), entryPoint.Arguments.Single()); return(null); } return(entryPoint); }
/// <summary> /// Set the value of the specified variable currently in memory based on its unique ID. /// </summary> /// <param name="variableRef">The reference to the variable to set.</param> /// <param name="value">The value to give to the variable</param> internal void SetVariable(VariableReferenceExpression variableRef, object value) { var variable = GetVariable(variableRef.VariableDeclarationID, variableRef.Name.Identifier, true); if (IsAborted) { return; } var valueInfo = ValueInfo.GetValueInfo(value); if (!valueInfo.IsNull) { if (variable.IsArray && !valueInfo.IsArray) { BaZicInterpreter.ChangeState(this, new NotAssignableException(L.BaZic.Runtime.Interpreters.Interpreter.FormattedArrayExpected(variableRef.Name)), variableRef); return; } else if (!variable.IsArray && valueInfo.IsArray) { BaZicInterpreter.ChangeState(this, new NotAssignableException(L.BaZic.Runtime.Interpreters.Interpreter.FormattedNotArrayExpected(variableRef.Name)), variableRef); return; } } variable.SetValue(value, valueInfo); if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.Interpreter.FormattedVariableSetted(variable.Name, variable)); } }
/// <summary> /// Retrieves the parent interpreter of the current executed method. /// </summary> /// <param name="includeThis">(optional) Defines whether the search must include the current interpreter.</param> /// <param name="throwIfNotFound">(optional) Defines whether an error must be thrown if the parent interpreter is not found.</param> /// <returns>The parent <see cref="MethodInterpreter"/></returns> internal MethodInterpreter GetParentMethodInterpreter(bool includeThis = false, bool throwIfNotFound = true) { if (includeThis && this is MethodInterpreter thisMethodInterpreter) { return(thisMethodInterpreter); } var parentInterpreter = ParentInterpreter; while (parentInterpreter != null) { if (parentInterpreter is MethodInterpreter methodInterpreter) { return(methodInterpreter); } parentInterpreter = parentInterpreter.ParentInterpreter; } if (throwIfNotFound) { BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.Interpreter.ParentMethodNotFound)); } return(null); }
/// <summary> /// Look for the specified variable currently in memory based on its unique ID. /// </summary> /// <param name="variableId">The unique ID that represents the variable.</param> /// <param name="variableName">The friendly name of the variable.</param> /// <param name="throwIfNotFound">(optional) Indicates whether an exception must be thrown if the variable is not found. By default, this argument is True.</param> /// <param name="searchInParents">Defines whether finding a variable can be performed in the parent interpreters.</param> /// <returns>Returns the variable if it has been found, otherwise, null or throws an exception.</returns> internal Variable GetVariable(Guid variableId, string variableName, bool throwIfNotFound = true, bool searchInParents = true) { var interpreter = this; do { var variable = interpreter.Variables.FirstOrDefault(v => v.Id == variableId); if (variable != null) { return(variable); } if (searchInParents) { interpreter = interpreter.ParentInterpreter; } } while (searchInParents && interpreter != null); if (throwIfNotFound) { BaZicInterpreter.ChangeState(this, new VariableNotFoundException(variableName)); } return(null); }
/// <summary> /// Assigns the specified value to a property. /// </summary> /// <param name="propertyReference">The reference to the property to set.</param> /// <param name="value">The value to assign.</param> private void AssignProperty(PropertyReferenceExpression propertyReference, object value) { if (string.IsNullOrWhiteSpace(propertyReference.PropertyName?.Identifier)) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.PropertyReferenceInterpreter.UndefinedName), propertyReference); } var targetObjectValue = ParentInterpreter.RunExpression(propertyReference.TargetObject); if (ParentInterpreter.IsAborted) { return; } if (targetObjectValue == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.PropertyReferenceInterpreter.NullValue), propertyReference); return; } if (propertyReference.TargetObject is ClassReferenceExpression && targetObjectValue is Type) { BaZicInterpreter.Reflection.SetStaticProperty((Type)targetObjectValue, propertyReference.PropertyName.Identifier, value); } else if (targetObjectValue is FrameworkElement) { BaZicInterpreter.ProgramInterpreter.UIDispatcher.Invoke(() => { BaZicInterpreter.Reflection.SetProperty(targetObjectValue, propertyReference.PropertyName.Identifier, value); }, System.Windows.Threading.DispatcherPriority.Background); } else { BaZicInterpreter.Reflection.SetProperty(targetObjectValue, propertyReference.PropertyName.Identifier, value); } }
/// <inheritdoc/> internal override object Run() { var declarations = BaZicInterpreter.MethodDeclarations.Where(m => string.Compare(m.Name.Identifier, Expression.MethodName.Identifier, StringComparison.Ordinal) == 0); if (declarations.Count() == 0) { BaZicInterpreter.ChangeState(this, new MethodNotFoundException(Expression.MethodName.Identifier, L.BaZic.Runtime.Interpreters.Expressions.InvokeMethodInterpreter.FormattedMethodNotFound(Expression.MethodName)), Expression); return(null); } else if (declarations.Count() > 1) { BaZicInterpreter.ChangeState(this, new MethodNotFoundException(Expression.MethodName.Identifier, L.BaZic.Runtime.Interpreters.Expressions.InvokeMethodInterpreter.FormattedSeveralMethods(Expression.MethodName)), Expression); return(null); } // If the invocation is made manually by the user (outisde of the execution flow). if (_failIfNotExtern) { if (!declarations.Single().IsExtern) { BaZicInterpreter.ChangeState(this, new MethodNotFoundException(Expression.MethodName.Identifier, L.BaZic.Runtime.Interpreters.Expressions.InvokeMethodInterpreter.FormattedMethodNotFound(Expression.MethodName)), Expression); return(null); } if (!declarations.Single().IsAsync&& Expression.Await) { Expression.Await = false; } } var methodInterpreter = new MethodInterpreter(BaZicInterpreter, ParentInterpreter, declarations.Single(), Expression, _executionFlowId); return(methodInterpreter.Invoke()); }
/// <inheritdoc/> internal override void Run() { if (!ParentInterpreter.State.IsInIteration) { BaZicInterpreter.ChangeState(this, new IncoherentStatementException(L.BaZic.Runtime.Interpreters.Statements.BreakInterpreter.Illegal), Statement); } ParentInterpreter.State.ExitIteration = true; }
/// <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()); }
/// <inheritdoc/> internal override void Run() { var expression = ParentInterpreter.RunExpression(Statement.Expression); var exception = expression as Exception; if (exception == null) { BaZicInterpreter.ChangeState(this, new BadTypeException(L.BaZic.Runtime.Interpreters.Statements.ThrowInterpreter.FormattedExceptionExpected(typeof(Exception).FullName))); return; } throw exception; }
/// <inheritdoc/> internal override object Run() { var parentBlockInterpreter = ParentInterpreter as BlockInterpreter; if (parentBlockInterpreter == null) { BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.Expressions.ExceptionInterpreter.BlockExpected), Expression); } if (parentBlockInterpreter.CaughtException == null) { BaZicInterpreter.ChangeState(this, new IncoherentStatementException(L.BaZic.Runtime.Interpreters.Expressions.ExceptionInterpreter.TryCatchExpected), Expression); } return(parentBlockInterpreter.CaughtException); }
/// <inheritdoc/> internal override object Run() { if (BaZicInterpreter.Verbose) { ParentInterpreter.VerboseLog(L.BaZic.Runtime.Interpreters.Expressions.PropertyReferenceInterpreter.FormattedGettingProperty(Expression)); } if (Expression.TargetObject == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.PropertyReferenceInterpreter.NullValue), Expression); return(null); } else if (string.IsNullOrWhiteSpace(Expression.PropertyName?.Identifier)) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.PropertyReferenceInterpreter.UndefinedName), Expression); return(null); } var targetObjectValue = ParentInterpreter.RunExpression(Expression.TargetObject); if (ParentInterpreter.IsAborted) { return(null); } if (targetObjectValue == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.PropertyReferenceInterpreter.NullValue), Expression); return(null); } if (Expression.TargetObject is ClassReferenceExpression && targetObjectValue is Type) { return(BaZicInterpreter.Reflection.GetStaticPropertyOrEnum((Type)targetObjectValue, Expression.PropertyName.Identifier)); } if (targetObjectValue is FrameworkElement) { return(BaZicInterpreter.ProgramInterpreter.UIDispatcher.Invoke(() => { return BaZicInterpreter.Reflection.GetProperty(targetObjectValue, Expression.PropertyName.Identifier); }, System.Windows.Threading.DispatcherPriority.Background)); } return(BaZicInterpreter.Reflection.GetProperty(targetObjectValue, Expression.PropertyName.Identifier)); }
/// <summary> /// Adds a new variable to the memory. /// </summary> /// <param name="variableDeclaration">The variable declaration.</param> /// <param name="variable">The variable created from the <paramref name="variableDeclaration"/>.</param> /// <param name="defaultValue">The default value retrieved from the <paramref name="variableDeclaration"/>.</param> /// <param name="defaultValueInfo">The information about the <paramref name="defaultValue"/>.</param> /// <param name="setValueIfNull">Defines whether the value of the variable must be set if the given default value is null.</param> private void AddVariable(VariableDeclaration variableDeclaration, Variable variable, object defaultValue, ValueInfo defaultValueInfo, bool setValueIfNull) { if (IsAborted) { return; } if (!defaultValueInfo.IsNull) { if (variable.IsArray && !defaultValueInfo.IsArray) { BaZicInterpreter.ChangeState(this, new NotAssignableException(L.BaZic.Runtime.Interpreters.Interpreter.FormattedNotArrayExpected(variableDeclaration.Name)), variableDeclaration.DefaultValue); return; } else if (!variable.IsArray && defaultValueInfo.IsArray) { BaZicInterpreter.ChangeState(this, new NotAssignableException(L.BaZic.Runtime.Interpreters.Interpreter.FormattedArrayExpected(variableDeclaration.Name)), variableDeclaration.DefaultValue); return; } } if (defaultValueInfo.IsNull) { if (setValueIfNull) { variable.SetValue(defaultValue, defaultValueInfo); } } else { variable.SetValue(defaultValue, defaultValueInfo); } _variables.Add(variable); if (GetType() != typeof(ProgramInterpreter)) { GetParentMethodInterpreter(includeThis: true).DebugCallInfo.Variables.Add(variable); } if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.Interpreter.FormattedVariableDeclared(variable.Name, variable)); } }
/// <inheritdoc/> internal override void Run() { if (BaZicInterpreter.Verbose) { ParentInterpreter.VerboseLog(L.BaZic.Runtime.Interpreters.Statements.AssignInterpreter.FormattedAssign(Statement.LeftExpression, Statement.RightExpression)); } if (!typeof(IAssignable).IsAssignableFrom(Statement.LeftExpression.GetType())) { BaZicInterpreter.ChangeState(this, new NotAssignableException(L.BaZic.Runtime.Interpreters.Statements.AssignInterpreter.NotAssignable), Statement); return; } var rightValue = ParentInterpreter.RunExpression(Statement.RightExpression); if (ParentInterpreter.IsAborted) { return; } switch (Statement.LeftExpression) { case ArrayIndexerExpression arrayIndexer: AssignArrayValue(arrayIndexer, rightValue); break; case PropertyReferenceExpression propertyReference: AssignProperty(propertyReference, rightValue); break; case VariableReferenceExpression variableReference: ParentInterpreter.SetVariable(variableReference, rightValue); break; default: throw new InternalException(L.BaZic.Runtime.Interpreters.Statements.AssignInterpreter.FormattedNoInterpreter(Statement.LeftExpression.GetType().FullName)); } if (BaZicInterpreter.Verbose && !ParentInterpreter.IsAborted) { var rightValueString = rightValue == null ? L.BaZic.Runtime.Debugger.ValueInfo.Null : $"'{rightValue}'(type:{ rightValue.GetType().FullName})"; ParentInterpreter.VerboseLog(L.BaZic.Runtime.Interpreters.Statements.AssignInterpreter.FormattedNowEqualsTo(Statement.LeftExpression, rightValueString)); } }
/// <inheritdoc/> internal override object Run() { if (Expression.CreateType == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.InstantiateInterpreter.FormattedCreateTypeNull(nameof(InstantiateExpression.CreateType), nameof(InstantiateExpression))), Expression); return(null); } var createType = ParentInterpreter.RunExpression(Expression.CreateType) as Type; if (ParentInterpreter.IsAborted) { return(null); } if (BaZicInterpreter.Verbose) { ParentInterpreter.VerboseLog(L.BaZic.Runtime.Interpreters.Expressions.InstantiateInterpreter.FormattedCreateInstance(Expression.CreateType)); } // Execute argument's values. if (BaZicInterpreter.Verbose) { ParentInterpreter.VerboseLog(L.BaZic.Runtime.Interpreters.MethodInterpreter.ExecutingArguments); } var argumentValues = new List <object>(); for (var i = 0; i < Expression.Arguments.Count; i++) { var argumentValue = ParentInterpreter.RunExpression(Expression.Arguments[i]); argumentValues.Add(argumentValue); } if (ParentInterpreter.IsAborted) { return(null); } return(BaZicInterpreter.Reflection.Instantiate(createType, argumentValues.ToArray())); }
/// <summary> /// Move the execution cursor to the specified label. If the label is in a parent block, it sets a flag to exit the current block. /// </summary> /// <param name="labelName">The name of the label to jump to.</param> private void JumpToLabel(string labelName) { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.BlockInterpreter.FormattedGoTo(labelName)); } var cursor = -1; if (!_labelRegistry.TryGetValue(labelName, out cursor)) { if (ParentInterpreter is BlockInterpreter blockInterpreter) { State.ExitBlockBecauseOfLabelJump = true; blockInterpreter.JumpToLabel(labelName); return; } BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.BlockInterpreter.FormattedLabelNotFound(labelName))); } _executionCursor = cursor; }
/// <inheritdoc/> internal override object Run() { if (Expression.Expression == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.NotOperatorInterpreter.FormattedExpressionNull(nameof(NotOperatorExpression))), Expression); return(null); } var expressionValue = ParentInterpreter.RunExpression(Expression.Expression); if (expressionValue == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.NotOperatorInterpreter.ValueNull), Expression); return(null); } else if (expressionValue.GetType() != typeof(bool)) { BaZicInterpreter.ChangeState(this, new BadTypeException(L.BaZic.Runtime.Interpreters.Expressions.NotOperatorInterpreter.FormattedBooleanExpected(expressionValue.GetType().Name)), Expression); return(null); } return(!(bool)expressionValue); }
/// <summary> /// Creates a new variable in memory. /// </summary> /// <param name="variableDeclaration">The variable declaration to use.</param> /// <param name="searchInParents">Defines whether finding a variable can be performed in the parent interpreters.</param> internal void AddVariable(VariableDeclaration variableDeclaration, bool searchInParents = true) { var existingVariable = GetVariable(variableDeclaration.Id, variableDeclaration.Name.Identifier, false, searchInParents); if (existingVariable != null) { if (!BaZicInterpreter.ProgramIsOptimized) { BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.Interpreter.FormattedDuplicatedVariableId(variableDeclaration.Id)), variableDeclaration); return; } else { var variableRef = new VariableReferenceExpression(existingVariable.Name) { Line = variableDeclaration.Line, Column = variableDeclaration.Column, StartOffset = variableDeclaration.StartOffset, NodeLength = variableDeclaration.NodeLength, VariableDeclarationID = existingVariable.Id }; SetVariable(variableRef, RunExpression(variableDeclaration.DefaultValue)); return; } } if (IsAborted) { return; } var defaultValue = RunExpression(variableDeclaration.DefaultValue); var defaultValueInfo = ValueInfo.GetValueInfo(defaultValue); var variable = new Variable(variableDeclaration); AddVariable(variableDeclaration, variable, defaultValue, defaultValueInfo, true); }
/// <summary> /// Creates a new control accessor in memory. /// </summary> /// <param name="controlAccessorDeclaration">The control accessor declaration to use.</param> internal void AddVariable(ControlAccessorDeclaration controlAccessorDeclaration) { if (GetType() != typeof(ProgramInterpreter)) { BaZicInterpreter.ChangeState(this, new IncoherentStatementException(L.BaZic.Runtime.Interpreters.Interpreter.ForbiddenBinding), controlAccessorDeclaration); return; } var existingVariable = GetVariable(controlAccessorDeclaration.Id, controlAccessorDeclaration.Variable.Name.Identifier, false, true); if (existingVariable != null) { BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.Interpreter.FormattedDuplicatedVariableId(controlAccessorDeclaration.Id)), controlAccessorDeclaration); return; } var defaultValue = RunExpression(controlAccessorDeclaration.Variable.DefaultValue); var defaultValueInfo = ValueInfo.GetValueInfo(defaultValue); if (IsAborted) { return; } var targetControl = ((ProgramInterpreter)this).UserInterface.FindName(controlAccessorDeclaration.ControlName); if (targetControl == null) { BaZicInterpreter.ChangeState(this, new UiException(L.BaZic.Runtime.Interpreters.Interpreter.FormattedUiControlNotFound(controlAccessorDeclaration.ControlName))); return; } var binding = new ControlAccessor(controlAccessorDeclaration, targetControl, BaZicInterpreter); AddVariable(controlAccessorDeclaration.Variable, binding, defaultValue, defaultValueInfo, false); }
/// <inheritdoc/> internal override object Run() { var expressionValue = ParentInterpreter.RunExpression(Expression.TargetObject); if (ParentInterpreter.IsAborted) { return(null); } if (expressionValue == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.NullValue), Expression); return(null); } var valueInfo = ValueInfo.GetValueInfo(expressionValue); if (!valueInfo.IsArray) { BaZicInterpreter.ChangeState(this, new BadTypeException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.FormattedIndexerForbidden(valueInfo.Type.Name)), Expression); return(null); } if (Expression.Indexes.Length != 1) { BaZicInterpreter.ChangeState(this, new OutOfRangeException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.OneIndexerAllowed), Expression); return(null); } var index = ParentInterpreter.RunExpression(Expression.Indexes[0]); if (ParentInterpreter.IsAborted) { return(null); } if (index == null) { BaZicInterpreter.ChangeState(this, new OutOfRangeException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.IndexMustNotBeNull), Expression); return(null); } if (valueInfo.Type == typeof(ObservableDictionary)) { var dictionary = (ObservableDictionary)expressionValue; object val = null; if (dictionary.TryGetValue(index, out val)) { return(val); } BaZicInterpreter.ChangeState(this, new OutOfRangeException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.FormattedKeyDoesNotExist(index?.ToString())), Expression); return(null); } else if (typeof(IDictionary).IsAssignableFrom(valueInfo.Type)) { return(((IDictionary)expressionValue)[index]); } else { var indexValue = index as int?; if (indexValue == null) { BaZicInterpreter.ChangeState(this, new BadArgumentException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.CastToNumber), Expression); return(null); } if (indexValue < 0 || indexValue >= valueInfo.Length) { BaZicInterpreter.ChangeState(this, new OutOfRangeException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.FormattedOutOfRange(indexValue.ToString(), (valueInfo.Length - 1).ToString())), Expression); return(null); } if (valueInfo.Type.IsArray || valueInfo.Type == typeof(Array)) { return(((Array)expressionValue).GetValue(indexValue.Value)); } else if (typeof(IList).IsAssignableFrom(valueInfo.Type)) { return(((IList)expressionValue)[indexValue.Value]); } } BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.FormattedUnsupportedArray(valueInfo.Type.FullName)), Expression); return(null); }
/// <inheritdoc/> internal override object Run() { var leftValue = ParentInterpreter.RunExpression(Expression.LeftExpression); if (ParentInterpreter.IsAborted) { return(null); } var rightValue = ParentInterpreter.RunExpression(Expression.RightExpression); if (ParentInterpreter.IsAborted) { return(null); } if (BaZicInterpreter.Verbose) { ParentInterpreter.VerboseLog(L.BaZic.Runtime.Interpreters.Expressions.BinaryOperatorInterpreter.FormattedPerformOperation(Expression.Operator)); } dynamic dynamicLeftValue = leftValue; dynamic dynamicRightValue = rightValue; switch (Expression.Operator) { case BinaryOperatorType.Equality: return(dynamicLeftValue == dynamicRightValue); case BinaryOperatorType.BitwiseOr: return(dynamicLeftValue | dynamicRightValue); case BinaryOperatorType.BitwiseAnd: return(dynamicLeftValue & dynamicRightValue); case BinaryOperatorType.LogicalOr: return(dynamicLeftValue || dynamicRightValue); case BinaryOperatorType.LogicalAnd: return(dynamicLeftValue && dynamicRightValue); case BinaryOperatorType.LessThan: return(dynamicLeftValue < dynamicRightValue); case BinaryOperatorType.LessThanOrEqual: return(dynamicLeftValue <= dynamicRightValue); case BinaryOperatorType.GreaterThan: return(dynamicLeftValue > dynamicRightValue); case BinaryOperatorType.GreaterThanOrEqual: return(dynamicLeftValue >= dynamicRightValue); case BinaryOperatorType.Addition: return(dynamicLeftValue + dynamicRightValue); case BinaryOperatorType.Subtraction: return(dynamicLeftValue - dynamicRightValue); case BinaryOperatorType.Multiply: return(dynamicLeftValue * dynamicRightValue); case BinaryOperatorType.Division: var convertedToLong = long.TryParse(rightValue.ToString(), out long num); if (convertedToLong && num == 0) { BaZicInterpreter.ChangeState(this, new DivideByZeroException(L.BaZic.Runtime.Interpreters.Expressions.BinaryOperatorInterpreter.DivideByZero), Expression.RightExpression); return(null); } return(dynamicLeftValue / dynamicRightValue); case BinaryOperatorType.Modulus: return(dynamicLeftValue % dynamicRightValue); default: throw new InternalException(L.BaZic.Runtime.Interpreters.Expressions.BinaryOperatorInterpreter.FormattedOperatorNotImplemented(Expression.Operator, nameof(BinaryOperatorInterpreter))); } }
/// <summary> /// Assigns the specified value to an array. /// </summary> /// <param name="arrayIndexer">The reference to the position in the array to set.</param> /// <param name="value">The value to assign.</param> private void AssignArrayValue(ArrayIndexerExpression arrayIndexer, object value) { var expressionValue = ParentInterpreter.RunExpression(arrayIndexer.TargetObject); if (ParentInterpreter.IsAborted) { return; } if (expressionValue == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Statements.AssignInterpreter.TargetObjectNull), arrayIndexer); return; } var valueInfo = ValueInfo.GetValueInfo(expressionValue); if (!valueInfo.IsArray) { BaZicInterpreter.ChangeState(this, new BadTypeException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.FormattedIndexerForbidden(valueInfo.Type.Name)), arrayIndexer); return; } if (arrayIndexer.Indexes.Length != 1) { BaZicInterpreter.ChangeState(this, new OutOfRangeException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.OneIndexerAllowed), arrayIndexer); return; } var index = ParentInterpreter.RunExpression(arrayIndexer.Indexes[0]); if (ParentInterpreter.IsAborted) { return; } if (index == null) { BaZicInterpreter.ChangeState(this, new OutOfRangeException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.IndexMustNotBeNull), arrayIndexer.Indexes[0]); return; } if (valueInfo.Type == typeof(ObservableDictionary)) { ((ObservableDictionary)expressionValue)[index] = value; return; } else if (typeof(IDictionary).IsAssignableFrom(valueInfo.Type)) { ((IDictionary)expressionValue)[index] = value; return; } else { var indexValue = index as int?; if (indexValue == null) { BaZicInterpreter.ChangeState(this, new BadArgumentException(L.BaZic.Runtime.Interpreters.Expressions.ArrayIndexerInterpreter.CastToNumber), arrayIndexer); return; } if (indexValue < 0 || indexValue >= valueInfo.Length) { BaZicInterpreter.ChangeState(this, new OutOfRangeException(L.BaZic.Runtime.Interpreters.Statements.AssignInterpreter.FormattedOutOfRange(indexValue, valueInfo.Length - 1)), arrayIndexer); return; } if (valueInfo.Type.IsArray || valueInfo.Type == typeof(Array)) { ((Array)expressionValue).SetValue(value, indexValue.Value); return; } else if (typeof(IList).IsAssignableFrom(valueInfo.Type)) { ((IList)expressionValue)[indexValue.Value] = value; return; } } BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.Statements.AssignInterpreter.FormattedUnsupportedArray(valueInfo.Type.FullName)), arrayIndexer); }
/// <summary> /// Add a new log /// </summary> /// <param name="message">the message</param> internal void VerboseLog(string message) { BaZicInterpreter.ChangeState(this, new BaZicInterpreterStateChangeEventArgs(message)); }
/// <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(Code.AbstractSyntaxTree.Expression expression) { if (expression == null) { return(null); } if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.Interpreter.FormattedExecutingExpression(expression.GetType().Name)); } object expressionResult = null; switch (expression) { case ArrayCreationExpression arrayCreation: expressionResult = new ArrayCreationInterpreter(BaZicInterpreter, this, arrayCreation).Run(); break; case ArrayIndexerExpression arrayIndexer: expressionResult = new ArrayIndexerInterpreter(BaZicInterpreter, this, arrayIndexer).Run(); break; case BinaryOperatorExpression binaryOperator: expressionResult = new BinaryOperatorInterpreter(BaZicInterpreter, this, binaryOperator).Run(); break; case ClassReferenceExpression classReference: expressionResult = new ClassReferenceInterpreter(BaZicInterpreter, this, classReference).Run(); break; case ExceptionReferenceExpression exceptionReference: expressionResult = new ExceptionInterpreter(BaZicInterpreter, this, exceptionReference).Run(); break; case InstantiateExpression instantiate: expressionResult = new InstantiateInterpreter(BaZicInterpreter, this, instantiate).Run(); break; case InvokeCoreMethodExpression invokeCoreMethod: expressionResult = new InvokeCoreMethodInterpreter(BaZicInterpreter, this, invokeCoreMethod, ExecutionFlowId).Run(); break; case InvokeMethodExpression invokeMethod: expressionResult = new InvokeMethodInterpreter(BaZicInterpreter, this, invokeMethod, ExecutionFlowId).Run(); break; case NotOperatorExpression notOperator: expressionResult = new NotOperatorInterpreter(BaZicInterpreter, this, notOperator).Run(); break; case PrimitiveExpression primitive: expressionResult = new PrimitiveInterpreter(BaZicInterpreter, this, primitive).Run(); break; case PropertyReferenceExpression propertyReference: expressionResult = new PropertyReferenceInterpreter(BaZicInterpreter, this, propertyReference).Run(); break; case VariableReferenceExpression variableReference: expressionResult = new VariableReferenceInterpreter(BaZicInterpreter, this, variableReference).Run(); break; default: BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.Interpreter.FormattedInterpreterNotFound(expression.GetType().Name)), expression); break; } if (IsAborted) { return(null); } if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.Interpreter.FormattedExpressionReturnedValue(expressionResult, ValueInfo.GetValueInfo(expressionResult))); } return(expressionResult); }
private void RunStatement(Code.AbstractSyntaxTree.Statement statement) { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.BlockInterpreter.FormattedExecutingStatement(statement.GetType().Name)); } switch (statement) { case AssignStatement assign: new AssignInterpreter(BaZicInterpreter, this, ExecutionFlowId, assign).Run(); break; case BreakStatement @break: new BreakInterpreter(BaZicInterpreter, this, ExecutionFlowId, @break).Run(); break; case CommentStatement comment: // Just ignore break; case ConditionStatement condition: var conditionInterpreter = new ConditionInterpreter(BaZicInterpreter, this, ExecutionFlowId, condition); conditionInterpreter.Run(); ApplyChildBlockState(conditionInterpreter.ChildBlockState); break; case GoToLabelStatement goToLabel: JumpToLabel(goToLabel.Name.Identifier); break; case IterationStatement iteration: var iterationInterpreter = new IterationInterpreter(BaZicInterpreter, this, ExecutionFlowId, iteration); iterationInterpreter.Run(); ApplyChildBlockState(iterationInterpreter.ChildBlockState); break; case LabelConditionStatement labelCondition: var labelConditionInterpreter = new LabelConditionInterpreter(BaZicInterpreter, this, ExecutionFlowId, labelCondition); labelConditionInterpreter.Run(); if (!IsAborted && labelConditionInterpreter.ConditionValidated) { JumpToLabel(labelCondition.LabelName.Identifier); } break; case LabelDeclaration labelDeclaration: // Just ignore break; case ReturnStatement @return: new ReturnInterpreter(BaZicInterpreter, this, ExecutionFlowId, @return).Run(); break; case ThrowStatement @throw: new ThrowInterpreter(BaZicInterpreter, this, ExecutionFlowId, @throw).Run(); break; case TryCatchStatement tryCatch: var tryCatchInterpreter = new TryCatchInterpreter(BaZicInterpreter, this, ExecutionFlowId, tryCatch); tryCatchInterpreter.Run(); ApplyChildBlockState(tryCatchInterpreter.ChildBlockState); break; case VariableDeclaration variableDeclaration: new VariableDeclarationInterpreter(BaZicInterpreter, this, ExecutionFlowId, variableDeclaration).Run(); break; case ExpressionStatement expressionStatement: new ExpressionStatementInterpreter(BaZicInterpreter, this, ExecutionFlowId, expressionStatement).Run(); break; case BreakpointStatement breakpoint: if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.BlockInterpreter.BreakpointIntercepted); } BaZicInterpreter.Pause(); Task.Delay(100).Wait(); break; default: BaZicInterpreter.ChangeState(this, new InternalException(L.BaZic.Runtime.Interpreters.BlockInterpreter.FormattedInterpreterNotFound(statement.GetType().FullName)), statement); break; } if (BaZicInterpreter.Verbose && (State.ExitMethod || State.ExitIteration || State.ExitBlockBecauseOfLabelJump)) { VerboseLog(L.BaZic.Runtime.Interpreters.BlockInterpreter.ExitingBlock); } }
/// <inheritdoc/> internal override object Run() { if (Expression.TargetObject == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.InvokeCoreMethodInterpreter.TargetObjectNull), Expression); return(null); } else if (string.IsNullOrWhiteSpace(Expression.MethodName?.Identifier)) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.InvokeCoreMethodInterpreter.UndefinedMethodName), Expression); return(null); } var targetObjectValue = ParentInterpreter.RunExpression(Expression.TargetObject); if (ParentInterpreter.IsAborted) { return(null); } if (targetObjectValue == null) { BaZicInterpreter.ChangeState(this, new NullValueException(L.BaZic.Runtime.Interpreters.Expressions.InvokeCoreMethodInterpreter.TargetObjectNull), Expression); return(null); } // Execute argument's values. if (BaZicInterpreter.Verbose) { ParentInterpreter.VerboseLog(L.BaZic.Runtime.Interpreters.MethodInterpreter.ExecutingArguments); } var argumentValues = new List <object>(); for (var i = 0; i < Expression.Arguments.Count; i++) { var argumentValue = ParentInterpreter.RunExpression(Expression.Arguments[i]); argumentValues.Add(argumentValue); } if (ParentInterpreter.IsAborted) { return(null); } object result = null; if (Expression.TargetObject is ClassReferenceExpression && targetObjectValue is Type) { result = BaZicInterpreter.Reflection.InvokeStaticMethod((Type)targetObjectValue, Expression.MethodName.Identifier, argumentValues.ToArray()); } else if (targetObjectValue is FrameworkElement) { BaZicInterpreter.ProgramInterpreter.UIDispatcher.Invoke(() => { result = BaZicInterpreter.Reflection.InvokeMethod(targetObjectValue, Expression.MethodName.Identifier, argumentValues.ToArray()); }, System.Windows.Threading.DispatcherPriority.Background); } else { result = BaZicInterpreter.Reflection.InvokeMethod(targetObjectValue, Expression.MethodName.Identifier, argumentValues.ToArray()); } if (Expression.Await) { if (result == null || !typeof(Task).IsAssignableFrom(result.GetType())) { BaZicInterpreter.ChangeState(this, new MethodNotAwaitableException(Expression.MethodName.Identifier), Expression); return(null); } else { var task = (Task)result; task.Wait(); var type = task.GetType(); if (!type.IsGenericType) { result = null; } else { result = type.GetProperty(nameof(Task <object> .Result)).GetValue(task); } task.Dispose(); } } else if (result != null && typeof(Task).IsAssignableFrom(result.GetType())) { var task = (Task)result; BaZicInterpreter.RunningStateManager.AddUnwaitedMethodInvocation(_executionFlowId, task); } return(result); }
internal object Invoke() { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.MethodInterpreter.FormattedPreparing(_invokeMethod.MethodName)); } DebugCallInfo = new Call(_invokeMethod); var awaitCall = _invokeMethod.Await; if (awaitCall && !_methodDeclaration.IsAsync) { BaZicInterpreter.ChangeState(this, new MethodNotAwaitableException(_methodDeclaration.Name.Identifier), _invokeMethod); return(ReturnedValue); } if (_methodDeclaration.Arguments.Count != _invokeMethod.Arguments.Count) { BaZicInterpreter.ChangeState(this, new MethodNotFoundException(_methodDeclaration.Name.Identifier, L.BaZic.Runtime.Interpreters.MethodInterpreter.FormattedBadArgumentCount(_methodDeclaration.Name, _invokeMethod.Arguments.Count)), _invokeMethod); return(ReturnedValue); } // Execute argument's values. if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.MethodInterpreter.ExecutingArguments); } var argumentValues = new List <object>(); for (var i = 0; i < _invokeMethod.Arguments.Count; i++) { var argumentValue = RunExpression(_invokeMethod.Arguments[i]); argumentValues.Add(argumentValue); } if (IsAborted) { return(ReturnedValue); } if (BaZicInterpreter.ProgramInterpreter.TotalSynchronousCallCount > 0 && BaZicInterpreter.ProgramInterpreter.TotalSynchronousCallCount % 500 == 0) { GC.Collect(); GC.WaitForPendingFinalizers(); } // Execute the method. if (_methodDeclaration.IsAsync) { if (awaitCall) { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.MethodInterpreter.FormattedAwait(_invokeMethod.MethodName)); } RunAsync(argumentValues).Wait(); return(ReturnedValue); } else { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.MethodInterpreter.FormattedAsync(_invokeMethod.MethodName)); } AsyncMethodCalledWithoutAwait = true; var task = RunAsync(argumentValues); BaZicInterpreter.RunningStateManager.AddUnwaitedMethodInvocation(ExecutionFlowId, task); return(task); } } else { if (BaZicInterpreter.Verbose) { VerboseLog(L.BaZic.Runtime.Interpreters.MethodInterpreter.FormattedSync(_invokeMethod.MethodName)); } BaZicInterpreter.ProgramInterpreter.SynchronousCallCount++; BaZicInterpreter.ProgramInterpreter.TotalSynchronousCallCount++; if (BaZicInterpreter.ProgramInterpreter.TotalSynchronousCallCount >= Consts.StackOverflowLimit) { BaZicInterpreter.ChangeState(this, new Debugger.Exceptions.StackOverflowException(L.BaZic.Runtime.Interpreters.MethodInterpreter.FormattedStackOverflow(Consts.StackOverflowLimit))); return(ReturnedValue); } if (BaZicInterpreter.ProgramInterpreter.SynchronousCallCount >= Consts.CallLimitBeforeNewThread) { BaZicInterpreter.ProgramInterpreter.SynchronousCallCount = 0; CallMethodNewThread(argumentValues).Wait(); } else { RunSync(argumentValues); } return(ReturnedValue); } }
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; } } }