コード例 #1
0
            LNode ConvertVarDeclToRunSequence(VList <LNode> attrs, LNode varType, LNode varName, LNode initValue)
            {
                initValue = BubbleUpBlocks(initValue);
                varType   = varType ?? F.Missing;
                LNode @ref;

                attrs = attrs.WithoutNodeNamed(S.Ref, out @ref);
                var varName_apos = varName.PlusAttr(_trivia_isTmpVar);

                if (@ref != null)
                {
                    varName_apos = varName_apos.PlusAttr(@ref);
                }
                {
                    LNode         resultValue;
                    VList <LNode> stmts;
                    if (initValue.CallsMin((Symbol)"#runSequence", 1) && (resultValue = initValue.Args[initValue.Args.Count - 1]) != null)
                    {
                        stmts = initValue.Args.WithoutLast(1);
                        var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, resultValue))));
                        return(initValue.WithArgs(stmts.Add(newVarDecl).Add(varName_apos)));
                    }
                    else
                    {
                        var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, initValue))));
                        return(LNode.Call((Symbol)"#runSequence", LNode.List(newVarDecl, varName_apos)));
                    }
                }
            }
コード例 #2
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);
        }
コード例 #3
0
 static LNode MergeIdentifiers(LNode left, LNode right)
 {
     if (left == null)
     {
         return(right);
     }
     if (right.IsIdNamed(S.Missing))
     {
         return(left);
     }
     {
         LNode right1, right2;
         if (right.Calls(CodeSymbols.Dot, 1) && (right2 = right.Args[0]) != null)
         {
             return(LNode.Call(CodeSymbols.Dot, LNode.List(left, right2)));
         }
         else if (right.Calls(CodeSymbols.Dot, 2) && (right1 = right.Args[0]) != null && (right2 = right.Args[1]) != null)
         {
             return(LNode.Call(CodeSymbols.Dot, LNode.List(MergeIdentifiers(left, right1), right2)));
         }
         else
         {
             throw new LogException(Severity.Note, right, "Multi-using statement seems malformed. Correct example: `using System(.Text, .Linq));`");
         }
     }
 }
コード例 #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
ファイル: LNodeExt.cs プロジェクト: saisirisha1835/ecsharp
        /// <summary>Adds additional trailing trivia to an attribute list.</summary>
        public static VList <LNode> PlusTrailingTrivia(this VList <LNode> attrs, LNode trivia)
        {
            VList <LNode> oldTrivia;

            attrs = WithoutTrailingTrivia(attrs, out oldTrivia);
            return(attrs.Add(LNode.Call(S.TriviaTrailing, oldTrivia.Add(trivia))));
        }
コード例 #7
0
        static LNode ToLNodeCore(ILNode node)
        {
            var attrs = VList <LNode> .Empty;

            for (int i = node.Min; i < -1; i++)
            {
                attrs.Add(ToLNodeCore(node[i]));
            }

            switch (node.Kind)
            {
            case LNodeKind.Id:
                return(LNode.Id(attrs, node.Name, node.Range, node.Style));

            case LNodeKind.Literal:
                return(LNode.Literal(attrs, node.Value, node.Range, node.Style));

            default:
                var args = VList <LNode> .Empty;
                for (int i = 0, max = node.Max; i <= max; i++)
                {
                    args.Add(ToLNodeCore(node[i]));
                }
                var target = ToLNodeCore(node.Target);
                return(LNode.Call(attrs, target, args, node.Range, node.Style));
            }
        }
コード例 #8
0
        public static LNode RangeIncl(LNode node, IMacroContext context)
        {
            LNode lo = null;

            {
                LNode hi;
                if (node.Args.Count == 2 && (lo = node.Args[0]) != null && (hi = node.Args[1]) != null || node.Args.Count == 1 && (hi = node.Args[0]) != null)
                {
                    if (lo == null || lo.IsIdNamed(__))
                    {
                        if (hi.IsIdNamed(__))
                        {
                            return(Range_Everything);
                        }
                        else
                        {
                            return(LNode.Call(Range_UntilInclusive, LNode.List(hi)));
                        }
                    }
                    else if (hi.IsIdNamed(__))
                    {
                        return(LNode.Call(Range_StartingAt, LNode.List(lo)));
                    }
                    else
                    {
                        return(LNode.Call(Range_Inclusive, LNode.List(lo, hi)));
                    }
                }
            }
            return(null);
        }
コード例 #9
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);
        }
