Ejemplo n.º 1
0
    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);
    }
Ejemplo n.º 2
0
 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 };
       }
 }
Ejemplo n.º 3
0
 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();
   } 
 }
Ejemplo n.º 4
0
    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);

    }
Ejemplo n.º 5
0
 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 + ")\"");
     }
 }
Ejemplo n.º 6
0
    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);
    }
Ejemplo n.º 7
0
 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);
 }
Ejemplo n.º 8
0
        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;
            }
        }
Ejemplo n.º 9
0
 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;
     }
 }
Ejemplo n.º 10
0
        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));
        }
Ejemplo n.º 11
0
    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;
      }
    }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
 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))
     });
Ejemplo n.º 14
0
        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));
        }
Ejemplo n.º 15
0
    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");
        }
Ejemplo n.º 17
0
        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>());
        }
Ejemplo n.º 18
0
        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));
        }
Ejemplo n.º 19
0
        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);
        }
Ejemplo n.º 20
0
        /// <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);
            }
        }
Ejemplo n.º 22
0
    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;
    }
Ejemplo n.º 23
0
        /// <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);
        }
Ejemplo n.º 24
0
        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);
        }
Ejemplo n.º 25
0
        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);
        }
Ejemplo n.º 26
0
        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;
            }
        }
Ejemplo n.º 27
0
        // 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);
        }
Ejemplo n.º 28
0
        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);
        }
Ejemplo n.º 29
0
        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);
              }
        }
Ejemplo n.º 30
0
 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);
 }
Ejemplo n.º 31
0
 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);
     }
 }
Ejemplo n.º 32
0
 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);
     }
 }
Ejemplo n.º 33
0
 /// <summary>
 /// Visits the binary expression tree
 /// </summary>
 /// <param name="exp"></param>
 public void Binary(BinaryExpr exp)
 {
     _callBack(exp);
     _callBack(exp.Left);
     _callBack(exp.Right);
 }
Ejemplo n.º 34
0
 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;
 }
Ejemplo n.º 35
0
    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;
    }
Ejemplo n.º 36
0
 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);
     }
 }
Ejemplo n.º 37
0
 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);
     }
 }
Ejemplo n.º 38
0
 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);
     }
 }
Ejemplo n.º 39
0
 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);
     }
 }
Ejemplo n.º 40
0
        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));
        }
Ejemplo n.º 41
0
    // 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);
    }
Ejemplo n.º 42
0
        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;
            }
        }
Ejemplo n.º 43
0
    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;
    }
Ejemplo n.º 44
0
 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;
 }
Ejemplo n.º 45
0
 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);
 }
Ejemplo n.º 47
0
        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);
            }
        }
Ejemplo n.º 48
0
 internal static CompilationError BinaryOperationError(BinaryExpr expr, BinaryOperatorKind kind, BindOptions options)
 {
     return(expr.Error(ErrorCode.BinaryOperationNotFound, BinaryOperatorSymbol.OperatorSymbol(kind), expr.Left.Datatype, expr.Right.Datatype));
 }
Ejemplo n.º 49
0
        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));
 }
Ejemplo n.º 51
0
 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);
     }
 }
Ejemplo n.º 52
0
        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);
            }
        }
Ejemplo n.º 53
0
 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);
 }
Ejemplo n.º 54
0
    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);
        }
    }
Ejemplo n.º 55
0
 public override Null Visit(BinaryExpr node)
 {
     context = null;
     node.computedType = new ErrorType();
     base.Visit(node);
     if (!SetUpBinaryOp(node)) {
         log.ErrorBinaryOpNotFound(node);
     }
     return null;
 }
Ejemplo n.º 56
0
        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;
            }
        }
Ejemplo n.º 57
0
    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;
    }