My solution to the GC problem
Menshikov
mensikovk817 at gmail.com
Sat Jan 7 00:18:31 UTC 2023
``` D
/*
I came up with an idea last night.
If the storages (variables, function arguments, structure or
class fields) store the type at compile time, why not store the
allocator at compile time?
That is, information about the allocator is stored neither in
the type nor in the value, but as an attribute of the store.
* First, it introduces new interesting idioms ('new void',
'new __stack', for example).
* Secondly, if possible, it does not generate a bunch of
template code and does not take up memory in values
* Third, it's readable
* And the fattest plus is that in order to rewrite std and
runtime for them,
you just need to add the new attribute to the function
arguments,
and in half the possible cases, it will work!
* I haven't seen it, in any language! Allocators are well
developed in beeflang, but it does not store the allocator in
storage, it is on the shoulders of the user.
What do you think of it?
*/
/***SYNTAX***/
newAttribute:
new aliasValue
new extern aliasValue
/*only in funcs*/
new
new: identifier
//alias aliasValue is either what alias can accept, or reserved
allocators (__GC, __stack), or the void keyword
/***VARIABLES***/
/*new*/{
string text new myAlloc;
/*
same as
scope string text new extern myAlloc; // 'extern' need to
don't generate scope(exit) and scope attr
scope(exit) destroy(text);
*/
text.length = 90; // ok
string text2 new myAlloc;
text2 = text; // error!
text2 = new string(text); //ok
text2 = move(text); //ok
}
/*new extern*/{
string text new extern myAlloc;
string textGC = text; //error: __GC != myAlloc
/*
string textGC new extern __GC;
*/
string text2 new extern myAlloc;
text2 = text; // OK!
text2.length = text2.length + 5;
assert(text2.ptr != text1.ptr);
destroy(text2);
destroy(text1);
}
/***STRUCTS***/
{
struct Person{
string name;
int age;
}
Person likesGC;
Preson hatesGC new myAlloc;
//pseudocode
static assert(__traits(isSame, allocof(hatesGC),
allocof(hatesGC.name)));
static assert(__traits(isSame, allocof(likesGC),
allocof(likesGC.name)));
}
{
struct Sample{
IAllocator alloc;
string text new alloc; // why not?
}
Sample instance;
}
{
struct Sample{
void method() {
string text new allocof(this);
pragma(msg, allocof(this)); //ERR: __alloc - rt function
argument
}
}
Sample sample new myAlloc;
sample.method();
}
{
struct Sample{
void method() new thisAlloc{
string text new thisAlloc;
pragma(msg, thisAlloc); //OK
}
}
Sample sample new myAlloc;
sample.method();
}
/***FUNCTIONS***/
/*
no additional code is generated, the only thing that happens is
type checking
*/
void someAlloc(ref char[] name new){
name.length = 4;
name[] = "jack";
pragma(msg, allocof(name)); // error! unknown in ct
}
void noAlloc(char[] new void){
assert(name.length == 4);
name[] = "jack";
}
//'new void' means that the type allacator is not known, and that
the methods of this structure that require the structure's
allacator cannot be called
void noAllocStruct(Person a new void){
a.age = 0; //ok
a.name = "Walter"; ///error: allocation
}
void multiArgs(string a new, string b new);
//something like a label is created and the caller checks the
storage allocators
string new a1 multiArgsSameAllocator(string a new: a1, string b
new: a1){
string text new a1;
pragma(msg, a1);//ERR a1 - AllacatorI
pragma(msg, typeof(a1));//=> AllacatorI
return a ~ b;
}
//known allocator at CT
//code generation!
void sample(alias Alloc)(string text new Alloc)
{
pragma(msg, allocof(text)); //OK
}
//ABI
void fu_one(string a new, int n)
->
void fu_one(string a, int n, IAllocator __a_alloc)
void fu_multi(string a new, string b new, int n)
->
void fu_multi(string a, string b, int n, ushort __a_id, ushort
__b_id, IAllocator[] __allocs...)
/***BONUS***/
{
string dtext;
char[] ctext new __stack = dtext.toStringz!__stack; //kinda
alloca in c library
ctext ~= "boo"; // error
ubyte[] result = someCShit(ctext)[0..length];
//PROFIT, no heap use
}
```
More information about the Digitalmars-d
mailing list