예제 #1
0
        internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler)
        {
            this.Condition = this.Condition.ResolveType(varScope, compiler);
            PType conditionType = this.Condition.ResolvedType;
            bool  isInt         = conditionType.IsIdentical(compiler, PType.INT);
            bool  isChar        = !isInt && conditionType.IsIdentical(compiler, PType.CHAR);

            if (!isInt && !isChar)
            {
                throw new ParserException(this.Condition.FirstToken, "Only ints and chars can be used in switch statements.");
            }

            // consider it all one scope
            for (int i = 0; i < this.Chunks.Length; ++i)
            {
                SwitchChunk chunk = this.Chunks[i];
                for (int j = 0; j < chunk.Cases.Length; ++j)
                {
                    Expression ex = chunk.Cases[j];
                    if (ex != null)
                    {
                        ex             = ex.ResolveType(varScope, compiler);
                        chunk.Cases[j] = ex;
                        if ((isInt && ex.ResolvedType.RootValue != "int") ||
                            (isChar && ex.ResolvedType.RootValue != "char"))
                        {
                            throw new ParserException(ex.FirstToken, isInt ? "Only ints may be used." : "Only chars may be used.");
                        }
                    }
                }

                Executable.ResolveTypes(chunk.Code, varScope, compiler);
            }
        }
예제 #2
0
        public static bool CheckReturnType(PType returnType, PType value)
        {
            if (returnType.IsIdentical(value))
            {
                return(true);
            }
            if (returnType.RootValue == "object")
            {
                return(true);
            }
            if (returnType.RootValue == "void")
            {
                return(false);
            }
            if (value.RootValue == "null")
            {
                if (returnType.RootValue == "string")
                {
                    return(true);
                }
                if (returnType.Generics.Length > 0)
                {
                    return(true);
                }

                // is struct?
                char c = returnType.RootValue[0];
                if (c >= 'A' && c <= 'Z')
                {
                    return(true);
                }
            }
            return(false);
        }
예제 #3
0
        internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler)
        {
            this.Root  = this.Root.ResolveType(varScope, compiler);
            this.Index = this.Index.ResolveType(varScope, compiler);

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

            bool badIndex = false;

            if (rootType.RootValue == "List" || rootType.RootValue == "Array")
            {
                badIndex          = !indexType.IsIdentical(PType.INT);
                this.ResolvedType = rootType.Generics[0];
            }
            else if (rootType.RootValue == "Dictionary")
            {
                badIndex          = !indexType.IsIdentical(rootType.Generics[0]);
                this.ResolvedType = rootType.Generics[1];
            }
            else if (rootType.RootValue == "string")
            {
                badIndex          = !indexType.IsIdentical(PType.INT);
                this.ResolvedType = PType.CHAR;
                if (this.Root is InlineConstant && this.Index is InlineConstant)
                {
                    string         c        = ((string)((InlineConstant)this.Root).Value)[(int)((InlineConstant)this.Index).Value].ToString();
                    InlineConstant newValue = new InlineConstant(PType.CHAR, this.FirstToken, c);
                    newValue.ResolveType(varScope, compiler);
                    return(newValue);
                }
            }
            else
            {
                badIndex = true;
            }

            if (badIndex)
            {
                throw new ParserException(this.BracketToken, "Cannot index into a " + rootType + " with a " + indexType + ".");
            }

            return(this);
        }
예제 #4
0
        internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler)
        {
            this.Root  = this.Root.ResolveType(varScope, compiler);
            this.Index = this.Index.ResolveType(varScope, compiler);

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

            bool badIndex = false;

            if (rootType.RootValue == "List" || rootType.RootValue == "Array")
            {
                badIndex          = !indexType.IsIdentical(PType.INT);
                this.ResolvedType = rootType.Generics[0];
            }
            else if (rootType.RootValue == "Dictionary")
            {
                badIndex          = !indexType.IsIdentical(rootType.Generics[0]);
                this.ResolvedType = rootType.Generics[1];
            }
            else if (rootType.RootValue == "string")
            {
                badIndex          = !indexType.IsIdentical(PType.INT);
                this.ResolvedType = PType.CHAR;
            }
            else
            {
                badIndex = true;
            }

            if (badIndex)
            {
                throw new ParserException(this.BracketToken, "Cannot index into a " + rootType + " with a " + indexType + ".");
            }

            return(this);
        }
        // Note that this class is instantiated in the ResolveType phase.
        public FunctionPointerInvocation(PastelCompiler compiler, Token firstToken, Expression root, IList <Expression> Args)
            : base(firstToken, root.Owner)
        {
            this.Root = root;
            this.Args = Args.ToArray();

            this.ResolvedType = this.Root.ResolvedType.Generics[0];

            if (this.Root.ResolvedType.Generics.Length - 1 != this.Args.Length)
            {
                throw new ParserException(this.Root.FirstToken, "This function has the incorrect number of arguments.");
            }
            for (int i = 0; i < this.Args.Length; ++i)
            {
                PType expectedArgType = this.Root.ResolvedType.Generics[i + 1];
                PType actualArgType   = this.Args[i].ResolvedType;
                if (!actualArgType.IsIdentical(compiler, expectedArgType))
                {
                    throw new ParserException(this.Args[i].FirstToken, "Incorrect argument type. Expected " + expectedArgType + " but found " + actualArgType + ".");
                }
            }
        }
예제 #6
0
        // when a templated type coincides with an actual value, add that template key to the lookup output param.
        public static bool CheckAssignmentWithTemplateOutput(PType templatedType, PType actualValue, Dictionary <string, PType> output)
        {
            if (templatedType.RootValue == "object")
            {
                return(true);
            }

            // Most cases, nothing to do
            if (templatedType.IsIdentical(actualValue))
            {
                return(true);
            }

            if (templatedType.RootValue.Length == 1)
            {
                if (output.ContainsKey(templatedType.RootValue))
                {
                    PType requiredType = output[templatedType.RootValue];
                    // if it's already encountered it better match the existing value
                    if (actualValue.IsIdentical(requiredType))
                    {
                        return(true);
                    }

                    // It's also possible that this is null, in which case the type must be nullable.
                    if (actualValue.RootValue == "null" && requiredType.IsNullable)
                    {
                        return(true);
                    }

                    return(false);
                }
                output[templatedType.RootValue] = actualValue;
                return(true);
            }

            if (templatedType.Generics.Length != actualValue.Generics.Length)
            {
                // completely different. don't even try to match templates
                return(false);
            }

            if (templatedType.RootValue != actualValue.RootValue)
            {
                if (templatedType.RootValue.Length == 1)
                {
                    if (output.ContainsKey(templatedType.RootValue))
                    {
                        // if it's already encountered it better match the existing value
                        if (actualValue.IsIdentical(output[templatedType.RootValue]))
                        {
                            // yup, that's okay
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        // first time this type was encountered.
                        output[templatedType.RootValue] = actualValue;
                    }
                }
                else
                {
                    // different type
                    return(false);
                }
            }

            for (int i = 0; i < templatedType.Generics.Length; ++i)
            {
                if (!CheckAssignmentWithTemplateOutput(templatedType.Generics[i], actualValue.Generics[i], output))
                {
                    return(false);
                }
            }

            return(true);
        }