예제 #1
0
        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        private bool TryBuildJumpTable(CaseBlock[] caseBlocks, out CaseBlock[] jumpTable, out long adjustment)
        {
            jumpTable  = null;
            adjustment = 0;

            var jumpTableLength = caseBlocks[caseBlocks.Length - 1].Int64 - caseBlocks[0].Int64 + 1;

            if (jumpTableLength > caseBlocks.Length * 2 + 1 || jumpTableLength > UInt32.MaxValue)
            {
                return(false);
            }

            jumpTable  = new CaseBlock[jumpTableLength];
            adjustment = -caseBlocks[0].Int64;
            var caseIndex = 0;

            for (int jumpIndex = 0; jumpIndex < jumpTableLength; jumpIndex++)
            {
                if (jumpIndex == caseBlocks[caseIndex].Int64 + adjustment)
                {
                    jumpTable[jumpIndex] = caseBlocks[caseIndex++];
                }
            }

            return(true);
        }
예제 #2
0
        public Dictionary <object, CodeBlock> ToDictionary(Executer exec, out CodeBlock _default)
        {
            Dictionary <object, CodeBlock> dict = new Dictionary <object, CodeBlock>();

            _default = null;
            for (int index = 0; index < Body.Count; index++)
            {
                CaseBlock caseBlock;
                index = CaseBlock.ParseBlock(index, Body, out caseBlock) - 1;

                if (caseBlock.Header.Name.EqualsIgnoreCase("DEFAULT"))
                {
                    _default = caseBlock;
                }
                else if (caseBlock.Header.Name.EqualsIgnoreCase("CASE"))
                {
                    dict.Add(
                        Evaluator.Evaluate(caseBlock.Condition, exec),
                        caseBlock
                        );
                }
                else
                {
                    throw ThrowHelper.InvalidTypeInExpression(Body[0].Text, "CASE");
                }
            }
            return(dict);
        }
예제 #3
0
        public void Equality_Default()
        {
            var a = new CaseBlock();
            var b = new CaseBlock();

            Assert.AreEqual(a, b);
            Assert.AreEqual(a.GetHashCode(), b.GetHashCode());
        }
예제 #4
0
        public void DefaultValues()
        {
            var sut = new CaseBlock();

            Assert.AreEqual(new UnknownExpression(), sut.Label);
            Assert.AreEqual(Lists.NewList <IStatement>(), sut.Body);
            Assert.AreNotEqual(0, sut.GetHashCode());
            Assert.AreNotEqual(1, sut.GetHashCode());
        }
예제 #5
0
        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public void Default(Action body)
        {
            if (m_Default != null)
            {
                throw new InvalidOperationException("Default case was already specified.");
            }

            m_Default = new CaseBlock(this, default(T));
            m_Default.Do(body);
        }
예제 #6
0
        public void Equality_DifferentBody()
        {
            var a = new CaseBlock {
                Body = { new ReturnStatement() }
            };
            var b = new CaseBlock();

            Assert.AreNotEqual(a, b);
            Assert.AreNotEqual(a.GetHashCode(), b.GetHashCode());
        }
예제 #7
0
        public void Equality_DifferentLabel()
        {
            var a = new CaseBlock {
                Label = Label("a")
            };
            var b = new CaseBlock();

            Assert.AreNotEqual(a, b);
            Assert.AreNotEqual(a.GetHashCode(), b.GetHashCode());
        }
예제 #8
0
        public void SettingValues()
        {
            var sut = new CaseBlock
            {
                Label = Label("a"),
                Body  = { new ReturnStatement() }
            };

            Assert.AreEqual(Label("a"), sut.Label);
            Assert.AreEqual(Lists.NewList(new ReturnStatement()), sut.Body);
        }
