Пример #1
0
        public static LNode ContractsOnLambda(LNode fn, IMacroContext context)
        {
            LNode oldFn = fn;

            if (fn.ArgCount == 2)
            {
                var rw = new CodeContractRewriter(LNode.Missing, Id_lambda_function, context);
                fn = ProcessArgContractAttributes(fn, 0, rw, isLambda: true);
                if (fn.HasAttrs)
                {
                    fn = fn.WithAttrs(rw.Process(fn.Attrs, null));
                }
                if (rw.PrependStmts.IsEmpty)
                {
                    return(null);
                }
                else
                {
                    var body = fn.Args[1];
                    if (!body.Calls(S.Braces))
                    {
                        body = LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(body)))).SetStyle(NodeStyle.Statement);
                    }
                    body = body.WithArgs(body.Args.InsertRange(0, rw.PrependStmts));
                    fn   = fn.WithArgChanged(1, body);
                    return(fn);
                }
            }
            return(null);
        }
Пример #2
0
        static LNode ProcessArgContractAttributes(LNode fn, int argsIndex, CodeContractRewriter rw, bool isLambda = false)
        {
            LNode fnArgs = fn.Args[argsIndex];

            if (fnArgs.CallsMin(isLambda ? S.Tuple : S.AltList, 1))
            {
                return(fn.WithArgChanged(argsIndex,
                                         fnArgs.WithArgs(arg => {
                    if (arg.HasAttrs)
                    {
                        return arg.WithAttrs(rw.Process(arg.Attrs, GetVarName(arg)));
                    }
                    return arg;
                })));
            }
            else if (isLambda)
            {
                var arg = fnArgs;                       // just one argument
                if (arg.HasAttrs)
                {
                    fn = fn.WithArgChanged(argsIndex,
                                           arg.WithAttrs(rw.Process(arg.Attrs, GetVarName(arg))));
                }
            }
            return(fn);
        }
Пример #3
0
        public static LNode ContractsOnMethod(LNode fn, IMacroContext context)
        {
            LNode oldFn = fn;

            if (fn.ArgCount >= 4)
            {
                var rw = new CodeContractRewriter(fn.Args[0], fn.Args[1], context);
                fn = ProcessArgContractAttributes(fn, 2, rw);
                if (fn.Args[0].HasAttrs)
                {
                    fn = fn.WithArgChanged(0, fn.Args[0].WithAttrs(rw.Process(fn.Args[0].Attrs, null)));
                }
                if (fn.HasAttrs)
                {
                    fn = fn.WithAttrs(rw.Process(fn.Attrs, null));
                }
                if (rw.PrependStmts.IsEmpty)
                {
                    return(null);
                }
                else
                {
                    var body = fn.Args[3];
                    if (!body.Calls(S.Braces))
                    {
                        body = LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(body)))).SetStyle(NodeStyle.Statement);
                    }
                    body = body.WithArgs(body.Args.InsertRange(0, rw.PrependStmts));
                    fn   = fn.WithArgChanged(3, body);
                    return(fn);
                }
            }
            return(null);
        }
Пример #4
0
        [LexicalMacro("([notnull] (x => ...)); ([notnull] x) => ...; ([requires(expr)] x) => ...; " + "([ensures(expr)] (x => ...)); ([ensuresOnThrow(expr)] (x => ...)); ", "Generates Contract checks in a lambda function. See the documentation of " + "ContractsOnMethod for more information about the contract attributes.", "=>", Mode = MacroMode.Passive | MacroMode.PriorityInternalFallback)] public static LNode ContractsOnLambda(LNode fn, IMacroContext context)
        {
            LNode oldFn = fn;

            if (fn.ArgCount == 2)
            {
                var rw = new CodeContractRewriter(LNode.Missing, Id_lambda_function, context);
                fn = ProcessArgContractAttributes(fn, 0, rw, isLambda: true);
                if (fn.HasAttrs)
                {
                    fn = fn.WithAttrs(rw.Process(fn.Attrs, null));
                }
                if (rw.PrependStmts.IsEmpty)
                {
                    return(null);
                }
                else
                {
                    var body = fn.Args[1];
                    if (!body.Calls(S.Braces))
                    {
                        body = LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(body)))).SetStyle(NodeStyle.Statement);
                    }
                    body = body.WithArgs(body.Args.InsertRange(0, rw.PrependStmts));
                    fn   = fn.WithArgChanged(1, body);
                    return(fn);
                }
            }
            return(null);
        }
