예제 #1
0
        // BinaryExpression: AndAlso, OrElse
        private Result RewriteLogicalBinaryExpression(Expression expr, Stack stack)
        {
            BinaryExpression node = (BinaryExpression)expr;
            // Left expression runs on a stack as left by parent
            Result left = RewriteExpression(node.Left, stack);
            // ... and so does the right one
            Result right = RewriteExpression(node.Right, stack);
            //conversion is a lambda. stack state will be ignored.
            Result conversion = RewriteExpression(node.Conversion, stack);

            RewriteAction action = left.Action | right.Action | conversion.Action;

            if (action != RewriteAction.None)
            {
                expr = BinaryExpression.Create(
                    node.NodeType,
                    left.Node,
                    right.Node,
                    node.Type,
                    node.Method,
                    (LambdaExpression)conversion.Node
                    );
            }
            return(new Result(action, expr));
        }
예제 #2
0
        // BinaryExpression: AndAlso, OrElse
        private Result RewriteLogicalBinaryExpression(Expression expr, Stack stack)
        {
            var node = (BinaryExpression)expr;

            // Left expression runs on a stack as left by parent
            Result left = RewriteExpression(node.Left, stack);
            // ... and so does the right one
            Result right = RewriteExpression(node.Right, stack);
            //conversion is a lambda. stack state will be ignored.
            Result conversion = RewriteExpression(node.Conversion, stack);

            RewriteAction action = left.Action | right.Action | conversion.Action;

            if (action != RewriteAction.None)
            {
                // We don't have to worry about byref parameters here, because the
                // factory doesn't allow it (it requires identical parameters and
                // return type from the AndAlso/OrElse method)

                expr = BinaryExpression.Create(
                    node.NodeType,
                    left.Node,
                    right.Node,
                    node.Type,
                    node.Method,
                    (LambdaExpression)conversion.Node
                    );
            }

            return(new Result(action, expr));
        }
예제 #3
0
        private Result RewriteBinaryExpression(Expression expr, Stack stack)
        {
            var node = (BinaryExpression)expr;

            var cr = new ChildRewriter(this, stack, 3);

            // Left expression executes on the stack as left by parent
            cr.Add(node.Left);
            // Right expression always has non-empty stack (left is on it)
            cr.Add(node.Right);
            // conversion is a lambda, stack state will be ignored
            cr.Add(node.Conversion);

            if (cr.Action == RewriteAction.SpillStack)
            {
                RequireNoRefArgs(node.Method);
            }

            return(cr.Finish(cr.Rewrite ?
                             BinaryExpression.Create(
                                 node.NodeType,
                                 cr[0] !,
                                 cr[1] !,
                                 node.Type,
                                 node.Method,
                                 (LambdaExpression?)cr[2]) :
                             expr));
        }
 public override void ExitExprRelPrecedence(OberonGrammarParser.ExprRelPrecedenceContext context)
 {
     context.expReturn = BinaryExpression.Create(
         context.op.Type,
         context.l.expReturn,
         context.r.expReturn,
         _parser.currentBlock);
 }
        public void TestUnaryOpException()
        {
            var m = new Module(null);
            var e = Assert.Throws <ArgumentException>(() => BinaryExpression.Create(OberonGrammarLexer.PLUS,
                                                                                    ConstantExpression.Create(false), null, m.Block));

            Assert.Equal("Cannot find operation '+' (Bool, Any)", e.Message);
        }
예제 #6
0
        public void ExpressionNot()
        {
            var m      = new Module(null);
            var e      = BinaryExpression.Create(OberonGrammarLexer.NOT, new ConstantBoolExpression(true), null, m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantBoolExpression;

            Assert.NotNull(result);
            Assert.False(result.ToBool());
        }
        public void ExpressionDiv3()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.DIV,
                ConstantExpression.Create("10.0"),
                ConstantExpression.Create(4),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.Equal(2.5, result.ToDouble());
        }
        public void ExpressionMult2()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.STAR,
                ConstantExpression.Create(6.1),
                ConstantExpression.Create(7),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.True(result.ToDouble() - 42.7 < double.Epsilon);
        }
        public void ExpressionAdd2()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.PLUS,
                ConstantExpression.Create(1),
                ConstantExpression.Create(1.42),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.Equal(2.42, result.ToDouble());
        }
