Esempio n. 1
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);
        }
Esempio n. 2
0
        protected LNode GenerateSetDecl(PGIntSet set, Symbol setName)
        {
            var ranges = set.InternalRangeList();
            IEnumerable <object> args;
            Symbol method;

            if (ranges.Count * 2 < set.SizeIgnoringInversion)               // use ranges
            {
                method = _NewSetOfRanges;
                args   = ranges.SelectMany(r => {
                    if (r.Lo >= 32 && r.Hi < 0xFFFC)
                    {
                        return new object[] { (char)r.Lo, (char)r.Hi }
                    }
                    ;
                    else
                    {
                        return new object[] { r.Lo, r.Hi }
                    };
                });
            }
            else
            {
                method = _NewSet;
                args   = set.IntegerSequence(false).Select(n =>
                                                           set.IsCharSet && n >= 32 && n < 0xFFFC ? (object)(char)n : (object)(int)n);
            }
            return
                (F.Attr(F.Id(S.Static), F.Id(S.Readonly),
                        F.Var(SetType, setName,
                              ApiCall(method, LNode.List(args.Select(a => F.Literal(a))), true))));
        }
Esempio n. 3
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);
        }
Esempio n. 4
0
        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);
        }
            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)));
                    }
                }
            }
Esempio n. 6
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);
        }
Esempio n. 7
0
        protected override void Stmt(string text, LNode expected, Action <EcsNodePrinter> configure = null, Mode mode = Mode.Both)
        {
            bool exprMode = (mode & Mode.Expression) != 0;

            if ((mode & Mode.ParserTest) == 0)
            {
                return;
            }
            // This is the easy way:
            //LNode result = EcsLanguageService.Value.ParseSingle(text, MessageSink.Console, exprMode ? ParsingService.Exprs : ParsingService.Stmts);
            // But to make debugging easier, I'll do it the long way:
            ILexer <Token> lexer        = EcsLanguageService.Value.Tokenize(new UString(text), "", MessageSink.Console);
            var            preprocessed = new EcsPreprocessor(lexer);
            var            treeified    = new TokensToTree(preprocessed, false);
            var            sink         = (mode & Mode.ExpectAndDropParserError) != 0 ? new MessageHolder() : (IMessageSink)MessageSink.Console;
            var            parser       = new EcsParser(treeified.Buffered(), lexer.SourceFile, sink);
            LNode          result       = exprMode ? parser.ExprStart(false) : LNode.List(parser.ParseStmtsGreedy()).AsLNode(S.Splice);

            AreEqual(TokenType.EOF, parser.LT0.Type(), string.Format("Parser stopped before EOF at [{0}] in {1}", parser.LT0.StartIndex, text));
            AreEqual(expected, result);
            if (sink is MessageHolder)
            {
                GreaterOrEqual(((MessageHolder)sink).List.Count, 1, "Expected an error but got none for " + text);
            }
        }
Esempio n. 8
0
        // Step 3
        void Process(Rule rule)
        {
            // Create $result variable if it was used
            bool usingResult = _data.OtherReferences.ContainsKey(_resultId) || _data.ProperLabels.TryGetValue(_result, false);

            if (usingResult && rule.ReturnType != null)
            {
                _data.ProperLabels[_result] = true;
                var type = rule.ReturnType;
                _newVarInitializers[_result] = Pair.Create(type, _codeGen.MakeInitializedVarDecl(type, false, _result));
            }

            Visit(rule.Pred);

            if (_newVarInitializers.Count != 0)
            {
                var decls = _newVarInitializers.OrderBy(p => p.Key.Name).Select(p => p.Value.B);
                var seq   = new Seq(new ActionPred(rule.Basis, LNode.List(decls)), rule.Pred);
                if (usingResult)
                {
                    seq = new Seq(seq, new ActionPred(rule.Basis, LNode.List(F.Call(S.Return, _resultId))));
                }
                rule.Pred = seq;
            }
        }
Esempio n. 9
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);
        }
Esempio n. 10
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);
        }
Esempio n. 11
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));`");
         }
     }
 }
Esempio n. 12
0
            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)));
                    }
                }
            }
Esempio n. 13
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))));
            }
Esempio n. 14
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)));
         }
     }
 }
Esempio n. 15
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));
            }
Esempio n. 16
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);
        }
Esempio n. 17
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);
        }
Esempio n. 18
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);
        }
Esempio n. 19
0
            LNodeList UnwrapRunSequence(ref LNode runSeq)
            {
                var result = LNode.List();

                if (runSeq.Calls(sy__numrunSequence))
                {
                    if (runSeq.ArgCount == 1 && runSeq[0].Calls(S.Braces))
                    {
                        result = runSeq[0].Args;
                    }
                    else
                    {
                        result = runSeq.Args;
                    }

                    if (result.Count == 0)
                    {
                        Context.Sink.Error(runSeq, "#runSequence() has no arguments, which is not supported.");
                    }
                    else if (result.Count == 1)
                    {
                        runSeq = result[0].PlusAttrs(runSeq.Attrs);
                        return(LNode.List());
                    }
                }
                return(result);
            }
Esempio n. 20
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, LNode.List()));                // erase alias from output
            }
            return(null);
        }
Esempio n. 21
0
        private static LNode ValidateOnStmt(LNode node, IMacroContext context, out VList <LNode> restOfStmts, out LNode firstArg)
        {
            var   a = node.Args;
            LNode on_handler;

            restOfStmts = LNode.List();
            firstArg    = null;
            if (a.Count == 2)
            {
                firstArg = a[0];
            }
            else if (a.Count != 1)
            {
                return(null);
            }
            if (!(on_handler = a.Last).Calls(S.Braces))
            {
                return(null);
            }
            if (context.RemainingNodes.Count == 0)
            {
                context.Write(Severity.Warning, node, "{0} should not be the final statement of a block.", node.Name);
            }
            restOfStmts = new VList <LNode>(context.RemainingNodes);
            context.DropRemainingNodes = true;
            return(on_handler);
        }
Esempio n. 22
0
            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)]`");
                }
            }