예제 #9
0
        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        #region IHapilSwitchSyntax<T> Members

        public IHapilSwitchCaseSyntax <T> Case(T constantValue)
        {
            if (m_CasesByValue.ContainsKey(constantValue))
            {
                throw new ArgumentException("There is already case for specified value", paramName: "constantValue");
            }

            var block = new CaseBlock(this, constantValue);

            m_CasesByValue.Add(constantValue, block);

            return(block);
        }
예제 #10
0
 public override void VisitCFGCaseBlock(CaseBlock x)
 {
     VisitCFGBlockInit(x);
     if (!x.CaseValue.IsOnlyBoundElement)
     {
         x.CaseValue.PreBoundStatements.ForEach(Accept);
     }
     if (!x.CaseValue.IsEmpty)
     {
         Accept(x.CaseValue.BoundElement);
     }
     VisitCFGBlockInternal(x);
 }
예제 #11
0
        // Build a case block statement
        public static void BuildCaseBlock(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode)
        {
            var caseBlock = new CaseBlock(parentExpression, currentNode.Token.Convert());

            parentExpression.ChildExpressions.Add(caseBlock);

            // Get the expression being tested against
            parser.ConsumeParseTree(root, caseBlock.Variable, currentNode.ChildNodes[1]);

            // Build the expressions in the body of the case block
            foreach (var e in currentNode.ChildNodes[2].ChildNodes)
            {
                parser.ConsumeParseTree(root, caseBlock, e);
            }
        }
예제 #12
0
        public void Equality_ReallyTheSame()
        {
            var a = new CaseBlock
            {
                Label = Label("a"),
                Body  = { new ReturnStatement() }
            };
            var b = new CaseBlock
            {
                Label = Label("a"),
                Body  = { new ReturnStatement() }
            };

            Assert.AreEqual(a, b);
            Assert.AreEqual(a.GetHashCode(), b.GetHashCode());
        }
예제 #13
0
 public void AddBlock(CaseBlock <double> caseBlock)
 {
     if (caseBlock != null)
     {
         if (double.IsNaN(NumericValue))
         {
             throw new SwitchBlockException("An expression was expected but provided in case.");
         }
         if (_numericBlocks.Any(cb => cb.Cases.Intersect(caseBlock.Cases).Any()))
         {
             var blockFound = _numericBlocks.First(cb => cb.Cases.Intersect(caseBlock.Cases).Any());
             var dupCase    = blockFound.Cases.Intersect(caseBlock.Cases);
             throw new SwitchBlockException($"Multiple instances of cases with comparison of values {string.Join(',', dupCase)}.");
         }
         _numericBlocks.Add(caseBlock);
     }
 }
예제 #14
0
            public void AddBlock(CaseBlock <string> caseBlock)
            {
                if (caseBlock != null)
                {
                    if (string.IsNullOrEmpty(StringValue))
                    {
                        throw new SwitchBlockException("String literal was expected but not provided in case.");
                    }
                    if (_stringBlocks.Any(cb => cb.Cases.Intersect(caseBlock.Cases).Any()))
                    {
                        var blockFound = _stringBlocks.First(cb => cb.Cases.Intersect(caseBlock.Cases).Any());
                        var dupCase    = blockFound.Cases.Intersect(caseBlock.Cases);

                        throw new SwitchBlockException($"Multiple instances of cases with comparison of values \"{string.Join(',', dupCase)}\".");
                    }
                    _stringBlocks.Add(caseBlock);
                }
            }
예제 #15
0
            public static int ParseBlock(int index, LineCollection all, out CaseBlock caseBlock)
            {
                LineCollection blockLines = new LineCollection();

                bool isBlock = false;

                for (; index < all.Count; index++)
                {
                    if (isBlock)
                    {
                        if (all[index].Name.EqualsIgnoreCase("CASE") ||
                            all[index].Name.EqualsIgnoreCase("DEFAULT"))
                        {
                            break;
                        }
                        else
                        {
                            blockLines.Add(all[index]);
                        }
                    }
                    else if (all[index].Name.EqualsIgnoreCase("CASE") ||
                             all[index].Name.EqualsIgnoreCase("DEFAULT"))
                    {
                        isBlock = true;
                        blockLines.Add(all[index]);
                    }
                }
                if (blockLines.Count > 0)
                {
                    caseBlock = new CaseBlock(blockLines);
                }
                else
                {
                    caseBlock = null;
                }
                return(index);
            }