コード例 #10
0
        public static LNode @case(LNode node, IMacroContext context)
        {
            LNode expr, braces = null;

            if (node.ArgCount == 2 && (braces = node.Args.Last).Calls(S.Braces) ||
                node.ArgCount == 1 && (node[0].Calls(S.Colon, 2) || node[0].Calls("'or", 2)))
            {
                expr = node[0];

                var results = LNode.List();
                while (expr.Calls("'or", 2))
                {
                    results.Add(LNode.Call(S.Case, LNode.List(expr[0]), expr[0]));
                    expr = expr[1];
                }
                if (braces != null)
                {
                    results.Add(LNode.Call(S.Case, LNode.List(expr), expr));
                    return(F.Call(S.Splice, results.Add(braces)));
                }
                else if (expr.Calls(S.Colon, 2))
                {
                    results.Add(LNode.Call(S.Case, LNode.List(expr[0]), expr[0]));
                    return(F.Call(S.Splice, results.Add(expr[1])));
                }
                else
                {
                    return(Les2.Reject(context, node, "Unrecognized syntax in case statement"));
                }
            }
            return(null);
        }
コード例 #11
0
ファイル: MatchCode.out.cs プロジェクト: dadhi/ecsharp
            private void MatchAttributes(LNode pattern, LNode candidate)
            {
                LNode  condition;
                bool   isParams, refExistingVar;
                Symbol listVar;
                var    pAttrs = pattern.PAttrs();

                if (pAttrs.Count == 1 && (listVar = DecodeSubstitutionExpr(pAttrs[0], out condition, out isParams, out refExistingVar)) != null && isParams)
                {
                    if (listVar != __ || condition != null)
                    {
                        if (!refExistingVar)
                        {
                            AddVar(listVar, true, errAt: pattern);
                        }
                        Tests.Add(LNode.Call(CodeSymbols.OrBits, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(LNode.List(LNode.InParensTrivia), CodeSymbols.Assign, LNode.List(F.Id(listVar), LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Attrs"))).SetStyle(NodeStyle.Operator))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"IsEmpty"))).SetStyle(NodeStyle.Operator), LNode.Literal(true))).SetStyle(NodeStyle.Operator));
                        if (condition != null)
                        {
                            Tests.Add(condition);
                        }
                    }
                }
                else if (pAttrs.Count != 0)
                {
                    Context.Sink.Error(pAttrs[0], "Currently, Attribute matching is very limited; you can only use `[$(...varName)]`");
                }
            }
コード例 #12
0
ファイル: ContractsMacro.out.cs プロジェクト: sizzles/ecsharp
            void ProcessRequiresAttribute(VList <LNode> conditions, Symbol mode, LNode variableName)
            {
                // Create a "Contract.Requires()" check for each provided condition.
                foreach (var condition_ in conditions)
                {
                    LNode condition = condition_;                       // make it writable so we can replace `_`
                    LNode conditionStr;

                    if (ReplaceContractUnderscore(ref condition, variableName))
                    {
                        if (variableName == null)
                        {
                            Context.Sink.Error(condition, "`{0}`: underscore has no meaning in this location.", mode);
                        }
                    }
                    if (mode == sy_assert)
                    {
                        PrependStmts.Add(LNode.Call((Symbol)"assert", LNode.List(condition)));                          // relies on assert() macro
                    }
                    else if (_haveCCRewriter)
                    {
                        PrependStmts.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id((Symbol)"Contract"), LNode.Id((Symbol)"Requires"))).SetStyle(NodeStyle.Operator), LNode.List(condition)));
                    }
                    else
                    {
                        conditionStr = ConditionToStringLit(condition, "Precondition failed: {1}");
                        PrependStmts.Add(LNode.Call(GetAssertMethodForRequires(), LNode.List(condition, conditionStr)));
                    }
                }
            }
コード例 #13
0
        [LexicalMacro("lo..hi; ..hi; lo.._", "Given `lo..hi, produces `Range.Excl(lo, hi)", "..")] public static LNode RangeExcl(LNode node, IMacroContext context)
        {
            LNode lo = null;

            {
                LNode hi;
                if (node.Args.Count == 2 && (lo = node.Args[0]) != null && (hi = node.Args[1]) != null || node.Args.Count == 1 && (hi = node.Args[0]) != null)
                {
                    if (lo == null || lo.IsIdNamed(__))
                    {
                        if (hi.IsIdNamed(__))
                        {
                            return(Range_Everything);
                        }
                        else
                        {
                            return(LNode.Call(Range_UntilExclusive, LNode.List(hi)));
                        }
                    }
                    else if (hi.IsIdNamed(__))
                    {
                        return(LNode.Call(Range_StartingAt, LNode.List(lo)));
                    }
                    else
                    {
                        return(LNode.Call(Range_ExcludeHi, LNode.List(lo, hi)));
                    }
                }
            }
            return(null);
        }
