protected override bool InnerOptimize(OptimizationContext context, Instruction matchedInstruction, Backtracer backtracer, int i)
        {
            var changed       = false;
            var j             = i;
            var patchedLabels = new Dictionary <(ushort label, short offset), ushort>();
            var offset        = matchedInstruction.Offset;
            var removedAt     = 0;

            context.RemoveAt(j);

            while (!IsChainBreaker(context[j], Instruction.Advance(offset), null))
            {
                var instruction = context[j];
                switch (instruction.Type)
                {
                case InstructionType.Advance:
                    offset   += instruction.Offset;
                    removedAt = j;
                    context.RemoveAt(j);
                    break;

                case InstructionType.BoundsCheck:
                case InstructionType.Char:
                    var targetLabel = instruction.Label;
                    if (context[context.GetLabelPosition(targetLabel) + 1].Type != InstructionType.RestorePosition)
                    {
                        if (patchedLabels.TryGetValue((targetLabel, offset), out var newTarget))
                        {
                            targetLabel = newTarget;
                        }
                        else if (offset != 0)
                        {
                            var oldLabel = targetLabel;
                            targetLabel = AddStub(context, targetLabel, Instruction.Advance(offset), ref j);
                            patchedLabels[(oldLabel, offset)] = targetLabel;
Example #2
0
        public override bool Optimize(OptimizationContext context)
        {
            var changed    = false;
            var offsetInfo = new VariableOffset[context.Count];

            for (var i = 0; i < offsetInfo.Length; i++)
            {
                offsetInfo[i] = new VariableOffset();
            }

            BuildOffsetInfo(context, offsetInfo);

            for (var i = context.Count - 1; i >= 0; i--)
            {
                var instruction = context[i];
                switch (instruction.Type)
                {
                case InstructionType.RestorePosition:
                    var offset = offsetInfo[i].Get(instruction.Data1);
                    if (offset == 0)
                    {
                        changed = true;
                        context.RemoveAt(i);
                    }
                    else if (offset > 0)
                    {
                        changed    = true;
                        context[i] = Instruction.Advance((short)-offset);
                    }
                    break;
                }
            }

            return(changed);
        }
        public void SimplePrecompiled()
        {
            var p = new PrecompiledPattern(new Method("Precompiled", new List <Instruction>()
            {
                Instruction.Char(0, 0, 0, 1),
                Instruction.Char(0, 1, 1, 2),
                Instruction.Advance(2),
                Instruction.Return(0),
                Instruction.MarkLabel(0),
                Instruction.Return(1),
            }, new List <CharRange>()
            {
                new CharRange('a', 'a'),
                new CharRange('b', 'b'),
            }, new List <LabelMap>(), 0, 1), new List <Pattern>());

            MustMatch(p, "ab");
            MustNotMatch(p, "bb");
            MustNotMatch(p, "ac");
        }
Example #4
0
        public override bool Optimize(OptimizationContext context)
        {
            var changed = false;

            for (var i = context.Count - 1; i >= 0; i--)
            {
                var instructionType = context[i].Type;
                if (instructionType == InstructionType.Advance)
                {
                    if (context[i].Offset == 0 || !IsNeeded(context, i))
                    {
                        changed = true;
                        context.RemoveAt(i);
                    }
                }
            }

            for (var i = 0; i < context.Count; i++)
            {
                if (context[i].Type == InstructionType.Advance && context[i + 1].Matches(InstructionType.Jump, out var jumpTargetLabel))
                {
                    var jumpTarget = context.GetLabelPosition(jumpTargetLabel) + 1;
                    if (context[jumpTarget].Type == InstructionType.Advance)
                    {
                        changed = true;
                        var newLabel = context.LabelAllocator++;
                        context[i]     = Instruction.Advance((short)(context[i].Offset + context[jumpTarget].Offset));
                        context[i + 1] = Instruction.Jump(newLabel);

                        context.Insert(jumpTarget + 1, Instruction.MarkLabel(newLabel));
                    }
                }
            }

            return(changed);
        }