void CFCMethod_override(CFCMethod *self, CFCMethod *orig) { // Check that the override attempt is legal. if (CFCMethod_final(orig)) { const char *orig_class = CFCMethod_get_class_name(orig); const char *my_class = CFCMethod_get_class_name(self); CFCUtil_die("Attempt to override final method '%s' from '%s' by '%s'", orig->macro_sym, orig_class, my_class); } if (!CFCMethod_compatible(self, orig)) { const char *func = CFCMethod_imp_func(self); const char *orig_func = CFCMethod_imp_func(orig); CFCUtil_die("Non-matching signatures for %s and %s", func, orig_func); } // Mark the Method as no longer novel. self->is_novel = false; }
static void S_run_basic_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*"); CFCParamList *param_list = CFCTest_parse_param_list(test, parser, "(Foo *self, int32_t count = 0)"); CFCMethod *method = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Return_An_Obj", return_type, param_list, NULL, 0, 0); OK(test, method != NULL, "new"); OK(test, CFCSymbol_parcel((CFCSymbol*)method), "parcel exposure by default"); { CFCMethod *dupe = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Return_An_Obj", return_type, param_list, NULL, 0, 0); OK(test, CFCMethod_compatible(method, dupe), "compatible"); CFCBase_decref((CFCBase*)dupe); } { CFCMethod *macro_sym_differs = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Eat", return_type, param_list, NULL, 0, 0); OK(test, !CFCMethod_compatible(method, macro_sym_differs), "different macro_sym spoils compatible"); OK(test, !CFCMethod_compatible(macro_sym_differs, method), "... reversed"); CFCBase_decref((CFCBase*)macro_sym_differs); } { static const char *param_strings[5] = { "(Foo *self, int32_t count = 0, int b)", "(Foo *self, int32_t count = 1)", "(Foo *self, int32_t count)", "(Foo *self, int32_t countess = 0)", "(Foo *self, uint32_t count = 0)" }; static const char *test_names[5] = { "extra param", "different initial_value", "missing initial_value", "different param name", "different param type" }; for (int i = 0; i < 5; ++i) { CFCParamList *other_param_list = CFCTest_parse_param_list(test, parser, param_strings[i]); CFCMethod *other = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Return_An_Obj", return_type, other_param_list, NULL, 0, 0); OK(test, !CFCMethod_compatible(method, other), "%s spoils compatible", test_names[i]); OK(test, !CFCMethod_compatible(other, method), "... reversed"); CFCBase_decref((CFCBase*)other_param_list); CFCBase_decref((CFCBase*)other); } } { CFCParamList *self_differs_list = CFCTest_parse_param_list(test, parser, "(Bar *self, int32_t count = 0)"); CFCMethod *self_differs = CFCMethod_new(neato_parcel, NULL, "Neato::Bar", "Bar", "Return_An_Obj", return_type, self_differs_list, NULL, 0, 0); OK(test, CFCMethod_compatible(method, self_differs), "different self type still compatible()," " since can't test inheritance"); OK(test, CFCMethod_compatible(self_differs, method), "... reversed"); CFCBase_decref((CFCBase*)self_differs_list); CFCBase_decref((CFCBase*)self_differs); } { CFCMethod *aliased = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Aliased", return_type, param_list, NULL, 0, 0); OK(test, !CFCMethod_get_host_alias(aliased), "no host alias by default"); CFCMethod_set_host_alias(aliased, "Host_Alias"); STR_EQ(test, CFCMethod_get_host_alias(aliased), "Host_Alias", "set/get host alias"); CFCBase_decref((CFCBase*)aliased); } { CFCMethod *excluded = CFCMethod_new(neato_parcel, NULL, "Neato::Foo", "Foo", "Excluded", return_type, param_list, NULL, 0, 0); OK(test, !CFCMethod_excluded_from_host(excluded), "not excluded by default"); CFCMethod_exclude_from_host(excluded); OK(test, CFCMethod_excluded_from_host(excluded), "exclude from host"); CFCBase_decref((CFCBase*)excluded); } CFCBase_decref((CFCBase*)parser); CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)return_type); CFCBase_decref((CFCBase*)param_list); CFCBase_decref((CFCBase*)method); CFCParcel_reap_singletons(); }