コード例 #14
0
            LNode GetOutputAsLNode()
            {
                WList <LNode> finalOutput = _handler.ToWList();

                for (int end = _output.Count - 1; end >= 0; end--)
                {
                    var   tmp_10 = _output[end];
                    Mode  mode   = tmp_10.Item1;
                    LNode code   = tmp_10.Item2;
                    if (mode == Mode.Condition)
                    {
                        // Merge adjacent conditions into the same if-statement
                        int start = end;
                        for (; start > 0 && _output[start - 1].A == mode; start--)
                        {
                        }
                        LNode cond = _output[start].B;
                        for (int i = start + 1; i <= end; i++)
                        {
                            cond = LNode.Call(CodeSymbols.And, LNode.List(cond, _output[i].B)).SetStyle(NodeStyle.Operator);
                        }
                        end = start;

                        finalOutput = new WList <LNode> {
                            LNode.Call(CodeSymbols.If, LNode.List(cond, finalOutput.ToVList().AsLNode(S.Braces)))
                        };
                    }
                    else
                    {
                        finalOutput.Insert(0, code);
                    }
                }
                return(finalOutput.ToVList().AsLNode(S.Braces));
            }
コード例 #15
0
        public static LNode ExpectAncestorStack(LNode node, IMacroContext context)
        {
            // Verify AncestorsAndPreviousSiblings
            Assert.AreEqual(node.ArgCount, context.AncestorsAndPreviousSiblings.Count);
            int index = 0;

            foreach (var expect in node.Args)
            {
                Assert.IsTrue(expect.Calls(S.Tuple));
                var pair = context.AncestorsAndPreviousSiblings[index];
                ExpectList(pair.Item1, expect.Args.WithoutLast(1));
                if (!expect.Args.Last.IsIdNamed("#skip"))
                {
                    Assert.AreEqual(expect.Args.Last, pair.Item2.Target);
                }
                index++;
            }

            // Verify PreviousSiblings
            var expectedPreviousSiblings = node.Args.Last.Args.WithoutLast(1);
            int i = 0;

            foreach (var expected in expectedPreviousSiblings)
            {
                if (!expected.IsIdNamed("#skip"))
                {
                    Assert.AreEqual(expected, context.PreviousSiblings[i]);
                }
                i++;
            }

            return(LNode.Call(S.Splice));            // delete this node
        }
コード例 #16
0
        public static LNode saveAndRestore(LNode node, IMacroContext context)
        {
            var tmp_10 = context.GetArgsAndBody(true);
            var args   = tmp_10.Item1;
            var body   = tmp_10.Item2;

            if (args.Count == 1)
            {
                LNode newValue = null;
                {
                    var   tmp_11 = args[0];
                    LNode property;
                    if (tmp_11.Calls(CodeSymbols.Assign, 2) && (property = tmp_11.Args[0]) != null && (newValue = tmp_11.Args[1]) != null || (property = tmp_11) != null)
                    {
                        string mainProp = KeyNameComponentOf(property).Name;
                        string varPrefix = "old" + mainProp + "_";
                        LNode  varName, varDecl = TempVarDecl(context, property, out varName, varPrefix);
                        LNode  tryFinally = LNode.Call(CodeSymbols.Try, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(body)).SetStyle(NodeStyle.StatementBlock), LNode.Call(CodeSymbols.Finally, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Assign, LNode.List(property, varName)).SetStyle(NodeStyle.Operator))).SetStyle(NodeStyle.StatementBlock)))));
                        if (newValue != null)
                        {
                            return(LNode.Call(CodeSymbols.Splice, LNode.List(varDecl, LNode.Call(CodeSymbols.Assign, LNode.List(property, newValue)).SetStyle(NodeStyle.Operator), tryFinally)).IncludingTriviaFrom(node));
                        }
                        else
                        {
                            return(LNode.Call(CodeSymbols.Splice, LNode.List(varDecl, tryFinally)).IncludingTriviaFrom(node));
                        }
                    }
                }
            }
            return(null);
        }
