public ParserType Visit(ParserApp app) { var lambdaType = app.Lambda.Accept(this); var expr = app.Expression.Accept(this); if (!(lambdaType is ParserLambdaType)) { throw new ArgumentException("In an application left expression must be a lambda. Type: " + lambdaType.ToString()); } ParserLambdaType lambda = lambdaType as ParserLambdaType; if (!lambda.InputType.Equivalent(expr)) { throw new ArgumentException(String.Format( "In an application the type of the right expression must match the type of the bound variable " + "Expr type: {0} Variable type: {1}", expr.ToString(), lambda.InputType.ToString())); } ParserType logicType = new ParserLogicType(); app.Type = logicType; return(logicType); }
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 ParserType Visit(ParserStringConstant constant) { switch (constant.Value) { case "T": case "F": ParserType logicType = new ParserLogicType(); constant.Type = logicType; return(logicType); default: throw new ArgumentException("Unknown Constant: " + constant.Value); } }
public ParserType Visit(ParserBinaryOp op) { ParserType leftType = op.Left.Accept(this); ParserType rightType = op.Right.Accept(this); if (leftType.Typ != rightType.Typ) { throw new ArgumentException(String.Format("Types in a binary operation must be the same. Left: {0} Right: {0}", leftType.ToString(), rightType.ToString())); } switch (op.OpType) { case ParserBinaryOpType.Add: if (leftType.Flags.HasFlag(ParserTypeFlags.Number) && leftType.Flags.HasFlag(ParserTypeFlags.Number)) { op.Type = leftType; return(leftType); } else { throw new ArgumentException("Cannot Add these expressions"); } case ParserBinaryOpType.Mul: if (leftType.Flags.HasFlag(ParserTypeFlags.Number) && leftType.Flags.HasFlag(ParserTypeFlags.Number)) { op.Type = leftType; return(leftType); } else { throw new ArgumentException("Cannot Multiply these expressions"); } case ParserBinaryOpType.And: if (leftType.Flags.HasFlag(ParserTypeFlags.Logic) && leftType.Flags.HasFlag(ParserTypeFlags.Logic)) { op.Type = leftType; return(leftType); } else { throw new ArgumentException("Cannot & these expressions"); } case ParserBinaryOpType.Or: if (leftType.Flags.HasFlag(ParserTypeFlags.Logic) && leftType.Flags.HasFlag(ParserTypeFlags.Logic)) { op.Type = leftType; return(leftType); } else { throw new ArgumentException("Cannot | these expressions"); } case ParserBinaryOpType.EQ: if (leftType.Flags.HasFlag(ParserTypeFlags.Discrete) && leftType.Flags.HasFlag(ParserTypeFlags.Discrete)) { ParserType logicType = new ParserLogicType(); op.Type = logicType; return(logicType); } else { throw new ArgumentException("Cannot == these expressions"); } case ParserBinaryOpType.NEQ: if (leftType.Flags.HasFlag(ParserTypeFlags.Hausdorff) && leftType.Flags.HasFlag(ParserTypeFlags.Hausdorff)) { ParserType logicType = new ParserLogicType(); op.Type = logicType; return(logicType); } else { throw new ArgumentException("Cannot != these expressions"); } case ParserBinaryOpType.GT: if (leftType.Flags.HasFlag(ParserTypeFlags.StrictOrder) && leftType.Flags.HasFlag(ParserTypeFlags.StrictOrder)) { ParserType logicType = new ParserLogicType(); op.Type = logicType; return(logicType); } else { throw new ArgumentException("Cannot > these expressions"); } case ParserBinaryOpType.LT: if (leftType.Flags.HasFlag(ParserTypeFlags.StrictOrder) && leftType.Flags.HasFlag(ParserTypeFlags.StrictOrder)) { ParserType logicType = new ParserLogicType(); op.Type = logicType; return(logicType); } else { throw new ArgumentException("Cannot < these expressions"); } case ParserBinaryOpType.GTE: if (leftType.Flags.HasFlag(ParserTypeFlags.LooseOrder) && leftType.Flags.HasFlag(ParserTypeFlags.LooseOrder)) { ParserType logicType = new ParserLogicType(); op.Type = logicType; return(logicType); } else { throw new ArgumentException("Cannot >= these expressions"); } case ParserBinaryOpType.LTE: if (leftType.Flags.HasFlag(ParserTypeFlags.LooseOrder) && leftType.Flags.HasFlag(ParserTypeFlags.LooseOrder)) { ParserType logicType = new ParserLogicType(); op.Type = logicType; return(logicType); } else { throw new ArgumentException("Cannot <= these expressions"); } default: throw new ArgumentException("Unknown Binary Operation"); } }