예제 #10
0
        public void ExpressionRelGe1()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.GE,
                ConstantExpression.Create(4),
                ConstantExpression.Create(4),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantBoolExpression;

            Assert.NotNull(result);
            Assert.True(result.ToBool());
        }
        public void ExpressionDiv1()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.DIV,
                ConstantExpression.Create(10),
                ConstantExpression.Create(2),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantIntExpression;

            Assert.NotNull(result);
            Assert.Equal(5, result.ToInt32());
        }
        public void ExpressionDiv0()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.DIV,
                ConstantExpression.Create("10.0"),
                ConstantIntExpression.Zero,
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.True(double.IsInfinity(result.ToDouble()));
        }
        public void ExpressionAnd()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.AND,
                ConstantExpression.Create(false),
                ConstantExpression.Create("true"),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantBoolExpression;

            Assert.NotNull(result);
            Assert.False(result.ToBool());
        }
예제 #14
0
        public void BinaryOperatorCheckParametersNull()
        {
            var b = new Module(null).Block;
            var e = Assert.Throws <ArgumentNullException>(
                () => new OpRelOp().Operate(null, b, null));

            Assert.Equal("e", e.ParamName);
            var e1 = Assert.Throws <ArgumentNullException>(
                () => new OpRelOp().Operate(
                    BinaryExpression.Create(OberonGrammarLexer.PLUS, ConstantExpression.Create(0),
                                            ConstantExpression.Create(1), b), null, null));

            Assert.Equal("block", e1.ParamName);
        }
