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