コード例 #17
0
        /// <summary>Adds additional trailing trivia to an attribute list.</summary>
        public static LNodeList PlusTrailingTrivia(this LNodeList attrs, LNode trivia)
        {
            LNodeList oldTrivia;

            attrs = WithoutTrailingTrivia(attrs, out oldTrivia);
            return(attrs.Add(LNode.Call(S.TriviaTrailing, oldTrivia.Add(trivia))));
        }
コード例 #18
0
ファイル: MatchMacro.out.cs プロジェクト: sizzles/ecsharp
        public static LNode match(LNode node, IMacroContext context)
        {
            {
                LNode         input;
                VList <LNode> contents;
                if (node.Args.Count == 2 && (input = node.Args[0]) != null && node.Args[1].Calls(CodeSymbols.Braces))
                {
                    contents = node.Args[1].Args;
                    var outputs = new WList <LNode>();
                    input = MaybeAddTempVarDecl(context, input, outputs);

                    int next_i = 0;
                    for (int case_i = 0; case_i < contents.Count; case_i = next_i)
                    {
                        var @case = contents[case_i];
                        if (!IsCaseLabel(@case))
                        {
                            return(Reject(context, contents[0], "In 'match': expected 'case' statement"));
                        }
                        for (next_i = case_i + 1; next_i < contents.Count; next_i++)
                        {
                            var stmt = contents[next_i];
                            if (IsCaseLabel(stmt))
                            {
                                break;
                            }
                            if (stmt.Calls(S.Break, 0))
                            {
                                next_i++;
                                break;
                            }
                        }
                        var handler = new VList <LNode>(contents.Slice(case_i + 1, next_i - (case_i + 1)));

                        if (@case.Calls(S.Case) && @case.Args.Count > 0)
                        {
                            var codeGen = new CodeGeneratorForMatchCase(context, input, handler);
                            foreach (var pattern in @case.Args)
                            {
                                outputs.Add(codeGen.GenCodeForPattern(pattern));
                            }
                        }
                        else                                    // default:
                        // Note: the extra {braces} around the handler are rarely
                        // needed. They are added just in case the handler declares a
                        // variable and a different handler declares another variable
                        // by the same name, which is illegal unless we add braces.
                        {
                            outputs.Add(LNode.Call(CodeSymbols.Braces, LNode.List(handler)).SetStyle(NodeStyle.Statement));
                            if (next_i < contents.Count)
                            {
                                context.Sink.Error(contents[next_i], "The default branch must be the final branch in a 'match' statement.");
                            }
                        }
                    }
                    return(LNode.Call(CodeSymbols.DoWhile, LNode.List(outputs.ToVList().AsLNode(S.Braces), LNode.Literal(false))));
                }
            }
            return(null);
        }
コード例 #19
0
 void ProcessRequiresAttribute(VList <LNode> conditions, Symbol mode, LNode variableName)
 {
     foreach (var condition_ in conditions)
     {
         LNode condition = condition_;
         LNode conditionStr;
         if (ReplaceContractUnderscore(ref condition, variableName))
         {
             if (variableName == null)
             {
                 Context.Write(Severity.Error, condition, "`{0}`: underscore has no meaning in this location.", mode);
             }
         }
         if (mode == sy_assert)
         {
             PrependStmts.Add(LNode.Call((Symbol)"assert", LNode.List(condition)));
         }
         else if (_haveCCRewriter)
         {
             PrependStmts.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id((Symbol)"Contract"), LNode.Id((Symbol)"Requires"))), LNode.List(condition)));
         }
         else
         {
             conditionStr = ConditionToStringLit(condition, "Precondition failed: {1}");
             PrependStmts.Add(LNode.Call(GetAssertMethodForRequires(), LNode.List(condition, conditionStr)));
         }
     }
 }
コード例 #20
0
ファイル: Prelude.Les.cs プロジェクト: jonathanvdc/Loyc
        public static LNode IfUnless(LNode node, bool isUnless, IMessageSink sink)
        {
            var   args = node.Args;
            LNode cond = args.TryGet(0, null), then = args.TryGet(1, null),
                  elseKW = args.TryGet(2, null), @else = args.TryGet(3, null);

            if (cond == null)
            {
                return(null);
            }
            if (then == null)
            {
                return(Reject(sink, cond, "'{0}' statement ended early", isUnless ? "unless" : "if"));
            }
            if (isUnless)
            {
                cond = F.Call(S.Not, cond);
            }
            if (elseKW == null)
            {
                return(node.With(S.If, cond, then));
            }
            if (!elseKW.IsIdNamed(_else))
            {
                return(Reject(sink, elseKW, "'{0}': expected else clause or end-of-statement marker", isUnless ? "unless" : "if"));
            }
            if (@else.IsId && args.Count > 4)
            {
                @else = LNode.Call(@else.Name, new VList <LNode>(args.Slice(4)), node);
            }
            return(node.With(S.If, cond, then, @else));
        }