Пример #5
0
        [LexicalMacro("notnull T method(notnull T arg) {...}; T method([requires(expr)] T arg) {...}; " + "[requires(expr)] T method(...) {...}; [ensures(expr)] T method(...) {...}; " + "[ensuresOnThrow(expr)] T method(...) {...}; [ensuresOnThrow<Exception>(expr)] T method(...) {...}", "Generates Contract checks in a method.\n\n" + "- [requires(expr)] and [assert(expr)] specify an expression that must be true at the beginning of the method; assert conditions are checked in debug builds only, while \"requires\" conditions are checked in all builds. The condition can include an underscore `_` that refers to the argument that the attribute is attached to, if any.\n" + "- [ensures(expr)] and [ensuresAssert(expr)] specify an expression that must be true if-and-when the method returns normally. assert conditions are checked in debug builds only. The condition can include an underscore `_` that refers to the return value of the method.\n" + "- [ensuresFinally(expr)] specifies an expression that must be true when the method exits, whether by exception or by a normal return. This is implemented by wrapping the method in a try-finally block.\n" + "- [ensuresOnThrow(expr)] and [ensuresOnThrow<ExceptionType>(expr)] specify a condition that must be true if the method throws an exception. When #haveContractRewriter is false, underscore `_` refers to the thrown exception object; this is not available in the MS Code Contracts Rewriter.\n" + "- notnull is equivalent to [requires(_ != null)] if applied to an argument, and [ensures(_ != null)] if applied to the method as a whole.\n" + "\nAll contract attributes (except notnull) can specify multiple expressions separated by commas, to produce multiple checks, each with its own error message.", "#fn", "#cons", Mode = MacroMode.Passive | MacroMode.PriorityInternalFallback)] public static LNode ContractsOnMethod(LNode fn, IMacroContext context)
        {
            LNode fnArgs, oldFn = fn;

            if (fn.ArgCount >= 4)
            {
                var rw = new CodeContractRewriter(fn.Args[0], fn.Args[1], context);
                fn = ProcessArgContractAttributes(fn, 2, rw);
                if (fn.Args[0].HasAttrs)
                {
                    fn = fn.WithArgChanged(0, fn.Args[0].WithAttrs(rw.Process(fn.Args[0].Attrs, null)));
                }
                if (fn.HasAttrs)
                {
                    fn = fn.WithAttrs(rw.Process(fn.Attrs, null));
                }
                if (rw.PrependStmts.IsEmpty)
                {
                    return(null);
                }
                else
                {
                    var body = fn.Args[3];
                    if (!body.Calls(S.Braces))
                    {
                        body = LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(body)))).SetStyle(NodeStyle.Statement);
                    }
                    body = body.WithArgs(body.Args.InsertRange(0, rw.PrependStmts));
                    fn   = fn.WithArgChanged(3, body);
                    return(fn);
                }
            }
            return(null);
        }
