Example #1
0
        public void FailsTypeCheckingForIncorrectNumberOfArguments()
        {
            var twoArgsToInteger = NamedType.Function(new[] { NamedType.Boolean, NamedType.Integer }, NamedType.Integer);

            ShouldFailTypeChecking("foo(true, 1, false)", foo => twoArgsToInteger).WithError(
                "Type mismatch: expected System.Func<bool, int, int>, found System.Func<bool, int, bool, int>.", 1, 1);
        }
Example #2
0
        public Expression TypeCheck(Call call, Scope scope)
        {
            var position   = call.Position;
            var callable   = call.Callable;
            var arguments  = call.Arguments;
            var isOperator = call.IsOperator;

            var typedCallable  = TypeCheck(callable, scope);
            var typedArguments = TypeCheck(arguments, scope);

            var calleeType         = typedCallable.Type;
            var calleeFunctionType = calleeType as NamedType;

            if (calleeFunctionType == null || calleeFunctionType.Name != "System.Func")
            {
                LogError(CompilerError.ObjectNotCallable(position));
                return(call);
            }

            var returnType    = calleeType.GenericArguments.Last();
            var argumentTypes = typedArguments.Select(x => x.Type).ToVector();

            Unify(position, calleeType, NamedType.Function(argumentTypes, returnType));

            var callType = unifier.Normalize(returnType);

            return(new Call(position, typedCallable, typedArguments, isOperator, callType));
        }
Example #3
0
        public void FailsTypeCheckingForMismatchedArgumentTypes()
        {
            var integerToBoolean = NamedType.Function(new[] { NamedType.Integer }, NamedType.Boolean);

            ShouldFailTypeChecking("even(true)", even => integerToBoolean).WithError(
                "Type mismatch: expected int, found bool.", 1, 1);
        }
Example #4
0
        public Expression TypeCheck(MethodInvocation methodInvocation, Scope scope)
        {
            var position   = methodInvocation.Position;
            var instance   = methodInvocation.Instance;
            var methodName = methodInvocation.MethodName;
            var arguments  = methodInvocation.Arguments;

            var typedInstance = TypeCheck(instance, scope);

            var instanceType      = typedInstance.Type;
            var instanceNamedType = instanceType as NamedType;

            if (instanceNamedType == null)
            {
                LogError(CompilerError.AmbiguousMethodInvocation(position));
                return(methodInvocation);
            }

            var typeMemberScope = new TypeMemberScope(typeRegistry.MembersOf(instanceNamedType));

            //TODO: This block is suspiciously like Call type checking, but Callable/MethodName is evaluated in a special scope and the successful return is different.

            var Callable = methodName;

            //Attempt to treat this method invocation as an extension method, if we fail to find the method in the type member scope.
            if (!typeMemberScope.Contains(Callable.Identifier))
            {
                var extensionMethodCall = TypeCheck(new Call(position, methodName, new[] { instance }.Concat(arguments)), scope);

                if (extensionMethodCall != null)
                {
                    return(extensionMethodCall);
                }
            }

            var typedCallable = TypeCheck(Callable, typeMemberScope);

            var typedArguments = TypeCheck(arguments, scope);

            var calleeType         = typedCallable.Type;
            var calleeFunctionType = calleeType as NamedType;

            if (calleeFunctionType == null || calleeFunctionType.Name != "System.Func")
            {
                LogError(CompilerError.ObjectNotCallable(position));
                return(methodInvocation);
            }

            var returnType    = calleeType.GenericArguments.Last();
            var argumentTypes = typedArguments.Select(x => x.Type).ToVector();

            Unify(position, calleeType, NamedType.Function(argumentTypes, returnType));

            var callType = unifier.Normalize(returnType);

            var typedMethodName = (Name)typedCallable;

            return(new MethodInvocation(position, typedInstance, typedMethodName, typedArguments, callType));
        }
Example #5
0
 public void HasAFunctionTypeWithReturnTypeEqualToTheTypeOfTheBodyExpression()
 {
     Type("fn () 1").ShouldEqual(NamedType.Function(Integer));
     Type("fn () true").ShouldEqual(NamedType.Function(Boolean));
     Type("fn () x", x => Integer).ShouldEqual(NamedType.Function(Integer));
     Type("fn () x", x => Boolean).ShouldEqual(NamedType.Function(Boolean));
     Type("fn (int x) x+1").ShouldEqual(NamedType.Function(new[] { Integer }, Integer));
     Type("fn (int x) x+1 > 0").ShouldEqual(NamedType.Function(new[] { Integer }, Boolean));
 }