コード例 #21
0
        public virtual LNode VisitInput(LNode stmt, IMessageSink sink)
        {
            LNode aliasSet;

            if ((stmt.Calls(_alias, 1) || stmt.CallsMin(S.Alias, 1)) &&
                (aliasSet = stmt.Args[0]).Calls(S.Assign, 2))
            {
                IEnumerable <KeyValuePair <LNode, LNode> > q;
                LNode alias = aliasSet.Args[0], replacement = aliasSet.Args[1], old;
                if (_definedAliases.TryGetValue(alias, out old))
                {
                    if (stmt.AttrNamed(S.Partial) == null || !old.Equals(replacement))
                    {
                        sink.Warning(alias, "Redefinition of alias '{0}'", alias);
                    }
                }
                else if ((q = _definedAliases.Where(pair => replacement.Equals(pair.Value))).Any())
                {
                    sink.Warning(replacement, "Aliases '{0}' and '{1}' have the same replacement value", q.First().Key, alias);
                }
                _definedAliases[alias] = replacement;
                return(LNode.Call(S.Splice, VList <LNode> .Empty));              // erase alias from output
            }
            return(null);
        }
コード例 #22
0
            public LNode GetItemDecl(int itemNum)
            {
                LNode ItemN = F.Id("Item" + itemNum);

                // ItemN properties are used by the code generated for pattern matching
                return(LNode.Call(LNode.List(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id((Symbol)"System"), LNode.Id((Symbol)"ComponentModel"))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"EditorBrowsable"))).SetStyle(NodeStyle.Operator), LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id((Symbol)"System"), LNode.Id((Symbol)"ComponentModel"))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"EditorBrowsableState"))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"Never"))).SetStyle(NodeStyle.Operator))), LNode.Id(CodeSymbols.Public)), CodeSymbols.Property, LNode.List(Type, ItemN, LNode.Missing, LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.get, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(NameId)))).SetStyle(NodeStyle.Statement))).SetStyle(NodeStyle.Special))).SetStyle(NodeStyle.Statement))));
            }
コード例 #23
0
        /// <summary>Converts <see cref="ILNode"/> to <see cref="LNode"/> recursively.</summary>
        public static LNode ToLNode(this ILNode node)
        {
            if (node is LNode n)
            {
                return(n);
            }

            var attrs = LNodeList.Empty;

            for (int i = node.Min; i < -1; i++)
            {
                attrs.Add(ToLNode(node[i]));
            }

            switch (node.Kind)
            {
            case LNodeKind.Id:
                return(LNode.Id(attrs, node.Name, new SourceRange(node.Range), node.Style));

            case LNodeKind.Literal:
                return(LNode.Literal(attrs, node.Value, new SourceRange(node.Range), node.Style));

            default:
                var args = LNodeList.Empty;
                for (int i = 0, max = node.Max; i <= max; i++)
                {
                    args.Add(ToLNode(node[i]));
                }
                var target = ToLNode(node.Target);
                return(LNode.Call(attrs, target, args, new SourceRange(node.Range), node.Style));
            }
        }
