public ParserType Visit(ParserBinder binder) { // idea: copy our current context, add the new bound variable, visit, remove bound variable // then merge back into our current context var newCtx = CloneContext(); newCtx[binder.VariableName] = binder.VariableType; var visitor = new TypeVisitor(newCtx); ParserType subExpr = binder.Expr.Accept(visitor); newCtx.Remove(binder.VariableName); JoinContext(newCtx); if (subExpr.Typ != ParserTypeEnum.Logic || !(subExpr is ParserLogicType)) { throw new ArgumentException("Bound subexpression must be a logical expression. Type: " + subExpr.ToString()); } var logicalExpr = subExpr as ParserLogicType; switch (binder.OpType) { case ParserBinderType.Exists: if ((binder.VariableType.Flags & ParserTypeFlags.Overt) == 0) { throw new ArgumentException("Exists can only bind overt variables"); } ParserType logicType = new ParserLogicType(); binder.Type = logicType; return(logicType); case ParserBinderType.Lambda: ParserType newType = new ParserLambdaType(binder.VariableType); binder.Type = newType; return(newType); case ParserBinderType.The: if (binder.VariableType is ParserNumType) { ParserType numType = new ParserNumType(); binder.Type = numType; return(numType); } else { throw new ArgumentException("'The' binder can only bind Nat types"); } default: throw new ArgumentException("Unknown Binder"); } }
public Expression Visit(ParserBinder binder) { Expression subExpr = binder.Expr.Accept(this); switch (binder.OpType) { case ParserBinderType.Exists: return(new NumExists(binder.VariableName, subExpr as LogicExpression)); case ParserBinderType.Lambda: return(new LambdaExpression(binder.VariableName, subExpr as LogicExpression)); case ParserBinderType.The: return(new NumThe(binder.VariableName, subExpr as LogicExpression)); default: break; } throw new ArgumentException("Unknown binder"); }