예제 #16
0
 private void ReadCase(Switch target)
 {
     var scb = new CaseBlock();
     BlockBase p;
     NodeBase[] s;
     for (; ; )
     {
         var t = Read();
         switch (t)
         {
             case null:
                 throw Abort("switch: }}}} が必要です。");
             case "case":
             case "default":
                 if (scb.Block != null)
                 {
                     target.Blocks.Add(scb);
                     scb = new CaseBlock();
                 }
                 if (scb.Case == null)
                     scb.Case = Case.New(target);
                 if (t == "case")
                 {
                     var v = ReadExpression() as NodeBase;
                     if (v == null)
                         throw Abort("case: 値が必要です。");
                     Check("case", ":");
                     scb.Case.Values.Add(v);
                 }
                 else
                     Check("default", ":");
                 break;
             case "}":
                 if (scb.Block != null) target.Blocks.Add(scb);
                 return;
             default:
                 Rewind();
                 if (scb.Case == null)
                     throw Abort("switch: 条件が必要です。");
                 if (scb.Block == null)
                     scb.Block = Block.New(target);
                 p = parent;
                 parent = target;
                 s = Sentence();
                 if (s != null) scb.Block.AddSentences(s);
                 parent = p;
                 break;
         }
     }
 }
예제 #17
0
파일: Edge.cs 프로젝트: iolevel/peachpie
        internal SwitchEdge(BoundBlock source, BoundExpression switchValue, CaseBlock[] caseBlocks, BoundBlock endBlock)
            : base(source)
        {
            Contract.ThrowIfNull(caseBlocks);
            _switchValue = switchValue;
            _caseBlocks = caseBlocks;
            _end = endBlock;

            Connect(source);
        }