Example #6
0
File: Scope.cs Project: plioi/rook
        public GlobalScope()
        {
            globals = new BindingDictionary();

            DataType @int  = NamedType.Integer;
            DataType @bool = NamedType.Boolean;

            DataType integerOperation  = NamedType.Function(new[] { @int, @int }, @int);
            DataType integerComparison = NamedType.Function(new[] { @int, @int }, @bool);
            DataType booleanOperation  = NamedType.Function(new[] { @bool, @bool }, @bool);

            globals["<"]  = integerComparison;
            globals["<="] = integerComparison;
            globals[">"]  = integerComparison;
            globals[">="] = integerComparison;
            globals["=="] = integerComparison;
            globals["!="] = integerComparison;

            globals["+"] = integerOperation;
            globals["*"] = integerOperation;
            globals["/"] = integerOperation;
            globals["-"] = integerOperation;

            globals["&&"] = booleanOperation;
            globals["||"] = booleanOperation;
            globals["!"]  = NamedType.Function(new[] { @bool }, @bool);

            var T = TypeVariable.CreateGeneric(); //TypeVariable 0
            var S = TypeVariable.CreateGeneric(); //TypeVariable 1

            var enumerableT = NamedType.Enumerable(T);
            var nullableT   = NamedType.Nullable(T);
            var vectorT     = NamedType.Vector(T);
            var enumerableS = NamedType.Enumerable(S);

            globals["??"]                   = NamedType.Function(new DataType[] { nullableT, T }, T);
            globals["Print"]                = NamedType.Function(new[] { T }, NamedType.Void);
            globals["Nullable"]             = NamedType.Function(new[] { T }, nullableT);
            globals["First"]                = NamedType.Function(new[] { enumerableT }, T);
            globals["Take"]                 = NamedType.Function(new[] { enumerableT, @int }, enumerableT);
            globals["Skip"]                 = NamedType.Function(new[] { enumerableT, @int }, enumerableT);
            globals["Any"]                  = NamedType.Function(new[] { enumerableT }, @bool);
            globals["Count"]                = NamedType.Function(new[] { enumerableT }, @int);
            globals["Select"]               = NamedType.Function(new[] { enumerableT, NamedType.Function(new[] { T }, S) }, enumerableS);
            globals["Where"]                = NamedType.Function(new[] { enumerableT, NamedType.Function(new[] { T }, @bool) }, enumerableT);
            globals["Each"]                 = NamedType.Function(new[] { vectorT }, enumerableT);
            globals[ReservedName.__index__] = NamedType.Function(new[] { vectorT, @int }, T);
            globals[ReservedName.__slice__] = NamedType.Function(new[] { vectorT, @int, @int }, vectorT);
            globals["Append"]               = NamedType.Function(new DataType[] { vectorT, T }, vectorT);
            globals["With"]                 = NamedType.Function(new[] { vectorT, @int, T }, vectorT);
        }
Example #7
0
        public void CanCreateFullyTypedInstance()
        {
            var lambda = (Lambda)Parse("fn (x, int y, bool z) x+y>0 && z");

            lambda.Parameters.ShouldHaveTypes(Unknown, Unknown, Unknown);
            lambda.Body.Type.ShouldEqual(Unknown);
            lambda.Type.ShouldEqual(Unknown);

            var typedLambda = WithTypes(lambda);

            typedLambda.Parameters.ShouldHaveTypes(Integer, Integer, Boolean);
            typedLambda.Body.Type.ShouldEqual(Boolean);
            typedLambda.Type.ShouldEqual(NamedType.Function(new[] { Integer, Integer, Boolean }, Boolean));
        }
Example #8
0
        public void PassesTypeCheckingEvenWhenMethodNamesAreTheSameAsNamesInTheSurroundingScope()
        {
            var fooClass = "class Foo { int A() {0} int B() {2} }".ParseClass();

            var typeRegistry            = new TypeRegistry();
            var constructorReturningFoo = NamedType.Constructor(new NamedType(fooClass));

            typeRegistry.Add(fooClass);

            var typeChecker = new TypeChecker(typeRegistry);

            typeChecker.TypeCheck(fooClass, Scope(B => NamedType.Function(NamedType.Boolean))).Type.ShouldEqual(constructorReturningFoo);
            typeChecker.HasErrors.ShouldBeFalse();
        }
Example #9
0
        public void CanCreateFullyTypedInstance()
        {
            var node = Parse("bool foo(int x, int y, bool z) {x+y>0 && z}");

            node.Parameters.ShouldHaveTypes(Unknown, Unknown, Unknown);
            node.Body.Type.ShouldEqual(Unknown);
            node.Type.ShouldEqual(Unknown);

            var typeChecker = new TypeChecker();
            var typedNode   = typeChecker.TypeCheck(node, Scope());

            typedNode.Parameters.ShouldHaveTypes(Integer, Integer, Boolean);
            typedNode.Body.Type.ShouldEqual(Boolean);
            typedNode.Type.ShouldEqual(NamedType.Function(new[] { Integer, Integer, Boolean }, Boolean));
        }
