Wednesday, 3 August 2011

Function overloading and more variables

Right. I can't ditch function literals, because overloading will be a total mess. What, do I introduce "variable overloading" or something to support it? I will simply have to make them self-referential, to avoid the "this" problem. That is,


using Standard;
using Attributes;
Factorial(i) {
    Factorial.Attributes(Pure, Threadsafe);
    if (i < 1)
        return i * Factorial(i - 1);
    else
        return i;
}


Now that yields an inconsistent interface to member functions. I could, of course, just remove "this". It's not like having to explicitly add "this" to the list will make life a lot harder for anyone, and it will make them much easier to deal with. And, of course, should anyone desire, they can always refer to the type name.


using Standard;
using Attributes;
type MahType {
    Func(MahType.Attributes(Const).Reference() this) {
        Func.Attributes(Pure, Threadsafe);
        return this.i;
    }
    int i = 0;
}


I've also seen a good idea in D, where instead of using the type's name as a destructor syntax, they just used "this". Now that's a good idea, because the type could be ... fun ... to express in metaprogrammed types. Now, I already wanted to have extension methods, so the additional uses of "this" won't be too bad to specify, and since it can't legally appear outside of a function definition, then it'd be just fine.

Now, let's talk briefly about extension methods. I fully plan on eliminating the free/member issue in C++, not least because you can add and remove member methods at any time and make member methods into free functions, and suchlike. However, in "DeadMG++" then "this" need not be the first argument. It's a named parameter, you see :) Of course, defining operator overloads in a type literal is not currently something the grammar supports, although I will have to remember to add that in.

type MahType {
    int i = 0;
    operator>>(Input, this) {
        Input >> i;
        return Input;
    }
}


Now, about those attributes...

using Standard;
using IO;
type MahType {
    int i = 0;
    // Hmmm.. without "const" given special treatment,
    // how could you write a function that doesn't care whether it binds to lvalue
    // or rvalue or the attributes, but as a reference to a MahType?
    operator+(auto.RvalueReference() this, auto.RvalueReference() Other) {
        // Acceptable?
        MahType.MemberFunctions["operator+"].Attributes(Pure, Threadsafe);
        return i + Other.i;
    }
}


I've decided that, well, I totally forgot that now regular objects are just fine to exist at compile-time and it's easy enough to define them as objects. This, along with restoring type and function literals, should solve the problem well enough.

using Standard;
using Concurrency;
using Containers;
type MahClass {
    Lock l;
    HashMap(TypeReference, TypeReference) Memoize;
    operator()(this, TypeReference t) {
        MahClass.MemberFunctions["operator()"].Attributes(Pure, Threadsafe);
        ScopedLock temp(l);
        if (Memoize.Find(t) != Memoize.End())
            return Memoize[t];
        return Memoize[t] = type {
        };
    }
}
namespace Standard {
    namespace Containers {
        MahClass.Attributes(Const) Vector;
    }
}



Finally, I've decided that there could be need for something I've thought about previously- explicit compile-time and run-time delineation. For example, it's easy for me to say that, since a FunctionReference exists as a bunch of data structures in this pass, and an executable function in the next pass, therefore if you call "operator()" then it's got to be at run-time. However, it becomes significantly harder when I consider how you might actually implement that. I mean, in the compiler, sure, but what would happen if you actually had a library that might operate that way?

No comments:

Post a Comment