Esempio n. 1
0
        protected virtual void CheckForIndentStyleMismatch(UString indent1, UString indent2, Token next)
        {
            int common = System.Math.Min(indent1.Length, indent2.Length);

            indent1 = indent1.Substring(0, common);
            indent2 = indent2.Substring(0, common);
            if (!indent1.Equals(indent2))
            {
                ErrorSink.Write(Severity.Warning, IndexToMsgContext(next), "Indentation style changed on this line from {0} to {1}",
                                Les2Printer.PrintLiteral(indent1.ToString()),
                                Les2Printer.PrintLiteral(indent2.ToString()));
            }
        }
Esempio n. 2
0
            void GetPatternComponents(LNode pattern, out LNode varBinding, out bool refExistingVar, out LNode cmpExpr, out LNode isType, out LNode inRange, out VList <LNode> subPatterns, out VList <LNode> conditions)
            {
                // Here's a typical pattern (case expr):
                //  is Shape(ShapeType.Circle, ref size, Location: p is Point<int>(x, y)):
                // When there is an arg list, we decode its Target and return the args.
                //
                // The caller is in charge of stripping out "Property:" prefix, if any,
                // so the most complex pattern that this method considers is something
                // like `(expr is Type in Range)(subPatterns) && conds` where `expr` is
                // a varName or $varName to deconstruct, or some expression to test for
                // equality. Assuming it's an equality test, the output will be
                //
                //   varBinding = null
                //   refExistingVar = false
                //   cmpExpr = quote(expr);
                //   isType = quote(Type);
                //   inRange = quote(Range);
                //   conds will have "conds" pushed to the front.
                //
                bool haveSubPatterns = false;

                subPatterns    = VList <LNode> .Empty;
                refExistingVar = pattern.AttrNamed(S.Ref) != null;

                // First, look for "pattern && condition"
                conditions = VList <LNode> .Empty;
                while (pattern.Calls(S.And, 2))
                {
                    conditions.Add(pattern.Args.Last);
                    pattern = pattern.Args[0];
                }

                LNode cmpExprOrBinding = null;

                varBinding = cmpExpr = isType = inRange = null;

                // Now decode the expression. Use three passes, each of which decodes
                // an "outer" layer such as A is B, A in B, or expr(args). Since you
                // can combine these operators, we may need multiple passes (e.g.
                // "X is T in R" and "X in R is T" are equivalent), and keep in mind
                // that operator trees like "A in B" are nearly identical to prefix-
                // calls like "foo(A, B)" except for the call target and the `BaseStyle`.
                for (int pass = 1; pass <= 3; pass++)
                {
                    LNode inRange2 = inRange, isType2 = isType;
                    {
                        LNode patternL;
                        if (pattern.Calls(CodeSymbols.In, 2) && (patternL = pattern.Args[0]) != null && (inRange = pattern.Args[1]) != null || pattern.Calls((Symbol)"in", 2) && (patternL = pattern.Args[0]) != null && (inRange = pattern.Args[1]) != null)
                        {
                            pattern = patternL;
                            if (inRange2 != null)
                            {
                                _context.Sink.Error(inRange2, "match-case does not support multiple 'in' operators");
                            }
                        }
                        else if (pattern.Calls(CodeSymbols.Is, 2) && (cmpExprOrBinding = pattern.Args[0]) != null && (isType = pattern.Args[1]) != null || pattern.Calls((Symbol)"is", 2) && (cmpExprOrBinding = pattern.Args[0]) != null && (isType = pattern.Args[1]) != null)
                        {
                            pattern = cmpExprOrBinding;
                            if (isType2 != null)
                            {
                                _context.Sink.Error(isType2, "match-case does not support multiple 'is' operators");
                            }
                        }
                        else if (pattern.Calls(CodeSymbols.Is, 1) && (isType = pattern.Args[0]) != null || pattern.Calls((Symbol)"is", 1) && (isType = pattern.Args[0]) != null)
                        {
                            if (isType2 != null)
                            {
                                _context.Sink.Error(isType2, "match-case does not support multiple 'is' operators");
                            }
                            goto doneAnalysis;
                        }
                        else if (pattern.Calls(CodeSymbols.DotDotDot, 2) || pattern.Calls(CodeSymbols.DotDot, 2) || pattern.Calls(CodeSymbols.DotDotDot, 1) || pattern.Calls(CodeSymbols.DotDot, 1))
                        {
                            inRange = pattern;
                            goto doneAnalysis;
                        }
                        else if (pattern.Calls(CodeSymbols.Tuple))
                        {
                            subPatterns      = pattern.Args;
                            cmpExprOrBinding = null;
                        }
                        else
                        {
                            // It's very tempting to detect NodeStyle.PrefixNotation to distinguish,
                            // say, A.B<C> from id(A, B, C), but I'm reluctant to do so. BaseStyle
                            // is by convention "unsemantic" and not guaranteed to be preserved
                            // across serializations or supported the same way by different parsers.
                            // So instead of asking "is this in PrefixNotation?" I ask "does the
                            // target appear to be a normal identifier?"
                            LNode target = pattern.Target;
                            if (!haveSubPatterns && pattern.IsCall && (!target.IsId || target.AttrNamed(S.TriviaInParens) != null || (!target.HasSpecialName && Les2Printer.IsNormalIdentifier(target.Name)))
                                )

                            {
                                haveSubPatterns = true;
                                subPatterns     = pattern.Args;
                                pattern         = pattern.Target;
                            }
                            else
                            {
                                cmpExprOrBinding = pattern;
                            }
                        }
                    }
                }
doneAnalysis:

                if (cmpExprOrBinding != null)
                {
                    if (cmpExprOrBinding.Calls(S.Substitute, 1))
                    {
                        varBinding = cmpExprOrBinding[0];
                    }
                    else if (refExistingVar)
                    {
                        varBinding = cmpExprOrBinding;
                    }
                    else if ((varBinding ?? cmpExprOrBinding).IsIdNamed(__))
                    {
                        cmpExprOrBinding = varBinding = null;
                    }
                    // Originally a plain identifier would be a binding, like $identifier
                    //if (cmpExprOrBinding.IsId && cmpExprOrBinding.AttrNamed(S.TriviaInParens) == null)
                    //	varBinding = cmpExprOrBinding;
                    if (varBinding != null)
                    {
                        if (varBinding.AttrNamed(S.Ref) != null)
                        {
                            refExistingVar = true;
                            varBinding     = varBinding.WithoutAttrs();
                        }
                        if (!varBinding.IsId)
                        {
                            _context.Sink.Error(varBinding, "Invalid variable name in match-case: {0}", varBinding);
                            varBinding = null;
                        }
                    }
                    if (varBinding == null)
                    {
                        cmpExpr = cmpExprOrBinding;
                    }
                }

                if (refExistingVar && varBinding == null)
                {
                    refExistingVar = false;
                    var got = cmpExprOrBinding ?? pattern;
                    _context.Sink.Warning(got, "'ref' expected a variable name (got `{0}`)", got);
                }
            }