internal override void CheckTransformation(HashSet<string> subs, AlphabetDef domAlph, AlphabetDef rangeAlph, FastPgm pgm) { foreach (var expr in args) expr.CheckTransformation(subs, domAlph, rangeAlph, pgm); var constsAndFuns = new Dictionary<string, FastSort>(); foreach (var def in pgm.defs) { if (def.kind == DefKind.Function) constsAndFuns.Add(((FunctionDef)def).name.text, ((FunctionDef)def).sort); if (def.kind == DefKind.Const) constsAndFuns.Add(((ConstDef)def).name.text, ((ConstDef)def).sort); } bool ok = CheckStandardOps(constsAndFuns); if (!ok) { string f = func.name.text; if (this is RecordExp) // --- record constrctor --- { if (rangeAlph.attrSort.fields.Count != args.Count) throw new FastParseException(func.name.Location, string.Format("unxecpected nr of attribute fields {0}, expecting {1}", args.Count, rangeAlph.attrSort.fields.Count)); for (int i = 0; i < args.Count; i++) { if (args[i].sort.name.text != rangeAlph.attrSort.fields[i].Value.name.text) throw new FastParseException(args[i].sort.name.Location, string.Format("invalid argument sort '{0}' of field '{1}', expecting sort '{2}'", args[i].sort.name.text, rangeAlph.attrSort.fields[i].Key.text, rangeAlph.attrSort.fields[i].Value.name.text)); } _sort = rangeAlph.attrSort; } else if (rangeAlph.symbols.Exists(_f => func.name.text == _f.name.text)) // --- tree constructor --- { if (!rangeAlph.IsValidSymbol(func.name, func.arity)) { throw new FastParseException(func.name.Location, string.Format("wrong number of arguments of constructor '{0}'", func.name)); } for (int i = 1; i < args.Count; i++) { if (args[i].sort.name.text != rangeAlph.id.text) throw new FastParseException(func.name.Location, string.Format("unexected argument of function '{0}'", func.name)); } _sort = rangeAlph.sort; } else { var def = pgm.FindDef(func.name); if (def.kind == DefKind.Trans) { if (args.Count != 1) throw new FastParseException(func.name.Location, string.Format("transduction '{0}' is unary", func.name)); var tdef = def as TransDef; if (tdef.domain.name.text != args[0].sort.name.text) throw new FastParseException(args[0].sort.name.Location, string.Format("transduction '{0}' has unexpected argument of sort '{1}', expecting sort '{2}'", func.name, args[0].sort.name.text, tdef.domain.name.text)); _sort = tdef.range; isTranDef = true; if (args[0].kind == FExpKind.App) throw new FastParseException(func.name.Location, string.Format("Transduction '{0}' cannot be nested inside another Transduction", func.name)); } else { throw new FastParseException(func.name.Location, string.Format("ID '{0}' is not a Transduction", func.name)); } } } }
internal override void CheckTransformation(HashSet<string> subs, AlphabetDef domAlph, AlphabetDef rangeAlph, FastPgm pgm) { }
internal override void CheckSubtreeGuard(Dictionary<string, FastSort> subs, AlphabetDef alph, FastPgm pgm) { Predicate<FExp> IsNotBool = (x => { return x.sort == null || x.sort.kind != FastSortKind.Bool; }); foreach (var expr in args) expr.CheckSubtreeGuard(subs, alph, pgm); if (func.name.text != "and" && func.name.text != "or" && !pgm.defs.Exists(d => d.id.text == func.name.text && d.kind == DefKind.Lang && ((LangDef)d).domain.name.text == alph.sort.name.text)) throw new FastParseException(func.name.Location, string.Format("illeagal identifier '{0}'", func.name.text)); if ((func.name.text == "and" || func.name.text == "or") && args.Exists(IsNotBool)) throw new FastParseException(func.name.Location, string.Format("arguments of '{0}' must be Boolean", func.name.text)); if (pgm.defs.Exists(d => d.id.text == func.name.text && d.kind == DefKind.Lang && ((LangDef)d).domain.name.text == alph.sort.name.text)) isLangDef = true; _sort = FastSort.Bool; }
internal virtual void SetConstructorSort(AlphabetDef alph) { }
internal override void CheckSubtreeGuard(Dictionary<string, FastSort> subs, AlphabetDef alph, FastPgm pgm) { }
internal override void CheckTransformation(HashSet<string> subs, AlphabetDef domAlph, AlphabetDef rangeAlph, FastPgm pgm) { if (subs.Contains(this.token.text)) { _sort = domAlph.sort; } else { //Check if the current variable is a constant FastSort s; foreach (var def in pgm.defs) { if (def.kind == DefKind.Const && ((ConstDef)def).id.text == this.token.text) { s = ((ConstDef)def).sort; if (s == null || (_sort != null && s.name.text != _sort.name.text)) throw new FastParseException(token.Location, string.Format("unexpected identifier '{0}'", token.text)); _sort = s; return; } } //Oterwise look for attr symbol if (Array.Exists(rangeAlph.symbols.ToArray(), x => x.name.text == this.token.text)) throw new FastParseException(this.token.Location, string.Format("the constructor '{0}' is not applied to a tuple", this.token.text)); if (domAlph == null) throw new FastParseException(this.token.Location, string.Format("the variable '{0}' is not defined", this.token.text)); s = domAlph.attrSort.getSort(this.token); if (s == null || (_sort != null && s.name.text != _sort.name.text)) throw new FastParseException(token.Location, string.Format("unexpected identifier '{0}'", token.text)); _sort = s; } }
//Generate the C# corresponding to the constructor of a Tree class, the MakeTree method and an accessor for the children private static bool GenerateConstructor(StringBuilder sb, AlphabetDef aDef) { sb.Append("private Tree" + aDef.id.text + "(" + aDef.id.text + " symbol"); foreach (var s in aDef.attrSort.fieldSorts) { if (s.Value.kind == FastSortKind.Real) { sb.Append(", double " + s.Key); } else { sb.Append(", " + s.Value.name + " " + s.Key); } } sb.AppendLine(", Tree" + aDef.id.text + "[] children){"); sb.AppendLine("this.symbol=symbol;"); foreach (var s in aDef.attrSort.fieldSorts) { sb.AppendLine("this." + s.Key + "=" + s.Key + ";"); } sb.AppendLine("this.children=children;"); sb.AppendLine("this.langsLabel = new HashSet<string>();"); sb.AppendLine("ComputeLabel();"); sb.AppendLine("}"); sb.AppendLine(); sb.AppendLine("public Tree" + aDef.id.text + " this [int _i]{get { return children[_i]; }}"); sb.AppendLine(); sb.Append("public static Tree" + aDef.id.text + " MakeTree(" + aDef.id.text + " symbol"); foreach (var s in aDef.attrSort.fieldSorts) { if (s.Value.kind == FastSortKind.Real) { sb.Append(", double " + s.Key); } else { sb.Append(", " + s.Value.name + " " + s.Key); } } sb.AppendLine(", Tree" + aDef.id.text + "[] children){"); sb.AppendLine("if(children.Length==" + aDef.id.text + "Util.getRank(symbol)){"); sb.Append("Tree" + aDef.id.text + " t = new Tree" + aDef.id.text + "(symbol"); foreach (var s in aDef.attrSort.fieldSorts) { sb.Append(", " + s.Key); } sb.AppendLine(", children);"); sb.AppendLine("return t;"); sb.AppendLine("}"); sb.AppendLine("return null;"); sb.AppendLine("}"); sb.AppendLine(); sb.AppendLine(); return true; }
//Generate the C# corresponding to a particular tree class (inferred from the alphabets) private static bool GenerateTreeClass(List<Def> defs, StringBuilder sb, AlphabetDef aDef) { sb.AppendLine("partial class Tree" + aDef.id.text + "{"); foreach (var s in aDef.attrSort.fieldSorts) if (s.Value.kind == FastSortKind.Real) sb.AppendLine("double " + s.Key + ";"); else sb.AppendLine(s.Value.name + " " + s.Key + ";"); sb.AppendLine(); sb.AppendLine(aDef.id.text + " symbol;"); sb.AppendLine(); sb.AppendLine("HashSet<string> langsLabel;"); sb.AppendLine("Tree" + aDef.id.text + "[] children;"); sb.AppendLine(); GenerateConsts(defs, sb); GenerateFuns(defs, sb); GenerateTrees(defs, sb, aDef); GenerateConstructor(sb, aDef); GenerateLookahead(defs, sb, aDef); GenerateLanguagesAndTransductions(defs, sb, aDef); sb.AppendLine("}"); sb.AppendLine(); return true; }
//Generate C# for all the consts in the program private static bool GenerateTrees(List<Def> defs, StringBuilder sb, AlphabetDef aDef) { foreach (var def in defs) switch (def.kind) { case (DefKind.Def): { if(((DefDef)def).ddkind == DefDefKind.Tree) if (((TreeDef)def).domain.name.text.Equals(aDef.id.text)) if (!GenerateTree((TreeDef)def, sb)) return false; break; } } return true; }
//Generates the code for a particular Transduction (def) in a particular class (aDef) private static bool GenerateTransduction(TransDef def, StringBuilder sb, AlphabetDef aDef) { sb.AppendLine((def.isPublic ? "public" : "private") + " IEnumerable<Tree" + def.range.name + "> " + def.func.name + "(){"); List<FastToken> children; foreach (var ruleCase in def.cases) { children = ruleCase.pat.children; //Check that the constructor is the one of the rule sb.AppendLine("if(this.symbol==" + aDef.id + "." + ruleCase.pat.symbol + "){"); //Check the where condition sb.Append("if("); PrintExpr(children, ruleCase.where, sb); sb.AppendLine("){"); //Compute the given subsets int childPos = 0; string childName, langName; HashSet<string>[] givenElelements = new HashSet<string>[children.Count]; for (int i = 0; i < givenElelements.Length; i++) givenElelements[i] = new HashSet<string>(); //Populate given elements foreach (var giv in ruleCase.given) { if (giv.kind == FExpKind.App) { langName = ((AppExp)giv).func.name.text; childName = ((AppExp)giv).args[0].token.text; childPos = 0; foreach (var child in children) { if (child.text == childName) break; childPos++; } //Array of sets of langauges if (!givenElelements[childPos].Contains(langName)) givenElelements[childPos].Add(langName); } } //Check given subsets are included in labeling bool needsComma; int givenUsed = 0; for (int i = 0; i < givenElelements.Length; i++) { if (givenElelements[i].Count != 0) { sb.Append("if(this.children[" + i + "].langsLabel.IsSupersetOf(new string[] {"); needsComma = false; foreach (var lang in givenElelements[i]) { if (needsComma) sb.Append(", "); sb.Append("\"" + lang + "\""); needsComma = true; } sb.Append("})){"); sb.AppendLine(); givenUsed++; } } iterCases = new List<List<string>>(); ComputeIterators((AppExp)ruleCase.to, def.range.name.text, sb, false); RemoveDuplicates(); PrintIterators(children, def.range.name.text, sb); sb.Append("yield return "); PrintOutputTree(children, (AppExp)ruleCase.to, def.range.name.text, sb, false); sb.Append(";"); //Close all parenthesis for (int j = 0; j < iterCases.Count; j++) sb.AppendLine("}"); for (int i = 0; i < givenUsed; i++) sb.AppendLine("}"); sb.AppendLine("}"); sb.AppendLine("}"); } //FOR EMPTY RULES CASES sb.AppendLine("if(false) yield return null;"); sb.AppendLine("}"); sb.AppendLine(); return true; }
//Generate CSharp for a definition of type TransDefDef private static bool GenerateTransductionDefinition(TransDefDef def, StringBuilder sb, AlphabetDef aDef) { int x; sb.AppendLine("public IEnumerable<Tree" + def.range.name + "> " + def.func.name + "(){"); GenerateDefExpr(def.expr, sb, "this", 0, out x); sb.AppendLine("}"); return true; }
//Generate the Lookahed computation for a particular language definition private static bool GenerateLookaheadExpr(LangDef def, StringBuilder sb, AlphabetDef aDef) { List<FastToken> children; foreach (var ruleCase in def.cases) { children = ruleCase.pat.children; sb.AppendLine("if(this.symbol==" + aDef.id.text + "." + ruleCase.pat.symbol + "){"); sb.Append("if("); PrintExpr(children, ruleCase.where, sb); sb.AppendLine("){"); #region Compute the given subsets int childPos = 0; string childName, langName; HashSet<string>[] givenElelements = new HashSet<string>[children.Count]; for (int i = 0; i < givenElelements.Length; i++) givenElelements[i] = new HashSet<string>(); #endregion #region Populate given elements foreach (var giv in ruleCase.given) { if (giv.kind == FExpKind.App) { langName = ((AppExp)giv).func.name.text; childName = ((AppExp)giv).args[0].token.text; childPos = 0; foreach (var child in children) { if (child.text == childName) break; childPos++; } //Array of sets of langauges if (!givenElelements[childPos].Contains(langName)) givenElelements[childPos].Add(langName); } } #endregion #region Compute lookahead bool needsComma; int givenUsed = 0; for (int i = 0; i < givenElelements.Length; i++) { if (givenElelements[i].Count != 0) { sb.Append("if(this.children[" + i + "].langsLabel.IsSupersetOf(new string[] {"); needsComma = false; foreach (var lang in givenElelements[i]) { if (needsComma) sb.Append(", "); sb.Append("\"" + lang + "\""); needsComma = true; } sb.Append("})){"); sb.AppendLine(); givenUsed++; } } sb.AppendLine("this.langsLabel.Add(\"" + def.func.name.text + "\");"); #endregion for (int i = 0; i < givenUsed; i++) sb.AppendLine("}"); sb.AppendLine("}"); sb.AppendLine("}"); } sb.AppendLine(); return true; }
//Generate the Lookahed computation for the tree private static bool GenerateLookahead(List<Def> defs, StringBuilder sb, AlphabetDef aDef) { sb.AppendLine("private void ComputeLabel(){"); foreach (var def in defs) { switch (def.kind) { case (DefKind.Lang): { if ((((LangDef)def).domain.name.text).Equals(aDef.id.text)) if (!GenerateLookaheadExpr((LangDef)def, sb, aDef)) return false; break; } } } sb.AppendLine("}"); return true; }
//Generates all the languages and transductions of a particular tree class (correposnding to aDef) private static bool GenerateLanguagesAndTransductions(List<Def> defs, StringBuilder sb, AlphabetDef aDef) { foreach (var def in defs) { switch (def.kind) { case (DefKind.Lang): { if (((LangDef)def).isPublic) if (((LangDef)def).domain.name.text.Equals(aDef.id.text)) if (!GenerateLanguage((LangDef)def, sb)) return false; break; } case (DefKind.Trans): { if (((TransDef)def).domain.name.text.Equals(aDef.id.text)) if (!GenerateTransduction((TransDef)def, sb, aDef)) return false; break; } case (DefKind.Def): { if (((DefDef)def).ddkind == DefDefKind.Trans) { if (((TransDefDef)def).domain.name.text.Equals(aDef.id.text)) if (!GenerateTransductionDefinition((TransDefDef)def, sb, aDef)) return false; } else { if (((DefDef)def).ddkind == DefDefKind.Lang) if (((LangDefDef)def).domain.name.text.Equals(aDef.id.text)) if (!GenerateLanguageDefinition((LangDefDef)def, sb)) return false; } break; } } } return true; }
internal override void SetConstructorSort(AlphabetDef alph) { for (int i=0; i < args.Count; i++) args[i].SetConstructorSort(alph); if (func.name.Kind == Tokens.ID && alph.IsValidSymbol(func.name, func.arity)) { func.alph = alph; func.isConstructor = true; } }
internal abstract void CheckSubtreeGuard(Dictionary<string, FastSort> subs, AlphabetDef alph, FastPgm pgm);
internal override void CheckSubtreeGuard(Dictionary<string, FastSort> subs, AlphabetDef alph, FastPgm pgm) { //Double check if (!subs.ContainsKey(token.text)) throw new FastParseException(token.Location, string.Format("unexpected identifier '{0}', expecting a subtree parameter", token.text)); else _sort = subs[token.text]; }
internal abstract void CheckTransformation(HashSet<string> subs, AlphabetDef domAlph, AlphabetDef rangeAlph, FastPgm pgm);
public RankedAlphabetSort(AlphabetDef def, Z3Provider z3p, FastTransducerInstance fti) { this.z3p = z3p; List<string> alphSymbols = new List<string>(); List<int> alphArities = new List<int>(); // Create list of symbols with corresponding arities foreach (var sym in def.symbols) { alphSymbols.Add(sym.name.text); alphArities.Add(sym.arity - 1); } alphFieldsSorts = new List<Sort>(); tupleKeys = new List<String>(); foreach (var field in def.attrSort.fieldSorts) { tupleKeys.Add(field.Key); switch (field.Value.kind) { case (FastSortKind.Char): { alphFieldsSorts.Add(z3p.CharSort); break; } case (FastSortKind.Real): { alphFieldsSorts.Add(z3p.RealSort); break; } case (FastSortKind.Bool): { alphFieldsSorts.Add(z3p.BoolSort); break; } case (FastSortKind.Int): { alphFieldsSorts.Add(z3p.IntSort); break; } case (FastSortKind.String): { alphFieldsSorts.Add(z3p.MkListSort(z3p.CharSort)); break; } case (FastSortKind.Tree): { foreach (var enumSort in fti.enums) { if (enumSort.name == field.Value.name.text) { alphFieldsSorts.Add(enumSort.sort); break; } } break; } } } this.tupleName = "$" + def.id.text; this.tupleTests = new FuncDecl[alphFieldsSorts.Count]; var tupsymbs = new Symbol[tupleKeys.Count]; int j = 0; foreach(var v in tupleKeys){ tupsymbs[j]= z3p.Z3.MkSymbol(v); j++; } var tup = z3p.Z3.MkTupleSort(z3p.Z3.MkSymbol(tupleName), tupsymbs, alphFieldsSorts.ToArray()); this.tupleSort = tup; this.tupleFuncDec = tup.MkDecl; this.tupleTests = tup.FieldDecls; this.alph = z3p.TT.MkRankedAlphabet(def.id.text, this.tupleSort, alphSymbols.ToArray(), alphArities.ToArray()); this.alphName = def.id.text; this.alphSort = this.alph.AlphabetSort; }
//Generate the C# corresponding to a particular alphabet (using enum) private static bool GenerateAlphabet(AlphabetDef def, StringBuilder sb) { //Generate enum for alphabet sb.Append("public enum " + def.id.text + " {"); foreach (var sym in def.symbols) { if (def.symbols.First().Equals(sym)) { sb.Append(sym.name); } else { sb.Append(", " + sym.name); } } sb.AppendLine("}"); sb.AppendLine(); sb.AppendLine("class " + def.id.text + "Util {"); sb.AppendLine("public static int getRank(" + def.id.text + " el){"); sb.AppendLine("switch(el){"); foreach (var sym in def.symbols) { sb.AppendLine("case(" + def.id.text + "." + sym.name + "):{"); sb.AppendLine("return " + (sym.arity - 1) + ";"); sb.AppendLine("}"); } sb.AppendLine("}"); sb.AppendLine("return -1;"); sb.AppendLine("}"); sb.AppendLine("}"); sb.AppendLine(); return true; }