예제 #1
0
        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);
        }
예제 #2
0
        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");
            }
        }