public static IEnumerable<object> EvalTacnyExpression(ProofState state, Expression expr) { Contract.Requires<ArgumentNullException>(state != null, "state"); Contract.Requires<ArgumentNullException>(expr != null, "expr"); if(expr is NameSegment) { var ns = (NameSegment)expr; if(state.ContainTacnyVal(ns.Name)) { yield return state.GetTacnyVarValue(ns.Name); } else { yield return ns; } } else if(expr is ApplySuffix) { var aps = (ApplySuffix)expr; if(state.IsTacticCall(aps)) { /* var us = new UpdateStmt(aps.tok, aps.tok, new List<Expression>() { aps.Lhs }, new List<AssignmentRhs>() { new ExprRhs(aps) }); foreach(var item in ApplyNestedTactic(state, state.DafnyVars(), us).Select(x => x.GetGeneratedCode())) { yield return item; } */ } else if(aps.Lhs is ExprDotName) { foreach(var item in EvalTacnyExpression(state, aps.Lhs)) { if(item is Expression) { yield return new ApplySuffix(aps.tok, (Expression)item, aps.Args); } else { Contract.Assert(false, "Unexpected ExprNotName case"); } } } else { // get the keyword of this application string sig = Util.GetSignature(aps); // Try to evaluate as tacny expression // using reflection find all classes that extend EAtomic var types = Assembly.GetAssembly(typeof(EAtomic.EAtomic)) .GetTypes() .Where(t => t.IsSubclassOf(typeof(EAtomic.EAtomic))); foreach(var eType in types) { var eatomInst = Activator.CreateInstance(eType) as EAtomic.EAtomic; if(sig == eatomInst?.Signature) { //TODO: validate input countx var enumerable = eatomInst?.Generate(aps, state); if(enumerable != null) foreach(var item in enumerable) { yield return item; yield break; } } } // if we reached this point, rewrite the apply suffix foreach(var item in EvalTacnyExpression(state, aps.Lhs)) { if(!(item is NameSegment)) { //TODO: warning } else { var argList = new List<Expression>(); foreach(var arg in aps.Args) { foreach(var result in EvalTacnyExpression(state, arg)) { if(result is Expression) argList.Add(result as Expression); else argList.Add(Util.VariableToExpression(result as IVariable)); break; } } yield return new ApplySuffix(aps.tok, aps.Lhs, argList); } } } } else if(expr is ExprDotName) { var edn = (ExprDotName)expr; var ns = edn.Lhs as NameSegment; if(ns != null && state.ContainDafnyVar(ns)) { var newLhs = state.GetTacnyVarValue(ns); var lhs = newLhs as Expression; if(lhs != null) yield return new ExprDotName(edn.tok, lhs, edn.SuffixName, edn.OptTypeArguments); } yield return edn; } else if(expr is UnaryOpExpr) { var op = (UnaryOpExpr)expr; foreach(var result in EvalTacnyExpression(state, op.E)) { switch(op.Op) { case UnaryOpExpr.Opcode.Cardinality: if(!(result is IEnumerable)) { var resultExp = result is IVariable ? Util.VariableToExpression(result as IVariable) : result as Expression; yield return new UnaryOpExpr(op.tok, op.Op, resultExp); } else { var enumerator = result as IList; if(enumerator != null) yield return new Dafny.LiteralExpr(op.tok, enumerator.Count); } yield break; case UnaryOpExpr.Opcode.Not: if(result is Dafny.LiteralExpr) { var lit = (Dafny.LiteralExpr)result; if(lit.Value is bool) { // inverse the bool value yield return new Dafny.LiteralExpr(op.tok, !(bool)lit.Value); } else { Contract.Assert(false); //TODO: error message } } else { var resultExp = result is IVariable ? Util.VariableToExpression(result as IVariable) : result as Expression; yield return new UnaryOpExpr(op.tok, op.Op, resultExp); } yield break; default: Contract.Assert(false, "Unsupported Unary Operator"); yield break; } } } else if(expr is DisplayExpression) { var dexpr = (DisplayExpression)expr; if(dexpr.Elements.Count == 0) { yield return dexpr.Copy(); } else { foreach(var item in EvalDisplayExpression(state, dexpr)) { yield return item; } } } else { yield return expr; } }
public static IEnumerable <object> EvalTacnyExpression(ProofState state, Expression expr) { Contract.Requires <ArgumentNullException>(state != null, "state"); Contract.Requires <ArgumentNullException>(expr != null, "expr"); if (expr is NameSegment) { var ns = (NameSegment)expr; if (state.ContainTacnyVal(ns.Name)) { yield return(state.GetTacnyVarValue(ns.Name)); } else { yield return(ns); } } else if (expr is ApplySuffix) { var aps = (ApplySuffix)expr; if (state.IsTacticCall(aps)) { /* * var us = new UpdateStmt(aps.tok, aps.tok, new List<Expression>() { aps.Lhs }, * new List<AssignmentRhs>() { new ExprRhs(aps) }); * foreach(var item in ApplyNestedTactic(state, state.DafnyVars(), us).Select(x => x.GetGeneratedCode())) { * yield return item; * } */ } else if (aps.Lhs is ExprDotName) { foreach (var item in EvalTacnyExpression(state, aps.Lhs)) { if (item is Expression) { yield return(new ApplySuffix(aps.tok, (Expression)item, aps.Args)); } else { Contract.Assert(false, "Unexpected ExprNotName case"); } } } else { // get the keyword of this application string sig = Util.GetSignature(aps); // Try to evaluate as tacny expression // using reflection find all classes that extend EAtomic var types = Assembly.GetAssembly(typeof(EAtomic.EAtomic)) .GetTypes() .Where(t => t.IsSubclassOf(typeof(EAtomic.EAtomic))); foreach (var eType in types) { var eatomInst = Activator.CreateInstance(eType) as EAtomic.EAtomic; if (sig == eatomInst?.Signature) { //TODO: validate input countx var enumerable = eatomInst?.Generate(aps, state); if (enumerable != null) { foreach (var item in enumerable) { yield return(item); yield break; } } } } // if we reached this point, rewrite the apply suffix foreach (var item in EvalTacnyExpression(state, aps.Lhs)) { if (!(item is NameSegment)) { //TODO: warning } else { var argList = new List <Expression>(); foreach (var arg in aps.Args) { foreach (var result in EvalTacnyExpression(state, arg)) { if (result is Expression) { argList.Add(result as Expression); } else { argList.Add(Util.VariableToExpression(result as IVariable)); } break; } } yield return(new ApplySuffix(aps.tok, aps.Lhs, argList)); } } } } else if (expr is ExprDotName) { var edn = (ExprDotName)expr; var ns = edn.Lhs as NameSegment; if (ns != null && state.ContainDafnyVar(ns)) { var newLhs = state.GetTacnyVarValue(ns); var lhs = newLhs as Expression; if (lhs != null) { yield return(new ExprDotName(edn.tok, lhs, edn.SuffixName, edn.OptTypeArguments)); } } yield return(edn); } else if (expr is UnaryOpExpr) { var op = (UnaryOpExpr)expr; foreach (var result in EvalTacnyExpression(state, op.E)) { switch (op.Op) { case UnaryOpExpr.Opcode.Cardinality: if (!(result is IEnumerable)) { var resultExp = result is IVariable ? Util.VariableToExpression(result as IVariable) : result as Expression; yield return(new UnaryOpExpr(op.tok, op.Op, resultExp)); } else { var enumerator = result as IList; if (enumerator != null) { yield return(new Dafny.LiteralExpr(op.tok, enumerator.Count)); } } yield break; case UnaryOpExpr.Opcode.Not: if (result is Dafny.LiteralExpr) { var lit = (Dafny.LiteralExpr)result; if (lit.Value is bool) { // inverse the bool value yield return(new Dafny.LiteralExpr(op.tok, !(bool)lit.Value)); } else { Contract.Assert(false); //TODO: error message } } else { var resultExp = result is IVariable?Util.VariableToExpression(result as IVariable) : result as Expression; yield return(new UnaryOpExpr(op.tok, op.Op, resultExp)); } yield break; default: Contract.Assert(false, "Unsupported Unary Operator"); yield break; } } } else if (expr is DisplayExpression) { var dexpr = (DisplayExpression)expr; if (dexpr.Elements.Count == 0) { yield return(dexpr.Copy()); } else { foreach (var item in EvalDisplayExpression(state, dexpr)) { yield return(item); } } } else { yield return(expr); } }