private Solution GenerateExpression(Statement st) { IVariable lv = null; List<Expression> callArguments = null; InitArgs(st, out lv, out callArguments); BinaryExpr bexp = null; foreach (var lhsValue in ResolveExpression(callArguments[0])) { Expression lhs = null; if (lhsValue is Expression) lhs = lhsValue as Expression; else if (lhsValue is IVariable) lhs = VariableToExpression(lhsValue as IVariable); foreach (var rhsValue in ResolveExpression(callArguments[2])) { Expression rhs = null; if (rhsValue is Expression) rhs = rhsValue as Expression; else if (rhsValue is IVariable) rhs = VariableToExpression(rhsValue as IVariable); foreach (var op in ResolveExpression(callArguments[1])) { var opLiteral = op as StringLiteralExpr; string opString = opLiteral?.Value.ToString(); bexp = new BinaryExpr(st.Tok, ToOpCode(opString), lhs, rhs); } } } return AddNewLocal(lv, bexp); }
internal static IEnumerable<Expression> SplitAndStich(BinaryExpr pair, BinaryExpr.Opcode separator) { foreach (var e1 in SplitExpr(pair.E1, separator)) { // Notice the token. This makes triggers/splitting-picks-the-right-tokens.dfy possible yield return new BinaryExpr(e1.tok, pair.Op, pair.E0, e1) { ResolvedOp = pair.ResolvedOp, Type = pair.Type }; } }
private static BinaryExpr.Opcode FlipOpcode(BinaryExpr.Opcode opCode) { if (opCode == BinaryExpr.Opcode.And) { return BinaryExpr.Opcode.Or; } else if (opCode == BinaryExpr.Opcode.Or) { return BinaryExpr.Opcode.And; } else { throw new ArgumentException(); } }
private bool IsChained(BinaryExpr expression) { if (!expression.Op.Equals(BinaryExpr.Opcode.And)) return false; var lhs = expression.E0 as BinaryExpr; var rhs = expression.E1 as BinaryExpr; if (lhs == null || rhs == null) return false; return BinaryExpr.IsEqualityOp(lhs.Op) && BinaryExpr.IsEqualityOp(rhs.Op); }
public static void ErrorBinaryOpNotFound(this Log log, BinaryExpr node) { if (node.left.computedType is ErrorType || node.right.computedType is ErrorType) { return; } if (node.op == BinaryOp.Assign) { log.Error(node.location, "cannot assign " + WrapType(node.right.computedType) + " to " + WrapType(node.left.computedType)); } else { log.Error(node.location, "no match for operator " + node.op.AsString() + " that takes arguments \"(" + node.left.computedType + ", " + node.right.computedType + ")\""); } }
public static bool IsConstant(Expression e) { UnaryExpr unary = e as UnaryExpr; BinaryExpr binary = e as BinaryExpr; if (unary != null) { return(IsConstant(unary.E)); } if (binary != null) { return(IsConstant(binary.E0) && IsConstant(binary.E1)); } return(e is LiteralExpr); }
protected BinaryExpr.Opcode ToOpCode(string op) { foreach (BinaryExpr.Opcode code in Enum.GetValues(typeof(BinaryExpr.Opcode))) { try { if (BinaryExpr.OpcodeString(code) == op) { return(code); } } catch (cce.UnreachableException) { throw new ArgumentException("Invalid argument; Expected binary operator, received " + op); } } throw new ArgumentException("Invalid argument; Expected binary operator, received " + op); }
public override void Visit(BinaryExpr expr) { expr.left.Accept(this); expr.right.Accept(this); switch (expr.op.type) { case TokenType.PLUS: chunk.WriteOpCode(OpCode.ADD); break; case TokenType.MINUS: chunk.WriteOpCode(OpCode.SUB); break; case TokenType.STAR: chunk.WriteOpCode(OpCode.MUL); break; case TokenType.SLASH: chunk.WriteOpCode(OpCode.DIV); break; case TokenType.EQUAL_EQUAL: chunk.WriteOpCode(OpCode.EQUAL); break; case TokenType.BANG_EQUAL: chunk.WriteOpCode(OpCode.NOT_EQUAL); break; case TokenType.GREATER: chunk.WriteOpCode(OpCode.GREATER); break; case TokenType.GREATER_EQUAL: chunk.WriteOpCode(OpCode.GREATER_EQUAL); break; case TokenType.LESS: chunk.WriteOpCode(OpCode.LESS); break; case TokenType.LESS_EQUAL: chunk.WriteOpCode(OpCode.LESS_EQUAL); break; } }
internal void UnionExpr(Expression e1, Expression e2, out Expression expr) { if (e1 != null && e2 != null) { expr = new BinaryExpr(new Token(TacnyDriver.TacticCodeTokLine, 0), BinaryExpr.Opcode.Add, e1, e2); } else if (e1 == null && e2 == null) { expr = null; } else { expr = e1 ?? e2; } }
private bool IsChained(BinaryExpr expression) { if (!expression.Op.Equals(BinaryExpr.Opcode.And)) { return(false); } var lhs = expression.E0 as BinaryExpr; var rhs = expression.E1 as BinaryExpr; if (lhs == null || rhs == null) { return(false); } return(BinaryExpr.IsEqualityOp(lhs.Op) && BinaryExpr.IsEqualityOp(rhs.Op)); }
internal static IEnumerable<Expression> SplitExpr(Expression expr, BinaryExpr.Opcode separator) { expr = expr.Resolved; var unary = expr as UnaryOpExpr; var binary = expr as BinaryExpr; if (unary != null && unary.Op == UnaryOpExpr.Opcode.Not) { foreach (var e in SplitExpr(unary.E, FlipOpcode(separator))) { yield return Not(e); } } else if (binary != null && binary.Op == separator) { foreach (var e in SplitExpr(binary.E0, separator)) { yield return e; } foreach (var e in SplitExpr(binary.E1, separator)) { yield return e; } } else if (binary != null && binary.Op == BinaryExpr.Opcode.Imp && separator == BinaryExpr.Opcode.Or) { foreach (var e in SplitExpr(Not(binary.E0), separator)) { yield return e; } foreach (var e in SplitExpr(binary.E1, separator)) { yield return e; } } else { yield return expr; } }
internal static BinaryOperatorSymbol BindBinaryOperation(BinaryExpr expr, BinaryOperatorKind kind, BindOptions options) { if (options.HasFlag(BindOptions.Logic)) { Convert(ref expr.Left, Compilation.Get(NativeType.Boolean), options); Convert(ref expr.Right, Compilation.Get(NativeType.Boolean), options); } var res = BinaryOperation(kind, ref expr.Left, ref expr.Right, options); if (res != null) { return(res); } throw BinaryOperationError(expr, kind, options); }
private object Evaluate(Expr expression) { return(expression switch { BinaryExpr binaryExpr => Evaluate(binaryExpr), BlockExpr blockExpr => Evaluate(blockExpr), BreakExpr breakExpr => Evaluate(breakExpr), CallExpr callExpr => Evaluate(callExpr), ContinueExpr continueExpr => Evaluate(continueExpr), Identifier identifier => Evaluate(identifier), IfExpr ifExpr => Evaluate(ifExpr), LambdaExpr lambdaExpr => Evaluate(lambdaExpr), Literal literal => Evaluate(literal), ReturnExpr returnExpr => Evaluate(returnExpr), UnaryExpr unaryExpr => Evaluate(unaryExpr), _ => throw new ArgumentOutOfRangeException(nameof(expression)) });
protected Expression EvaluateExpression(ExpressionTree expt, ProofState state) { Contract.Requires(expt != null); if (expt.IsLeaf()) { return(EvaluateLeaf(expt, state) as LiteralExpr); } var bexp = (BinaryExpr)expt.Data; if (BinaryExpr.IsEqualityOp(bexp.Op)) { bool boolVal = EvaluateEqualityExpression(expt, state); return(new LiteralExpr(new Token(), boolVal)); } var lhs = EvaluateExpression(expt.LChild, state) as LiteralExpr; var rhs = EvaluateExpression(expt.RChild, state) as LiteralExpr; // for now asume lhs and rhs are integers var l = (BigInteger)lhs?.Value; var r = (BigInteger)rhs?.Value; BigInteger res = 0; switch (bexp.Op) { case BinaryExpr.Opcode.Sub: res = BigInteger.Subtract(l, r); break; case BinaryExpr.Opcode.Add: res = BigInteger.Add(l, r); break; case BinaryExpr.Opcode.Mul: res = BigInteger.Multiply(l, r); break; case BinaryExpr.Opcode.Div: res = BigInteger.Divide(l, r); break; } return(new LiteralExpr(lhs.tok, res)); }
private Expression mul_div_mod_rem() { Expression higher_precedence = unary(); while (expect(Token.Type.Multiply) || expect(Token.Type.Divide) || expect(Token.Type.Mod) || expect(Token.Type.NoRemainder)) { Token op = consume(); // Check for compound assignment if (consume(Token.Type.Assignment) != null) { Expression value = unary(); // Check the type of the higher precidence // If we are assigning to a non-object variable if (higher_precedence.GetType() == typeof(VariableExpr)) { VariableExpr var = (VariableExpr)higher_precedence; return(new AssignExpr(var.name, new BinaryExpr(higher_precedence, op, value))); } // If we are assigning to a namespace value else if (higher_precedence.GetType() == typeof(NamespaceValueExpr)) { NamespaceValueExpr var = (NamespaceValueExpr)higher_precedence; return(new AssignNamespaceExpr(var, new BinaryExpr(higher_precedence, op, value))); } // If we are assigning to a member variable else if (higher_precedence.GetType() == typeof(ObjGetExpr)) { ObjGetExpr member = (ObjGetExpr)higher_precedence; return(new ObjSetExpr(member.obj, member.identifier, new BinaryExpr(higher_precedence, op, value))); } else { throw new ParseExceptionUnexpectedToken("Compound assignment cannot be applied to " + higher_precedence.GetType()); } } else { Expression right = unary(); higher_precedence = new BinaryExpr(higher_precedence, op, right); } } return(higher_precedence); }
public void TestIncorrectBinaryExpression() { var program = new ProgramNode(0, 0); program.Block = new BlockStmt(0, 0); var declaration = CreateVarDeclaration("var1", new SimpleType(0, 0, ExprType.Bool)); var expr = new BinaryExpr(0, 0); expr.Left = new IntLiteralExpr(0, 0, 1); expr.Right = new RealLiteralExpr(0, 0, (float)3.4); expr.Op = Operator.Modulus; var assign = new AssignmentStmt(0, 0); assign.AssignmentExpr = expr; assign.Variable = new VariableExpr(0, 0, "var1"); program.Block.Statements.Add(declaration); program.Block.Statements.Add(assign); AssertErrorContains(program, "Can't apply operator Modulus on types Real and Int"); }
private void Math(Memory memory, object left, object right, Operator op, double expected) { Expr expLeft = (left.GetType() == typeof(string)) ? (Expr) new VariableExpr(left.ToString()) : (Expr) new ConstantExpr(left); Expr expRight = (right.GetType() == typeof(string)) ? (Expr) new VariableExpr(right.ToString()) : (Expr) new ConstantExpr(right); var ctx = new Context() { Memory = memory }; expLeft.Ctx = ctx; expRight.Ctx = ctx; var exp = new BinaryExpr(expLeft, op, expRight); Assert.AreEqual(expected, exp.EvaluateAs <double>()); }
private Solution GenerateExpression(Statement st) { IVariable lv = null; List <Expression> callArguments = null; InitArgs(st, out lv, out callArguments); BinaryExpr bexp = null; foreach (var lhsValue in ResolveExpression(callArguments[0])) { Expression lhs = null; if (lhsValue is Expression) { lhs = lhsValue as Expression; } else if (lhsValue is IVariable) { lhs = VariableToExpression(lhsValue as IVariable); } foreach (var rhsValue in ResolveExpression(callArguments[2])) { Expression rhs = null; if (rhsValue is Expression) { rhs = rhsValue as Expression; } else if (rhsValue is IVariable) { rhs = VariableToExpression(rhsValue as IVariable); } foreach (var op in ResolveExpression(callArguments[1])) { var opLiteral = op as StringLiteralExpr; string opString = opLiteral?.Value.ToString(); bexp = new BinaryExpr(st.Tok, ToOpCode(opString), lhs, rhs); } } } return(AddNewLocal(lv, bexp)); }
public void TestRelationalExpression() { // 1 + 2 < 3 * 4 var programSource = new TokenList() { { TokenType.Identifier, "x" }, { TokenType.OpAssignment }, { TokenType.IntLiteral, "1" }, { TokenType.Plus }, { TokenType.IntLiteral, "2" }, { TokenType.OpLess }, { TokenType.IntLiteral, "3" }, { TokenType.OpMultiply }, { TokenType.IntLiteral, "4" } }; Parser parser = new Parser(CreateMockScanner(programSource), new ErrorHandler()); ProgramNode program = parser.Parse(); var leftExpr = new BinaryExpr(0, 0); leftExpr.Left = new IntLiteralExpr(0, 0, 1); leftExpr.Right = new IntLiteralExpr(0, 0, 2); leftExpr.Op = Operator.Plus; var rightExpr = new BinaryExpr(0, 0); rightExpr.Left = new IntLiteralExpr(0, 0, 3); rightExpr.Right = new IntLiteralExpr(0, 0, 4); rightExpr.Op = Operator.Times; var comp = new BinaryExpr(0, 0); comp.Left = leftExpr; comp.Right = rightExpr; comp.Op = Operator.Less; var assignment = new AssignmentStmt(0, 0); assignment.AssignmentExpr = comp; assignment.Variable = new VariableExpr(0, 0, "x"); expected.Block.Statements.Add(assignment); program.ShouldBeEquivalentTo(expected); }
/// <summary> /// Checks for division by zero. /// </summary> /// <param name="semActs"></param> /// <param name="exp"></param> private void CheckDivisionByZero(SemActs semActs, BinaryExpr exp) { if (exp.Op != Operator.Divide) { return; } if (!(exp.Right is ConstantExpr)) { return; } object val = ((ConstantExpr)exp.Right).Value; if (val is int || val is double) { var d = Convert.ToDouble(val); if (d == 0) { AddError("Division by zero", exp.Right); } } }
public string GenerateString(BinaryExpr expression) { string left = string.Empty; // = expression.E0.tok.val; string right = string.Empty; //expression.E1.tok.val; if (expression.E0.tok.val == "(" && !(expression.E0 is ApplySuffix) && !(expression.E0 is MultiSetFormingExpr)) { left = "(" + GenerateString(expression.E0.SubExpressions.First()) + ")"; } else { left = GenerateString(expression.E0); } if (expression.E1.tok.val == "(" && !(expression.E1 is ApplySuffix) && !(expression.E1 is MultiSetFormingExpr)) { right = "(" + GenerateString(expression.E1.SubExpressions.First()) + ")"; } else { right = GenerateString(expression.E1); } string op = string.Empty; op = GenerateString(expression.Op); // For some reason, in case of "<==" operator, // E0 and E1 switch "sides". if (expression.Op == BinaryExpr.Opcode.Exp) { return(right + " " + op + " " + left); } else { return(left + " " + op + " " + right); } }
private List<Expression> SplitExpression(BinaryExpr.Opcode op, BinaryExpr expression) { var expList = new List<Expression>(); if (!expression.Op.Equals(op)) { expList.Add(expression); } else if (IsChained(expression)) { expList.Add(expression); expList.AddRange(SplitExpression(op, expression.E0 as BinaryExpr)); expList.AddRange(SplitExpression(op, expression.E1 as BinaryExpr)); } else { if (!(expression.E0 is BinaryExpr)) expList.Add(expression.E0); else { expList.AddRange(SplitExpression(op, expression.E0 as BinaryExpr)); } if (!(expression.E1 is BinaryExpr)) expList.Add(expression.E1); else { expList.AddRange(SplitExpression(op, expression.E1 as BinaryExpr)); } } return expList; }
/// <summary> /// Checks for division by zero. /// </summary> /// <param name="semActs"></param> /// <param name="exp"></param> private SemanticCheckResult CheckDivisionByZero(SemActs semActs, BinaryExpr exp) { if (exp.Op != Operator.Divide) { return(SemanticCheckResult.Valid); } if (!(exp.Right.IsNodeType(NodeTypes.SysConstant))) { return(SemanticCheckResult.Valid); } var val = (LObject)((ConstantExpr)exp.Right).Value; if (val.Type == LTypes.Number) { var d = ((LNumber)val).Value; if (d == 0) { AddError("Division by zero", exp.Right); } } return(SemanticCheckResult.Valid); }
public DataType Visit(BinaryExpr expr) { DataType type1 = expr.Left.Accept(this); DataType type2 = expr.Right.Accept(this); DataType finalType = ApplyCastingRuleIfNeeded(expr.Operator.Position, type2, type1, expr.Right, expr.Left); // Comparison expressions are of type boolean if (expr.Operator.Type.IsComparisonOperator()) { expr.DataType = new DataType(BaseType.Boolean, 0); } else // Arithmetic operators are of the operands' type. { expr.DataType = finalType; } return(expr.DataType); }
public Construct VisitBinaryExpr(BinaryExpr node) { // Visit left side. this.Visit(node.LeftSide); // Visit right side. this.Visit(node.RightSide); // Pop right side off the stack. LlvmValue rightSide = this.valueStack.Pop(); // Pop left side off the stack. LlvmValue leftSide = this.valueStack.Pop(); // Create a value buffer. LlvmValue binaryExpr = this.builder.CreateAdd(leftSide, rightSide, node.ResultIdentifier); // Push the resulting value onto the stack. this.valueStack.Push(binaryExpr); // Return the node. return(node); }
public void Visit(BinaryExpr t, IEnvironment env) { if (debug) { System.Console.WriteLine("BinaryExpr: " + t.GetType().ToString()); } string op = t.Operator; if (op == ":=") { t.Right.Accept(this, env); if (result is ErrorValue) { return; } object right = result; result = ComputeAssign(t, env, right); return; } else { t.Left.Accept(this, env); if (result is ErrorValue) { return; } object left = result; t.Right.Accept(this, env); if (result is ErrorValue) { return; } object right = result; result = ComputeOp(t, left, op, right); return; } }
// math operations can be turned into a Boogie-level function as in the // case with /noNLarith. public static bool TranslateToFunctionCall(Expression expr) { if (!(expr is BinaryExpr)) { return(false); } BinaryExpr e = (BinaryExpr)expr; bool isReal = e.E0.Type.IsNumericBased(Type.NumericPersuation.Real); switch (e.ResolvedOp) { case BinaryExpr.ResolvedOpcode.Lt: case BinaryExpr.ResolvedOpcode.Le: case BinaryExpr.ResolvedOpcode.Ge: case BinaryExpr.ResolvedOpcode.Gt: case BinaryExpr.ResolvedOpcode.Add: case BinaryExpr.ResolvedOpcode.Sub: if (!isReal && !e.E0.Type.IsBitVectorType && !e.E0.Type.IsBigOrdinalType && DafnyOptions.O.DisableNLarith) { return(true); } break; case BinaryExpr.ResolvedOpcode.Mul: case BinaryExpr.ResolvedOpcode.Div: case BinaryExpr.ResolvedOpcode.Mod: if (!isReal && !e.E0.Type.IsBitVectorType && !e.E0.Type.IsBigOrdinalType) { if (DafnyOptions.O.DisableNLarith || (DafnyOptions.O.ArithMode != 0 && DafnyOptions.O.ArithMode != 3)) { return(true); } } break; } return(false); }
public void Can_Validate_Variable_Does_Not_Exist() { var symScope = new Symbols(); symScope.DefineVariable("result"); var semacts = new SemActs(); var a = new VariableExpr("a"); a.Ref = new ScriptRef("", 1, 1); a.SymScope = symScope.Current; var zero = new ConstantExpr(2); zero.Ref = new ScriptRef("", 1, 5); zero.SymScope = symScope.Current; var divExpr = new BinaryExpr(a, Operator.Divide, zero); divExpr.SymScope = symScope.Current; var assignExpr = new AssignExpr(true, new VariableExpr("result"), divExpr); assignExpr.SymScope = symScope.Current; var stmts = new List <Expr>(); stmts.Add(assignExpr); var success = semacts.Validate(stmts); var results = semacts.Results; Assert.IsFalse(success); Assert.IsFalse(results.Success); Assert.IsTrue(results.HasResults); Assert.AreEqual(results.Results.Count, 1); }
Function CloneFunction(IToken tok, Function f, bool isGhost, List<Expression> moreEnsures, Expression moreBody, Expression replacementBody, bool checkPrevPostconditions, Attributes moreAttributes) { Contract.Requires(tok != null); Contract.Requires(moreBody == null || f is Predicate); Contract.Requires(moreBody == null || replacementBody == null); var tps = f.TypeArgs.ConvertAll(refinementCloner.CloneTypeParam); var formals = f.Formals.ConvertAll(refinementCloner.CloneFormal); var req = f.Req.ConvertAll(refinementCloner.CloneExpr); var reads = f.Reads.ConvertAll(refinementCloner.CloneFrameExpr); var decreases = refinementCloner.CloneSpecExpr(f.Decreases); List<Expression> ens; if (checkPrevPostconditions) // note, if a postcondition includes something that changes in the module, the translator will notice this and still re-check the postcondition ens = f.Ens.ConvertAll(rawCloner.CloneExpr); else ens = f.Ens.ConvertAll(refinementCloner.CloneExpr); if (moreEnsures != null) { ens.AddRange(moreEnsures); } Expression body; Predicate.BodyOriginKind bodyOrigin; if (replacementBody != null) { body = replacementBody; bodyOrigin = Predicate.BodyOriginKind.DelayedDefinition; } else if (moreBody != null) { if (f.Body == null) { body = moreBody; bodyOrigin = Predicate.BodyOriginKind.DelayedDefinition; } else { body = new BinaryExpr(f.tok, BinaryExpr.Opcode.And, refinementCloner.CloneExpr(f.Body), moreBody); bodyOrigin = Predicate.BodyOriginKind.Extension; } } else { body = refinementCloner.CloneExpr(f.Body); bodyOrigin = Predicate.BodyOriginKind.OriginalOrInherited; } if (f is Predicate) { return new Predicate(tok, f.Name, f.HasStaticKeyword, f.IsProtected, isGhost, tps, formals, req, reads, ens, decreases, body, bodyOrigin, refinementCloner.MergeAttributes(f.Attributes, moreAttributes), null, f); } else if (f is InductivePredicate) { return new InductivePredicate(tok, f.Name, f.HasStaticKeyword, f.IsProtected, tps, formals, req, reads, ens, body, refinementCloner.MergeAttributes(f.Attributes, moreAttributes), null, f); } else if (f is CoPredicate) { return new CoPredicate(tok, f.Name, f.HasStaticKeyword, f.IsProtected, tps, formals, req, reads, ens, body, refinementCloner.MergeAttributes(f.Attributes, moreAttributes), null, f); } else if (f is TwoStatePredicate) { return new TwoStatePredicate(tok, f.Name, f.HasStaticKeyword, tps, formals, req, reads, ens, decreases, body, refinementCloner.MergeAttributes(f.Attributes, moreAttributes), null, f); } else if (f is TwoStateFunction) { return new TwoStateFunction(tok, f.Name, f.HasStaticKeyword, tps, formals, refinementCloner.CloneType(f.ResultType), req, reads, ens, decreases, body, refinementCloner.MergeAttributes(f.Attributes, moreAttributes), null, f); } else { return new Function(tok, f.Name, f.HasStaticKeyword, f.IsProtected, isGhost, tps, formals, refinementCloner.CloneType(f.ResultType), req, reads, ens, decreases, body, refinementCloner.MergeAttributes(f.Attributes, moreAttributes), null, f); } }
private static bool ShallowEq(BinaryExpr expr1, BinaryExpr expr2) { Contract.Requires(expr1.ResolvedOp != BinaryExpr.ResolvedOpcode.YetUndetermined); Contract.Requires(expr2.ResolvedOp != BinaryExpr.ResolvedOpcode.YetUndetermined); return(expr1.ResolvedOp == expr2.ResolvedOp); }
void Factor(out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op; BitvectorFactor(out e0, allowSemi, allowLambda, allowBitwiseOps); while (IsMulOp()) { MulOp(out x, out op); BitvectorFactor(out e1, allowSemi, allowLambda, allowBitwiseOps); e0 = new BinaryExpr(x, op, e0, e1); } }
void BitvectorFactor(out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op; AsExpression(out e0, allowSemi, allowLambda, allowBitwiseOps); if (allowBitwiseOps && IsBitwiseOp()) { if (la.kind == 136) { op = BinaryExpr.Opcode.BitwiseAnd; Get(); x = t; AsExpression(out e1, allowSemi, allowLambda, allowBitwiseOps); e0 = new BinaryExpr(x, op, e0, e1); while (IsBitwiseAndOp()) { Expect(136); x = t; AsExpression(out e1, allowSemi, allowLambda, allowBitwiseOps); e0 = new BinaryExpr(x, op, e0, e1); } } else if (la.kind == 24) { op = BinaryExpr.Opcode.BitwiseOr; Get(); x = t; AsExpression(out e1, allowSemi, allowLambda, allowBitwiseOps); e0 = new BinaryExpr(x, op, e0, e1); while (IsBitwiseOrOp()) { Expect(24); x = t; AsExpression(out e1, allowSemi, allowLambda, allowBitwiseOps); e0 = new BinaryExpr(x, op, e0, e1); } } else if (la.kind == 137) { op = BinaryExpr.Opcode.BitwiseXor; Get(); x = t; AsExpression(out e1, allowSemi, allowLambda, allowBitwiseOps); e0 = new BinaryExpr(x, op, e0, e1); while (IsBitwiseXorOp()) { Expect(137); x = t; AsExpression(out e1, allowSemi, allowLambda, allowBitwiseOps); e0 = new BinaryExpr(x, op, e0, e1); } } else SynErr(248); } }
/// <summary> /// Visits the binary expression tree /// </summary> /// <param name="exp"></param> public void Binary(BinaryExpr exp) { _callBack(exp); _callBack(exp.Left); _callBack(exp.Right); }
public static BinaryExpr MakeBinaryExpr(BinaryExpr.Opcode op, BinaryExpr.ResolvedOpcode rop, Type t, Expression e0, Expression e1) { Util.Assert(t != null && e0.Type != null && e1.Type != null); BinaryExpr e = new BinaryExpr(e0.tok, op, e0, e1); e.ResolvedOp = rop; e.Type = t; return e; }
public override Null Visit(BinaryExpr node) { if (node.op == BinaryOp.And || node.op == BinaryOp.Or) { FlowNode endTrue = next.GetTrue(); FlowNode endFalse = next.GetFalse(); // Calculate flow for the right expression node.right.Accept(this); FlowNode right = next.Get(); // Apply the short-circuit logic if (node.op == BinaryOp.And) { next.Set(right, endFalse); } else { next.Set(endTrue, right); } // Calculate flow for the left expression node.left.Accept(this); } else if (node.op == BinaryOp.Equal || node.op == BinaryOp.NotEqual) { base.Visit(node); // Find the function-local symbol being compared with null, if any IdentExpr identExpr; if (node.left is IdentExpr && node.right is CastExpr && ((CastExpr)node.right).value is NullExpr) { identExpr = (IdentExpr)node.left; } else if (node.right is IdentExpr && node.left is CastExpr && ((CastExpr)node.left).value is NullExpr) { identExpr = (IdentExpr)node.right; } else { return null; } if (identExpr.symbol.def.info.funcDef != null) { IsNull isNull = (node.op == BinaryOp.Equal) ? IsNull.Yes : IsNull.No; next.Set( new CheckNode(identExpr.symbol, isNull, next.GetTrue()), new CheckNode(identExpr.symbol, isNull ^ IsNull.Maybe, next.GetFalse()) ); } } else if (node.op == BinaryOp.Assign) { // Check for assignment to a local variable if (node.left is IdentExpr) { IdentExpr identExpr = (IdentExpr)node.left; HandleAssignment(identExpr.symbol, node.right); } base.Visit(node); } else { base.Visit(node); } return null; }
void LogicalExpression(out Expression e0, bool allowSemi, bool allowLambda) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; RelationalExpression(out e0, allowSemi, allowLambda); if (IsAndOp() || IsOrOp()) { if (la.kind == 117 || la.kind == 118) { AndOp(); x = t; RelationalExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); while (IsAndOp()) { AndOp(); x = t; RelationalExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1); } } else if (la.kind == 119 || la.kind == 120) { OrOp(); x = t; RelationalExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); while (IsOrOp()) { OrOp(); x = t; RelationalExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1); } } else SynErr(220); } }
void ImpliesExpression(out Expression e0, bool allowSemi, bool allowLambda) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; LogicalExpression(out e0, allowSemi, allowLambda); if (IsImpliesOp()) { ImpliesOp(); x = t; ImpliesExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); } }
void ImpliesExpliesExpression(out Expression e0, bool allowSemi, bool allowLambda) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; LogicalExpression(out e0, allowSemi, allowLambda); if (IsImpliesOp() || IsExpliesOp()) { if (la.kind == 113 || la.kind == 114) { ImpliesOp(); x = t; ImpliesExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.Imp, e0, e1); } else if (la.kind == 115 || la.kind == 116) { ExpliesOp(); x = t; LogicalExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e0, e1); while (IsExpliesOp()) { ExpliesOp(); x = t; LogicalExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.Exp, e0, e1); } } else SynErr(219); } }
void EquivExpression(out Expression e0, bool allowSemi, bool allowLambda) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; ImpliesExpliesExpression(out e0, allowSemi, allowLambda); while (IsEquivOp()) { EquivOp(); x = t; ImpliesExpliesExpression(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, BinaryExpr.Opcode.Iff, e0, e1); } }
public override Expression Substitute(Expression expr) { if (TryGetExprSubst(expr, out var ie)) { Contract.Assert(ie != null); return(ie); } if (expr is QuantifierExpr e) { var newAttrs = SubstAttributes(e.Attributes); var newRange = e.Range == null ? null : Substitute(e.Range); var newTerm = Substitute(e.Term); var newBounds = SubstituteBoundedPoolList(e.Bounds); if (newAttrs == e.Attributes && newRange == e.Range && newTerm == e.Term && newBounds == e.Bounds) { return(e); } var newBoundVars = new List <BoundVar>(e.BoundVars); if (newBounds == null) { newBounds = new List <ComprehensionExpr.BoundedPool>(); } else if (newBounds == e.Bounds) { // create a new list with the same elements, since the .Add operations below would otherwise add elements to the original e.Bounds newBounds = new List <ComprehensionExpr.BoundedPool>(newBounds); } // conjoin all the new equalities to the range of the quantifier foreach (var entry in usedSubstMap) { var eq = new BinaryExpr(e.tok, BinaryExpr.ResolvedOpcode.EqCommon, entry.Item2, entry.Item1); newRange = newRange == null ? eq : new BinaryExpr(e.tok, BinaryExpr.ResolvedOpcode.And, eq, newRange); newBoundVars.Add((BoundVar)entry.Item2.Var); newBounds.Add(new ComprehensionExpr.ExactBoundedPool(entry.Item1)); } QuantifierExpr newExpr; if (expr is ForallExpr) { newExpr = new ForallExpr(e.tok, e.TypeArgs, newBoundVars, newRange, newTerm, newAttrs) { Bounds = newBounds }; } else { Contract.Assert(expr is ExistsExpr); newExpr = new ExistsExpr(e.tok, e.TypeArgs, newBoundVars, newRange, newTerm, newAttrs) { Bounds = newBounds }; } usedSubstMap.Clear(); newExpr.Type = expr.Type; return(newExpr); } return(base.Substitute(expr)); }
// This needs hugely optimizing... public object visit_binary(BinaryExpr binary_expr) { object left = evaluate(binary_expr.left); object right = evaluate(binary_expr.right); switch (binary_expr.op.type) { case Token.Type.BitwiseShiftLeft: { if (left is double && right is double) { return(Convert.ToInt32(left) << (Convert.ToInt32(right))); } else if (left is int && right is int) { return((int)left << (int)right); } else if (left is int && right is double) { return((int)left << Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) << (int)right); } throw new RuntimeException("Can only bit-shift numeric objects"); } case Token.Type.BitwiseShiftRight: { if (left is double && right is double) { return(Convert.ToInt32(left) >> (Convert.ToInt32(right))); } else if (left is int && right is int) { return((int)left >> (int)right); } else if (left is int && right is double) { return((int)left >> Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) >> (int)right); } throw new RuntimeException("Can only bit-shift numeric objects"); } case Token.Type.Plus: { if (left is double && right is double) { return((double)left + (double)right); } else if (left is int && right is int) { return((int)left + (int)right); } else if (left is int && right is double) { return((int)left + Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) + (int)right); } else if (left is string && right is string) { return((string)left + (string)right); } else if (left is double && right is string) { return(left.ToString() + (string)right); } else if (left is string && right is double) { return((string)left + right.ToString()); } throw new RuntimeException("Cannot add non primitive types"); } case Token.Type.Minus: { if (left is double && right is double) { return((double)left - (double)right); } else if (left is int && right is int) { return((int)left - (int)right); } else if (left is int && right is double) { return((int)left - Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) - (int)right); } throw new RuntimeException("Cannot subtract non primitive types"); } case Token.Type.Multiply: { if (left is double && right is double) { return((double)left * (double)right); } else if (left is int && right is int) { return((int)left * (int)right); } else if (left is int && right is double) { return((int)left * Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) * (int)right); } else if (left is double && right is string) { return(String.Concat(Enumerable.Repeat((string)right, Convert.ToInt32(left)))); } else if (left is string && right is double) { return(String.Concat(Enumerable.Repeat((string)left, Convert.ToInt32(right)))); } throw new RuntimeException("Cannot multiply non primitive types"); } case Token.Type.Divide: { if (left is double && right is double) { return((double)left * (double)right); } else if (left is int && right is int) { return((int)left * (int)right); } else if (left is int && right is double) { return((int)left * Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) * (int)right); } throw new RuntimeException("Cannot divide non primitive types"); } case Token.Type.Mod: { if (left is double && right is double) { return((double)left % (double)right); } else if (left is int && right is int) { return((int)left % (int)right); } else if (left is int && right is double) { return((int)left % Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) % (int)right); } throw new RuntimeException("Cannot modulo non primitive types"); } case Token.Type.NoRemainder: { if (left is double && right is double) { return(Convert.ToInt32(left) / Convert.ToInt32(right)); } else if (left is int && right is int) { return((int)left / (int)right); } else if (left is int && right is double) { return((int)left / Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) / (int)right); } throw new RuntimeException("Cannot modulo non primitive types"); } case Token.Type.Greater: { if (left is double && right is double) { return((double)left > (double)right); } else if (left is int && right is int) { return((int)left > (int)right); } else if (left is int && right is double) { return((int)left > Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) > (int)right); } else if (left is string && right is string) { return(((string)left).Length > ((string)right).Length); } else if (left is double && right is string) { return(left.ToString().Length > ((string)right).Length); } else if (left is string && right is double) { return(((string)left).Length > right.ToString().Length); } throw new RuntimeException("Cannot compare non primitive types"); } case Token.Type.Less: { if (left is double && right is double) { return((double)left < (double)right); } else if (left is int && right is int) { return((int)left < (int)right); } else if (left is int && right is double) { return((int)left < Convert.ToInt32(right)); } else if (left is double && right is int) { return(Convert.ToInt32(left) < (int)right); } else if (left is string && right is string) { return(((string)left).Length < ((string)right).Length); } else if (left is double && right is string) { return(left.ToString().Length < ((string)right).Length); } else if (left is string && right is double) { return(((string)left).Length < right.ToString().Length); } throw new RuntimeException("Cannot compare non primitive types"); } case Token.Type.GreaterEqual: { if (left is double && right is double) { return((double)left >= (double)right); } else if (left is int && right is int) { return((int)left >= (int)right); } else if (left is string && right is string) { return(((string)left).Length >= ((string)right).Length); } else if (left is double && right is string) { return(left.ToString().Length >= ((string)right).Length); } else if (left is string && right is double) { return(((string)left).Length >= right.ToString().Length); } throw new RuntimeException("Cannot compare non primitive types"); } case Token.Type.LessEqual: { if (left is double && right is double) { return((double)left <= (double)right); } else if (left is int && right is int) { return((int)left <= (int)right); } else if (left is string && right is string) { return(((string)left).Length <= ((string)right).Length); } else if (left is double && right is string) { return(left.ToString().Length <= ((string)right).Length); } else if (left is string && right is double) { return(((string)left).Length <= right.ToString().Length); } throw new RuntimeException("Cannot compare non primitive types"); } case Token.Type.NotEquals: { if (left is double && right is double) { return((double)left != (double)right); } else if (left is int && right is int) { return((int)left != (int)right); } else if (left is string && right is string) { return((string)left != (string)right); } else if (left is double && right is string) { return(left.ToString() != (string)right); } else if (left is string && right is double) { return((string)left != right.ToString()); } return(get_truth(left) != get_truth(right)); } case Token.Type.Equals: { if (left is double && right is double) { return((double)left == (double)right); } else if (left is int && right is int) { return((int)left == (int)right); } else if (left is string && right is string) { return((string)left == (string)right); } else if (left is double && right is string) { return(left.ToString() == (string)right); } else if (left is string && right is double) { return((string)left == right.ToString()); } return(get_truth(left) == get_truth(right)); } } return(null); }
public Expr Parse(ParserContext context) { // If this is a binary operation, find it's precedence. while (true) { // Capture the current token. Token token = context.Stream.Current; // Calculate precedence for the current token. int firstPrecedence = Precedence.Get(token); /* * If this is a binary operation that binds at least as tightly * as the current binary operation, consume it. Otherwise, the process * is complete. */ if (firstPrecedence < this.minimalPrecedence) { // TODO: This should throw error? Research. return(this.leftSide); } // At this point, it's a binary operation. TokenType binaryOperator = token.Type; // TODO: Should check if it's a BINARY operator, not just an operator. // Ensure the captured operator is validated. if (!TokenIdentifier.IsOperator(binaryOperator)) { throw context.NoticeRepository.CreateException($"Expected token to be a binary operator but got token type '{binaryOperator}'"); } // Skip operator. context.Stream.Skip(); // Parse the right-side. Expr rightSide = new PrimaryExprParser().Parse(context); // Ensure that the right-side was successfully parsed. if (rightSide == null) { throw new Exception("Unable to parse the right-side of the binary expression"); } // Determine the token precedence of the current token. int secondPrecedence = Precedence.Get(token); /* * If binary operator binds less tightly with the right-side than * the operator after right-side, let the pending operator take the * right-side as its left-side. */ if (firstPrecedence < secondPrecedence) { // Invoke the right-side parser. rightSide = new BinaryOpRightSideParser(rightSide, firstPrecedence + 1).Parse(context); // Ensure the right-side was successfully parsed. if (rightSide == null) { throw new Exception("Unable to parse the right-side of the binary expression"); } } // Create the binary expression entity. BinaryExpr binaryExpr = new BinaryExpr(binaryOperator, this.leftSide, rightSide, firstPrecedence); // TODO: Name is temporary? // Set the name of the binary expression's output. binaryExpr.SetName("tmp"); // Merge left-side/right-side. this.leftSide = binaryExpr; } }
private bool SetUpBinaryOpHelper(BinaryExpr node, bool resultIsBool) { Type left = node.left.computedType; Type right = node.right.computedType; if (left.EqualsType(right)) { node.computedType = resultIsBool ? new PrimType { kind = PrimKind.Bool } : left; return true; } if (left.CanImplicitlyConvertTo(right)) { node.left = InsertCast(node.left, right); node.computedType = resultIsBool ? new PrimType { kind = PrimKind.Bool } : right; return true; } if (right.CanImplicitlyConvertTo(left)) { node.right = InsertCast(node.right, left); node.computedType = resultIsBool ? new PrimType { kind = PrimKind.Bool } : left; return true; } return false; }
List<Expression> GenerateAutoReqs(Expression expr, Function parent) { List<Expression> reqs = new List<Expression>(); Func<Expression,List<Expression>> generateAutoReqs = e => GenerateAutoReqs(e, parent); if (expr is LiteralExpr) { } else if (expr is ThisExpr) { } else if (expr is IdentifierExpr) { } else if (expr is SeqDisplayExpr) { SeqDisplayExpr e = (SeqDisplayExpr)expr; foreach (var elt in e.Elements) { reqs.AddRange(generateAutoReqs(elt)); } } else if (expr is MemberSelectExpr && ((MemberSelectExpr)expr).Member is Field) { MemberSelectExpr e = (MemberSelectExpr)expr; reqs.AddRange(generateAutoReqs(e.Obj)); } else if (expr is SeqSelectExpr) { SeqSelectExpr e = (SeqSelectExpr)expr; reqs.AddRange(generateAutoReqs(e.Seq)); if (e.E0 != null) { reqs.AddRange(generateAutoReqs(e.E0)); } if (e.E1 != null) { reqs.AddRange(generateAutoReqs(e.E1)); } } else if (expr is SeqUpdateExpr) { SeqUpdateExpr e = (SeqUpdateExpr)expr; reqs.AddRange(generateAutoReqs(e.Seq)); reqs.AddRange(generateAutoReqs(e.Index)); reqs.AddRange(generateAutoReqs(e.Value)); } else if (expr is FunctionCallExpr) { FunctionCallExpr e = (FunctionCallExpr)expr; foreach (var arg in e.Args) { reqs.AddRange(generateAutoReqs(arg)); } if (parent == null || parent.Name != e.name) { ReqFunction(e.Function); reqs.AddRange(GatherReqs(e.Function, e.Args)); } } else if (expr is DatatypeValue) { DatatypeValue dtv = (DatatypeValue)expr; for (int i = 0; i < dtv.Arguments.Count; i++) { Expression arg = dtv.Arguments[i]; reqs.AddRange(generateAutoReqs(arg)); } } else if (expr is OldExpr) { } else if (expr is MatchExpr) { MatchExpr e = (MatchExpr)expr; reqs.AddRange(generateAutoReqs(e.Source)); List<MatchCaseExpr> newMatches = new List<MatchCaseExpr>(); foreach (MatchCaseExpr caseExpr in e.Cases) { MatchCaseExpr c = new MatchCaseExpr(caseExpr.name, caseExpr.Arguments, Andify(generateAutoReqs(caseExpr.Body))); newMatches.Add(c); } reqs.Add(new MatchExpr(e.Source, newMatches)); } else if (expr is UnaryOpExpr) { UnaryOpExpr e = (UnaryOpExpr)expr; Expression arg = e.E; reqs.AddRange(generateAutoReqs(arg)); } else if (expr is BinaryExpr) { BinaryExpr e = (BinaryExpr)expr; switch (e.Op) { case BinaryExpr.Opcode.Imp: case BinaryExpr.Opcode.And: reqs.AddRange(generateAutoReqs(e.E0)); foreach (var req in generateAutoReqs(e.E1)) { reqs.Add(new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.Imp, e.E0, req)); } break; case BinaryExpr.Opcode.Or: reqs.AddRange(generateAutoReqs(e.E0)); foreach (var req in generateAutoReqs(e.E1)) { reqs.Add(new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.Imp, new UnaryOpExpr(Token.NoToken, UnaryOpExpr.Opcode.Not, e.E0), req)); } break; default: reqs.AddRange(generateAutoReqs(e.E0)); reqs.AddRange(generateAutoReqs(e.E1)); break; } } else if (expr is LetExpr) { var e = (LetExpr)expr; if (e.Exact) { foreach (var rhs in e.RHSs) { reqs.AddRange(generateAutoReqs(rhs)); } var new_reqs = generateAutoReqs(e.Body); if (new_reqs.Count > 0) { reqs.Add(new LetExpr(e.Exact, e.LHSs, e.RHSs, Andify(new_reqs))); } } } else if (expr is QuantifierExpr) { QuantifierExpr e = (QuantifierExpr)expr; var auto_reqs = generateAutoReqs(e.Term); if (auto_reqs.Count > 0) { Expression allReqsSatisfied = Andify(auto_reqs); Expression allReqsSatisfiedAndTerm = new BinaryExpr(Token.NoToken, BinaryExpr.Opcode.And, allReqsSatisfied, e.Term); e.Term = allReqsSatisfiedAndTerm; } } else if (expr is StmtExpr) { var e = (StmtExpr)expr; reqs.AddRange(generateAutoReqs(e.E)); } else if (expr is ITEExpr) { ITEExpr e = (ITEExpr)expr; reqs.AddRange(generateAutoReqs(e.Test)); reqs.Add(new ITEExpr(e.Test, Andify(generateAutoReqs(e.Thn)), Andify(generateAutoReqs(e.Els)))); } return reqs; }
void MulOp(out IToken x, out BinaryExpr.Opcode op) { Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/; if (la.kind == 57) { Get(); x = t; op = BinaryExpr.Opcode.Mul; } else if (la.kind == 129) { Get(); x = t; op = BinaryExpr.Opcode.Div; } else if (la.kind == 130) { Get(); x = t; op = BinaryExpr.Opcode.Mod; } else SynErr(224); }
public virtual void Visit(BinaryExpr binaryExpression) { VisitNullableExpression(binaryExpression.E0); VisitNullableExpression(binaryExpression.E1); }
void RelationalExpression(out Expression e, bool allowSemi, bool allowLambda) { Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken x, firstOpTok = null; Expression e0, e1, acc = null; BinaryExpr.Opcode op; List<Expression> chain = null; List<BinaryExpr.Opcode> ops = null; List<Expression/*?*/> prefixLimits = null; Expression k; int kind = 0; // 0 ("uncommitted") indicates chain of ==, possibly with one != // 1 ("ascending") indicates chain of ==, <, <=, possibly with one != // 2 ("descending") indicates chain of ==, >, >=, possibly with one != // 3 ("illegal") indicates illegal chain // 4 ("disjoint") indicates chain of disjoint set operators bool hasSeenNeq = false; Term(out e0, allowSemi, allowLambda); e = e0; if (IsRelOp()) { RelOp(out x, out op, out k); firstOpTok = x; Term(out e1, allowSemi, allowLambda); if (k == null) { e = new BinaryExpr(x, op, e0, e1); if (op == BinaryExpr.Opcode.Disjoint) acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, e0, e1); // accumulate first two operands. } else { Contract.Assert(op == BinaryExpr.Opcode.Eq || op == BinaryExpr.Opcode.Neq); e = new TernaryExpr(x, op == BinaryExpr.Opcode.Eq ? TernaryExpr.Opcode.PrefixEqOp : TernaryExpr.Opcode.PrefixNeqOp, k, e0, e1); } while (IsRelOp()) { if (chain == null) { chain = new List<Expression>(); ops = new List<BinaryExpr.Opcode>(); prefixLimits = new List<Expression>(); chain.Add(e0); ops.Add(op); prefixLimits.Add(k); chain.Add(e1); switch (op) { case BinaryExpr.Opcode.Eq: kind = 0; break; case BinaryExpr.Opcode.Neq: kind = 0; hasSeenNeq = true; break; case BinaryExpr.Opcode.Lt: case BinaryExpr.Opcode.Le: kind = 1; break; case BinaryExpr.Opcode.Gt: case BinaryExpr.Opcode.Ge: kind = 2; break; case BinaryExpr.Opcode.Disjoint: kind = 4; break; default: kind = 3; break; } } e0 = e1; RelOp(out x, out op, out k); switch (op) { case BinaryExpr.Opcode.Eq: if (kind != 0 && kind != 1 && kind != 2) { SemErr(x, "chaining not allowed from the previous operator"); } break; case BinaryExpr.Opcode.Neq: if (hasSeenNeq) { SemErr(x, "a chain cannot have more than one != operator"); } if (kind != 0 && kind != 1 && kind != 2) { SemErr(x, "this operator cannot continue this chain"); } hasSeenNeq = true; break; case BinaryExpr.Opcode.Lt: case BinaryExpr.Opcode.Le: if (kind == 0) { kind = 1; } else if (kind != 1) { SemErr(x, "this operator chain cannot continue with an ascending operator"); } break; case BinaryExpr.Opcode.Gt: case BinaryExpr.Opcode.Ge: if (kind == 0) { kind = 2; } else if (kind != 2) { SemErr(x, "this operator chain cannot continue with a descending operator"); } break; case BinaryExpr.Opcode.Disjoint: if (kind != 4) { SemErr(x, "can only chain disjoint (!!) with itself."); kind = 3; } break; default: SemErr(x, "this operator cannot be part of a chain"); kind = 3; break; } Term(out e1, allowSemi, allowLambda); ops.Add(op); prefixLimits.Add(k); chain.Add(e1); if (k != null) { Contract.Assert(op == BinaryExpr.Opcode.Eq || op == BinaryExpr.Opcode.Neq); e = new TernaryExpr(x, op == BinaryExpr.Opcode.Eq ? TernaryExpr.Opcode.PrefixEqOp : TernaryExpr.Opcode.PrefixNeqOp, k, e0, e1); } else if (op == BinaryExpr.Opcode.Disjoint && acc != null) { // the second conjunct always holds for legal programs e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, acc, e1)); acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, acc, e1); //e0 has already been added. } else { e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, e0, e1)); } } } if (chain != null) { e = new ChainingExpression(firstOpTok, chain, ops, prefixLimits, e); } }
internal static CompilationError BinaryOperationError(BinaryExpr expr, BinaryOperatorKind kind, BindOptions options) { return(expr.Error(ErrorCode.BinaryOperationNotFound, BinaryOperatorSymbol.OperatorSymbol(kind), expr.Left.Datatype, expr.Right.Datatype)); }
void RelOp(out IToken/*!*/ x, out BinaryExpr.Opcode op, out Expression k) { Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/; IToken y; k = null; switch (la.kind) { case 54: { Get(); x = t; op = BinaryExpr.Opcode.Eq; if (la.kind == 106) { Get(); Expect(48); Expression(out k, true, true); Expect(49); } break; } case 52: { Get(); x = t; op = BinaryExpr.Opcode.Lt; break; } case 53: { Get(); x = t; op = BinaryExpr.Opcode.Gt; break; } case 107: { Get(); x = t; op = BinaryExpr.Opcode.Le; break; } case 108: { Get(); x = t; op = BinaryExpr.Opcode.Ge; break; } case 55: { Get(); x = t; op = BinaryExpr.Opcode.Neq; if (la.kind == 106) { Get(); Expect(48); Expression(out k, true, true); Expect(49); } break; } case 126: { Get(); x = t; op = BinaryExpr.Opcode.In; break; } case 58: { Get(); x = t; op = BinaryExpr.Opcode.NotIn; break; } case 121: { Get(); x = t; y = Token.NoToken; if (la.val == "!") { Expect(121); y = t; } if (y == Token.NoToken) { SemErr(x, "invalid RelOp"); } else if (y.pos != x.pos + 1) { SemErr(x, "invalid RelOp (perhaps you intended \"!!\" with no intervening whitespace?)"); } else { x.val = "!!"; op = BinaryExpr.Opcode.Disjoint; } break; } case 56: { Get(); x = t; op = BinaryExpr.Opcode.Neq; break; } case 109: { Get(); x = t; op = BinaryExpr.Opcode.Le; break; } case 110: { Get(); x = t; op = BinaryExpr.Opcode.Ge; break; } default: SynErr(221); break; } }
public bool Visit(BinaryExpr node) { return(this.Visit(node.left) && this.Visit(node.right)); }
void Term(out Expression e0, bool allowSemi, bool allowLambda) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op; Factor(out e0, allowSemi, allowLambda); while (IsAddOp()) { AddOp(out x, out op); Factor(out e1, allowSemi, allowLambda); e0 = new BinaryExpr(x, op, e0, e1); } }
void ShiftTerm(out Expression e0, bool allowSemi, bool allowLambda, bool allowBitwiseOps) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken x = Token.NoToken; Expression e1; BinaryExpr.Opcode op = BinaryExpr.Opcode.LeftShift/*(dummy)*/; Term(out e0, allowSemi, allowLambda, allowBitwiseOps); while (IsShiftOp()) { if (la.kind == 56) { Get(); x = t; op = BinaryExpr.Opcode.LeftShift; Expect(56); x.val = "<<"; Contract.Assert(t.pos == x.pos + 1); } else if (la.kind == 57) { Get(); x = t; op = BinaryExpr.Opcode.RightShift; Expect(57); x.val = "<<"; Contract.Assert(t.pos == x.pos + 1); } else SynErr(245); Term(out e1, allowSemi, allowLambda, allowBitwiseOps); e0 = new BinaryExpr(x, op, e0, e1); } }
void AddOp(out IToken x, out BinaryExpr.Opcode op) { Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryExpr.Opcode.Add/*(dummy)*/; if (la.kind == 127) { Get(); x = t; op = BinaryExpr.Opcode.Add; } else if (la.kind == 128) { Get(); x = t; op = BinaryExpr.Opcode.Sub; } else SynErr(222); }
public RtlExp GhostExpressionRec(Expression exp, bool inRecSpec = false, bool inRequiresOrOld = false) { Util.Assert(!isPrinting); exp = GetExp(exp); StmtExpr stmtExpr = exp as StmtExpr; IdentifierExpr idExp = exp as IdentifierExpr; LiteralExpr literal = exp as LiteralExpr; BinaryExpr binary = exp as BinaryExpr; UnaryExpr unary = exp as UnaryExpr; ITEExpr ite = exp as ITEExpr; ExistsExpr existsExp = exp as ExistsExpr; ForallExpr forallExp = exp as ForallExpr; LetExpr letExp = exp as LetExpr; MatchExpr matchExp = exp as MatchExpr; OldExpr oldExp = exp as OldExpr; FunctionCallExpr funCall = exp as FunctionCallExpr; DatatypeValue dataVal = exp as DatatypeValue; MemberSelectExpr memberSelect = exp as MemberSelectExpr; SeqSelectExpr seqSelect = exp as SeqSelectExpr; SeqUpdateExpr seqUpdate = exp as SeqUpdateExpr; SeqDisplayExpr seqDisplay = exp as SeqDisplayExpr; Func<Expression,RtlExp> G = e => GhostExpression(e, inRecSpec, inRequiresOrOld); if (stmtExpr != null) { if (stmtExprEnabled) { if (ignoreStmtExpr == 0) { AddGhostStatement(stmtExpr.S, null); } return G(stmtExpr.E); } else { throw new Exception("not implemented: cannot handle statement expression here"); } } else if (idExp != null) { return AsVar(idExp); } else if (literal != null && literal.Value is BigInteger) { return new RtlInt((BigInteger)(literal.Value)); } else if (literal != null && literal.Value is bool) { return new RtlLiteral((bool)(literal.Value) ? "true" : "false"); } else if (literal != null && literal.Value == null) { return new RtlLiteral("ArrayOfInt(0 - 1, NO_ABS)"); } else if (literal != null && literal.Value is Microsoft.Basetypes.BigDec) { return new RtlLiteral(((Microsoft.Basetypes.BigDec)literal.Value).ToDecimalString()); } else if (binary != null) { string op = null; string internalOp = null; CompileFunction compileFunction = this as CompileFunction; string thisFuncName = (compileFunction == null) ? null : compileFunction.function.Name; switch (binary.ResolvedOp) { case BinaryExpr.ResolvedOpcode.SeqEq: return new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.E0.Type), "Seq_Equal"), new RtlExp[] { G(binary.E0), G(binary.E1) }); case BinaryExpr.ResolvedOpcode.SeqNeq: return new RtlLiteral("(!" + new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.E0.Type), "Seq_Equal"), new RtlExp[] { G(binary.E0), G(binary.E1) }) + ")"); case BinaryExpr.ResolvedOpcode.Concat: return new RtlApply(dafnySpec.GetSeqOperationName(AppType(binary.Type), "Seq_Append"), new RtlExp[] { G(binary.E0), G(binary.E1) }); } if (binary.Op == BinaryExpr.Opcode.Exp) { binary = new BinaryExpr(binary.tok, BinaryExpr.Opcode.Imp, binary.E0, binary.E1); } switch (binary.Op) { case BinaryExpr.Opcode.Disjoint: case BinaryExpr.Opcode.In: case BinaryExpr.Opcode.NotIn: throw new Exception("not implemented: binary operator '" + BinaryExpr.OpcodeString(binary.Op) + "'"); } if (AppType(binary.E0.Type) is IntType && AppType(binary.E1.Type) is IntType) { switch (binary.Op) { case BinaryExpr.Opcode.Le: internalOp = "INTERNAL_le_boogie"; break; case BinaryExpr.Opcode.Lt: internalOp = "INTERNAL_lt_boogie"; break; case BinaryExpr.Opcode.Ge: internalOp = "INTERNAL_ge_boogie"; break; case BinaryExpr.Opcode.Gt: internalOp = "INTERNAL_gt_boogie"; break; case BinaryExpr.Opcode.Add: internalOp = "INTERNAL_add_boogie"; break; case BinaryExpr.Opcode.Sub: internalOp = "INTERNAL_sub_boogie"; break; case BinaryExpr.Opcode.Mul: op = "*"; if (thisFuncName != "INTERNAL_mul") { internalOp = FunName("INTERNAL__mul"); } break; case BinaryExpr.Opcode.Div: op = "div"; if (thisFuncName != "INTERNAL_div") { internalOp = FunName("INTERNAL__div"); } break; case BinaryExpr.Opcode.Mod: op = "mod"; if (thisFuncName != "INTERNAL_mod") { internalOp = FunName("INTERNAL__mod"); } break; default: op = BinaryExpr.OpcodeString(binary.Op); break; } } else { op = BinaryExpr.OpcodeString(binary.Op); } if (internalOp == null) { return new RtlBinary(op, G(binary.E0), G(binary.E1)); } else { return new RtlApply(internalOp, new RtlExp[] { G(binary.E0), G(binary.E1) }); } } else if (unary != null) { if (unary is UnaryOpExpr) { UnaryOpExpr unaryOp = (UnaryOpExpr)unary; if (unaryOp.Op == UnaryOpExpr.Opcode.Not) { return new RtlLiteral("(!(" + G(unaryOp.E) + "))"); } else if (unaryOp.Op == UnaryOpExpr.Opcode.Cardinality) { return new RtlApply(dafnySpec.GetSeqOperationName(AppType(unaryOp.E.Type), "Seq_Length"), new RtlExp[] { G(unaryOp.E) }); } else if (unaryOp.Op == UnaryOpExpr.Opcode.Fresh) { Util.Assert(DafnySpec.IsArrayType(unaryOp.E.Type)); string abs = G(unaryOp.E) + ".arrAbs"; return new RtlLiteral("(heap_old.absData[" + abs + "] is AbsNone)"); } else { throw new Exception("not implemented: " + exp); } } else if (unary is ConversionExpr) { var e = (ConversionExpr)unary; var fromInt = e.E.Type.IsNumericBased(Type.NumericPersuation.Int); var toInt = e.ToType.IsNumericBased(Type.NumericPersuation.Int); if (fromInt && !toInt) { return new RtlApply("real", new RtlExp[] { G(e.E) }); } else if (!fromInt && toInt) { return new RtlApply("int", new RtlExp[] { G(e.E) }); } else { Util.Assert(fromInt == toInt); return GhostExpressionRec(e.E, inRecSpec, inRequiresOrOld); } } else { throw new Exception("not implemented: " + exp); } } else if (ite != null) { return GhostIfThenElse(G(ite.Test), () => G(ite.Thn), () => G(ite.Els)); } else if (funCall != null) { switch (funCall.Function.Name) { case "left": case "right": case "relation": case "public": Util.Assert(funCall.Args.Count == 1); return new RtlApply(funCall.Function.Name, new RtlExp[] { G(funCall.Args[0]) }); case "sizeof": Util.Assert(funCall.Args.Count == 1); return new RtlApply(funCall.Function.Name + "##" + TypeString(AppType(funCall.Args[0].Type)), new RtlExp[] { G(funCall.Args[0]) }); case "INTERNAL_add_raw": Util.Assert(funCall.Args.Count == 2); return new RtlBinary("+", G(funCall.Args[0]), G(funCall.Args[1])); case "INTERNAL_sub_raw": Util.Assert(funCall.Args.Count == 2); return new RtlBinary("-", G(funCall.Args[0]), G(funCall.Args[1])); } TypeApply app = dafnySpec.Compile_Function(funCall.Function, funCall.TypeArgumentSubstitutions.ToDictionary(p => p.Key, p => AppType(p.Value))); string name = FunName(SimpleName(app.AppName())); string fullName = FunName(SimpleName(app.AppFullName())); List<RtlExp> rtlArgs = funCall.Args.Select(G).ToList(); List<RtlExp> rtlReads = funCall.Function.Reads.Where(e => e.Field != null).ToList() .ConvertAll(e => (RtlExp)new RtlVar( GhostVar(e.FieldName), e.Field.IsGhost, AppType(e.Field.Type))); rtlArgs = rtlReads.Concat(rtlArgs).ToList(); if (name.EndsWith("__INTERNAL__HEAP")) { name = name.Substring(0, name.Length - "__INTERNAL__HEAP".Length); } else if (DafnySpec.IsHeapFunction(funCall.Function)) { rtlArgs.Insert(0, new RtlLiteral(inRequiresOrOld ? "$absMem_old" : "$absMem")); } if (Attributes.Contains(funCall.Function.Attributes, "opaque") && funCall.Function.Formals.Count + rtlReads.Count == 0) { rtlArgs.Insert(0, new RtlLiteral("true")); } if (fullName == recFunName) { name = fullName; } if (name == recFunName) { recCalls.Add(new List<RtlExp>(rtlArgs)); rtlArgs.Insert(0, new RtlApply("decreases_" + name, new List<RtlExp>(rtlArgs))); rtlArgs.Insert(1, new RtlLiteral(inRecSpec ? "__unroll" : "__unroll + 1")); name = "rec_" + name; } return new RtlApply(name, rtlArgs); } else if (dataVal != null) { bool isSeq = dataVal.Type.TypeName(null).StartsWith("Seq<"); return new RtlApply((isSeq ? "_" : "") + dafnySpec.Compile_Constructor( dataVal.Type, dataVal.Ctor.Name, dataVal.InferredTypeArgs, typeApply.typeArgs).AppName(), dataVal.Arguments.Select(G)); } else if (existsExp != null || forallExp != null) { QuantifierExpr qExp = (QuantifierExpr)exp; bool isForall = forallExp != null; var varTuples = qExp.BoundVars.Select(v => Tuple.Create(GhostVar(v.Name), v.IsGhost, v.Type)); var oldRenamer = PushRename(qExp.BoundVars.Select(v => v.Name)); var oldStmtExprEnabled = stmtExprEnabled; stmtExprEnabled = false; RtlExp rExp = new RtlLiteral((isForall ? "(forall " : "(exists ") + string.Join(", ", qExp.BoundVars.Select(v => GhostVar(v.Name) + ":" + TypeString(AppType(v.Type)))) + " :: " + Triggers(qExp.Attributes, G) + " " + GetTypeWellFormedExp(varTuples.ToList(), isForall ? "==>" : "&&", G(qExp.Term)) + ")"); stmtExprEnabled = oldStmtExprEnabled; PopRename(oldRenamer); return rExp; } else if (letExp != null) { List<RtlExp> rhss; if (letExp.Exact) { rhss = letExp.RHSs.ConvertAll(e => G(e)); } else if (letExp.LHSs.Count == 1 && LiteralExpr.IsTrue(letExp.RHSs[0]) && AppType(letExp.LHSs[0].Var.Type) is IntType) { rhss = new List<RtlExp> { new RtlLiteral("0") }; } else { throw new Exception("not implemented: LetExpr: " + letExp); } return GhostLet(exp.tok, letExp.LHSs.ConvertAll(lhs => lhs.Var), rhss, () => G(letExp.Body)); } else if (matchExp != null) { if (matchExp.MissingCases.Count != 0) { throw new Exception("not implemented: MatchExpr with missing cases: " + matchExp); } //- match src case c1(ps1) => e1 ... cn(psn) => en //- --> //- let x := src in //- if x is c1 then let ps1 := ...x.f1... in e1 else //- if x is c2 then let ps2 := ...x.f2... in e2 else //- let ps3 := ...x.f3... in e3 var src = G(matchExp.Source); var cases = matchExp.Cases; string x = TempName(); Func<RtlExp> body = null; for (int i = cases.Count; i > 0; ) { i--; MatchCaseExpr c = cases[i]; Func<List<RtlExp>> cRhss = () => c.Ctor.Formals.ConvertAll(f => (RtlExp)new RtlLiteral("(" + f.Name + "#" + c.Ctor.Name + "(" + GhostVar(x) + "))")); Func<RtlExp> ec = () => GhostLet(exp.tok, c.Arguments, cRhss(), () => G(c.Body)); if (body == null) { body = ec; } else { var prevBody = body; body = () => GhostIfThenElse(new RtlLiteral("(" + GhostVar(x) + " is " + c.Ctor.Name + ")"), ec, prevBody); } } return GhostLet(exp.tok, new List<BoundVar> { new BoundVar(exp.tok, x, matchExp.Source.Type) }, new List<RtlExp> { src }, body); } else if (oldExp != null) { return new RtlLiteral("old(" + GhostExpression(oldExp.E, inRecSpec, true) + ")"); } else if (memberSelect != null && memberSelect.MemberName.EndsWith("?")) { string constructor = memberSelect.MemberName.Substring(0, memberSelect.MemberName.Length - 1); constructor = dafnySpec.Compile_Constructor(memberSelect.Obj.Type, constructor, null, typeApply.typeArgs).AppName(); bool isSeq = memberSelect.Obj.Type.TypeName(null).StartsWith("Seq<"); return isSeq ? new RtlLiteral("is_" + constructor + "(" + G(memberSelect.Obj) + ")") : new RtlLiteral("((" + G(memberSelect.Obj) + ") is " + constructor + ")"); } else if (memberSelect != null && memberSelect.Member is Field && !memberSelect.Member.IsStatic && AppType(memberSelect.Obj.Type) is UserDefinedType && memberSelect.Member is DatatypeDestructor) { DatatypeDestructor field = (DatatypeDestructor) memberSelect.Member; string constructor = dafnySpec.Compile_Constructor(memberSelect.Obj.Type, field.EnclosingCtor.Name, null, typeApply.typeArgs).AppName(); bool isSeq = memberSelect.Obj.Type.TypeName(null).StartsWith("Seq<"); return new RtlLiteral("(" + memberSelect.MemberName + (isSeq ? "_" : "#") + constructor + "(" + G(memberSelect.Obj) + "))"); } else if (memberSelect != null && memberSelect.Member is Field && DafnySpec.IsArrayType(AppType(memberSelect.Obj.Type)) && memberSelect.MemberName == "Length") { return new RtlLiteral("(Arr_Length(" + G(memberSelect.Obj) + "))"); } else if (memberSelect != null && memberSelect.Member is Field && memberSelect.Obj is ImplicitThisExpr) { //- we don't support objects yet, so interpret this as a global variable return new RtlVar(GhostVar(memberSelect.MemberName), true, memberSelect.Type); } else if (seqSelect != null) { if (seqSelect.SelectOne && DafnySpec.IsArrayType(AppType(seqSelect.Seq.Type))) { return new RtlExpComputed(e => "fun_INTERNAL__array__elems__index(" + (inRequiresOrOld ? "$absMem_old" : "$absMem") + "[" + e.args[0] + ".arrAbs], (" + e.args[1] + "))", new RtlExp[] { G(seqSelect.Seq), G(seqSelect.E0) }); } else if (seqSelect.SelectOne) { return new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Seq.Type), "Seq_Index"), new RtlExp[] { G(seqSelect.Seq), G(seqSelect.E0) }); } else { RtlExp seq = G(seqSelect.Seq); if (DafnySpec.IsArrayType(AppType(seqSelect.Seq.Type))) { seq = new RtlApply(FunName("Seq__FromArray"), new RtlExp[] { new RtlLiteral(inRequiresOrOld ? "$absMem_old" : "$absMem"), seq }); } if (seqSelect.E1 != null) { seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Type), "Seq_Take"), new RtlExp[] { seq, G(seqSelect.E1) }); } if (seqSelect.E0 != null) { seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqSelect.Type), "Seq_Drop"), new RtlExp[] { seq, G(seqSelect.E0) }); } return seq; } } else if (seqUpdate != null) { if (seqUpdate.ResolvedUpdateExpr != null) { return GhostExpressionRec(seqUpdate.ResolvedUpdateExpr, inRecSpec, inRequiresOrOld); } return new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqUpdate.Seq.Type), "Seq_Update"), new RtlExp[] { G(seqUpdate.Seq), G(seqUpdate.Index), G(seqUpdate.Value) }); } else if (seqDisplay != null) { RtlExp seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqDisplay.Type), "Seq_Empty"), new RtlExp[0]); foreach (Expression ei in seqDisplay.Elements) { seq = new RtlApply(dafnySpec.GetSeqOperationName(AppType(seqDisplay.Type), "Seq_Build"), new RtlExp[] { seq, G(ei) }); } return seq; } else { throw new Exception("not implemented: " + exp); } }
public override Null Visit(BinaryExpr node) { context = null; node.computedType = new ErrorType(); base.Visit(node); if (!SetUpBinaryOp(node)) { log.ErrorBinaryOpNotFound(node); } return null; }
public Expr Parse(TokenStream stream) { // If this is a binary operation, find it's precedence. while (true) { var firstPrecedence = Precedence.Get(stream.Get()); /* * If this is a binary operation that binds at least as tightly * as the current binary operation, consume it. Otherwise, the process * is complete. */ if (firstPrecedence < minimalPrecedence) { return(leftSide); } // At this point, it's a binary operation. TokenType binaryOperator = stream.Get().Type; // TODO: Should check if it's a BINARY operator, not just an operator. // Ensure the captured operator is validated. if (!TokenIdentifier.IsOperator(binaryOperator)) { throw new Exception( $"Expected token to be a binary operator but got token type '{binaryOperator}'"); } // Skip operator. stream.Skip(); // Parse the right-side. Expr rightSide = new PrimaryExprParser().Parse(stream); // Ensure that the right-side was successfully parsed. if (rightSide == null) { throw new Exception("Unable to parse the right-side of the binary expression"); } // Determine the token precedence of the current token. var secondPrecedence = Precedence.Get(stream.Get()); /* * If binary operator binds less tightly with the right-side than * the operator after right-side, let the pending operator take the * right-side as its left-side. */ if (firstPrecedence < secondPrecedence) { // Invoke the right-side parser. rightSide = new BinaryOpRightSideParser(rightSide, firstPrecedence + 1).Parse(stream); // Ensure the right-side was successfully parsed. if (rightSide == null) { throw new Exception("Unable to parse the right-side of the binary expression"); } } // Create the binary expression entity. var binaryExpr = new BinaryExpr(leftSide, rightSide, firstPrecedence); // Merge left-side/right-side. leftSide = binaryExpr; } }
private bool SetUpBinaryOp(BinaryExpr node) { Type left = node.left.computedType; Type right = node.right.computedType; // Binary operators aren't supported on type literals if (left is MetaType || right is MetaType) { return false; } switch (node.op) { case BinaryOp.Assign: if (left.EqualsType(right)) { node.computedType = left; return true; } else if (right.CanImplicitlyConvertTo(left)) { node.right = InsertCast(node.right, left); node.computedType = left; return true; } break; case BinaryOp.NullableDefault: if (left is NullableType) { Type type = ((NullableType)left).type; if (right.EqualsType(type)) { node.computedType = type; return true; } else if (right.CanImplicitlyConvertTo(type)) { node.right = InsertCast(node.right, type); node.computedType = type; return true; } } break; case BinaryOp.And: case BinaryOp.Or: if (left.IsBool() && right.IsBool()) { node.computedType = new PrimType { kind = PrimKind.Bool }; return true; } break; case BinaryOp.Add: if (((left.IsNumeric() && right.IsNumeric()) || (left.IsString() && right.IsString())) && SetUpBinaryOpHelper(node, false)) { return true; } break; case BinaryOp.Subtract: case BinaryOp.Multiply: case BinaryOp.Divide: if (left.IsNumeric() && right.IsNumeric() && SetUpBinaryOpHelper(node, false)) { return true; } break; case BinaryOp.LShift: case BinaryOp.RShift: case BinaryOp.BitAnd: case BinaryOp.BitOr: case BinaryOp.BitXor: if (left.IsInt() && right.IsInt() && SetUpBinaryOpHelper(node, false)) { return true; } break; case BinaryOp.Equal: case BinaryOp.NotEqual: if (SetUpBinaryOpHelper(node, true)) { return true; } break; case BinaryOp.LessThan: case BinaryOp.GreaterThan: case BinaryOp.LessThanEqual: case BinaryOp.GreaterThanEqual: if (((left.IsNumeric() && right.IsNumeric()) || (left.IsString() && right.IsString())) && SetUpBinaryOpHelper(node, true)) { return true; } break; } return false; }