Пример #6
0
        public static LNode ContractsOnMethod(LNode fn, IMacroContext context)
        {
            // Performance note: one should keep in mind that this macro usually
            // has no effect. It looks for contracts and usually finds none, so
            // we should try to search quickly. Luckily, LNode methods like
            // n.WithArgChanged(i,N) do not allocate a new node if the new value
            // equals the old value (if n[i] == N).
            LNode oldFn = fn;

            if (fn.ArgCount >= 4)
            {
                var rw = new CodeContractRewriter(fn.Args[0], fn.Args[1], context);

                // If this thing has an argument list, scan it
                fn = ProcessArgContractAttributes(fn, 2, rw);

                // Scan attributes on return type, then attributes on the whole method
                if (fn.Args[0].HasAttrs)
                {
                    fn = fn.WithArgChanged(0, fn.Args[0].WithAttrs(rw.Process(fn.Args[0].Attrs, null)));
                }
                if (fn.HasAttrs)
                {
                    fn = fn.WithAttrs(rw.Process(fn.Attrs, null));
                }

                if (rw.PrependStmts.IsEmpty)
                {
                    return(null);                       // this is the common case
                }
                else
                {
                    var body = fn.Args[3];
                    if (!body.Calls(S.Braces)                           // Add braces in case of void LambdaMethod() => expr;
                        )
                    {
                        body = LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(body)))).SetStyle(NodeStyle.Statement);
                    }
                    body = body.WithArgs(body.Args.InsertRange(0, rw.PrependStmts));
                    fn   = fn.WithArgChanged(3, body);
                    return(fn);
                }
            }
            return(null);
        }
Пример #7
0
        public static LNode ContractsOnLambda(LNode fn, IMacroContext context)
        {
            // Performance note: one should keep in mind that this macro usually
            // has no effect. It looks for contracts and usually finds none.
            LNode oldFn = fn;

            if (fn.ArgCount == 2)
            {
                var rw = new CodeContractRewriter(LNode.Missing, Id_lambda_function, context);

                // If this thing has an argument list, scan it
                fn = ProcessArgContractAttributes(fn, 0, rw, isLambda: true);

                // Scan attributes on the lambda as a whole
                if (fn.HasAttrs)
                {
                    fn = fn.WithAttrs(rw.Process(fn.Attrs, null));
                }

                if (rw.PrependStmts.IsEmpty)
                {
                    return(null);                       // this is the common case
                }
                else
                {
                    var body = fn.Args[1];
                    if (!body.Calls(S.Braces)                           // Add braces in case of void LambdaMethod() => expr;
                        )
                    {
                        body = LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(body)))).SetStyle(NodeStyle.Statement);
                    }
                    body = body.WithArgs(body.Args.InsertRange(0, rw.PrependStmts));
                    fn   = fn.WithArgChanged(1, body);
                    return(fn);
                }
            }
            return(null);
        }
Пример #8
0
        public static LNode ContractsOnProperty(LNode prop, IMacroContext context)
        {
            // Performance note: one should keep in mind that this macro usually
            // has no effect. It looks for contracts and usually finds none.
            LNode oldProp = prop;

            if (prop.ArgCount == 4)
            {
                LNode braces    = prop[3];
                var   oldBraces = braces;
                var   rw        = new CodeContractRewriter(prop.Args[0], prop.Args[1], context);

                // If this has an argument list (this[...]), process its contract attributes
                prop = ProcessArgContractAttributes(prop, 2, rw);

                // Remove contract attributes from the property and store in a list
                VList <LNode> cAttrs = LNode.List();
                prop = prop.WithArgChanged(0, GrabContractAttrs(prop.Args[0], ref cAttrs, ContractAppliesTo.Getter));
                prop = GrabContractAttrs(prop, ref cAttrs);

                // Find the getter and setter
                LNode         getter = null, setter = null;
                int           getterIndex = -1, setterIndex = -1;
                VList <LNode> getterAttrs = LNode.List(), setterAttrs = LNode.List();
                bool          isLambdaProperty = !braces.Calls(S.Braces);
                if (isLambdaProperty)
                {
                    if (cAttrs.Count == 0)
                    {
                        return(null);                           // lambda property has no contract attributes
                    }
                    // Transform into a normal property
                    getterAttrs = cAttrs;
                    getter      = LNode.Call(CodeSymbols.get, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(braces)))).SetStyle(NodeStyle.Statement))).SetStyle(NodeStyle.Special);
                    braces      = LNode.Call(CodeSymbols.Braces, LNode.List(getter)).SetStyle(NodeStyle.Statement);
                    getterIndex = 0;
                }
                else
                {
                    for (int i = 0; i < braces.Args.Count; i++)
                    {
                        var part = braces.Args[i];
                        if (part.Calls(S.get))
                        {
                            getter = part; getterIndex = i;
                        }
                        if (part.Calls(S.set))
                        {
                            setter = part; setterIndex = i;
                        }
                    }

                    // Now create separate lists of contract attributes for the getter and the setter
                    if (cAttrs.Count != 0)
                    {
                        getterAttrs = cAttrs.SmartWhere(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Getter) != 0);
                        setterAttrs = cAttrs.SmartWhere(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Setter) != 0);
                    }
                }

                // Process the discovered attributes to produce prepended statements
                var sharedPrependStmts = rw.PrependStmts;
                if (getter != null)
                {
                    getter = GrabContractAttrs(getter, ref getterAttrs);
                    rw.Process(getterAttrs, null);
                    rw.PrependStmtsToGetterOrSetter(ref braces, getterIndex, getter);
                }
                if (setter != null)
                {
                    rw.PrependStmts = sharedPrependStmts;
                    setter          = GrabContractAttrs(setter, ref setterAttrs);
                    rw.Process(setterAttrs, LNode.Id(CodeSymbols.value), true);
                    rw.PrependStmtsToGetterOrSetter(ref braces, setterIndex, setter);
                }

                // Update the property
                if (braces == oldBraces)
                {
                    return(null);                       // this is the common case
                }
                else
                {
                    return(prop.WithArgChanged(3, braces));
                }
            }
            return(null);
        }