Example #10
0
        public void CanCreateFullyTypedInstance()
        {
            var node = (MethodInvocation)Parse("math.Even(two)");

            node.Instance.Type.ShouldEqual(Unknown);
            node.MethodName.Type.ShouldEqual(Unknown);
            node.Arguments.Single().Type.ShouldEqual(Unknown);
            node.Type.ShouldEqual(Unknown);

            var typedNode = WithTypes(node, math => mathType, two => Integer);

            typedNode.Instance.Type.ShouldEqual(mathType);
            typedNode.MethodName.Type.ShouldEqual(NamedType.Function(new[] { Integer }, Boolean));
            typedNode.Arguments.Single().Type.ShouldEqual(Integer);
            typedNode.Type.ShouldEqual(Boolean);
        }
Example #11
0
        public void CanCreateFullyTypedInstance()
        {
            var call = (Call)Parse("func(yes, zero)");

            call.Callable.Type.ShouldEqual(Unknown);
            call.Arguments.ShouldHaveTypes(Unknown, Unknown);
            call.Type.ShouldEqual(Unknown);

            var typedCall = WithTypes(call,
                                      func => Function(new[] { Boolean, Integer }, Integer),
                                      yes => Boolean,
                                      zero => Integer);

            typedCall.Callable.Type.ShouldEqual(NamedType.Function(new[] { Boolean, Integer }, Integer));
            typedCall.Arguments.ShouldHaveTypes(Boolean, Integer);
            typedCall.Type.ShouldEqual(Integer);
        }
Example #12
0
        public Expression TypeCheck(Lambda lambda, Scope scope)
        {
            var position   = lambda.Position;
            var parameters = lambda.Parameters;
            var body       = lambda.Body;

            var typedParameters = GetTypedParameters(parameters).ToVector();

            var localScope = CreateLocalScope(scope, typedParameters);

            var typedBody = TypeCheck(body, localScope);

            var normalizedParameters = NormalizeTypes(typedParameters);

            var parameterTypes = normalizedParameters.Select(p => p.Type).ToArray();

            return(new Lambda(position, normalizedParameters, typedBody, NamedType.Function(parameterTypes, typedBody.Type)));
        }
Example #13
0
        public void ShouldGetMemberBindingsWhenGivenTheNamedTypeOfRegisteredClasses()
        {
            var math     = "class Math { int Square(int x) {x*x} bool Zero(int x) {x==0} int Max(int* ints) {0} }".ParseClass();
            var mathType = new NamedType(math);

            typeRegistry.Add(math);
            var members = typeRegistry.MembersOf(mathType);

            var square = members[0];
            var zero   = members[1];
            var max    = members[2];

            square.Identifier.ShouldEqual("Square");
            square.Type.ShouldEqual(NamedType.Function(new[] { NamedType.Integer }, NamedType.Integer));

            zero.Identifier.ShouldEqual("Zero");
            zero.Type.ShouldEqual(NamedType.Function(new[] { NamedType.Integer }, NamedType.Boolean));

            max.Identifier.ShouldEqual("Max");
            max.Type.ShouldEqual(NamedType.Function(new[] { NamedType.Enumerable(NamedType.Integer) }, NamedType.Integer));
        }
Example #14
0
 public void HasATypeIncludingInputTypesAndReturnType()
 {
     Type("int foo() {1}").ShouldEqual(NamedType.Function(Integer));
     Type("bool foo(int x) {false}").ShouldEqual(NamedType.Function(new[] { Integer }, Boolean));
     Type("int foo(int x, bool y) {1}").ShouldEqual(NamedType.Function(new[] { Integer, Boolean }, Integer));
 }
Example #15
0
 public void FailsTypeCheckingForNamesThatAreNotConstructorNames()
 {
     ShouldFailTypeChecking("new Foo()", Foo => Integer).WithError("Cannot construct 'Foo' because it is not a type.", 1, 5);
     ShouldFailTypeChecking("new Foo()", Foo => NamedType.Function(Integer)).WithError("Cannot construct 'Foo' because it is not a type.", 1, 5);
 }
Example #16
0
 public void InfersParameterTypesFromUsages()
 {
     Type("fn (x) x+1").ShouldEqual(NamedType.Function(new[] { Integer }, Integer));
     Type("fn (x, y) x+y").ShouldEqual(NamedType.Function(new[] { Integer, Integer }, Integer));
     Type("fn (x) x+1 > 0").ShouldEqual(NamedType.Function(new[] { Integer }, Boolean));
 }
Example #17
0
        public NamedType DeclaredType(Function function)
        {
            var parameterTypes = function.Parameters.Select(p => TypeOf(p.DeclaredTypeName)).ToArray();

            return(NamedType.Function(parameterTypes, TypeOf(function.ReturnTypeName)));
        }
Example #18
0
 private static DataType Function(IEnumerable <DataType> parameterTypes, DataType returnType)
 {
     return(NamedType.Function(parameterTypes, returnType));
 }
Example #19
0
 public void EvaluatesBodyExpressionTypesInANewScopeIncludingParameters()
 {
     Type("int foo(int x) {x}").ShouldEqual(NamedType.Function(new[] { Integer }, Integer));
     Type("bool foo(int x, int y, bool b) {x==y || b}").ShouldEqual(
         NamedType.Function(new[] { Integer, Integer, Boolean }, Boolean));
 }