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); }
// 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); }