Пример #9
0
        public static LNode ContractsOnProperty(LNode prop, IMacroContext context)
        {
            LNode oldProp = prop;

            if (prop.ArgCount == 4)
            {
                LNode braces    = prop[3];
                var   oldBraces = braces;
                var   rw        = new CodeContractRewriter(prop.Args[0], prop.Args[1], context);
                prop = ProcessArgContractAttributes(prop, 2, rw);
                VList <LNode> cAttrs = LNode.List();
                prop = prop.WithArgChanged(0, GrabContractAttrs(prop.Args[0], ref cAttrs, ContractAppliesTo.Getter));
                prop = GrabContractAttrs(prop, ref cAttrs);
                LNode         getter = null, setter = null;
                int           getterIndex = -1, setterIndex = -1;
                VList <LNode> getterAttrs = LNode.List(), setterAttrs = LNode.List();
                bool          isLambdaProperty = !braces.Calls(S.Braces);
                if (isLambdaProperty)
                {
                    if (cAttrs.Count == 0)
                    {
                        return(null);
                    }
                    getterAttrs = cAttrs;
                    getter      = LNode.Call(CodeSymbols.get, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(braces)))).SetStyle(NodeStyle.Statement))).SetStyle(NodeStyle.Special);
                    braces      = LNode.Call(CodeSymbols.Braces, LNode.List(getter)).SetStyle(NodeStyle.Statement);
                    getterIndex = 0;
                }
                else
                {
                    for (int i = 0; i < braces.Args.Count; i++)
                    {
                        var part = braces.Args[i];
                        if (part.Calls(S.get))
                        {
                            getter      = part;
                            getterIndex = i;
                        }
                        if (part.Calls(S.set))
                        {
                            setter      = part;
                            setterIndex = i;
                        }
                    }
                    if (cAttrs.Count != 0)
                    {
                        getterAttrs = cAttrs.SmartWhere(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Getter) != 0);
                        setterAttrs = cAttrs.SmartWhere(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Setter) != 0);
                    }
                }
                var sharedPrependStmts = rw.PrependStmts;
                if (getter != null)
                {
                    getter = GrabContractAttrs(getter, ref getterAttrs);
                    rw.Process(getterAttrs, null);
                    rw.PrependStmtsToGetterOrSetter(ref braces, getterIndex, getter);
                }
                if (setter != null)
                {
                    rw.PrependStmts = sharedPrependStmts;
                    setter          = GrabContractAttrs(setter, ref setterAttrs);
                    rw.Process(setterAttrs, LNode.Id(CodeSymbols.value), true);
                    rw.PrependStmtsToGetterOrSetter(ref braces, setterIndex, setter);
                }
                if (braces == oldBraces)
                {
                    return(null);
                }
                else
                {
                    return(prop.WithArgChanged(3, braces));
                }
            }
            return(null);
        }