Esempio n. 23
0
        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);
        }
Esempio n. 24
0
        public IListSource <LNode> ParseExprs(bool allowTrailingComma = false, bool allowUnassignedVarDecl = false)
        {
            var list = LNode.List();

            try {
                ExprList(ref list, allowTrailingComma, allowUnassignedVarDecl);
            } catch (Exception ex) { UnhandledException(ex); }
            return(list);
        }
Esempio n. 25
0
        protected override void Stmt(string text, LNode expected, Action <EcsPrinterOptions> configure = null, Mode mode = Mode.Both)
        {
            bool exprMode = (mode & Mode.Expression) != 0;

            if ((mode & (Mode.ParserTest | Mode.ExpectAndDropParserError)) == 0)
            {
                return;
            }
            var sink = (mode & Mode.ExpectAndDropParserError) != 0 ? new MessageHolder() : (IMessageSink)ConsoleMessageSink.Value;

            using (Token.SetToStringStrategy(TokenExt.ToString))             // debugging aid
            {
                // This is the easy way:
                //   LNode result = EcsLanguageService.Value.ParseSingle(text, sink, exprMode ? ParsingMode.Expressions : ParsingMode.Statements, preserveComments: true);
                // But to make debugging easier, I'll do it the long way:
                ILexer <Token> lexer        = EcsLanguageService.Value.Tokenize(new UString(text), "", sink);
                var            preprocessed = new EcsPreprocessor(lexer, true);
                var            treeified    = new TokensToTree(preprocessed, false);
                var            parser       = new EcsParser(treeified.Buffered(), lexer.SourceFile, sink, null);
                LNodeList      results      = exprMode ? LNode.List(parser.ExprStart(false)) : LNode.List(parser.ParseStmtsGreedy());

                // Inject comments
                var injector = new EcsTriviaInjector(preprocessed.TriviaList, preprocessed.SourceFile, (int)TokenType.Newline, "/*", "*/", "//", (mode & Mode.Expression) == 0);
                results = LNode.List(injector.Run(results.GetEnumerator()).ToList());

                LNode result = results.AsLNode(S.Splice);
                AreEqual(TokenType.EOF, parser.LT0.Type(), string.Format("Parser stopped before EOF at [{0}] in {1}", parser.LT0.StartIndex, text));

                if ((mode & Mode.IgnoreTrivia) != 0)
                {
                    result = result.ReplaceRecursive(n => n.IsTrivia ? Maybe <LNode> .NoValue : n, LNode.ReplaceOpt.ProcessAttrs).Value;
                }
                if (sink is MessageHolder)
                {
                    ((MessageHolder)sink).WriteListTo(TraceMessageSink.Value);
                    GreaterOrEqual(((MessageHolder)sink).List.Count(m => m.Severity >= Severity.Error), 1,
                                   "Expected an error but got none for " + text);
                    if (expected == null)
                    {
                        return;
                    }
                }
                if (!expected.Equals(result, LNode.CompareMode.TypeMarkers))
                {
                    if ((mode & Mode.CompareAsLes) != 0)
                    {
                        using (LNode.SetPrinter(Syntax.Les.Les3LanguageService.Value))
                            AreEqual(expected.ToString(), result.ToString());
                    }
                    else
                    {
                        AreEqual(expected, result);
                    }
                    Fail("{0} has a different type marker than {1}", expected, result);
                }
            }
        }
Esempio n. 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);
 }
Esempio n. 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);
 }
Esempio n. 28
0
        public IListSource <LNode> ParseStmtsGreedy()
        {
            var list = LNode.List();

            try {
                StmtList(ref list);
            } catch (Exception ex) { UnhandledException(ex); }
            ExpectEOF();
            return(list);
        }
Esempio n. 29
0
        private List <LogMessage> RunLeMPAndCaptureErrors(UString inputText)
        {
            MessageHolder       messages  = new MessageHolder();
            MacroProcessor      lemp      = NewLemp(0xFFFF, EcsLanguageService.Value).With(mp => mp.Sink = messages);
            IListSource <LNode> inputCode = EcsLanguageService.Value.Parse(inputText, MessageSink.Default);

            lemp.ProcessSynchronously(LNode.List(inputCode));

            return(messages.List.Where(m => m.Severity == Severity.Error).ToList());
        }
Esempio n. 30
0
        /// <summary>A method called to create a virtual node to apply trivia to an empty source file.</summary>
        /// <remarks>Default implementation attaches all trivia to a "missing" node
        /// (zero-length identifier). If this method returns null then the result is discarded.</remarks>
        protected virtual LNode GetEmptyResultSet()
        {
            if (SortedTrivia.Count == 0)
            {
                return(null);
            }
            var dummy = LNode.Id(LNode.List(LNode.Id(CodeSymbols.TriviaDummyNode)), GSymbol.Empty, GetRange(SortedTrivia[0]));

            return(AttachTriviaTo(dummy, SortedTrivia, TriviaLocation.TrailingExtra, null, -1) ?? dummy);
        }