Beispiel #1
0
        //m[m][b] := c;
        //m:A b:B c:C
        // type(m) = [A] ([B]C)
        // ==>               m [m :=                       m[m] [b:=c]]
        // ==> MU<[A]([B]C)>(m, m ,MU<[B]C>( ML<[A]([B]C)>(m,m), b, c )

        //m[m] := b
        // ==> m := m[m:=b]
        // ==> m := MU<[A]B>(m,m,b)

        /////////////////////////////////////////////////////////////////////////////////////
        private Expression getAssignmentSourceExpression(MapAssignLhs target, Expression source)
        {
            var arguments = new List <Expression>();

            arguments.Add(procedure.expressionFactory.makeExpression(target.Map.AsExpr));

            foreach (var e in target.Indexes)
            {
                arguments.Add(procedure.expressionFactory.makeExpression(e));
            }

            arguments.Add(source);

            var mt = arguments[0].type as MapType;

            Debug.Assert(mt != null);

            var argumentTypes = new IType[arguments.Count];

            for (int i = 0; i < arguments.Count; i++)
            {
                argumentTypes[i] = arguments[i].type;
            }

            IType resultType = arguments[0].type;

            var typeArguments = new IType[target.TypeParameters.FormalTypeParams.Count];

            for (int i = 0; i < typeArguments.Length; i++)
            {
                typeArguments[i] = makeType(target.TypeParameters[target.TypeParameters.FormalTypeParams[i]]);
            }

            Expression recSource = new BasicFAE(
                BasicMapWrite.makeMapWrite(typeArguments, argumentTypes, resultType), new ExpressionList(arguments)
                );

            return(getAssignmentSourceExpression(target.Map, recSource));
        }
Beispiel #2
0
        ////////////////////////////////////////////////////////////////////////////////////
        private Expression makeExpression(NAryExpr fae, bool old)
        {
            if (fae.Fun is TypeCoercion)
            {
                return(makeExpression(fae.Args[0], old));
            }
            var      arguments = new ExpressionList((from Expr e in fae.Args select makeExpression(e, old)).ToArray());
            Function function;

            if (fae.Fun is MapSelect)
            {
                var typeArguments = new IType[fae.TypeParameters.FormalTypeParams.Count];
                for (int i = 0; i < fae.TypeParameters.FormalTypeParams.Count; i++)
                {
                    typeArguments[i] = makeType(fae.TypeParameters[fae.TypeParameters.FormalTypeParams[i]]);
                }
                var argumentTypes = TypeTuple.make(from a in arguments select a.type);
                function = BasicMapRead.mapRead(
                    typeArguments,
                    argumentTypes,
                    makeType(fae.Type)
                    );
            }
            else if (fae.Fun is MapStore)
            {
                var typeArguments = new IType[fae.TypeParameters.FormalTypeParams.Count];
                for (int i = 0; i < fae.TypeParameters.FormalTypeParams.Count; i++)
                {
                    typeArguments[i] = makeType(fae.TypeParameters[fae.TypeParameters.FormalTypeParams[i]]);
                }
                function = BasicMapWrite.makeMapWrite(typeArguments, (from a in arguments select a.type).ToArray(),
                                                      makeType(fae.ShallowType));
            }
            else if (fae.Fun.FunctionName == "==" || fae.Fun.FunctionName == "!=")
            {
                if (arguments[0].type.isEquivalent(arguments[1].type))
                {
                    function = BFunction.eq(arguments[0].type);
                }
                else
                {
                    Debug.Assert(!arguments[0].type.isGround || !arguments[1].type.isGround);
                    function = BFunction.eq(arguments[0].type, arguments[1].type);
                }
                if (fae.Fun.FunctionName == "!=")
                {
                    arguments = new ExpressionList(
                        new BasicFAE(
                            function,
                            arguments
                            )
                        );
                    function = scope.getFunction("!", TypeTuple.make());
                }
            }
            else if (fae.Fun.FunctionName == "<:")
            {
                function = scope.getFunction(fae.Fun.FunctionName, TypeTuple.make(new[] { arguments[0].type }));
            }
            else if (fae.Fun.FunctionName == BFunctionTemplate.iteName)
            {
                function = scope.getFunction(fae.Fun.FunctionName, TypeTuple.make(new[] { arguments[1].type }));
            }
            else if (fae.Fun.FunctionName == @"-" && fae.Fun.ArgumentCount == 1)
            {
                arguments = new ExpressionList(new[] { new BasicLiteralExpression(IntegerValue.make(0)), arguments[0] });
                function  = scope.getFunction(@"-", TypeTuple.make());
            }
            else
            {
                var typeArguments = TypeTuple.make((fae.TypeParameters == null)
                                                ? new IType[0]
                                                : (from ftp in fae.TypeParameters.FormalTypeParams
                                                   select scope.typeFactory.makeTypeI(fae.TypeParameters[ftp], context)));
                function = scope.getFunction(fae.Fun.FunctionName, typeArguments);
            }
            var result = new BoogieFunctionApplicationExpression(fae, function, arguments);

            Debug.Assert(result.type.ToStringN() ==
                         makeType(fae.Type == null ? fae.ShallowType : fae.Type).ToStringN());
            Debug.Assert(result != null);
            foreach (var fv in result.freeVariables)
            {
                Debug.Assert(context.lookupVariableByOwnName(fv.name) == fv);
            }
            foreach (var ftv in result.freeTypeVariables)
            {
                Debug.Assert(ReferenceEquals(context.lookupTypeVariable(ftv.name), ftv));
            }

            return(result);
        }