Пример #10
0
        [LexicalMacro("notnull T Prop {...}; T this[[requires(expr)] T arg] {...}; " + "T Prop { [requires(expr)] set; }; [ensures(expr)] T Prop {...}; " + "[ensuresOnThrow(expr)] T Prop {...}; [ensuresOnThrow<Exception>(expr)] T Prop {...}", "Generates contract checks in a property. You can apply contract attributes to " + "the property itself, to the getter, to the setter, or all three. When the [requires] " + "or [assert] attributes are applied to the property itself, they are treated as if " + "they were applied to the getter; but when the [ensures], [ensuresAssert], notnull, " + "and [ensuresOnThrow] attributes are applied to the property itself, they are treated " + "as if they were applied to both the getter and the setter separately.", "#property", Mode = MacroMode.Passive | MacroMode.PriorityInternalFallback)] public static LNode ContractsOnProperty(LNode prop, IMacroContext context)
        {
            LNode propArgs, oldProp = prop;

            if (prop.ArgCount == 4)
            {
                LNode braces    = prop[3];
                var   oldBraces = braces;
                var   rw        = new CodeContractRewriter(prop.Args[0], prop.Args[1], context);
                prop = ProcessArgContractAttributes(prop, 2, rw);
                VList <LNode> cAttrs = LNode.List();
                prop = prop.WithArgChanged(0, GrabContractAttrs(prop.Args[0], ref cAttrs, ContractAppliesTo.Getter));
                prop = GrabContractAttrs(prop, ref cAttrs);
                LNode         getter = null, setter = null;
                int           getterIndex = -1, setterIndex = -1;
                VList <LNode> getterAttrs = LNode.List(), setterAttrs = LNode.List();
                bool          isLambdaProperty = !braces.Calls(S.Braces);
                if (isLambdaProperty)
                {
                    if (cAttrs.Count == 0)
                    {
                        return(null);
                    }
                    getterAttrs = cAttrs;
                    getter      = LNode.Call(CodeSymbols.get, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(braces)))).SetStyle(NodeStyle.Statement))).SetStyle(NodeStyle.Special);
                    braces      = LNode.Call(CodeSymbols.Braces, LNode.List(getter)).SetStyle(NodeStyle.Statement);
                    getterIndex = 0;
                }
                else
                {
                    for (int i = 0; i < braces.Args.Count; i++)
                    {
                        var part = braces.Args[i];
                        if (part.Calls(S.get))
                        {
                            getter      = part;
                            getterIndex = i;
                        }
                        if (part.Calls(S.set))
                        {
                            setter      = part;
                            setterIndex = i;
                        }
                    }
                    if (cAttrs.Count != 0)
                    {
                        getterAttrs = cAttrs.Where(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Getter) != 0);
                        setterAttrs = cAttrs.Where(a => (PropertyContractInterpretation(a) & ContractAppliesTo.Setter) != 0);
                    }
                }
                var sharedPrependStmts = rw.PrependStmts;
                if (getter != null)
                {
                    getter = GrabContractAttrs(getter, ref getterAttrs);
                    rw.Process(getterAttrs, null);
                    rw.PrependStmtsToGetterOrSetter(ref braces, getterIndex, getter);
                }
                if (setter != null)
                {
                    rw.PrependStmts = sharedPrependStmts;
                    setter          = GrabContractAttrs(setter, ref setterAttrs);
                    rw.Process(setterAttrs, LNode.Id(CodeSymbols.value), true);
                    rw.PrependStmtsToGetterOrSetter(ref braces, setterIndex, setter);
                }
                if (braces == oldBraces)
                {
                    return(null);
                }
                else
                {
                    return(prop.WithArgChanged(3, braces));
                }
            }
            return(null);
        }