Beispiel #1
0
        internal static bool CheckReturnType(PastelCompiler compiler, PType returnType, PType value)
        {
            // This is an assert, not a user-facing exception. Null should never appear here.
            if (value == null)
            {
                throw new ParserException(returnType.FirstToken, "This should not happen.");
            }

            if (value.IsIdenticalOrChildOf(compiler, returnType))
            {
                return(true);
            }
            if (returnType.Category == TypeCategory.OBJECT)
            {
                return(true);
            }
            if (returnType.Category == TypeCategory.VOID)
            {
                return(false);
            }
            if (value.Category == TypeCategory.NULL)
            {
                if (returnType.Category == TypeCategory.PRIMITIVE && returnType.TypeName == "string")
                {
                    return(true);
                }
                if (returnType.Generics.Length > 0)
                {
                    return(true);
                }
                if (returnType.IsStructOrClass)
                {
                    return(true);
                }
            }
            return(false);
        }
Beispiel #2
0
        // when a templated type coincides with an actual value, add that template key to the lookup output param.
        internal static bool CheckAssignmentWithTemplateOutput(PastelCompiler compiler, PType templatedType, PType actualValue, Dictionary <string, PType> output)
        {
            if (templatedType.Category == TypeCategory.OBJECT)
            {
                return(true);
            }

            // Most cases, nothing to do
            if (templatedType.IsIdenticalOrChildOf(compiler, 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.IsIdenticalOrChildOf(compiler, requiredType))
                    {
                        return(true);
                    }

                    // It's also possible that this is null, in which case the type must be nullable.
                    if (actualValue.Category == TypeCategory.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(compiler, 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(compiler, templatedType.Generics[i], actualValue.Generics[i], output))
                {
                    return(false);
                }
            }

            return(true);
        }