// 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)); }
// 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)); }
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); }
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()); }
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()); }
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); }
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); }
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); }
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; } }
// 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)); }
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); }
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(); }