Esempio n. 1
0
        public override Expression ResolveTypes(ParserContext context, VariableScope varScope)
        {
            this.Root  = this.Root.ResolveTypes(context, varScope);
            this.Index = this.Index.ResolveTypes(context, varScope);

            ResolvedType rootType  = this.Root.ResolvedType;
            ResolvedType indexType = this.Index.ResolvedType;

            if (rootType.IsArray)
            {
                if (indexType.PrimitiveType != "int")
                {
                    throw new ParserException(this.Index.FirstToken, "Array index must be an integer.");
                }

                this.ResolvedType = rootType.Generics[0];
            }
            else if (rootType.IsIDictionary(context))
            {
                if (!indexType.CanBeAssignedTo(rootType.Generics[0], context))
                {
                    throw new ParserException(this.Index.FirstToken, "Incorrect key type.");
                }
                this.ResolvedType = rootType.Generics[1];
            }
            else
            {
                throw new System.NotImplementedException();
            }

            return(this);
        }
Esempio n. 2
0
        public Expression ResolveTypesWithExteriorHint(
            ParserContext context,
            VariableScope varScope,
            ResolvedType[] expectedArgsAndReturnTypes)
        {
            VariableScope lambdaScope = new VariableScope(varScope);

            if (this.Args.Length != expectedArgsAndReturnTypes.Length - 1)
            {
                throw new ParserException(this.ArrowToken, "The expected number of args was " + (expectedArgsAndReturnTypes.Length - 1));
            }

            for (int i = 0; i < this.Args.Length; ++i)
            {
                lambdaScope.DeclareVariable(this.Args[i].Value, expectedArgsAndReturnTypes[i]);
            }

            this.Code = Executable.ResolveTypesForCode(this.Code, context, lambdaScope);
            ResolvedType returnType = null;

            if (this.Code.Length == 1 && this.Code[0] is ExpressionAsExecutable)
            {
                returnType = ((ExpressionAsExecutable)this.Code[0]).Expression.ResolvedType;
            }
            else if (this.Code.Length > 0 && this.Code[this.Code.Length - 1] is ReturnStatement)
            {
                ReturnStatement ret = (ReturnStatement)this.Code[this.Code.Length - 1];
                if (ret.Value == null)
                {
                    throw new ParserException(ret.FirstToken, "Return statement in lambda must have a value.");
                }
                returnType = ret.Value.ResolvedType;
            }
            else
            {
                throw new ParserException(this.FirstToken, "Not implemented: the return is hiding in this lambda.");
            }

            ResolvedType expectedReturnType = expectedArgsAndReturnTypes[expectedArgsAndReturnTypes.Length - 1];

            if (expectedReturnType == null)
            {
                expectedReturnType = returnType;
            }
            else
            {
                if (!returnType.CanBeAssignedTo(expectedReturnType, context))
                {
                    throw new ParserException(this.FirstToken, "This lambda does not seem to be returning the expected type.");
                }
            }

            List <ResolvedType> argTypes = new List <ResolvedType>(expectedArgsAndReturnTypes);

            argTypes.RemoveAt(argTypes.Count - 1);

            this.ResolvedType = ResolvedType.CreateFunction(expectedReturnType, argTypes.ToArray());
            return(this);
        }
Esempio n. 3
0
        public void ResolveTypesForInitialData(ParserContext context, VariableScope varScope)
        {
            switch (this.InitialDataFormat)
            {
            case InitialDataFormatType.NONE: break;

            case InitialDataFormatType.ITEM_LIST:
                if (this.Class.Generics.Length != 1)
                {
                    throw new ParserException(this.FirstToken, "The generics of this constructor does not support an initialization list.");
                }
                ResolvedType itemType = this.Class.Generics[0];
                for (int i = 0; i < this.InitialDataValues.Length; ++i)
                {
                    Expression item = this.InitialDataValues[i].ResolveTypes(context, varScope);
                    this.InitialDataValues[i] = item;
                    if (!itemType.CanBeAssignedTo(item.ResolvedType, context))
                    {
                        throw new ParserException(item.FirstToken, "Incorrect type. Cannot convert a " + item.ResolvedType + " to a " + itemType);
                    }
                }
                break;

            case InitialDataFormatType.KEY_VALUES:
                for (int i = 0; i < this.InitialDataValues.Length; ++i)
                {
                    this.InitialDataKeys[i]   = this.InitialDataKeys[i].ResolveTypes(context, varScope);
                    this.InitialDataValues[i] = this.InitialDataValues[i].ResolveTypes(context, varScope);
                }
                break;

            case InitialDataFormatType.PROPERTIES:
                for (int i = 0; i < this.InitialDataValues.Length; ++i)
                {
                    this.InitialDataValues[i] = this.InitialDataValues[i].ResolveTypes(context, varScope);
                }
                break;
            }
        }