예제 #15
0
        public void ExpressionNot2()
        {
            var m = new Module(null);

            m.Block.Declarations.Add(new Declaration("a", m.Block.LookupType("BOOLEAN")));
            var e = BinaryExpression.Create(
                OberonGrammarLexer.NOT,
                VariableReferenceExpression.Create(m.Block.LookupVar("a"), null),
                null,
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as BinaryExpression;

            Assert.NotNull(result);
        }
예제 #16
0
        public void ExpressionRelVar()
        {
            var m = new Module(null);

            m.Block.Declarations.Add(new Declaration("a", m.Block.LookupType("INTEGER")));
            var e = BinaryExpression.Create(
                OberonGrammarLexer.NOTEQUAL,
                VariableReferenceExpression.Create(m.Block.LookupVar("a"), null),
                ConstantExpression.Create(10),
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as BinaryExpression;

            Assert.NotNull(result);
            Assert.False(result.IsConst);
        }
        public void ExpressionAddRes0()
        {
            var m = new Module(null);
            var e = BinaryExpression.Create(
                OberonGrammarLexer.PLUS,
                ConstantExpression.Create(1),
                ConstantDoubleExpression.Zero,
                m.Block);
            var result = ConstantSolver.Solve(e, m.Block) as ConstantDoubleExpression;

            Assert.NotNull(result);
            Assert.Equal(1, result.ToInt32());
            Assert.Equal(1.0, result.ToDouble());
            Assert.True(result.ToBool());
            Assert.False(result.IsUnary);
            Assert.True(result.IsConst);
        }
예제 #18
0
        public override Expression Reduce(Expression root, ExpressionReductor reductor)
        {
            if (root is BinaryExpression)
            {
                Expression left  = reductor.Reduce((root as BinaryExpression).Left);
                Expression right = reductor.Reduce((root as BinaryExpression).Right);
                if (left is BinaryExpression && ExpressionSnippets.GetOperatorLevel((left as BinaryExpression).Operator) == ExpressionSnippets.GetOperatorLevel((root as BinaryExpression).Operator))
                {
                    Expression ll = reductor.Reduce((left as BinaryExpression).Left);
                    Expression lr = reductor.Reduce((left as BinaryExpression).Right);

                    if (lr.IsConstantExpression())
                    {
                        return(BinaryExpression.Create((left as BinaryExpression).Operator, ll, BinaryExpression.Create((root as BinaryExpression).Operator, lr, right)));
                    }
                }
            }


            return(root);
        }
        public override void ExitExprNotExpression(OberonGrammarParser.ExprNotExpressionContext context)
        {
            switch (context.op.Type)
            {
            case OberonGrammarLexer.MINUS:
                context.expReturn = BinaryExpression.Create(
                    OberonGrammarLexer.MINUS,
                    context.e.expReturn,
                    null,
                    _parser.currentBlock);
                break;

            case OberonGrammarLexer.NOT:
                context.expReturn = BinaryExpression.Create(
                    OberonGrammarLexer.NOT,
                    context.e.expReturn,
                    null,
                    _parser.currentBlock);
                break;
            }
        }
예제 #20
0
        // BinaryExpression
        private Result RewriteBinaryExpression(Expression expr, Stack stack)
        {
            BinaryExpression node = (BinaryExpression)expr;

            ChildRewriter cr = new ChildRewriter(this, stack, 3);

            // Left expression executes on the stack as left by parent
            cr.Add(node.Left);
            // Right expression always has non-empty stack (left is on it)
            cr.Add(node.Right);
            // conversion is a lambda, stack state will be ignored
            cr.Add(node.Conversion);

            return(cr.Finish(cr.Rewrite ?
                             BinaryExpression.Create(
                                 node.NodeType,
                                 cr[0],
                                 cr[1],
                                 node.Type,
                                 node.Method,
                                 (LambdaExpression)cr[2]) :
                             expr));
        }
예제 #21
0
        public static VariableContextExpression ucomb(VariableContextExpression func, Matrix r, Vector u)
        {
            int count = func.Variables.Length;

            VariableContextExpression[] diffs = func.Variables.Select(i => ExpressionFuncs.diff(func, i.Name)).ToArray();


            Expression e1 = null;

            for (int i = 0; i <= count - 1; i++)
            {
                Expression right = BinaryExpression.Create(BinaryOperator.Multiply,
                                                           ConstantExpression.create(u[i] * u[i], 0, 0),
                                                           new FunctionCallExpression("pow",
                                                                                      new Expression[]
                {
                    diffs[i].Expression,
                    ConstantExpression.create(2, 0, 0)
                },
                                                                                      0,
                                                                                      0));

                e1 = e1 == null ? right : BinaryExpression.Create(BinaryOperator.Add, e1, right);
            }


            Expression e2 = null;

            for (int i = 1; i <= count - 1; i++)
            {
                for (int j = i + 1; j <= count; j++)
                {
                    Expression right = BinaryExpression.Create(BinaryOperator.Multiply,
                                                               ConstantExpression.create(u[i - 1] * u[j - 1] * r[i - 1, j - 1], 0, 0),
                                                               BinaryExpression.Create(BinaryOperator.Multiply,
                                                                                       diffs[i - 1].Expression,
                                                                                       diffs[j - 1].Expression));

                    e2 = e2 == null ? right : BinaryExpression.Create(BinaryOperator.Add, e2, right);
                }
            }

            e2 = BinaryExpression.Create(BinaryOperator.Multiply,
                                         ConstantExpression.create(2, 0, 0),
                                         e2);


            Expression e = BinaryExpression.Create(BinaryOperator.Add,
                                                   e1,
                                                   e2);


            VariableContext     c       = func.VariableContext;
            TypeCheckingContext context = new MathyLanguageService().CreateTypeCheckingContext(c);

            foreach (VariableInfo variable in func.Variables)
            {
                c.Set(variable.Name, context.CreateAutoCreatedVariableValue(variable.Type));
            }

            VariableContextExpression result = new VariableContextExpression(e, func.Variables, 0, 0)
            {
                VariableContext = func.VariableContext
            };

            new MathyLanguageService().CreateTypeChecker().PerformTypeChecking(result, context);

            result = new VariableContextExpression(new Cherimoya.Reduction.ExpressionReductor(new MathyLanguageService()).Reduce(e), func.Variables, 0, 0)
            {
                VariableContext = func.VariableContext
            };
            new MathyLanguageService().CreateTypeChecker().PerformTypeChecking(result, context);

            foreach (VariableInfo variable in func.Variables)
            {
                context.VariableContext.Remove(variable.Name);
            }


            return(result);
        }
예제 #22
0
        private Expression CalculateDiff(Expression e)
        {
            if (IsConstant(e))
            {
                return(ConstantExpression.create(0, e.FromPosition, e.ToPosition));
            }
            else if (e is VariableExpression)
            {
                return(ConstantExpression.create(1, e.FromPosition, e.ToPosition));
            }
            else if (e is FunctionCallExpression)
            {
                FunctionCallExpression func = e as FunctionCallExpression;

                // (x^n)' = n * x^(n-1)
                if (func.MethodName == "pow")
                {
                    Expression p0 = func.Parameters[0];
                    Expression p1 = func.Parameters[1];

                    if (IsConstant(p1))
                    {
                        return(BinaryExpression.Create(BinaryOperator.Multiply,
                                                       CalculateDiff(p0),
                                                       BinaryExpression.Create(BinaryOperator.Multiply,
                                                                               p1,
                                                                               new FunctionCallExpression("pow", new Expression[]
                        {
                            p0,
                            BinaryExpression.Create(BinaryOperator.Subtract, p1, ConstantExpression.create(1, p1.FromPosition, p1.ToPosition))
                        },
                                                                                                          p0.FromPosition,
                                                                                                          p0.ToPosition))
                                                       ));
                    }
                }
                // (sin(u))' = cos(u) * u'
                else if (func.MethodName == "sin")
                {
                    Expression p0 = func.Parameters[0];
                    return(BinaryExpression.Create(BinaryOperator.Multiply,
                                                   CalculateDiff(p0),
                                                   new FunctionCallExpression("cos", new Expression[] { p0 }, 0, 0)
                                                   ));
                }
                // (cos(u))' = -sin(u) * u'
                else if (func.MethodName == "cos")
                {
                    Expression p0 = func.Parameters[0];
                    return(BinaryExpression.Create(BinaryOperator.Multiply,
                                                   CalculateDiff(p0),
                                                   new FunctionCallExpression("sin", new Expression[] { p0 }, 0, 0)
                                                   ));
                }
            }
            else if (e is UnaryExpression)
            {
                UnaryExpression unary = e as UnaryExpression;

                // (-x)' = -(x')
                if (unary.Operator == UnaryOperator.Negation)
                {
                    return(new UnaryExpression(UnaryOperator.Negation, CalculateDiff(unary.Operand), unary.FromPosition, unary.ToPosition));
                }
            }
            else if (e is BinaryExpression)
            {
                BinaryExpression binary = e as BinaryExpression;

                // (u + v)' = u' + v'
                if (binary.Operator == BinaryOperator.Add)
                {
                    return(BinaryExpression.Create(BinaryOperator.Add, CalculateDiff(binary.Left), CalculateDiff(binary.Right)));
                }
                // (u - v)' = u' - v'
                else if (binary.Operator == BinaryOperator.Subtract)
                {
                    return(BinaryExpression.Create(BinaryOperator.Subtract, CalculateDiff(binary.Left), CalculateDiff(binary.Right)));
                }
                else if (binary.Operator == BinaryOperator.Multiply)
                {
                    // (c*u)' = c(u')
                    if (IsConstant(binary.Left))
                    {
                        return(BinaryExpression.Create(
                                   BinaryOperator.Multiply,
                                   binary.Left,
                                   CalculateDiff(binary.Right)));
                    }
                    // (u*c)' = c(u')
                    else if (IsConstant(binary.Right))
                    {
                        return(BinaryExpression.Create(
                                   BinaryOperator.Multiply,
                                   binary.Right,
                                   CalculateDiff(binary.Left)));
                    }
                    // (u*v)' = uv' + vu'
                    else
                    {
                        return(BinaryExpression.Create(BinaryOperator.Add,
                                                       BinaryExpression.Create(BinaryOperator.Multiply, binary.Right, CalculateDiff(binary.Left)),
                                                       BinaryExpression.Create(BinaryOperator.Multiply, binary.Left, CalculateDiff(binary.Right))));
                    }
                }
                else if (binary.Operator == BinaryOperator.Divide)
                {
                    // (c/u)' = -cu^(-2)
                    if (IsConstant(binary.Left))
                    {
                        return(BinaryExpression.Create(
                                   BinaryOperator.Multiply,
                                   new UnaryExpression(UnaryOperator.Negation, binary.Left, binary.Left.FromPosition, binary.Left.ToPosition),
                                   new FunctionCallExpression("pow",
                                                              new Expression[]
                        {
                            binary.Right,
                            ConstantExpression.create(-2, binary.Right.FromPosition, binary.Right.ToPosition)
                        },
                                                              binary.Right.FromPosition,
                                                              binary.Right.ToPosition)));
                    }
                    // (u/c)' = (1/c)u'
                    else if (IsConstant(binary.Right))
                    {
                        return(BinaryExpression.Create(
                                   BinaryOperator.Multiply,
                                   BinaryExpression.Create(BinaryOperator.Divide,
                                                           ConstantExpression.create(1, binary.Right.FromPosition, binary.Right.ToPosition),
                                                           binary.Right),
                                   CalculateDiff(binary.Left)));
                    }
                    // (u/v)' = (vu'-uv')/v^2
                    else
                    {
                        return
                            (BinaryExpression.Create(BinaryOperator.Divide,
                                                     BinaryExpression.Create(BinaryOperator.Subtract,
                                                                             BinaryExpression.Create(BinaryOperator.Multiply, binary.Left, CalculateDiff(binary.Right)),
                                                                             BinaryExpression.Create(BinaryOperator.Multiply, binary.Right, CalculateDiff(binary.Left))),
                                                     new FunctionCallExpression("pow", new Expression[] { binary.Right }, binary.Right.FromPosition, binary.Right.ToPosition)
                                                     ));
                    }
                }
            }


            throw new Exception();
        }