digitalmars.D - My solution to the GC problem
- Menshikov (157/157) Jan 06 2023 ``` D
- Richard (Rikki) Andrew Cattermole (6/6) Jan 06 2023 The problem isn't syntax.
- IGotD- (8/12) Jan 07 2023 Ideas how to get of the dlang GC jail is always welcome. One
``` 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 } ```
Jan 06 2023
The problem isn't syntax. Its semantics, lifetime analysis. Being able to specify memory allocators has long been desired, but getting it actually working... that's the hard part. A large part of it is indirection issues in memory lifetime. Currently not a solved problem for us.
Jan 06 2023
On Saturday, 7 January 2023 at 00:18:31 UTC, Menshikov wrote:string text2 new myAlloc; text2 = text; // error! text2 = new string(text); //ok text2 = move(text); //okIdeas how to get of the dlang GC jail is always welcome. One question is how is the type information going to be stored when you use "string text2 new myAlloc" for example. What is the type of 'text2'? Since you want to prevent assignment of a type that is allocated differently that information must be stored somehow. BTW. Beef language looks interesting, haven't paid attention to it previously. Worth checking out.
Jan 07 2023