コード例 #24
0
ファイル: Literals.out.cs プロジェクト: dadhi/ecsharp
        public static LNode ArrayLiteral(LNode node, IMacroContext context)
        {
            var value = node.Value;

            if (value is Array array)
            {
                Type   elementType     = value.GetType().GetElementType();
                string elementTypeName = elementType.NameWithGenericArgs();
                LNode  elementTypeN    = LNode.Call(S.CsRawText, LNode.List(LNode.Literal(elementTypeName)));

                Func <object, LNode, LNode> newLiteral = (el, pnode) => LNode.Literal(el, pnode);
                // Reduce output text size by preventing the printer from using casts
                // e.g. print `23` instead of `(byte) 23` or `(short) 23`. Also, unbox
                // ints to save memory (ideally we'd do this for all Value Types)
                if (elementType == typeof(byte))
                {
                    newLiteral = (el, pnode) => LNode.Literal((int)(byte)el, pnode);
                }
                if (elementType == typeof(sbyte))
                {
                    newLiteral = (el, pnode) => LNode.Literal((int)(sbyte)el, pnode);
                }
                if (elementType == typeof(short))
                {
                    newLiteral = (el, pnode) => LNode.Literal((int)(short)el, pnode);
                }
                if (elementType == typeof(ushort))
                {
                    newLiteral = (el, pnode) => LNode.Literal((int)(ushort)el, pnode);
                }
                if (elementType == typeof(int))
                {
                    newLiteral = (el, pnode) => LNode.Literal((int)(int)el, pnode);
                }

                if (array.Rank == 1)
                {
                    var initializers = new List <LNode>();
                    int count        = 0;
                    foreach (object element in array)
                    {
                        LNode elemNode = newLiteral(element, node);
                        if ((count++ & 7) == 0 && array.Length > 8)
                        {
                            elemNode = elemNode.PlusAttr(LNode.Id(S.TriviaNewline));
                        }
                        initializers.Add(elemNode);
                    }
                    return(LNode.Call(CodeSymbols.New, LNode.List().Add(LNode.Call(LNode.Call(CodeSymbols.Of, LNode.List(LNode.Id(CodeSymbols.Array), elementTypeN)))).AddRange(initializers)));
                }
                else
                {
                    return(null);                       // TODO
                    //Stmt("int[,] Foo = new[,] { {\n 0 }, {\n 1,\n 2, }, };", F.Call(S.Var, F.Of(S.TwoDimensionalArray, S.Int32),
                    //	F.Call(S.Assign, Foo, F.Call(S.New, F.Call(S.TwoDimensionalArray), F.Braces(zero), F.Braces(one, two)))));
                }
            }
            return(null);
        }
コード例 #25
0
ファイル: Macros.cs プロジェクト: murven/Loyc
        public static LNode ECSharpRule(LNode node, IMacroContext context)
        {
            // This will be called for all methods and properties, so we have to
            // examine it for the earmarks of a rule definition.
            bool isProp;

            if (!(isProp = node.Calls(S.Property, 4)) && !node.Calls(S.Fn, 4))
            {
                return(null);
            }
            LNode returnType = node.Args[0];
            bool  isToken;
            bool  retValIsRule = (isToken = returnType.IsIdNamed(_token)) || returnType.IsIdNamed(_rule);

            var   attrs    = node.Attrs;
            LNode lastAttr = null;

            if (!retValIsRule)
            {
                if (attrs.IsEmpty)
                {
                    return(null);
                }
                lastAttr = attrs.Last;
                if (!(isToken = lastAttr.IsIdNamed(_hash_token)) && !lastAttr.IsIdNamed(_hash_rule))
                {
                    return(null);
                }
                attrs.RemoveAt(attrs.Count - 1);
            }
            else
            {
                returnType = F.Void;
            }

            //node = context.PreProcessChildren();

            LNode name = node.Args[1];
            LNode args = node.Args[2];

            if (args.IsIdNamed(S.Missing))       // @``
            {
                args = F.List();                 // output will be a #fn, which does not allow @`` as its arg list
            }
            LNode newBody = ParseRuleBody(node.Args.Last, context);

            if (newBody != null)
            {
                return(LNode.Call(isToken ? _hash_token : _hash_rule,
                                  new VList <LNode> {
                    returnType, name, args, newBody
                },
                                  node.Range, node.Style).WithAttrs(attrs));
            }
            else
            {
                return(null);
            }
        }
コード例 #26
0
 public static LNode In(LNode node, IMacroContext context)
 {
     {
         LNode range, x;
         if (node.Calls(CodeSymbols.In, 2) && (x = node.Args[0]) != null && (range = node.Args[1]) != null)
         {
             LNode parens;
             range = range.WithoutAttrNamed(S.TriviaInParens, out parens);
             if (parens == null)
             {
                 {
                     LNode hi, lo;
                     if (range.Calls(CodeSymbols.DotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null)
                     {
                         if (lo.IsIdNamed(__))
                         {
                             return(LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator));
                         }
                         else if (hi.IsIdNamed(__))
                         {
                             return(LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator));
                         }
                         else
                         {
                             return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol)"IsInRangeExcludeHi"))), LNode.List(lo, hi)));
                         }
                     }
                     else if (range.Calls(CodeSymbols.DotDot, 1) && (hi = range.Args[0]) != null)
                     {
                         return(LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator));
                     }
                     else if (range.Calls(CodeSymbols.DotDotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null)
                     {
                         if (lo.IsIdNamed(__))
                         {
                             return(LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator));
                         }
                         else if (hi.IsIdNamed(__))
                         {
                             return(LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator));
                         }
                         else
                         {
                             return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol)"IsInRange"))), LNode.List(lo, hi)));
                         }
                     }
                     else if (range.Calls(CodeSymbols.DotDotDot, 1) && (hi = range.Args[0]) != null)
                     {
                         return(LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator));
                     }
                 }
             }
             return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(range, LNode.Id((Symbol)"Contains"))), LNode.List(x)));
         }
     }
     return(null);
 }
