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 CalcSort(Func<FastToken, FastSort> context, FastPgm program) { foreach (var arg in this.args) arg.CalcSort(context, program); if (func.alph != null) //func is a costructor { if (args.Count != func.arity) throw new FastParseException(func.name.Location, string.Format("Invalid use of constructor '{0}' of alphabet '{1}', wrong nr of arguments", func.name.text, func.alph.sort)); if (!args[0].sort.Equals(func.alph.attrSort)) throw new FastParseException(func.name.Location, string.Format("Invalid use of constructor '{0}' of alphabet '{1}', wrong attribute sort", func.name.text, func.alph.sort)); for (int i = 1; i < args.Count; i++) if (!args[i].sort.Equals(func.alph.sort)) throw new FastParseException(func.name.Location, string.Format("Invalid use of constructor '{0}' of alphabet '{1}', subtree nr {2} has unexpected sort '{3}'", func.name.text, func.alph.sort, i, args[i].sort)); _sort = func.alph.sort; return; } switch (func.name.Kind) { case (Tokens.EQ): case (Tokens.NE): { if (this.args.Count != 2) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 2 arguments"); if (!args[0].sort.name.text.Equals(args[1].sort.name.text)) throw new FastParseException(func.name.Location, "Both arguments must have the same sort"); _sort = FastSort.Bool; break; } case (Tokens.LE): case (Tokens.GE): case (Tokens.LT): case (Tokens.GT): { if (this.args.Count != 2) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 2 arguments"); if (!args[0].sort.name.text.Equals(args[1].sort.name.text)) throw new FastParseException(func.name.Location, "Both arguments must have the same sort"); if (!(args[0].sort.kind == FastSortKind.Char || args[0].sort.kind == FastSortKind.Int || args[0].sort.kind == FastSortKind.Real)) throw new FastParseException(func.name.Location, "Arguments have wrong sort, expecting numeric sort"); _sort = FastSort.Bool; break; } case (Tokens.AND): case (Tokens.OR): case (Tokens.IMPLIES): { if (this.args.Count != 2) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 2 arguments"); if (!args[0].sort.name.text.Equals(args[1].sort.name.text)) throw new FastParseException(func.name.Location, "Both arguments must have the same sort"); if (!(args[0].sort.kind == FastSortKind.Bool)) throw new FastParseException(func.name.Location, "Arguments must be Boolean"); _sort = FastSort.Bool; break; } case (Tokens.PLUS): case (Tokens.MINUS): case (Tokens.TIMES): case (Tokens.DIV): { if (this.args.Count != 2) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 2 arguments"); if (!args[0].sort.name.text.Equals(args[1].sort.name.text)) throw new FastParseException(func.name.Location, "Both arguments must have the same sort"); if (!(args[0].sort.kind == FastSortKind.Char || args[0].sort.kind == FastSortKind.Int || args[0].sort.kind == FastSortKind.Real)) throw new FastParseException(func.name.Location, "Wrong argument sorts"); _sort = args[0].sort; break; } case (Tokens.MOD): case (Tokens.SHL): case (Tokens.SHR): case (Tokens.BVAND): case (Tokens.BAR): case (Tokens.BVXOR): { if (this.args.Count != 2) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 2 arguments"); if (!args[0].sort.name.text.Equals(args[1].sort.name.text)) throw new FastParseException(func.name.Location, "Both arguments must have the same sort"); if (!(args[0].sort.kind == FastSortKind.Char || args[0].sort.kind == FastSortKind.Int)) throw new FastParseException(func.name.Location, "Wrong argument sorts"); _sort = args[0].sort; break; } case (Tokens.NOT): { if (this.args.Count != 1) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 1 argument"); if (!(args[0].sort.kind == FastSortKind.Bool)) throw new FastParseException(func.name.Location, string.Format("Wrong argument sort, expecting '{0}'",FastSort.Bool.name.text)); _sort = args[0].sort; break; } case (Tokens.BVNOT): { if (this.args.Count != 1) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 1 argument"); if (!(args[0].sort.kind == FastSortKind.Char || args[0].sort.kind == FastSortKind.Int)) throw new FastParseException(func.name.Location, "Wrong argument sort, expecting 'char' or 'int'"); _sort = args[0].sort; break; } case (Tokens.COMPLEMENT): { if (this.args.Count != 1) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 1 argument"); if (!(args[0].sort.kind == FastSortKind.Tree)) throw new FastParseException(func.name.Location, "Wrong argument sort, expecting a tree sort"); _sort = args[0].sort; break; } case (Tokens.INTERSECT): case (Tokens.UNION): { if (this.args.Count != 2) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 2 arguments"); if (!(args[0].sort.kind == FastSortKind.Tree && args[1].sort.kind == FastSortKind.Tree)) throw new FastParseException(func.name.Location, "Wrong argument sort, expecting a tree sort"); if (!(args[0].sort.name.Equals(args[1].sort.name))) throw new FastParseException(func.name.Location, "Both arguments must have the same tree sort"); _sort = args[0].sort; break; } case (Tokens.EQ_LANG): { if (this.args.Count != 2) throw new FastParseException(func.name.Location, "Wrong nr of arguments, expecting 2 arguments"); if (!(args[0].sort.kind == FastSortKind.Tree && args[1].sort.kind == FastSortKind.Tree)) throw new FastParseException(func.name.Location, "Wrong argument sort, expecting a tree sort"); if (!(args[0].sort.name.Equals(args[1].sort.name))) throw new FastParseException(func.name.Location, "Both arguments must have the same tree sort"); _sort = FastSort.Bool; break; } case (Tokens.ITE): { if (this.args.Count != 3) throw new FastParseException(func.name.Location, "Wrong nr of arguments of If-Then-Else expression, expecting 3 arguments"); if (!(args[0].sort.kind == FastSortKind.Bool)) throw new FastParseException(func.name.Location, string.Format("If-Then-Else condition has wrong sort '{0}' expecting '{1}'", args[0].sort.name.text, FastSort.Bool.name.text)); if (!(args[1].sort.name.text.Equals(args[2].sort.name.text))) throw new FastParseException(func.name.Location, string.Format("If-Then-Else true and false cases have different sorts '{0}' and '{1}' but must have the same sort", args[1].sort.name.text, args[2].sort.name.text)); _sort = args[1].sort; break; } case (Tokens.ID): { var fdef = program.FindDef(func.name); var tdef = fdef as TransDef; if (tdef != null) { if (1 != args.Count) throw new FastParseException(func.name.Location, string.Format("Transduction '{0}' arity is 1 not {2}", func.name.text, 1, args.Count)); if (!args[0].sort.Equals(tdef.domain)) throw new FastParseException(func.name.Location, string.Format("Transduction '{0}' has domain '{0}' not '{1}'", func.name.text, tdef.domain, args[0].sort)); _sort = tdef.range; isTranDef = true; } else { var ldef = fdef as LangDef; if (ldef != null) { if (1 != args.Count) throw new FastParseException(func.name.Location, string.Format("Acceptor '{0}' arity is 1 not {2}", func.name.text, 1, args.Count)); if (!args[0].sort.Equals(ldef.domain)) throw new FastParseException(func.name.Location, string.Format("Acceptor '{0}' has domain '{0}' not '{1}'", func.name.text, ldef.domain, args[0].sort)); _sort = FastSort.Bool; isLangDef = true; } else { FunctionDef d = fdef as FunctionDef; if (d == null) throw new FastParseException(func.name.Location, string.Format("Unexpected ID '{0}' ", func.name.text)); if (d.inputVariables.Count != args.Count) throw new FastParseException(func.name.Location, string.Format("Function '{0}' arity is {1} not {2}", func.name.text, d.inputVariables.Count, args.Count)); for (int i = 0; i < args.Count; i++) { var expectedSort = d.inputVariables[i].Value; var actualSort = args[i].sort; if (expectedSort.kind != actualSort.kind || !expectedSort.name.text.Equals(actualSort.name.text)) throw new FastParseException(func.name.Location, string.Format("Function '{0}' parameter (#{4}) '{3}' has sort '{1}' not '{2}'", func.name.text, d.inputVariables[i].Key.text, expectedSort.name.text, actualSort.name.text, i + 1)); } _sort = d.outputSort; } } break; } case (Tokens.LBRACKET): //Record constructor { List<KeyValuePair<FastToken, FastSort>> sorts = new List<KeyValuePair<FastToken, FastSort>>(); for (int i = 0; i < args.Count; i++) sorts.Add(new KeyValuePair<FastToken, FastSort>(new FastToken("_" + (1+i).ToString()), args[i].sort)); _sort = new RecordSort(sorts); break; } default: throw new FastParseException(func.name.Location, string.Format("Unexpected function '{0}'", func.name.text)); } }