STb <FuncDecl, Expr, Sort> GenerateEncoder() { var ctx = _automataCtx.Z3; Expr inputVar = _automataCtx.MkVar(0, ctx.MkBitVecSort(8)); Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort()); Sort outputSort = ctx.BoolSort; var stb = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, _automataCtx.MkTuple(), 0); var leafPatterns = new Dictionary <byte, bool[]>(); FindLeafPatterns(leafPatterns, _tree, new Stack <bool>()); var patterns = new bool[256][]; foreach (var entry in leafPatterns) { patterns[entry.Key] = entry.Value; } Debug.Assert(patterns.Select((x, i) => patterns.Select((y, j) => i == j || x.Length != y.Length || x.Zip(y, (a, b) => Tuple.Create(a, b)).Any(z => z.Item1 != z.Item2)).All(z => z)).All(z => z)); Debug.Assert(patterns.All(x => x != null), "Internal Huffman tree is missing leaves"); stb.AssignRule(0, GetBinarySearchRule(ctx, (BitVecExpr)inputVar, registerVar, patterns, 0, patterns.Length)); stb.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, 0)); stb = stb.Compose(GenerateToBytes()); stb = stb.ExploreBools(); if (ShowGraphStages.Count > 0) { stb.ToST().ShowGraph(); } return(stb); }
STb <FuncDecl, Expr, Sort> GenerateDecoder() { var ctx = _automataCtx.Z3; Expr inputVar = _automataCtx.MkVar(0, ctx.BoolSort); Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort()); Sort outputSort = ctx.MkBitVecSort(8); var stb = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, _automataCtx.MkTuple(), 0); int nextState = 0; var states = new Dictionary <HuffmanDecision, int>(); PreOrder(_tree, node => { var decision = node as HuffmanDecision; if (decision != null) { states.Add(decision, nextState++); } }); Func <HuffmanNode, BaseRule <Expr> > getBaseRule = node => { var decision = node as HuffmanDecision; if (decision != null) { return(new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, states[decision])); } else { var leaf = (HuffmanLeaf)node; return(new BaseRule <Expr>(new Sequence <Expr>(ctx.MkBV(leaf.Symbol, 8)), registerVar, 0)); } }; PreOrder(_tree, node => { var decision = node as HuffmanDecision; if (decision != null) { stb.AssignRule(states[decision], new IteRule <Expr>(inputVar, getBaseRule(decision.Left), getBaseRule(decision.Right))); stb.AssignFinalRule(states[decision], new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, states[decision])); } }); if (ShowGraphStages.Count > 0) { stb.ToST().ShowGraph(); } return(stb); }
internal STbMinimizer(STb <FUNC, TERM, SORT> stb) { this.stb = stb; this.st = stb.ToST(); }
STb <FuncDecl, Expr, Sort> Generate() { var name = DeclarationType.ContainingNamespace.Name + "." + (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name; Console.WriteLine("XPath " + name); var parser = new XPathParser <IXPathNode>(); IXPathNode root; try { root = parser.Parse(_xpath, new XPathNodeBuilder()); Console.WriteLine(root); } catch (XPathParserException e) { throw new TransducerCompilationException("XPath parsing failed", e); } var resultSort = _ctx.MkBitVecSort(32); var levelCounterSort = _ctx.MkBitVecSort(32); var regSort = _ctx.MkTupleSort(resultSort, levelCounterSort); var initReg = _ctx.MkTuple(_ctx.MkNumeral(0, resultSort), _ctx.MkNumeral(0, levelCounterSort)); var stb = new STb <FuncDecl, Expr, Sort>(_ctx, "stb", _ctx.CharSort, _ctx.MkBitVecSort(32), regSort, initReg, 0); int freeState = 1; Func <int> nextState = () => freeState++; var resultProj = _ctx.MkProj(0, stb.RegVar); var levelCounterProj = _ctx.MkProj(1, stb.RegVar); Func <int, IgnorerInfo> CreateIgnorer = (exitState) => { IgnorerInfo info = new IgnorerInfo(); int outsideTagState = nextState(); int freshTagState = nextState(); int openingTagState = nextState(); int standaloneTagState = nextState(); int closingTagState = nextState(); stb.AssignRule(outsideTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, freshTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, outsideTagState))); stb.AssignRule(freshTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState))); var counterOne = _ctx.MkNumeral(1, levelCounterSort); var levelCounterInc = _ctx.MkTuple(resultProj, _ctx.MkBvAdd(levelCounterProj, counterOne)); stb.AssignRule(openingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterInc, outsideTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState)))); var counterZero = _ctx.MkNumeral(0, levelCounterSort); var levelCounterZeroed = _ctx.MkTuple(resultProj, counterZero); stb.AssignRule(standaloneTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new IteRule <Expr>(_ctx.MkEq(levelCounterProj, counterZero), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, exitState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, outsideTagState)), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState)))); var levelCounterDec = _ctx.MkTuple(resultProj, _ctx.MkBvSub(levelCounterProj, counterOne)); stb.AssignRule(closingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new IteRule <Expr>(_ctx.MkEq(levelCounterProj, counterOne), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, exitState), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterDec, outsideTagState)), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState))); info.MoveToTagOpening = new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, openingTagState); info.MoveToTagOpeningOrStandalone = new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, standaloneTagState), info.MoveToTagOpening); var levelCounterSet = _ctx.MkTuple(resultProj, counterOne); info.MoveToOutsideTag = new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterSet, outsideTagState); return(info); }; var next = root; int?parentState = null; int startState = stb.InitialState; int childState = nextState(); var zeroResult = _ctx.MkTuple(_ctx.MkNumeral(0, resultSort), levelCounterProj); while (next != null) { XPathAxisNode current; var step = next as XPathStepNode; if (step != null) { current = step.Left as XPathAxisNode; next = step.Right; } else { current = next as XPathAxisNode; next = null; } if (current.Axis == XPathAxis.Root) { continue; } if (current == null) { throw new TransducerCompilationException("Unsupported XPath node type: " + next.GetType()); } if (current.Axis != XPathAxis.Child) { throw new TransducerCompilationException("Unsupported axis: " + current.Axis); } if (current.Type != System.Xml.XPath.XPathNodeType.Element) { throw new TransducerCompilationException("Unsupported node type: " + current.Type); } int freshTagState = nextState(); int closingTagState = nextState(); int standaloneMatchState = nextState(); int matchedOpeningTagState = nextState(); int matchedStandaloneTagState = nextState(); var ignorer = CreateIgnorer(startState); stb.AssignRule(startState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, freshTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState))); int matchState = freshTagState; int nextMatchState = nextState(); bool first = true; foreach (char c in current.Label) { STbRule <Expr> matchRule; if (first) { matchRule = new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, c), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, nextMatchState), new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), ignorer.MoveToOutsideTag, ignorer.MoveToTagOpening))); first = false; } else { matchRule = new IteRule <Expr>(EqualsChar(stb.InputVar, c), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, nextMatchState), new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), ignorer.MoveToOutsideTag, ignorer.MoveToTagOpeningOrStandalone)); } stb.AssignRule(matchState, matchRule); matchState = nextMatchState; nextMatchState = nextState(); } stb.AssignRule(closingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), parentState != null ? (STbRule <Expr>) new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, parentState.Value) : new UndefRule <Expr>(), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState))); stb.AssignRule(matchState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, zeroResult, childState), new IteRule <Expr>(EqualsChar(stb.InputVar, ' '), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneMatchState), ignorer.MoveToTagOpening)))); stb.AssignRule(standaloneMatchState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState), new UndefRule <Expr>())); stb.AssignRule(matchedOpeningTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, zeroResult, childState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedStandaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState)))); stb.AssignRule(matchedStandaloneTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedStandaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState)))); parentState = startState; startState = childState; childState = nextState(); } Func <Expr, Expr> AddZeros = (c) => { uint k = (uint)(32 - (int)_ctx.CharSetProvider.Encoding); if (k == 0) { return(c); } else { return(_ctx.MkZeroExt(k, c)); } }; var toIntUpdate = _ctx.MkTuple( _ctx.MkBvAdd(_ctx.MkBvMul(_ctx.MkNumeral(10, resultSort), resultProj), _ctx.MkBvSub(AddZeros(stb.InputVar), _ctx.MkNumeral((int)'0', resultSort))), levelCounterProj); var expectSlashState = nextState(); var scanTagState = nextState(); stb.AssignRule(startState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(new Sequence <Expr>(resultProj), zeroResult, expectSlashState), new BaseRule <Expr>(Sequence <Expr> .Empty, toIntUpdate, startState))); stb.AssignRule(expectSlashState, new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, scanTagState), new UndefRule <Expr>())); stb.AssignRule(scanTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), parentState != null ? (STbRule <Expr>) new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, parentState.Value) : new UndefRule <Expr>(), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, scanTagState))); Console.WriteLine(stb.StateCount); foreach (var state in stb.States) { stb.AssignFinalRule(state, new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, state)); } if (ShowGraphStages.Count > 0) { stb.ToST().ShowGraph(); } return(stb); }
STb <FuncDecl, Expr, Sort> GenerateSTb() { var name = DeclarationType.ContainingNamespace.Name + "." + (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name; Console.WriteLine("Exploring " + name); Expr inputVar = _info.AutomataCtx.MkVar(0, Mapper.GetSortMapping(_transducerType.TypeArguments[0]).Sort); Expr registerVar = _info.AutomataCtx.MkVar(1, Mapper.GetSortMapping(DeclarationType).Sort); Mutator register = Mapper.GetSortMapping(DeclarationType).MutatorForValue(registerVar); var methods = DeclarationType.DeclaringSyntaxReferences.Select(r => r.GetSyntax()) .SelectMany(s => s.DescendantNodes(n => !(n is MethodDeclarationSyntax))) .OfType <MethodDeclarationSyntax>().Select(Syntax => new { Syntax, Symbol = Model.GetDeclaredSymbol(Syntax) as IMethodSymbol }) .Where(x => x.Symbol != null); // Find the Update function var updateMethods = methods.Where(x => x.Symbol.MetadataName == "Update" && x.Symbol.IsOverride && x.Symbol.Parameters.Length == 1 && x.Symbol.Parameters[0].Type == InputTypeSymbol).ToArray(); if (updateMethods.Length == 0) { throw new SyntaxErrorException("No IEnumerable<" + OutputTypeSymbol + "> Update(" + InputTypeSymbol + ") method declared"); } else if (updateMethods.Length > 1) { throw new SyntaxErrorException("Multiple Update methods declared"); } var updateMethod = updateMethods[0]; // Explore the Update function var updateCfg = new ControlFlowGraph(updateMethod.Syntax.Body, Model); Dictionary <ISymbol, Mutator> parameters = updateMethod.Symbol.Parameters .ToDictionary(p => (ISymbol)p, p => Mapper.GetSortMapping(_transducerType.TypeArguments[0]).MutatorForValue(inputVar)); var updateEntryState = new MainExplorationState(_info, updateCfg.EntryPoint, register, parameters, new[] { inputVar, registerVar }); var updateRule = updateEntryState.Explore(); // Find the Finish function var finishMethods = methods.Where(x => x.Symbol.MetadataName == "Finish" && x.Symbol.IsOverride && x.Symbol.Parameters.Length == 0).ToArray(); STbRule <Expr> finishRule; if (finishMethods.Length == 0) { finishRule = new BaseRule <Expr>(Sequence <Expr> .Empty, register.CreateUpdate(), 0); } else { if (finishMethods.Length > 1) { throw new SyntaxErrorException("Multiple Finish methods declared"); } var finishMethod = finishMethods[0]; // Explore the Finish function var finishCfg = new ControlFlowGraph(finishMethod.Syntax.Body, Model); var finishEntryState = new MainExplorationState(_info, finishCfg.EntryPoint, register, new Dictionary <ISymbol, Mutator>(), new[] { registerVar }); finishRule = finishEntryState.Explore(); } var outputSort = Mapper.GetSortMapping(_transducerType.TypeArguments[1]).Sort; var stb = new STb <FuncDecl, Expr, Sort>(_info.AutomataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, Mapper.GetSortMapping(DeclarationType).MutatorForDefaultValue().CreateUpdate().SafeSimplify(Ctx), 0); stb.AssignRule(0, updateRule); stb.AssignFinalRule(0, finishRule); if (ShowGraphStages.Contains(ShowGraph.Stage.UnSimplified)) { stb.ShowGraph(); } stb = stb.Flatten(); if (ShowGraphStages.Contains(ShowGraph.Stage.Simplified)) { stb.ToST().ShowGraph(); } return(stb); }