apoch / epoch-language

Home of the Epoch Programming Language Project
Other
72 stars 3 forks source link

Adding overloads to library does not work correctly (throws exception) #99

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Let us assume we want strings that are mildly useful, so we start by adding a 
slice operator... except we wish to have overloads of the operator to provide 
for a more useful interface... say

slice : (string(str), integer(startIndex), integer(endIndex), integer(stride)) 
-> string(ret, "")
slice : (string(str), integer(startIndex), integer(endIndex)) -> string(ret, "")
slice : (string(str), integer(startIndex)) -> string(ret, "")

Given that we define three C++ methods:

    void StringSliceFull(StringHandle functionname, VM::ExecutionContext& context)
    {
        Integer32 stride = context.State.Stack.PopValue<Integer32>();
        Integer32 endIndex = context.State.Stack.PopValue<Integer32>();
        Integer32 startIndex = context.State.Stack.PopValue<Integer32>();
        StringHandle p1 = context.State.Stack.PopValue<StringHandle>();

        std::wstring value = context.OwnerVM.GetPooledString(p1);
        std::wstring result = StringSliceMethod(value, startIndex, endIndex, stride);
        StringHandle rethandle = context.OwnerVM.PoolString(result);

        context.State.Stack.PushValue(rethandle);
        context.TickStringGarbageCollector();
    }

    void StringSliceNoStride(StringHandle functionname, VM::ExecutionContext& context)
    {
        Integer32 stride = 1;
        Integer32 endIndex = context.State.Stack.PopValue<Integer32>();
        Integer32 startIndex = context.State.Stack.PopValue<Integer32>();
        StringHandle p1 = context.State.Stack.PopValue<StringHandle>();

        std::wstring value = context.OwnerVM.GetPooledString(p1);
        std::wstring result = StringSliceMethod(value, startIndex, endIndex, stride);
        StringHandle rethandle = context.OwnerVM.PoolString(result);

        context.State.Stack.PushValue(rethandle);
        context.TickStringGarbageCollector();
    }

    void StringSliceNoUpperBoundOrStride(StringHandle functionname, VM::ExecutionContext& context)
    {
        Integer32 stride = 1;
        Integer32 endIndex = std::wstring().max_size();
        Integer32 startIndex = context.State.Stack.PopValue<Integer32>();
        StringHandle p1 = context.State.Stack.PopValue<StringHandle>();

        std::wstring value = context.OwnerVM.GetPooledString(p1);
        std::wstring result = StringSliceMethod(value, startIndex, endIndex, stride);
        StringHandle rethandle = context.OwnerVM.PoolString(result);

        context.State.Stack.PushValue(rethandle);
        context.TickStringGarbageCollector();
    }

Add the appropriate registers:

    AddToMapNoDupe(table, std::make_pair(stringpool.Pool(L"slice@@full_slice"), StringSliceFull));
    AddToMapNoDupe(table, std::make_pair(stringpool.Pool(L"slice@@long_slice"), StringSliceNoStride));
    AddToMapNoDupe(table, std::make_pair(stringpool.Pool(L"slice@@short_slice"), StringSliceNoUpperBoundOrStride));

    {
        FunctionSignature signature;
        signature.AddParameter(L"s", VM::EpochType_String, false);
        signature.AddParameter(L"startIndex", VM::EpochType_Integer, false);
        signature.SetReturnType(VM::EpochType_String);
        AddToMapNoDupe(signatureset, std::make_pair(stringpool.Pool(L"slice@@short_slice"), signature));
    }
    {
        FunctionSignature signature;
        signature.AddParameter(L"s", VM::EpochType_String, false);
        signature.AddParameter(L"startIndex", VM::EpochType_Integer, false);
        signature.AddParameter(L"endIndex", VM::EpochType_Integer, false);
        signature.SetReturnType(VM::EpochType_String);
        AddToMapNoDupe(signatureset, std::make_pair(stringpool.Pool(L"slice@@long_slice"), signature));
    }
    {
        FunctionSignature signature;
        signature.AddParameter(L"s", VM::EpochType_String, false);
        signature.AddParameter(L"startIndex", VM::EpochType_Integer, false);
        signature.AddParameter(L"endIndex", VM::EpochType_Integer, false);
        signature.AddParameter(L"stride", VM::EpochType_Integer, false);
        signature.SetReturnType(VM::EpochType_String);
        AddToMapNoDupe(signatureset, std::make_pair(stringpool.Pool(L"slice@@full_slice"), signature));
    }

and define (AND CALL) the overload registration method:
void StringLibrary::RegisterLibraryOverloads(OverloadMap& overloadmap, 
StringPoolManager& stringpool)
{
    {
        StringHandle functionnamehandle = stringpool.Pool(L"slice");
        overloadmap[functionnamehandle].insert(stringpool.Pool(L"slice@@full_slice"));
        overloadmap[functionnamehandle].insert(stringpool.Pool(L"slice@@long_slice"));
        overloadmap[functionnamehandle].insert(stringpool.Pool(L"slice@@short_slice"));
    }
}

This throws an exception sometime during phase 2 with an error about attempting 
to replace a string in the stringpool

Original issue reported on code.google.com by ryoohki@gmail.com on 1 Feb 2012 at 11:01

Attachments:

GoogleCodeExporter commented 9 years ago
Will try and repro/fix in current trunk.

Original comment by don.ap...@gmail.com on 15 Feb 2012 at 5:40

GoogleCodeExporter commented 9 years ago
Assigned to Release 12.

Original comment by don.ap...@gmail.com on 2 Apr 2012 at 4:13

GoogleCodeExporter commented 9 years ago
Seems to be fixed up; library function overloads are working fine now.

Original comment by don.ap...@gmail.com on 15 Apr 2012 at 5:40