Esempio n. 4
0
        public override Expression ResolveTypes(ParserContext context, VariableScope varScope)
        {
            for (int i = 0; i < this.Expressions.Length; ++i)
            {
                this.Expressions[i] = this.Expressions[i].ResolveTypes(context, varScope);
            }

            ResolvedType cumulativeType = this.Expressions[0].ResolvedType;

            for (int i = 0; i < this.Ops.Length; ++i)
            {
                Expression   leftExpr  = this.Expressions[i];
                Expression   rightExpr = this.Expressions[i + 1];
                ResolvedType leftType  = leftExpr.ResolvedType;
                ResolvedType rightType = rightExpr.ResolvedType;
                switch (this.Ops[i].Value)
                {
                case "==":
                case "!=":
                    // anything is fine on either end.
                    cumulativeType = ResolvedType.Bool();
                    break;

                case ">=":
                case ">":
                case "<=":
                case "<":
                    if (!leftType.IsNumber)
                    {
                        throw new ParserException(leftExpr.FirstToken, NOT_A_NUMBER_ERROR);
                    }
                    if (!rightType.IsNumber)
                    {
                        throw new ParserException(rightExpr.FirstToken, NOT_A_NUMBER_ERROR);
                    }
                    cumulativeType = ResolvedType.Bool();
                    break;

                case "+":
                    if (leftType.IsString || rightType.IsString)
                    {
                        cumulativeType = ResolvedType.String();
                    }
                    else
                    {
                        cumulativeType = CombineNumberTypes(leftExpr, rightExpr);
                    }
                    break;

                case "-":
                case "/":
                case "*":
                    cumulativeType = CombineNumberTypes(leftExpr, rightExpr);
                    break;

                case "<<":
                case ">>":
                case "&":
                case "|":
                case "^":
                    if (!leftType.IsIntLike)
                    {
                        throw new ParserException(leftExpr.FirstToken, INT_REQUIRED_ERROR);
                    }
                    if (!rightType.IsIntLike)
                    {
                        throw new ParserException(rightExpr.FirstToken, INT_REQUIRED_ERROR);
                    }
                    cumulativeType = CombineNumberTypes(leftExpr, rightExpr);
                    break;


                case "&&":
                case "||":
                    if (!leftType.IsBool)
                    {
                        throw new ParserException(leftExpr.FirstToken, BOOLEAN_REQUIRED_ERROR);
                    }
                    if (!rightType.IsBool)
                    {
                        throw new ParserException(rightExpr.FirstToken, BOOLEAN_REQUIRED_ERROR);
                    }
                    cumulativeType = ResolvedType.Bool();
                    break;

                case "??":
                    if (!leftType.IsReferenceType)
                    {
                        throw new ParserException(leftExpr.FirstToken, "This type is not nullable and cannot be used with '??'");
                    }
                    if (!rightType.IsReferenceType)
                    {
                        throw new ParserException(rightExpr.FirstToken, "This type is not nullable and cannot be used with '??'");
                    }
                    if (leftType.CanBeAssignedTo(rightType, context))
                    {
                        cumulativeType = rightType;
                    }
                    else if (rightType.CanBeAssignedTo(leftType, context))
                    {
                        cumulativeType = leftType;
                    }
                    else
                    {
                        throw new ParserException(leftExpr.FirstToken, "Cannot use ?? on these two types. It is unclear what the resulting type should be.");
                    }
                    break;

                default:
                    throw new ParserException(this.Ops[i], "The type resolution for this op is not yet implemented.");
                }
            }

            this.ResolvedType = cumulativeType;
            return(this);
        }