예제 #18
0
        public override void ExecuteDirective()
        {
            var line = Assembler.LineIterator.Current;

            if (!line.InstructionName.Equals(".switch"))
            {
                return;
            }
            SwitchContext      context      = null;
            CaseBlock <string> stringBlock  = null;
            CaseBlock <double> numericBlock = null;

            if (Line.OperandHasToken)
            {
                if (!Assembler.SymbolManager.SymbolExists(Line.OperandExpression))
                {
                    if (Line.Operand.Children[0].Name.Equals("("))
                    {
                        if (Line.Operand.Children[0].Children.Count > 0 &&
                            Line.Operand.Children[0].Children[0].ToString().EnclosedInDoubleQuotes())
                        {
                            context = new SwitchContext(Line.Operand.Children[0].Children[0].ToString());
                        }
                        else
                        {
                            context = new SwitchContext(Evaluator.Evaluate(Line.Operand));
                        }
                    }
                }
                else
                {
                    context = new SwitchContext(Evaluator.Evaluate(Line.Operand));
                }
            }
            if (context == null)
            {
                Assembler.Log.LogEntry(Line, Line.Operand, "Expression must be a valid symbol or constant expression.");
                return;
            }
            Token lastInstruction = null;

            if (!(line.OperandHasToken &&
                  (Assembler.SymbolManager.SymbolExists(line.Operand.Children[0].Children[0].Name) || line.Operand.Children[0].Name.Equals("("))))
            {
                string error;
                if (!line.OperandHasToken)
                {
                    error = "Expression must follow \".switch\" directive.";
                }
                else
                {
                    error = "Expression must be a valid symbol or an expression.";
                }
                Assembler.Log.LogEntry(line, line.Instruction.Position, error);
                return;
            }
            var defaultIndex = -1;

            if (!string.IsNullOrEmpty(context.StringValue))
            {
                stringBlock = new CaseBlock <string>();
            }
            else
            {
                numericBlock = new CaseBlock <double>();
            }
            while ((line = Assembler.LineIterator.GetNext()) != null &&
                   !line.InstructionName.Equals(".endswitch"))
            {
                if (!string.IsNullOrEmpty(line.InstructionName))
                {
                    lastInstruction = line.Instruction;
                }
                if (line.InstructionName.Equals(".case"))
                {
                    if (defaultIndex > -1)
                    {
                        Assembler.Log.LogEntry(line, line.Instruction.Position, "\".case\" directive cannot follow a \".default\" directive.");
                    }
                    else if (stringBlock?.FallthroughIndex > -1 || numericBlock?.FallthroughIndex > -1)
                    {
                        Assembler.Log.LogEntry(line, line.Instruction.Position, "\".case\" directive must follow a \".break\" directive.");
                    }
                    {
                        stringBlock?.Cases.Add(line.Operand.Name);
                        numericBlock?.Cases.Add(Evaluator.Evaluate(line.Operand));
                    }
                }
                else if (line.InstructionName.Equals(".break"))
                {
                    if ((stringBlock?.Cases.Count == 0 || numericBlock?.Cases.Count == 0) &&
                        defaultIndex < 0)
                    {
                        Assembler.Log.LogEntry(line, line.Instruction.Position,
                                               "\".break\" directive must follow a \".case\" or \".default\" directive.");
                    }
                    else
                    {
                        context.AddBlock(stringBlock);
                        context.AddBlock(numericBlock);

                        if (stringBlock != null)
                        {
                            stringBlock = new CaseBlock <string>();
                        }
                        else
                        {
                            numericBlock = new CaseBlock <double>();
                        }
                    }
                }
                else if (line.InstructionName.Equals(".default"))
                {
                    if (defaultIndex > -1)
                    {
                        Assembler.Log.LogEntry(line, line.Instruction.Position,
                                               "There can only be one \".default\" directive in a switch block.");
                    }
                    else
                    {
                        defaultIndex = Assembler.LineIterator.Index;
                    }
                }
                else
                {
                    if (line.Label != null)
                    {
                        Assembler.Log.LogEntry(line, line.Label.Position, "Label cannot be defined inside a switch block.");
                    }
                    if (line.Instruction != null)
                    {
                        if ((stringBlock?.Cases.Count == 0 || numericBlock?.Cases.Count == 0) && defaultIndex < 0)
                        {
                            Assembler.Log.LogEntry(line, line.Instruction.Position, "\".case\" or \".default\" directive expected");
                        }
                        else if (stringBlock?.FallthroughIndex < 0 || numericBlock?.FallthroughIndex < 0)
                        {
                            if (stringBlock != null)
                            {
                                stringBlock.FallthroughIndex = Assembler.LineIterator.Index;
                            }
                            if (numericBlock != null)
                            {
                                numericBlock.FallthroughIndex = Assembler.LineIterator.Index;
                            }
                        }
                    }
                }
            }
            if (lastInstruction == null || (line != null && !string.IsNullOrEmpty(lastInstruction.Name) && !lastInstruction.Name.Equals(".break")))
            {
                if (line == null)
                {
                    line = Line;
                }
                Assembler.Log.LogEntry(line, "Switch statement must end with a \".break\" directive.");
            }
            else if (line != null)
            {
                if (defaultIndex < 0 || !context.AnyCaseDefined())
                {
                    if (defaultIndex >= 0)
                    {
                        Assembler.Log.LogEntry(line, line.Instruction, "Only a default case was specified.", false);
                    }
                    else if (!context.AnyCaseDefined())
                    {
                        Assembler.Log.LogEntry(line, line.Instruction, "Switch statement did not encounter any cases to evaluate.");
                        return;
                    }
                    else
                    {
                        Assembler.Log.LogEntry(line, line.Instruction, "Switch statement does not have a default case.", false);
                    }
                }
                int fallthroughIndex = context.GetFallthroughIndex();
                if (fallthroughIndex < 0)
                {
                    fallthroughIndex = defaultIndex;
                }

                if (fallthroughIndex > -1)
                {
                    Assembler.LineIterator.Rewind(fallthroughIndex - 1);
                }
            }
        }