コード例 #27
0
 [LexicalMacro("x in lo..hi; x in lo...hi; x in ..hi; x in lo..._; x in range", "Converts an 'in' expression to a normal C# expression using the following rules " + "(keeping in mind that the EC# parser treats `..<` as an alias for `..`):\n" + "1. `x in _..hi` and `x in ..hi` become `x.IsInRangeExcl(hi)`\n" + "2. `x in _...hi` and `x in ...hi` become `x.IsInRangeIncl(hi)`\n" + "3. `x in lo.._` and `x in lo..._` become simply `x >= lo`\n" + "4. `x in lo..hi` becomes `x.IsInRangeExcludeHi(lo, hi)`\n" + "5. `x in lo...hi` becomes `x.IsInRange(lo, hi)`\n" + "6. `x in range` becomes `range.Contains(x)`\n" + "The first applicable rule is used.", "#in")] public static LNode In(LNode node, IMacroContext context)
 {
     {
         LNode range, x;
         if (node.Calls(CodeSymbols.In, 2) && (x = node.Args[0]) != null && (range = node.Args[1]) != null)
         {
             LNode parens;
             range = range.WithoutAttrNamed(S.TriviaInParens, out parens);
             if (parens == null)
             {
                 {
                     LNode hi, lo;
                     if (range.Calls(CodeSymbols.DotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null)
                     {
                         if (lo.IsIdNamed(__))
                         {
                             return(LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator));
                         }
                         else if (hi.IsIdNamed(__))
                         {
                             return(LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator));
                         }
                         else
                         {
                             return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol)"IsInRangeExcludeHi"))), LNode.List(lo, hi)));
                         }
                     }
                     else if (range.Calls(CodeSymbols.DotDot, 1) && (hi = range.Args[0]) != null)
                     {
                         return(LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator));
                     }
                     else if (range.Calls(CodeSymbols.DotDotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null)
                     {
                         if (lo.IsIdNamed(__))
                         {
                             return(LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator));
                         }
                         else if (hi.IsIdNamed(__))
                         {
                             return(LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator));
                         }
                         else
                         {
                             return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol)"IsInRange"))), LNode.List(lo, hi)));
                         }
                     }
                     else if (range.Calls(CodeSymbols.DotDotDot, 1) && (hi = range.Args[0]) != null)
                     {
                         return(LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator));
                     }
                 }
             }
             return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(range, LNode.Id((Symbol)"Contains"))), LNode.List(x)));
         }
     }
     return(null);
 }
コード例 #28
0
        /// <summary>Removes all existing trailing trivia from an attribute list and adds a new list of trailing trivia.</summary>
        /// <remarks>This method has a side-effect of recreating the %trailing
        /// node, if there is one, at the end of the attribute list. If <c>trivia</c>
        /// is empty then all calls to %trailing are removed.</remarks>
        public static LNodeList WithTrailingTrivia(this LNodeList attrs, LNodeList trivia)
        {
            var attrs2 = WithoutTrailingTrivia(attrs);

            if (trivia.IsEmpty)
            {
                return(attrs2);
            }
            return(attrs2.Add(LNode.Call(S.TriviaTrailing, trivia)));
        }
コード例 #29
0
ファイル: Macros.cs プロジェクト: dadhi/ecsharp
        public static LNode ECSharpRule(LNode node, IMacroContext context)
        {
            // This will be called for all methods and properties, so we have to
            // examine it for the earmarks of a rule definition.
            bool isProp;

            if (!(isProp = node.Calls(S.Property, 4)) && !node.Calls(S.Fn, 4))
            {
                return(null);
            }
            LNode returnType = node.Args[0];
            bool  isToken;
            bool  retValIsRule = (isToken = returnType.IsIdNamed(_token)) || returnType.IsIdNamed(_rule);

            var attrs = node.Attrs;

            if (!retValIsRule)
            {
                int?i_rule = attrs.FinalIndexWhere(n => n.IsIdNamed(_hash_token) || n.IsIdNamed(_hash_rule));
                if (i_rule == null)
                {
                    return(null);
                }
                isToken |= attrs[i_rule.Value].IsIdNamed(_hash_token);
                attrs.RemoveAt(i_rule.Value);
            }
            else
            {
                returnType = F.Void;
            }

            //node = context.PreProcessChildren();

            LNode name = node.Args[1];
            LNode args = node.Args[2];

            if (args.IsIdNamed(S.Missing))          // @``
            {
                args = F.AltList();                 // output will be a #fn, which does not allow @`` as its arg list
            }
            LNode newBody = ParseRuleBody(node.Args.Last, context);

            if (newBody != null)
            {
                // #rule($returnType, $name, $args, $newBody)
                return(LNode.Call(isToken ? _hash_token : _hash_rule,
                                  LNode.List(returnType, name, args, newBody),
                                  node.Range, node.Style).WithAttrs(attrs));
            }
            else
            {
                return(null);
            }
        }
