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;
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"); }
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); }