public static bool IsEqualTo(this TypedTerm first, TypedTerm second)
        {
            if (first.Tag != second.Tag)
            {
                return(false);
            }

            switch (first.Tag)
            {
            case TypedProductions.Universe:
            {
                var universe1 = (TypedTerm.Universe)first;
                var universe2 = (TypedTerm.Universe)second;

                return(universe1.Content.IsEqualTo(universe2.Content));
            }

            case TypedProductions.Type:
            {
                var type1 = (TypedTerm.Type)first;
                var type2 = (TypedTerm.Type)second;

                return(type1.Content.IsEqualTo(type2.Content));
            }

            case TypedProductions.Constructor:
            {
                return(false);
            }

            case TypedProductions.Destructor:
            {
                var destructor1 = (TypedTerm.Destructor)first;
                var destructor2 = (TypedTerm.Destructor)second;

                return(destructor1.Operator.IsEqualTo(destructor2.Operator) &&
                       destructor1.Content.IsEqualTo(destructor2.Content));
            }

            case TypedProductions.Variable:
            {
                var variable1 = (TypedTerm.Variable)first;
                var variable2 = (TypedTerm.Variable)second;

                return(variable1.Identifier == variable2.Identifier);
            }

            case TypedProductions.Constant:
            {
                return(false);
            }

            default:
                throw new InvalidProgramException("Should never happen.");
            }
        }