コード例 #30
0
ファイル: MatchMacro.out.cs プロジェクト: jonathanvdc/Loyc
 [LexicalMacro("match (var) { case ...: ... }; // In LES, use a => b instead of case a: b", "Attempts to match and deconstruct an object against a \"pattern\", such as a tuple or an algebraic data type. Example:\n" + "match (obj) {  \n" + "   case is Shape(ShapeType.Circle, $size, Location: $p is Point<int>($x, $y)): \n" + "      Circle(size, x, y); \n" + "}\n\n" + "This is translated to the following C# code: \n" + "do { \n" + "   Point<int> p; \n" + "   Shape tmp1; \n" + "   if (obj is Shape) { \n" + "      var tmp1 = (Shape)obj; \n" + "      if (tmp1.Item1 == ShapeType.Circle) { \n" + "         var size = tmp1.Item2; \n" + "         var tmp2 = tmp1.Location; \n" + "         if (tmp2 is Point<int>) { \n" + "            var p = (Point<int>)tmp2; \n" + "            var x = p.Item1; \n" + "            var y = p.Item2; \n" + "            Circle(size, x, y); \n" + "            break; \n" + "         } \n" + "      }\n" + "   }\n" + "} while(false); \n" + "`break` is not expected at the end of each handler (`case` code block), but it can " + "be used to exit early from a `case`. You can associate multiple patterns with the same " + "handler using `case pattern1, pattern2:` in EC#, but please note that (due to a " + "limitation of plain C#) this causes code duplication since the handler will be repeated " + "for each pattern.")] public static LNode match(LNode node, IMacroContext context)
 {
     {
         LNode         input;
         VList <LNode> contents;
         if (node.Args.Count == 2 && (input = node.Args[0]) != null && node.Args[1].Calls(CodeSymbols.Braces))
         {
             contents = node.Args[1].Args;
             var outputs = new WList <LNode>();
             input = MaybeAddTempVarDecl(input, outputs);
             int next_i = 0;
             for (int case_i = 0; case_i < contents.Count; case_i = next_i)
             {
                 var @case = contents[case_i];
                 if (!IsCaseLabel(@case))
                 {
                     return(Reject(context, contents[0], "In 'match': expected 'case' statement"));
                 }
                 for (next_i = case_i + 1; next_i < contents.Count; next_i++)
                 {
                     var stmt = contents[next_i];
                     if (IsCaseLabel(stmt))
                     {
                         break;
                     }
                     if (stmt.Calls(S.Break, 0))
                     {
                         next_i++;
                         break;
                     }
                 }
                 var handler = new VList <LNode>(contents.Slice(case_i + 1, next_i - (case_i + 1)));
                 if (@case.Calls(S.Case) && @case.Args.Count > 0)
                 {
                     var codeGen = new CodeGeneratorForMatchCase(context, input, handler);
                     foreach (var pattern in @case.Args)
                     {
                         outputs.Add(codeGen.GenCodeForPattern(pattern));
                     }
                 }
                 else
                 {
                     outputs.Add(LNode.Call(CodeSymbols.Braces, LNode.List(handler)).SetStyle(NodeStyle.Statement));
                     if (next_i < contents.Count)
                     {
                         context.Write(Severity.Error, contents[next_i], "The default branch must be the final branch in a 'match' statement.");
                     }
                 }
             }
             return(LNode.Call(CodeSymbols.DoWhile, LNode.List(outputs.ToVList().AsLNode(S.Braces), LNode.Literal(false))));
         }
     }
     return(null);
 }
コード例 #31
0
ファイル: LNodeVisitor.cs プロジェクト: default0/LoycCore
		public void Visit(LNode node) { node.Call(this); }