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));
        }
示例#2
0
        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);
        }
示例#3
0
        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));
        }
示例#5
0
        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));
        }
示例#6
0
        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"));
        }
示例#8
0
        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));
        }
示例#9
0
        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));
        }
示例#10
0
        public void TestAddAndGetFunction()
        {
            var function = new FunctionDefinitionExpression("test");
            var scope    = new InterpreterScope();

            scope.AddFunction(function);
            Assert.That(scope.GetFunction("test"), Is.SameAs(function));
        }
示例#11
0
        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));
        }
示例#12
0
        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);
        }
示例#13
0
        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);
        }
示例#15
0
        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);
        }
示例#16
0
        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)));
        }
示例#17
0
        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"));
        }
示例#18
0
        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));
        }
示例#19
0
        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"));
        }
示例#20
0
        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"));
        }
示例#21
0
        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"));
        }
示例#22
0
        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"));
        }
示例#25
0
        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)));
        }
示例#26
0
        [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));
        }
示例#29
0
        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));
        }
示例#30
0
        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));
        }