private Expr GenerateZ3Expr(AppExp expr, FastTransducerInstance fti) { List<Expr> termList = new List<Expr>(); switch (expr.func.name.Kind) { case (Tokens.EQ): { return z3p.MkEq(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.AND): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromExpr(arg, fti)); return z3p.MkAnd(termList.ToArray()); } //case ("xor"): // { // return z3p.Z3.MkXor((BoolExpr)GenerateZ3ExprFromExpr(expr.args[0], fti), (BoolExpr)GenerateZ3ExprFromExpr(expr.args[1], fti)); // } case (Tokens.NOT): { return z3p.MkNot(GenerateZ3ExprFromExpr(expr.args[0], fti)); } case (Tokens.OR): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromExpr(arg, fti)); return z3p.MkOr(termList.ToArray()); } case (Tokens.IMPLIES): { return z3p.MkOr(z3p.MkNot(GenerateZ3ExprFromExpr(expr.args[0], fti)), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.PLUS): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromExpr(arg, fti)); if (z3p.GetSort(termList[0]).SortKind == Z3_sort_kind.Z3_BV_SORT) return z3p.MkBvAddMany(termList.ToArray()); return z3p.MkAdd(termList.ToArray()); } case (Tokens.DIV): { return z3p.MkCharDiv(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.MINUS): { return z3p.MkCharSub(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.TIMES): { return z3p.MkCharMul(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.LT): { return z3p.MkCharLt(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.LE): { return z3p.MkCharLe(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.GT): { return z3p.MkCharGt(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.GE): { return z3p.MkCharGe(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (Tokens.MOD): { return z3p.MkMod(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } //case ("concat"): // { // throw new Exception("concat not defined yet"); // //return z3p.MkL(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); // } case (Tokens.ITE): { return z3p.MkIte(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti), GenerateZ3ExprFromExpr(expr.args[2], fti)); } case (Tokens.ID): { foreach (var f in fti.functions) { if (this.name == f.name) throw new Exception("cannot define recursive functions"); if (expr.func.name.text == f.name) { List<Expr> argsExprs = new List<Expr>(); foreach (var a in expr.args) { argsExprs.Add(GenerateZ3ExprFromExpr(a, fti)); } return z3p.ApplySubstitution(f.functionDef, f.variableExprs.Values.ToArray(), argsExprs.ToArray<Expr>()); //return z3p.MkApp(f.funcDecl, argsExprs.ToArray<Expr>()); } } throw new FastException(FastExceptionKind.UnknownFunction); } default: throw new FastException(FastExceptionKind.UnknownFunction); } }
private Expr GenerateZ3Expr(AppExp expr, FastTransducerInstance fti) { List<Expr> termList = new List<Expr>(); switch (expr.func.name.text) { case ("="): { return z3p.MkEq(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case ("and"): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromExpr(arg, fti)); return z3p.MkAnd(termList.ToArray()); } case ("xor"): { if (expr.args.Count > 2) throw new Exception("Too many arguments"); return z3p.Z3.MkXor((BoolExpr)GenerateZ3ExprFromExpr(expr.args[0], fti), (BoolExpr)GenerateZ3ExprFromExpr(expr.args[1], fti)); } case ("not"): { return z3p.MkNot(GenerateZ3ExprFromExpr(expr.args[0], fti)); } case ("or"): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromExpr(arg, fti)); return z3p.MkOr(termList.ToArray()); } case ("=>"): { return z3p.MkOr(z3p.MkNot(GenerateZ3ExprFromExpr(expr.args[0], fti)), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case ("+"): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromExpr(arg, fti)); if (z3p.GetSort(termList[0]).SortKind == Z3_sort_kind.Z3_BV_SORT) return z3p.MkBvAddMany(termList.ToArray()); return z3p.MkAdd(termList.ToArray()); } case ("/"): { return z3p.MkDiv(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case ("-"): { return z3p.MkSub(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case ("*"): { return z3p.MkMul(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case ("<"): { return z3p.MkLt(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case ("<="): { return z3p.MkLe(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (">"): { return z3p.MkGt(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case (">="): { return z3p.MkGe(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti)); } case ("if"): { return z3p.MkIte(GenerateZ3ExprFromExpr(expr.args[0], fti), GenerateZ3ExprFromExpr(expr.args[1], fti), GenerateZ3ExprFromExpr(expr.args[2], fti)); } default: { foreach (var f in fti.functions) { if (expr.func.name.text == f.name) { List<Expr> argsExprs = new List<Expr>(); foreach (var a in expr.args) { argsExprs.Add(GenerateZ3ExprFromExpr(a, fti)); } return z3p.ApplySubstitution(f.functionDef, f.variableExprs.Values.ToArray(), argsExprs.ToArray<Expr>()); //return z3p.MkApp(f.funcDecl, argsExprs.ToArray<Expr>()); } } throw new Exception("Function not defined"); } } }
private Expr GenerateZ3ToExpr(AppExp expr, RankedAlphabetSort outputAlph, List<FastToken> children, int from, List<string> reachedStates, List<Def> queue, Dictionary<string, Def> defs, FastTransducerInstance fti, List<int>[] nextStatesL) { List<Expr> termList = new List<Expr>(); switch (expr.func.name.Kind) { #region predefined functions case (Tokens.EQ): { return z3p.MkEq(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.AND): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromToExpr(arg, outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); return z3p.MkAnd(termList.ToArray()); } //case ("xor"): // { // if (expr.args.Count > 2) // throw new Exception("Too many arguments"); // return z3p.Z3.MkXor((BoolExpr)GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), (BoolExpr)GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); // } case (Tokens.NOT): { return z3p.MkNot(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.OR): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromToExpr(arg, outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); return z3p.MkOr(termList.ToArray()); } case (Tokens.IMPLIES): { return z3p.MkOr(z3p.MkNot(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.PLUS): { foreach (var arg in expr.args) termList.Add(GenerateZ3ExprFromToExpr(arg, outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); if (z3p.GetSort(termList[0]).SortKind == Z3_sort_kind.Z3_BV_SORT) return z3p.MkBvAddMany(termList.ToArray()); return z3p.MkAdd(termList.ToArray()); } case (Tokens.DIV): { return z3p.MkCharDiv(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.MINUS): { return z3p.MkCharSub(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.TIMES): { return z3p.MkCharMul(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.LT): { return z3p.MkCharLt(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.LE): { return z3p.MkCharLe(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.GT): { return z3p.MkCharGt(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.GE): { return z3p.MkCharGe(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.MOD): { return z3p.MkMod(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } case (Tokens.ITE): { return z3p.MkIte(GenerateZ3ExprFromToExpr(expr.args[0], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[1], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL), GenerateZ3ExprFromToExpr(expr.args[2], outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL)); } #endregion default: { if (expr.IsTranDef) { //The application is a transduction applied to a subtree //Check if the current trans has been processed, if not add it to the queue String name = ((AppExp)expr).func.name.text; int pos = reachedStates.IndexOf(name); if (pos == -1) { reachedStates.Add(name); var transDef = defs[name]; queue.Add((TransDef)transDef); pos = reachedStates.Count-1; } //Find the child number and return the transition int childPosition = 1; foreach (var child in children) { if (child.text == ((AppExp)expr).args[0].token.text) { break; } childPosition++; } if (!nextStatesL[childPosition - 1].Contains(pos)) nextStatesL[childPosition - 1].Add(pos); return alphabet.alph.MkTrans(outputAlph.alph, pos, childPosition); } //It means the app is a constructor Expr[] terms = new Expr[expr.args.Count-1]; var terms_0 = GenerateZ3ToExpr((RecordExp)expr.args.ElementAt<FExp>(0), outputAlph, fti); for (int i = 1; i < expr.args.Count; i++) { terms[i-1] = GenerateZ3ExprFromToExpr(expr.args.ElementAt<FExp>(i), outputAlph, children, from, reachedStates, queue, defs, fti, nextStatesL); } return outputAlph.alph.MkTree(expr.func.name.text, terms_0, terms); } } }
//Generates the code for an output of a transduction when the expression is an Expr private static bool PrintOutputTree(List<FastToken> children, AppExp ex, String range, StringBuilder sb, bool isapplied) { if (ex.IsTranDef) { //We hit the new function invocation sb.Append(ex.func.name); PrintOutputTree(children, ex.args[0], range, sb, true); return true; } else { //The function symbol is a constructor in the output alphabet //Create a new Tree of the result kind based on the current function arity sb.Append("Tree" + range + ".MakeTree(" + range + "." + ex.func.name); foreach (var att in ((RecordExp)ex.args[0]).args) { sb.Append(", "); PrintExpr(children, att, sb); } sb.Append(", new Tree" + range + "[" + (ex.func.arity - 1) + "]{"); int i = 0; foreach (var node in ex.args) { if (i == 0) { } else { if (i == 1) { PrintOutputTree(children, node, range, sb, false); } else { sb.Append(", "); PrintOutputTree(children, node, range, sb, false); } } i++; } sb.Append("}"); sb.Append(")"); return true; } }
//Generates the code for an AppExpr expression private static bool PrintExpr(List<FastToken> children, AppExp ex, StringBuilder sb) { sb.Append("("); switch (ex.func.name.text) { case ("="): { PrintExpr(children, ex.args[0], sb); sb.Append(" == "); PrintExpr(children, ex.args[1], sb); break; } case ("and"): { for (int i = 0; i < ex.func.arity; i++) { if (i == 0) { PrintExpr(children, ex.args[i], sb); } else { sb.Append(" && "); PrintExpr(children, ex.args[i], sb); } } break; } case ("xor"): { for (int i = 0; i < ex.func.arity; i++) { if (i == 0) { PrintExpr(children, ex.args[i], sb); } else { sb.Append(" ^ "); PrintExpr(children, ex.args[i], sb); } } break; } case ("not"): { sb.Append("!"); PrintExpr(children, ex.args[0], sb); break; } case ("or"): { for (int i = 0; i < ex.func.arity; i++) { if (i == 0) { PrintExpr(children, ex.args[i], sb); } else { sb.Append(" || "); PrintExpr(children, ex.args[i], sb); } } break; } case ("=>"): { sb.Append("(!"); PrintExpr(children, ex.args[0], sb); sb.Append(")"); sb.Append(" || "); PrintExpr(children, ex.args[1], sb); break; } case ("+"): { for (int i = 0; i < ex.func.arity; i++) { if (i == 0) { PrintExpr(children, ex.args[i], sb); } else { sb.Append(" + "); PrintExpr(children, ex.args[i], sb); } } break; } case ("/"): { for (int i = 0; i < ex.func.arity; i++) { if (i == 0) { PrintExpr(children, ex.args[i], sb); } else { sb.Append(" / "); PrintExpr(children, ex.args[i], sb); } } break; } case ("-"): { for (int i = 0; i < ex.func.arity; i++) { if (i == 0) { PrintExpr(children, ex.args[i], sb); } else { sb.Append(" - "); PrintExpr(children, ex.args[i], sb); } } break; } case ("*"): { for (int i = 0; i < ex.func.arity; i++) { if (i == 0) { PrintExpr(children, ex.args[i], sb); } else { sb.Append(" * "); PrintExpr(children, ex.args[i], sb); } } break; } case ("<"): { PrintExpr(children, ex.args[0], sb); sb.Append(" < "); PrintExpr(children, ex.args[1], sb); break; } case ("<="): { PrintExpr(children, ex.args[0], sb); sb.Append(" <= "); PrintExpr(children, ex.args[1], sb); break; } case (">"): { PrintExpr(children, ex.args[0], sb); sb.Append(" > "); PrintExpr(children, ex.args[1], sb); break; } case (">="): { PrintExpr(children, ex.args[0], sb); sb.Append(" >= "); PrintExpr(children, ex.args[1], sb); break; } case ("mod"): { PrintExpr(children, ex.args[0], sb); sb.Append(" % "); PrintExpr(children, ex.args[1], sb); break; } case ("if"): { PrintExpr(children, ex.args[0], sb); sb.Append(" ? "); PrintExpr(children, ex.args[1], sb); sb.Append(" : "); PrintExpr(children, ex.args[2], sb); break; } default: { if (ex.IsLangDef) { PrintExpr(children, ex.args[0], sb); sb.Append("." + ex.func.name.text + "()"); } else{ sb.Append(ex.func.name.text + "("); PrintExpr(children, ex.args[0], sb); sb.Append(")"); } break; } } sb.Append(")"); return true; }
//Compute all the iterators necessary to generate a particular output of a transduction when expr is AppExpr private static bool ComputeIterators(AppExp ex, String range, StringBuilder sb, bool isApplied) { if (ex.IsTranDef) { List<String> t = new List<String>(); t.Add(ex.func.name.text); iterCases.Insert(0, t); return ComputeIterators((Variable)ex.args[0], range, sb, true); } else { int i = 0; foreach (var node in ex.args) { if (i != 0) ComputeIterators(node, range, sb, false); i++; } return true; } }