public virtual void Visit(ChainingExpression chainingExpression) { foreach (var operand in chainingExpression.Operands) { Visit(operand); } }
public string GenerateConditionString(ChainingExpression expression, IDictionary <string, string> rename) { var bob = new StringBuilder(); int i; for (i = 0; i < expression.Operators.Count; i++) { var operand = GenerateConditionString(expression.Operands[i], rename); var op = GenerateString(expression.Operators[i]); bob.Append(operand + " " + op + " "); } var last = GenerateConditionString(expression.Operands[i], rename); bob.Append(last); return(bob.ToString()); }
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); } }
public Expression TreeToExpression() { Contract.Ensures(Contract.Result <Expression>() != null); if (IsLeaf()) { return(Data); } if (Data is TacnyBinaryExpr) { TacnyBinaryExpr bexp = (TacnyBinaryExpr)Data; Expression E0 = LChild.TreeToExpression(); Expression E1 = RChild?.TreeToExpression(); return(new TacnyBinaryExpr(bexp.tok, bexp.Op, E0, E1)); } if (Data is BinaryExpr) { BinaryExpr bexp = (BinaryExpr)Data; Expression E0 = LChild.TreeToExpression(); Expression E1 = RChild?.TreeToExpression(); return(new BinaryExpr(bexp.tok, bexp.Op, E0, E1)); } if (Data is ChainingExpression) { List <Expression> operands = null; ChainingExpression ce = (ChainingExpression)Data; operands = GetLeafData(); operands.RemoveAt(1); // hack to remove the duplicate name statement List <BinaryExpr.Opcode> operators = new List <BinaryExpr.Opcode>(); BinaryExpr expr = (BinaryExpr)LChild.TreeToExpression(); operators.Add(((BinaryExpr)expr.E0).Op); operators.Add(((BinaryExpr)expr.E1).Op); return(new ChainingExpression(ce.tok, operands, operators, ce.PrefixLimits, expr)); } if (Data is ParensExpression) { return(new ParensExpression(Data.tok, LChild.TreeToExpression())); } if (Data is QuantifierExpr) { QuantifierExpr qexp = (QuantifierExpr)Data; if (Data is ForallExpr) { return(new ForallExpr(qexp.tok, qexp.BoundVars, qexp.Range, LChild.TreeToExpression(), qexp.Attributes)); } if (Data is ExistsExpr) { return(new ExistsExpr(qexp.tok, qexp.BoundVars, qexp.Range, LChild.TreeToExpression(), qexp.Attributes)); } } else if (Data is NegationExpression) { return(new NegationExpression(Data.tok, LChild.TreeToExpression())); } else if (Data is SeqSelectExpr) { var e = (SeqSelectExpr)Data; return(new SeqSelectExpr(e.tok, e.SelectOne, e.Seq, LChild.TreeToExpression(), RChild?.TreeToExpression())); } return(Data); }