Hi, whats the plan WRT to CALL__BUILD? I've written a patch that makes it the default, but does a fallback to "__init" if no BUILD property is set. If the __init method does not exists, no exception is thrown (like before), whereas now an exception is thrown if you specify a BUILD property and the specified method does not exists. A special case is if you set BUILD to an empty string, then no constructor is called for the class, not even __init if it exists.
All tests are passing, plus two new tests for the new functionality (exception if constructor not found and constructor disabling) Should I apply it? jens
Index: src/objects.c =================================================================== RCS file: /cvs/public/parrot/src/objects.c,v retrieving revision 1.90 diff -u -w -r1.90 objects.c --- src/objects.c 27 Apr 2004 12:00:43 -0000 1.90 +++ src/objects.c 14 May 2004 15:09:34 -0000 @@ -482,6 +482,7 @@ void * __ptr; } __ptr_u; STRING *meth; + *meth_str = NULL; #if 0 prop = VTABLE_getprop(interpreter, class, prop_str); if (!VTABLE_defined(interpreter, prop)) @@ -509,6 +510,7 @@ PMC *classsearch_array = get_attrib_num(class_data, PCD_ALL_PARENTS); PMC *parent_class; INTVAL i, nparents; +#if 0 int free_it; static void *what = (void*)-1; /* @@ -527,6 +529,7 @@ Parrot_base_vtables[enum_class_delegate]->init(interpreter, object); } else { +#endif /* * 1) if class has a CONSTRUCT property run it on the object * no redispatch @@ -538,6 +541,7 @@ STRING *meth_str; PMC *meth = get_init_meth(interpreter, class, CONST_STRING(interpreter, "CONSTRUCT"), &meth_str); + int default_meth; if (meth) { if (init) Parrot_run_meth_fromc_args_save(interpreter, meth, @@ -556,6 +560,16 @@ classsearch_array, i); meth = get_init_meth(interpreter, parent_class, CONST_STRING(interpreter, "BUILD"), &meth_str); + /* no method found and no BUILD property set? */ + if (!meth && meth_str == NULL) { + /* use __init as fallback constructor method, if it exists */ + meth_str = string_from_cstring(interpreter, "__init", 6); + meth = Parrot_find_method_with_cache(interpreter, + parent_class, meth_str); + default_meth = 1; + } + else + default_meth = 0; if (meth) { if (init) Parrot_run_meth_fromc_args_save(interpreter, meth, @@ -564,9 +578,23 @@ Parrot_run_meth_fromc_save(interpreter, meth, object, meth_str); } + else if (meth_str != NULL && + string_length(interpreter, meth_str) != 0 && !default_meth) { + real_exception(interpreter, NULL, METH_NOT_FOUND, + "Method '%Ss' not found", meth_str); + } } meth = get_init_meth(interpreter, class, CONST_STRING(interpreter, "BUILD"), &meth_str); + /* no method found and no BUILD property set? */ + if (!meth && meth_str == NULL) { + /* use __init as fallback constructor method, if it exists */ + meth_str = string_from_cstring(interpreter, "__init", 6); + meth = Parrot_find_method_with_cache(interpreter, class, meth_str); + default_meth = 1; + } + else + default_meth = 0; if (meth) { if (init) Parrot_run_meth_fromc_args_save(interpreter, meth, @@ -575,7 +603,14 @@ Parrot_run_meth_fromc_save(interpreter, meth, object, meth_str); } + else if (meth_str != NULL && string_length(interpreter, meth_str) != 0 + && !default_meth) { + real_exception(interpreter, NULL, METH_NOT_FOUND, + "Method '%Ss' not found", meth_str); } +#if 0 + } +#endif } /* Index: t/pmc/object-meths.t =================================================================== RCS file: /cvs/public/parrot/t/pmc/object-meths.t,v retrieving revision 1.17 diff -u -w -r1.17 object-meths.t --- t/pmc/object-meths.t 10 Apr 2004 12:50:23 -0000 1.17 +++ t/pmc/object-meths.t 14 May 2004 15:09:35 -0000 @@ -16,7 +16,7 @@ =cut -use Parrot::Test tests => 19; +use Parrot::Test tests => 21; use Test::More; output_like(<<'CODE', <<'OUTPUT', "callmethod - unknown method"); @@ -136,6 +136,52 @@ ok 2 OUTPUT +output_is(<<'CODE', <<'OUTPUT', "disabling the constructor"); + newclass P1, "Foo" + new P0, .PerlString + setprop P1, "BUILD", P0 + find_type I1, "Foo" + new P3, I1 + print "ok 1\n" + end +.namespace ["Foo"] +.pcc_sub __init: + print "nok ok!\n" + invoke P1 +CODE +ok 1 +OUTPUT + +output_is(<<'CODE', <<'OUTPUT', "specified constructor method does not exist"); + newclass P1, "Foo" + new P0, .PerlString + set P0, "bar" + setprop P1, "BUILD", P0 + + newsub P20, .Exception_Handler, _handler + set_eh P20 + + find_type I1, "Foo" + new P3, I1 + print "not ok 1\n" + end + +_handler: + print "catched it\n" + set S0, P5["_message"] # P5 is the exception object + print S0 + print "\n" + end + +.namespace ["Foo"] +.pcc_sub __init: + print "nok ok 2!\n" + invoke P1 +CODE +catched it +Method 'bar' not found +OUTPUT + output_is(<<'CODE', <<'OUTPUT', "constructor - init attr"); newclass P1, "Foo" addattribute P1, ".i" @@ -604,8 +650,6 @@ OUTPUT }; -$ENV{"CALL__BUILD"} = "1"; - output_is(<<'CODE', <<'OUTPUT', "constructor - parents BUILD"); new P10, .PerlString set P10, "_new" @@ -658,8 +702,6 @@ in sub done OUTPUT - -delete $ENV{"CALL__BUILD"}; output_is(<<'CODE', <<'OUTPUT', "same method name in two namespaces"); ##PIR##