示例#2
0
        public static bool FreeVariable(TypedTerm term, string identifier)
        {
            switch (term.Tag)
            {
            case TypedProductions.Universe:
            {
                return(false);
            }

            case TypedProductions.Type:
            {
                var type = (TypedTerm.Type)term;

                switch (type.Content.Tag)
                {
                case TypeStructs.Quantified:
                    var arrow = (TypeStruct.Quantified)type.Content;

                    return(FreeVariable(arrow.Content.From.Type, identifier) || FreeVariable(arrow.Content.To, identifier));

                case TypeStructs.Module:
                    var module = (TypeStruct.Module)type.Content;

                    foreach (var entry in module.Content.Members)
                    {
                        if (FreeVariable(entry.Type, identifier))
                        {
                            return(true);
                        }

                        if (entry.Term == identifier)
                        {
                            break;
                        }
                    }

                    return(false);

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            case TypedProductions.Constructor:
            {
                var constructor = (TypedTerm.Constructor)term;

                switch (constructor.Content.Type)
                {
                case TypeStructs.Quantified:
                    var lambda = (Constructors.Arrow)constructor.Content;

                    if (lambda.Content.Identifier == identifier)
                    {
                        return(false);
                    }

                    return(FreeVariable(lambda.Content.Body, identifier));

                case TypeStructs.Module:
                    var module = (Constructors.Module)constructor.Content;

                    return(module.Content.Members.Any(member => FreeVariable(member, identifier)));

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            case TypedProductions.Destructor:
            {
                var destructor = (TypedTerm.Destructor)term;

                if (FreeVariable(destructor.Operator.Term, identifier))
                {
                    return(true);
                }

                switch (destructor.Content.Type)
                {
                case TypeStructs.Quantified:
                    var apply = (Destructors.Arrow)destructor.Content;

                    return(FreeVariable(apply.Content.Operand, identifier));

                case TypeStructs.Module:
                    var access = (Destructors.Module)destructor.Content;

                    return(false);

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            case TypedProductions.Variable:
            {
                var variable = (TypedTerm.Variable)term;

                return(variable.Identifier == identifier);
            }

            case TypedProductions.Constant:
            {
                return(false);
            }

            default:
                throw new InvalidProgramException("Should never happen.");
            }
        }
示例#3
0
        public static TypedTerm CheckType(Func <string, Classification <dynamic> > doImport, Environment <Classification <TypedTerm> > environment, Classification <TypedTerm> expected, Term term)
        {
            switch (term.Tag)
            {
            case Productions.Universe:
            {
                var universe = (Term.Universe)term;

                var higher = (TypedTerm.Universe)expected.Term;

                if (higher.Content.Rank == universe.Content.Rank + 1)
                {
                    var @checked = new TypedTerm.Universe(universe.Content);

                    return(@checked);
                }

                throw new ArgumentException("Universe must be within a higher universe.");
            }

            case Productions.Quantified:
            {
                var type = (Term.Quantified)term;

                return(EnsureQuantifiedType(doImport, environment, expected.Some(), type).Term);
            }

            case Productions.Lambda:
            {
                var constructor = (Term.Lambda)term;

                var type  = (TypedTerm.Type)expected.Term;
                var arrow = (TypeStruct.Quantified)type.Content;

                if (arrow.Content.Polarity != Polarity.Forall)
                {
                    throw new ArgumentException("Type constraint on lambda is of the wrong polarity.");
                }

                var identifier = constructor.Content.Parameter.Identifier;

                if (environment.Maps(identifier))
                {
                    throw new ArgumentException("Shadowing identifier: " + identifier);
                }

                foreach (var declared in constructor.Content.Parameter.Constraint.Each())
                {
                    var annotation = InferType(doImport, environment, declared).Normalized(environment);

                    if (!annotation.IsEqualTo(arrow.Content.From.TypeOf()))
                    {
                        throw new ArgumentException("Unexpected domain in lambda term.");
                    }
                }

                var binding = arrow.Content.From.TypeOf().ShiftDown(identifier);

                environment = environment.Push(binding);

                var domain = expected.TypeOf().ShiftDown(arrow.Content.To);

                var body = CheckType(doImport, environment, domain, constructor.Content.Body);

                return(new TypedTerm.Constructor(new Constructors.Arrow(new TypedLambda(identifier, body))));
            }

            case Productions.Apply:
            {
                var destructor = (Term.Apply)term;

                var argument = InferType(doImport, environment, destructor.Content.Argument);

                var arrow = expected.Fmap <TypedTerm, TypedTerm>(@return => new TypedTerm.Type(new TypeStruct.Quantified(new TypedQuantifier(Polarity.Forall, argument.TypeOf().Declared("*"), @return))));

                var @operator = CheckType(doImport, environment, arrow, destructor.Content.Operator);

                return(new TypedTerm.Destructor(arrow.ShiftDown(@operator), new Destructors.Arrow(new TypedApply(argument.Term))));
            }

            case Productions.Module:
            {
                var module = (Term.Module)term;

                var universe = (TypedTerm.Universe)expected.Term;

                var signature = InferSignature(doImport, environment, module.Content);

                return(new TypedTerm.Type(new TypeStruct.Module(signature)));
            }

            case Productions.New:
            {
                var @new = (Term.New)term;

                var type   = (TypedTerm.Type)expected.Term;
                var module = (TypeStruct.Module)type.Content;

                var length = @new.Content.Members.Length;
                if (length != module.Content.Members.Length)
                {
                    throw new ArgumentException("Mismatch between size of signature and module.");
                }

                TypedTerm[] newStruct = new TypedTerm[length];

                foreach (var index in ArrayOperations.CountUp(length))
                {
                    var quantifier = module.Content.Members[index];

                    var definition = @new.Content.Members[index];

                    if (quantifier.Term != definition.Identifier)
                    {
                        throw new ArgumentException("Mismatch between signature and module member name: " + quantifier.Term);
                    }

                    var memberType = quantifier.TypeOf().Normalized(environment);

                    var body = newStruct[index] = CheckType(doImport, environment, memberType, definition.Body);

                    var bodySubstitution = memberType.ShiftDown(body);

                    if (quantifier.Universe.Rank != 0)
                    {
                        bodySubstitution = bodySubstitution.Normalized(environment);
                    }

                    environment = environment.Push(quantifier.Term, bodySubstitution.Normalized(environment));
                }

                return(new TypedTerm.Constructor(new Constructors.Module(new TypedModule(newStruct))));
            }

            case Productions.Access:
            {
                var access = (Term.Access)term;

                var typed = InferMemberAccess(doImport, environment, access.Content);

                if (!typed.TypeOf().IsEqualTo(expected))
                {
                    throw new ArgumentException("Mismatch between member type and type constraints: " + access.Content.Name);
                }

                return(typed.Term);
            }

            case Productions.Variable:
            {
                var variable = (Term.Variable)term;

                var type = environment.Lookup(variable.Content).TypeOf();

                if (!type.IsEqualTo(expected))
                {
                    throw new ArgumentException("Mismatch between type declaration and type constraints: " + variable.Content);
                }

                return(new TypedTerm.Variable(variable.Content));
            }

            case Productions.Annotation:
            {
                var annotation = (Term.Annotation)term;

                var type = InferType(doImport, environment, annotation.Content.Type).Normalized(environment);

                if (!type.IsEqualTo(expected))
                {
                    throw new ArgumentException("Mismatch between type annotation and type constraints.");
                }

                return(CheckType(doImport, environment, expected, annotation.Content.Term));
            }

            case Productions.LetBinding:
            {
                var letBinding = (Term.LetBinding)term;

                if (environment.Maps(letBinding.Content.Identifier))
                {
                    throw new ArgumentException("Shadowing identifier: " + letBinding.Content.Identifier);
                }

                var defined = InferLet(doImport, environment, letBinding.Content);

                var identifier = defined.Term.Key;

                environment = environment.Push(identifier, defined.Fmap(_ => _.Value));

                var continuation = CheckType(doImport, environment, expected, letBinding.Continuation);

                return(new TypedTerm.Destructor(
                           @operator: new Classification <TypedTerm>(
                               universe: expected.Declared("*").Universe,
                               type: new TypedTerm.Type(new TypeStruct.Quantified(new TypedQuantifier(Polarity.Forall, defined.TypeOf().Declared("*"), expected.Term))),
                               term: new TypedTerm.Constructor(new Constructors.Arrow(new TypedLambda(identifier, continuation)))),
                           content: new Destructors.Arrow(new TypedApply(@operand: defined.Term.Value))));
            }

            case Productions.Constant:
            {
                var constant = (Term.Constant)term;

                if (!constant.Content.TypeOf().IsEqualTo(expected))
                {
                    throw new ArgumentException("Mismatch between constant expression and type constraint.");
                }

                return(new TypedTerm.Constant(constant.Content.Term));
            }

            case Productions.TypeOf:
            {
                var typeOf = (Term.TypeOf)term;

                var content = InferType(doImport, environment, typeOf.Content).TypeOf();

                if (!content.TypeOf().IsEqualTo(expected))
                {
                    throw new ArgumentException("Mismatch between type of expression and type constraint.");
                }

                return(content.Term);
            }

            case Productions.Import:
            {
                var import = (Term.Import)term;

                var content = doImport(import.Filename);

                if (!content.TypeOf().IsEqualTo(expected))
                {
                    throw new ArgumentException("Mismatch between type of import and type constraint.");
                }

                return(new TypedTerm.Constant(content.Term));
            }

            default:
                throw new InvalidProgramException("Should never happen.");
            }
        }
示例#4
0
 public TypedApply(TypedTerm operand)
 {
     Operand = operand;
 }
示例#5
0
 public TypedLambda(string identifier, TypedTerm body)
 {
     Identifier = identifier;
     Body       = body;
 }
示例#6
0
 public TypedQuantifier(Polarity polarity, Classification <string> @from, TypedTerm to)
 {
     Polarity = polarity;
     From     = @from;
     To       = to;
 }
示例#7
0
        public static dynamic Evaluate(Environment <dynamic> environment, TypedTerm term)
        {
            switch (term.Tag)
            {
            case TypedProductions.Constructor:
            {
                var constructor = (TypedTerm.Constructor)term;

                switch (constructor.Content.Type)
                {
                case TypeStructs.Quantified:
                    var lambda = (Constructors.Arrow)constructor.Content;

                    return(new Func <dynamic, dynamic>(x => Evaluate(Push <dynamic>(environment, lambda.Content.Identifier, x), lambda.Content.Body)));

                case TypeStructs.Module:
                    var module = (Constructors.Module)constructor.Content;

                    return(module.Content.Members.Fmap(member => Evaluate(environment, member)));

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            case TypedProductions.Destructor:
            {
                var destructor = (TypedTerm.Destructor)term;
                var type       = (TypedTerm.Type)destructor.Operator.Type;

                var @operator = Evaluate(environment, destructor.Operator.Term);

                switch (destructor.Content.Type)
                {
                case TypeStructs.Quantified:
                    var apply = (Destructors.Arrow)destructor.Content;
                    var arrow = (TypeStruct.Quantified)type.Content;

                    var operand = Evaluate(environment, apply.Content.Operand);

                    return(@operator(operand));

                case TypeStructs.Module:
                    var access = (Destructors.Module)destructor.Content;

                    return(@operator[access.Content.Member]);

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            case TypedProductions.Variable:
            {
                var variable = (TypedTerm.Variable)term;

                return(environment.Lookup(variable.Identifier));
            }

            case TypedProductions.Constant:
            {
                var constant = (TypedTerm.Constant)term;

                return(constant.Value);
            }

            case TypedProductions.Universe:
            case TypedProductions.Type:
            {
                return(null);
            }

            default:
                throw new InvalidProgramException("Should never happen.");
            }
        }