On Mon, Aug 18, 2008 at 12:55 PM, Will Coleda <[EMAIL PROTECTED]> wrote:
> On Sun, Aug 17, 2008 at 5:49 PM,  <[EMAIL PROTECTED]> wrote:
>> Author: chromatic
>> Date: Sun Aug 17 14:49:39 2008
>> New Revision: 30286
>>
>> Modified:
>>   trunk/src/pmc/namespace.pmc
>>   trunk/t/pmc/namespace.t
>>
>> Log:
>> [PMC] Fixed co-recursion bug in NameSpace, when iterating through its 
>> contents.
>> The problem is that, when the key is a Key and not a String, sometimes 
>> there's
>> an infinite loop when the Key isn't a string, integer, or PMC key -- the
>> default path for the switch in key_string() calls the get_string() vtable 
>> entry
>> on the key, which calls key_string(), which....
>>
>> The short-term solution is to call the parent PMC (Hash) implementation of
>> get_pmc_keyed() and return the results, if they're accurate.  This fixes the
>> crash and keeps Rakudo working.  Replacing the body of the vtable entry with
>> the SUPER() call breaks Rakudo.
>>
>> The long-term solution is to fix the Key PMC, which is poorly designed and
>> poorly implemented.
>>
>> See RT #57668 and RT #58040, for starters.
>>
>> Modified: trunk/src/pmc/namespace.pmc
>> ==============================================================================
>> --- trunk/src/pmc/namespace.pmc (original)
>> +++ trunk/src/pmc/namespace.pmc Sun Aug 17 14:49:39 2008
>> @@ -382,26 +382,26 @@
>>     }
>>
>>     VTABLE PMC *get_pmc_keyed(PMC *key) {
>> -        PMC    *ns = SELF;
>> +        PMC    *ns = SUPER(key);
>>
>> -        if (key->vtable->base_type == enum_class_String)
>> -            return SELF.get_pmc_keyed_str(VTABLE_get_string(INTERP, key));
>> +        if (!PMC_IS_NULL(ns))
>> +            return ns;
>> +
>> +        ns = SELF;
>>
>>         if (key->vtable->base_type == enum_class_Key) {
>> -            while (key) {
>> -                STRING * const part = key_string(INTERP, key);
>> -                key  = key_next(INTERP, key);
>> +            STRING * const part = key_string(INTERP, key);
>> +            key  = key_next(INTERP, key);
>>
>> -                if (!key)
>> -                    return VTABLE_get_pmc_keyed_str(INTERP, ns, part);
>> +            if (!key)
>> +                return VTABLE_get_pmc_keyed_str(INTERP, ns, part);
>>
>> -                ns = Parrot_get_namespace_keyed_str(INTERP, ns, part);
>> +            ns = Parrot_get_namespace_keyed_str(INTERP, ns, part);
>>
>> -                if (PMC_IS_NULL(ns))
>> -                    return PMCNULL;
>> -            }
>> +            if (PMC_IS_NULL(ns))
>> +                return PMCNULL;
>>
>> -            return ns;
>> +            return VTABLE_get_pmc_keyed(INTERP, ns, key);
>>         }
>>
>>         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_GLOBAL_NOT_FOUND,
>>
>> Modified: trunk/t/pmc/namespace.t
>> ==============================================================================
>> --- trunk/t/pmc/namespace.t     (original)
>> +++ trunk/t/pmc/namespace.t     Sun Aug 17 14:49:39 2008
>> @@ -1736,7 +1736,7 @@
>>  /Null PMC access in get_string()/
>>  OUT
>>
>> -pir_output_is( <<'CODE', <<OUT, "RT #57668", todo => "iterate through a 
>> NameSpace PMC, RT #57668" );
>> +pir_output_is( <<'CODE', <<OUT, "iterate through a NameSpace PMC" );
>>  .namespace [ 'bar' ]
>>
>>  .sub 'main' :main
>>
>
> This causes languages/tcl/cmd_namespace.t to fail. (Reverting this one
> change locally allows the test to pass).
>
> --
> Will "Coke" Coleda
>

You can duplicate the error with:

../../parrot tcl.pbc -e "namespace exists a"

The error occurs at line 141 of languages/tcl/runtime/builtin/namespace.pir.

-- 
Will "Coke" Coleda

Reply via email to