Exemple #1
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.ToLNodeList().AsLNode(S.Braces)))
                        };
                    }
                    else
                    {
                        finalOutput.Insert(0, code);
                    }
                }
                return(finalOutput.ToLNodeList().AsLNode(S.Braces));
            }
Exemple #2
0
            public void Generate(Rule rule)
            {
                CGH.BeginRule(rule);
                _currentRule           = rule;
                _target                = new WList <LNode>();
                _laVarsNeeded          = 0;
                _separatedMatchCounter = _stopLabelCounter = 0;
                _recognizerMode        = rule.IsRecognizer;
                _labelsInUse.Clear();

                Visit(rule.Pred);

                if (_laVarsNeeded != 0)
                {
                    LNode laVars = F.Call(S.Var, CGH.LAType());
                    for (int i = 0; _laVarsNeeded != 0; i++, _laVarsNeeded >>= 1)
                    {
                        if ((_laVarsNeeded & 1) != 0)
                        {
                            laVars = laVars.PlusArg(F.Id("la" + i.ToString()));
                        }
                    }
                    _target.Insert(0, laVars);
                }

                LNode method;

                if (rule.TryWrapperName != null)
                {
                    Debug.Assert(rule.IsRecognizer);
                    method = F.OnNewLine(CGH.CreateTryWrapperForRecognizer(rule));
                    _classBody.SpliceAdd(method, S.Splice);
                }

                method = CGH.CreateRuleMethod(rule, _target.ToLNodeList());
                if (!rule.IsRecognizer)
                {
                    method = F.OnNewLine(method);
                }
                _classBody.SpliceAdd(method, S.Splice);
            }
Exemple #3
0
        public static LNode unroll(LNode var, LNodeList cases, LNode body, IMessageSink sink)
        {
            // Maps identifiers => replacements. The integer counts how many times replacement occurred.
            var replacements = InternalList <Triplet <Symbol, LNode, int> > .Empty;

            if (var.IsId && !var.HasPAttrs())
            {
                replacements.Add(Triplet.Create(var.Name, (LNode)LNode.Missing, 0));
            }
            else
            {
                var vars = var.Args;
                if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs()))
                {
                    replacements = new Triplet <Symbol, LNode, int> [vars.Count].AsInternalList();
                    for (int i = 0; i < vars.Count; i++)
                    {
                        replacements.InternalArray[i].A = vars[i].Name;

                        // Check for duplicate names
                        for (int j = 0; j < i; j++)
                        {
                            if (replacements[i].A == replacements[j].A && replacements[i].A.Name != "_")
                            {
                                sink.Error(vars[i], "Duplicate name in the left-hand tuple");                                 // non-fatal
                            }
                        }
                    }
                }
                else
                {
                    return(Reject(sink, var, "The left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers."));
                }
            }

            UnrollCtx ctx = new UnrollCtx {
                Replacements = replacements
            };
            WList <LNode> output = new WList <LNode>();
            int iteration        = 0;
            foreach (LNode replacement in cases)
            {
                iteration++;
                bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces);
                int  count = tuple ? replacement.ArgCount : 1;
                if (replacements.Count != count)
                {
                    sink.Error(replacement, "iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Count, count);
                    if (count < replacements.Count)
                    {
                        continue;                         // too few
                    }
                }
                for (int i = 0; i < replacements.Count; i++)
                {
                    replacements.InternalArray[i].B = tuple ? replacement.Args[i] : replacement;
                }

                if (body.Calls(S.Braces))
                {
                    foreach (LNode stmt in body.Args)
                    {
                        output.Add(ctx.Replace(stmt).Value);
                    }
                }
                else
                {
                    output.Add(ctx.Replace(body).Value);
                }
            }

            foreach (var r in replacements)
            {
                if (r.C == 0 && !r.A.Name.StartsWith("_"))
                {
                    sink.Write(Severity.Warning, var, "Replacement variable '{0}' was never used", r.A);
                }
            }

            return(body.With(S.Splice, output.ToLNodeList()));
        }
Exemple #4
0
        public static LNode match(LNode node, IMacroContext context)
        {
            {
                LNode     input;
                LNodeList 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);

                    // Process the braced block, one case at a time
                    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)                         // `case ...:` or `default:`
                            )
                        {
                            return(Reject(context, contents[0], "In 'match': expected 'case' statement"));
                        }
                        // Find the end of the current case/default block
                        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;
                            }
                        }
                        //  handler: the list of statements underneath `case`
                        var handler = new LNodeList(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.StatementBlock));
                            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.ToLNodeList().AsLNode(S.Braces), LNode.Literal(false))));
                }
            }
            return(null);
        }