예제 #19
0
 public virtual void VisitCFGCaseBlock(CaseBlock x)
 {
     Accept(x.CaseValue);
     VisitCFGBlockInternal(x);
 }
예제 #20
0
        public override void ExecuteDirective(RandomAccessIterator <SourceLine> lines)
        {
            var line = lines.Current;

            if (line.Instruction.Name.Equals(".endswitch", Services.StringComparison))
            {
                return;
            }
            CaseBlock <string> stringBlock  = null;
            CaseBlock <double> numericBlock = null;
            SwitchContext      context      = null;
            var it = line.Operands.GetIterator();

            if (it.MoveNext())
            {
                if (StringHelper.ExpressionIsAString(it, Services))
                {
                    context = new SwitchContext(StringHelper.GetString(it, Services));
                }
                else
                {
                    context = new SwitchContext(Services.Evaluator.Evaluate(it, false));
                }
                if (it.Current != null)
                {
                    throw new SyntaxException(it.Current, "Unexpected expression.");
                }
            }
            if (context == null)
            {
                string error;
                if (line.Operands.Count == 0)
                {
                    error = "Expression must follow \".switch\" directive.";
                }
                else
                {
                    error = "Expression must be a valid symbol or an expression.";
                }
                Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, error);
                return;
            }
            var defaultIndex = -1;

            if (!string.IsNullOrEmpty(context.StringValue))
            {
                stringBlock = new CaseBlock <string>();
            }
            else
            {
                numericBlock = new CaseBlock <double>();
            }
            while ((line = lines.GetNext()) != null &&
                   (line.Instruction == null || !line.Instruction.Name.Equals(".endswitch", Services.StringComparison)))
            {
                if (line.Instruction != null)
                {
                    if (line.Instruction.Name.Equals(".case", Services.StringComparison))
                    {
                        if (defaultIndex > -1)
                        {
                            Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position,
                                                  "\".case\" directive cannot follow a \".default\" directive.");
                        }
                        else if (stringBlock?.FallthroughIndex > -1 || numericBlock?.FallthroughIndex > -1)
                        {
                            Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position,
                                                  "\".case\" does not fall through.");
                        }
                        else if (line.Operands.Count == 0)
                        {
                            Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position,
                                                  "Expression expected.");
                        }
                        else
                        {
                            var iterator = line.Operands.GetIterator();
                            if (stringBlock != null)
                            {
                                if (!StringHelper.ExpressionIsAString(iterator, Services))
                                {
                                    Services.Log.LogEntry(line.Filename, line.LineNumber, line.Operands[0].Position,
                                                          "String expression expected.");
                                }
                                else
                                {
                                    stringBlock.Cases.Add(StringHelper.GetString(iterator, Services));
                                }
                            }
                            else
                            {
                                numericBlock?.Cases.Add(Services.Evaluator.Evaluate(iterator));
                            }
                            if (iterator.Current != null)
                            {
                                throw new SyntaxException(iterator.Current, "Unexpected expression.");
                            }
                        }
                    }
                    else if (Reserved.IsOneOf("BreakContReturn", line.Instruction.Name))
                    {
                        if ((stringBlock?.Cases.Count == 0 || numericBlock?.Cases.Count == 0) &&
                            defaultIndex < 0)
                        {
                            Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position,
                                                  $"\"{line.Instruction}\" directive must follow a \".case\" or \".default\" directive.");
                        }
                        else
                        {
                            if (line.Instruction.Name.Equals(".return", Services.StringComparison) &&
                                (stringBlock?.FallthroughIndex < 0 || numericBlock?.FallthroughIndex < 0))
                            {
                                if (stringBlock != null)
                                {
                                    stringBlock.FallthroughIndex = lines.Index;
                                }
                                if (numericBlock != null)
                                {
                                    numericBlock.FallthroughIndex = lines.Index;
                                }
                            }
                            else if (!line.Instruction.Name.Equals(".return", Services.StringComparison) && line.Operands.Count > 0)
                            {
                                throw new SyntaxException(line.Operands[0], "Unexpected expression.");
                            }
                            context.AddBlock(stringBlock);
                            context.AddBlock(numericBlock);
                            Services.SymbolManager.PopScope();
                            if (stringBlock != null)
                            {
                                stringBlock = new CaseBlock <string>();
                            }
                            else
                            {
                                numericBlock = new CaseBlock <double>();
                            }
                        }
                    }
                    else if (line.Instruction.Name.Equals(".default", Services.StringComparison))
                    {
                        if (line.Operands.Count > 0)
                        {
                            throw new SyntaxException(line.Operands[0], "Unexpected expression.");
                        }
                        if (defaultIndex > -1)
                        {
                            Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position,
                                                  "There can only be one \".default\" directive in a switch block.");
                        }
                        else
                        {
                            defaultIndex = lines.Index + 1;
                        }
                    }
                    else if (line.Label != null)
                    {
                        Services.Log.LogEntry(line.Filename, line.LineNumber, line.Label.Position,
                                              "Label cannot be defined inside a switch block.");
                    }
                    else
                    {
                        if ((stringBlock?.Cases.Count == 0 || numericBlock?.Cases.Count == 0) && defaultIndex < 0)
                        {
                            Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position, "\".case\" or \".default\" directive expected");
                        }
                        else if (stringBlock?.FallthroughIndex < 0 || numericBlock?.FallthroughIndex < 0)
                        {
                            if (stringBlock != null)
                            {
                                stringBlock.FallthroughIndex = lines.Index;
                            }
                            if (numericBlock != null)
                            {
                                numericBlock.FallthroughIndex = lines.Index;
                            }
                        }
                    }
                }
            }
            if (line != null)
            {
                if (defaultIndex < 0 || !context.AnyCaseDefined())
                {
                    if (defaultIndex >= 0)
                    {
                        Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position,
                                              "Only a default case was specified.", false);
                    }
                    else if (!context.AnyCaseDefined())
                    {
                        Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position,
                                              "Switch statement did not encounter any cases to evaluate.");
                        return;
                    }
                    else
                    {
                        Services.Log.LogEntry(line.Filename, line.LineNumber, line.Instruction.Position,
                                              "Switch statement does not have a default case.", false);
                    }
                }
                var fallthroughIndex = context.GetFallthroughIndex();
                if (fallthroughIndex < 0)
                {
                    fallthroughIndex = defaultIndex;
                }

                if (fallthroughIndex > -1)
                {
                    lines.Rewind(fallthroughIndex - 1);
                }
                Services.SymbolManager.PushScope(lines.Index.ToString());
            }
        }
예제 #21
0
 public override void VisitCFGCaseBlock(CaseBlock x)
 {
     VisitCFGBlockInit(x);
     Accept(x.CaseValue);
     VisitCFGBlockInternal(x);
 }
 public SyntaxList <SwitchSectionSyntax> Convert(CaseBlock node)
 {
     return(SyntaxFactory.List(node.Clauses.ToCsNodes <SwitchSectionSyntax>()));
 }
예제 #23
0
 public override void VisitCFGCaseBlock(CaseBlock x)
 {
     VisitCFGBlockInit(x);
     Accept(x.CaseValue);
     VisitCFGBlockInternal(x);
 }
예제 #24
0
        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        public SwitchStatement(IOperand <T> value)
        {
            m_Value        = value;
            m_CasesByValue = new SortedDictionary <T, CaseBlock>();
            m_Default      = null;
        }