public void TestReplaceVariables(string input, string expected) { input = input.Replace("A", "byte(10)"); input = input.Replace("B", "byte(11)"); input = input.Replace("C", "byte(12)"); expected = expected.Replace("A", "byte(10)"); expected = expected.Replace("B", "byte(11)"); expected = expected.Replace("C", "byte(12)"); var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input)); var expression = ExpressionBase.Parse(tokenizer); var scope = new InterpreterScope(); scope.AddFunction(new MemoryAccessorFunction("byte", FieldSize.Byte)); scope.AddFunction(new AlwaysTrueFunction()); scope.AddFunction(new AlwaysFalseFunction()); scope.Context = new TriggerBuilderContext(); ExpressionBase result; Assert.That(expression.ReplaceVariables(scope, out result), Is.True); var builder = new StringBuilder(); result.AppendString(builder); Assert.That(builder.ToString(), Is.EqualTo(expected)); }
private string EvaluateError(string formatString, ExpressionBase[] parameters) { var newParameters = new List <ExpressionBase>(); newParameters.Add(new StringConstantExpression(formatString)); newParameters.AddRange(parameters); var expression = new FunctionCallExpression("format", newParameters); var scope = new InterpreterScope(); scope.AddFunction(new FormatFunction()); scope.AddFunction(new AddFunction()); ExpressionBase result; Assert.That(expression.Evaluate(scope, out result), Is.False); Assert.That(result, Is.InstanceOf <ParseErrorExpression>()); var parseError = (ParseErrorExpression)result; while (parseError.InnerError != null) { parseError = parseError.InnerError; } return(parseError.Message); }
public void TestReplaceVariablesMethodCall() { var input = "function func(i) { j = i }"; var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input)); tokenizer.Match("function"); var functionDefinition = (FunctionDefinitionExpression)FunctionDefinitionExpression.Parse(tokenizer); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) }); var value1 = new IntegerConstantExpression(98); var expr = new DictionaryExpression(); expr.Entries.Add(new DictionaryExpression.DictionaryEntry { Key = functionCall, Value = value1 }); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.False); Assert.That(result, Is.InstanceOf <ParseErrorExpression>()); Assert.That(((ParseErrorExpression)result).Message, Is.EqualTo("func did not return a value")); }
public void TestEvaluateDictionaryByReference() { // ensures the dictionary is passed by reference to func(), so it can be modified // within func(). it's also much more efficient to pass the dictionary by reference // instead of evaluating it (which creates a copy). var functionDefinition = Parse("function func(d) { d[\"key\"] = 2 }"); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); var dict = new DictionaryExpression(); dict.Add(new StringConstantExpression("key"), new IntegerConstantExpression(1)); scope.AssignVariable(new VariableExpression("dict"), dict); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new VariableExpression("dict") }); ExpressionBase result; Assert.That(functionCall.Evaluate(scope, out result), Is.True); Assert.That(result, Is.Null); Assert.That(dict.Count, Is.EqualTo(1)); Assert.That(dict[0].Value, Is.InstanceOf <IntegerConstantExpression>()); Assert.That(((IntegerConstantExpression)dict[0].Value).Value, Is.EqualTo(2)); }
public void TestReplaceVariablesIndexFunctionCall() { var functionDefinition = UserFunctionDefinitionExpression.ParseForTest("function func(i) => 6"); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) }); var value = new IntegerConstantExpression(98); var variable = new VariableExpression("variable"); var dict = new DictionaryExpression(); dict.Add(new IntegerConstantExpression(6), value); var scope = new InterpreterScope(); scope.AssignVariable(variable, dict); scope.AddFunction(functionDefinition); var expr = new IndexedVariableExpression(variable, functionCall); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.True); Assert.That(result, Is.InstanceOf <IntegerConstantExpression>()); Assert.That(((IntegerConstantExpression)result).Value, Is.EqualTo(98)); }
public void TestPopComparison() { var scope = new InterpreterScope(); var array = new ArrayExpression(); var funcCall = new FunctionCallExpression("happy", new ExpressionBase[] { new IntegerConstantExpression(1) }); array.Entries.Add(new ComparisonExpression(funcCall, ComparisonOperation.Equal, new IntegerConstantExpression(2))); scope.DefineVariable(new VariableDefinitionExpression("arr"), array); var happyFunc = new FunctionDefinitionExpression("happy"); happyFunc.Parameters.Add(new VariableDefinitionExpression("num1")); happyFunc.Expressions.Add(new ReturnExpression(new VariableExpression("num1"))); scope.AddFunction(happyFunc); var entry = Evaluate("array_pop(arr)", scope); Assert.That(entry, Is.InstanceOf <ComparisonExpression>()); var comparison = (ComparisonExpression)entry; Assert.That(comparison.Left, Is.InstanceOf <FunctionCallExpression>()); Assert.That(((FunctionCallExpression)comparison.Left).FunctionName.Name, Is.EqualTo("happy")); Assert.That(comparison.Right, Is.InstanceOf <IntegerConstantExpression>()); Assert.That(((IntegerConstantExpression)comparison.Right).Value, Is.EqualTo(2)); }
public void TestReplaceVariablesMethodCall() { var functionDefinition = UserFunctionDefinitionExpression.ParseForTest("function func(i) { j = i }"); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) }); var value1 = new IntegerConstantExpression(98); var expr = new DictionaryExpression(); expr.Add(functionCall, value1); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.False); Assert.That(result, Is.InstanceOf <ParseErrorExpression>()); var parseError = (ParseErrorExpression)result; while (parseError.InnerError != null) { parseError = parseError.InnerError; } Assert.That(parseError.Message, Is.EqualTo("func did not return a value")); }
public void TestReplaceVariablesIndexFunctionCall() { var input = "function func(i) => 6"; var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input)); tokenizer.Match("function"); var functionDefinition = (FunctionDefinitionExpression)FunctionDefinitionExpression.Parse(tokenizer); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) }); var value = new IntegerConstantExpression(98); var variable = new VariableExpression("variable"); var dict = new DictionaryExpression(); dict.Entries.Add(new DictionaryExpression.DictionaryEntry { Key = new IntegerConstantExpression(6), Value = value }); var scope = new InterpreterScope(); scope.AssignVariable(variable, dict); scope.AddFunction(functionDefinition); var expr = new IndexedVariableExpression(variable, functionCall); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.True); Assert.That(result, Is.InstanceOf <IntegerConstantExpression>()); Assert.That(((IntegerConstantExpression)result).Value, Is.EqualTo(98)); }
public void TestReplaceVariablesFunctionCall() { var input = "function func(i) => 6"; var tokenizer = new PositionalTokenizer(Tokenizer.CreateTokenizer(input)); tokenizer.Match("function"); var functionDefinition = (FunctionDefinitionExpression)FunctionDefinitionExpression.Parse(tokenizer); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) }); var value1 = new IntegerConstantExpression(98); var expr = new DictionaryExpression(); expr.Entries.Add(new DictionaryExpression.DictionaryEntry { Key = functionCall, Value = value1 }); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.True); Assert.That(result, Is.InstanceOf <DictionaryExpression>()); var dictResult = (DictionaryExpression)result; Assert.That(dictResult.Entries.Count, Is.EqualTo(1)); Assert.That(dictResult.Entries[0].Key, Is.EqualTo(new IntegerConstantExpression(6))); Assert.That(dictResult.Entries[0].Value, Is.EqualTo(value1)); }
public void TestAddAndGetFunction() { var function = new FunctionDefinitionExpression("test"); var scope = new InterpreterScope(); scope.AddFunction(function); Assert.That(scope.GetFunction("test"), Is.SameAs(function)); }
public void TestMerge() { var scope1 = new InterpreterScope(); scope1.DefineVariable(new VariableDefinitionExpression("a"), new IntegerConstantExpression(1)); var scope2 = new InterpreterScope(); scope2.DefineVariable(new VariableDefinitionExpression("a"), new IntegerConstantExpression(4)); scope2.DefineVariable(new VariableDefinitionExpression("d"), new IntegerConstantExpression(5)); scope2.AddFunction(new FunctionDefinitionExpression("f1")); var scope3 = new InterpreterScope(); scope3.DefineVariable(new VariableDefinitionExpression("b"), new IntegerConstantExpression(2)); scope3.DefineVariable(new VariableDefinitionExpression("c"), new IntegerConstantExpression(3)); var scope4 = new InterpreterScope(); scope4.AddFunction(new FunctionDefinitionExpression("f1")); scope4.AddFunction(new FunctionDefinitionExpression("f2")); var union = new InterpreterScope(); Assert.That(union.VariableCount, Is.EqualTo(0)); Assert.That(union.FunctionCount, Is.EqualTo(0)); union.Merge(scope1); Assert.That(union.VariableCount, Is.EqualTo(1)); Assert.That(union.FunctionCount, Is.EqualTo(0)); union.Merge(scope2); Assert.That(union.VariableCount, Is.EqualTo(2)); Assert.That(union.FunctionCount, Is.EqualTo(1)); Assert.That(union.GetVariable("a"), Is.EqualTo(new IntegerConstantExpression(4))); union.Merge(scope3); Assert.That(union.VariableCount, Is.EqualTo(4)); Assert.That(union.FunctionCount, Is.EqualTo(1)); union.Merge(scope4); Assert.That(union.VariableCount, Is.EqualTo(4)); Assert.That(union.FunctionCount, Is.EqualTo(2)); }
private string Evaluate(string formatString, ExpressionBase[] parameters) { var newParameters = new List <ExpressionBase>(); newParameters.Add(new StringConstantExpression(formatString)); newParameters.AddRange(parameters); var expression = new FunctionCallExpression("format", newParameters); var scope = new InterpreterScope(); scope.AddFunction(new FormatFunction()); scope.AddFunction(new AddFunction()); ExpressionBase result; Assert.IsTrue(expression.Evaluate(scope, out result)); Assert.IsTrue(result is StringConstantExpression); return(((StringConstantExpression)result).Value); }
public void TestFunctionCall() { var scope = new InterpreterScope(); var array = new ArrayExpression(); scope.DefineVariable(new VariableDefinitionExpression("arr"), array); scope.AddFunction(UserFunctionDefinitionExpression.ParseForTest( "function happy(val) => val + \"rama\"" )); Assert.That(Evaluate("length(happy(\"banana\"))", scope), Is.EqualTo(10)); }
public void TestIsTrueUserFunctionReturningBoolean() { var userFunc = Parse("function u() => always_true()"); var expr = new FunctionCallExpression("u", new ExpressionBase[0]); var scope = new InterpreterScope(AchievementScriptInterpreter.GetGlobalScope()); scope.AddFunction(userFunc); ParseErrorExpression error; Assert.That(expr.IsTrue(scope, out error), Is.True); Assert.That(error, Is.Null); }
public void TestEvaluateMethod() { var functionDefinition = Parse("function func(i) { j = i }"); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); var value = new IntegerConstantExpression(6); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { value }); ExpressionBase result; Assert.That(functionCall.Evaluate(scope, out result), Is.True); Assert.That(result, Is.Null); }
public void TestEvaluateMathematical() { var functionDefinition = Parse("function func(i) { return i * 2 }"); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); var value = new IntegerConstantExpression(6); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { value }); ExpressionBase result; Assert.That(functionCall.Evaluate(scope, out result), Is.True); Assert.That(result, Is.EqualTo(new IntegerConstantExpression(12))); }
public void TestReplaceVariablesFunctionName() { var variable = new VariableExpression("func"); var scope = new InterpreterScope(); scope.AddFunction(new FunctionDefinitionExpression("func")); ExpressionBase result; Assert.That(variable.ReplaceVariables(scope, out result), Is.True); Assert.That(result, Is.InstanceOf <FunctionReferenceExpression>()); Assert.That(((FunctionReferenceExpression)result).Name, Is.EqualTo("func")); }
public void TestReplaceVariablesVariable() { var functionDefinition = Parse("function func(i) { return i }"); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); var value = new IntegerConstantExpression(6); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { value }); ExpressionBase result; Assert.That(functionCall.ReplaceVariables(scope, out result), Is.True); Assert.That(result, Is.EqualTo(value)); }
public void TestReplaceVariablesFunctionName() { var variable = new VariableExpression("func"); var scope = new InterpreterScope(); scope.AddFunction(new FunctionDefinitionExpression("func")); ExpressionBase result; Assert.That(variable.ReplaceVariables(scope, out result), Is.False); Assert.That(result, Is.InstanceOf <ParseErrorExpression>()); Assert.That(((ParseErrorExpression)result).Message, Is.EqualTo("Function used like a variable: func")); }
public void TestModulusZero() { var left = new FunctionCallExpression("byte", new[] { new IntegerConstantExpression(0) }); var right = new IntegerConstantExpression(0); var expr = new MathematicExpression(left, MathematicOperation.Modulus, right); var scope = new InterpreterScope(); scope.Context = new TriggerBuilderContext(); scope.AddFunction(new MemoryAccessorFunction("byte", FieldSize.Byte)); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.False); Assert.That(((ParseErrorExpression)result).Message, Is.EqualTo("Division by zero")); }
public void TestReplaceVariablesMethod() { var functionDefinition = Parse("function func(i) { j = i }"); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); var value = new IntegerConstantExpression(6); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { value }); ExpressionBase result; Assert.That(functionCall.ReplaceVariables(scope, out result), Is.False); Assert.That(result, Is.InstanceOf <ParseErrorExpression>()); Assert.That(((ParseErrorExpression)result).Message, Is.EqualTo("func did not return a value")); }
public void TestAddZero() { var left = new FunctionCallExpression("byte", new[] { new IntegerConstantExpression(0) }); var right = new IntegerConstantExpression(0); var expr = new MathematicExpression(left, MathematicOperation.Add, right); var scope = new InterpreterScope(); scope.Context = new TriggerBuilderContext(); scope.AddFunction(new MemoryAccessorFunction("byte", FieldSize.Byte)); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.True); Assert.That(result.ToString(), Is.EqualTo(left.ToString())); }
public void TestReplaceVariablesUnknownParameter() { var functionDefinition = Parse("function func(i) { return i }"); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); var value = new VariableExpression("var"); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { value }); ExpressionBase result; Assert.That(functionCall.ReplaceVariables(scope, out result), Is.False); Assert.That(result, Is.InstanceOf <ParseErrorExpression>()); var parseError = (ParseErrorExpression)result; Assert.That(parseError.InnermostError.Message, Is.EqualTo("Unknown variable: var")); }
public void TestUnderflowAdjustmentImpossible() { var input = "5 + byte(0x1234) == 2"; var tokenizer = Tokenizer.CreateTokenizer(input); var expr = ExpressionBase.Parse(new PositionalTokenizer(tokenizer)); var scope = new InterpreterScope(); scope.Context = new RATools.Parser.TriggerBuilderContext(); scope.AddFunction(new MemoryAccessorFunction("byte", RATools.Data.FieldSize.Byte)); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.False); Assert.That(result, Is.InstanceOf <ParseErrorExpression>()); Assert.That(((ParseErrorExpression)result).Message, Is.EqualTo("Expression can never be true")); }
public void TestEvaluateConditional() { var functionDefinition = Parse("function func(i) { if (i < 3) return 4 else return 8 }"); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); var value = new IntegerConstantExpression(6); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { value }); ExpressionBase result; Assert.That(functionCall.Evaluate(scope, out result), Is.True); Assert.That(result, Is.EqualTo(new IntegerConstantExpression(8))); value = new IntegerConstantExpression(2); functionCall = new FunctionCallExpression("func", new ExpressionBase[] { value }); Assert.That(functionCall.Evaluate(scope, out result), Is.True); Assert.That(result, Is.EqualTo(new IntegerConstantExpression(4))); }
[TestCase("byte(0) & 12 - 5", "byte(0) & 7")] // addition has higher precedence public void TestCombining(string input, string expected) { var expr = ExpressionBase.Parse(new PositionalTokenizer(Tokenizer.CreateTokenizer(input))); Assert.That(expr, Is.InstanceOf <MathematicExpression>()); var scope = new InterpreterScope(); scope.Context = new TriggerBuilderContext(); scope.AddFunction(new MemoryAccessorFunction("byte", FieldSize.Byte)); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.True); var builder = new StringBuilder(); result.AppendString(builder); Assert.That(builder.ToString(), Is.EqualTo(expected)); }
public void TestReplaceVariablesLogicalFunctionCall() { var functionDefinition = UserFunctionDefinitionExpression.ParseForTest("function func(i) => byte(i) == 1"); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { new IntegerConstantExpression(2) }); var value1 = new IntegerConstantExpression(98); var expr = new DictionaryExpression(); expr.Add(functionCall, value1); var scope = new InterpreterScope(AchievementScriptInterpreter.GetGlobalScope()); scope.AddFunction(functionDefinition); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.False); Assert.That(result, Is.InstanceOf <ParseErrorExpression>()); Assert.That(((ParseErrorExpression)result).Message, Is.EqualTo("Dictionary key must evaluate to a constant")); }
public void TestEvaluateDictionaryDirect() { // ensures that a dictionary being passed directly to a function is evaluated var functionDefinition = Parse("function func(d) { return d[\"key\"] }"); var scope = new InterpreterScope(); scope.AddFunction(functionDefinition); var dict = new DictionaryExpression(); dict.Add(new StringConstantExpression("key"), new VariableExpression("variable")); scope.AssignVariable(new VariableExpression("variable"), new IntegerConstantExpression(123)); var functionCall = new FunctionCallExpression("func", new ExpressionBase[] { dict }); ExpressionBase result; Assert.That(functionCall.Evaluate(scope, out result), Is.True); Assert.That(result, Is.InstanceOf <IntegerConstantExpression>()); Assert.That(((IntegerConstantExpression)result).Value, Is.EqualTo(123)); }
public void TestReplaceVariables() { var functionDefinition = Parse("function func(i,j,k) => i*j+k"); var variable1 = new VariableExpression("variable1"); var variable2 = new VariableExpression("variable2"); var value1 = new IntegerConstantExpression(98); var value2 = new IntegerConstantExpression(99); var value3 = new IntegerConstantExpression(3); var expr = new FunctionCallExpression("func", new ExpressionBase[] { variable1, value3, variable2 }); var scope = new InterpreterScope(); scope.AssignVariable(variable1, value1); scope.AssignVariable(variable2, value2); scope.AddFunction(functionDefinition); ExpressionBase result; Assert.That(expr.ReplaceVariables(scope, out result), Is.True); Assert.That(result, Is.InstanceOf <IntegerConstantExpression>()); Assert.That(((IntegerConstantExpression)result).Value, Is.EqualTo(98 * 3 + 99)); }
public void TestPopFunctionCall() { var scope = new InterpreterScope(); var array = new ArrayExpression(); array.Entries.Add(new FunctionCallExpression("happy", new ExpressionBase[] { new IntegerConstantExpression(1) })); scope.DefineVariable(new VariableDefinitionExpression("arr"), array); var happyFunc = new FunctionDefinitionExpression("happy"); happyFunc.Parameters.Add(new VariableDefinitionExpression("num1")); happyFunc.Expressions.Add(new ReturnExpression(new VariableExpression("num1"))); scope.AddFunction(happyFunc); var entry = Evaluate("array_pop(arr)", scope); // function call should not be evaluated when it's popped off the array Assert.That(entry, Is.InstanceOf <FunctionCallExpression>()); Assert.That(((FunctionCallExpression)entry).FunctionName.Name, Is.EqualTo("happy")); Assert.That(((FunctionCallExpression)entry).Parameters.Count, Is.EqualTo(1)); Assert.That(array.Entries.Count, Is.EqualTo(0)); }