digitalmars.D - How to delegate varargs
- Frank Benoit (7/7) Nov 20 2007 How can I delegate the variadic argument list to another variadic
- Tomas Lindquist Olsen (5/14) Nov 20 2007 You have to write a "wrapper" function that explicitly takes the hidden
- Sean Kelly (4/17) Nov 20 2007 Yup, and this stinks. I don't suppose some language feature could be
- Jarrett Billingsley (6/23) Nov 20 2007 It would be nice if varargs were passed instead as a reference to an arr...
- Tomas Lindquist Olsen (65/83) Nov 20 2007 It should be possible, I can't really see anything that could be a
- Tomas Lindquist Olsen (2/2) Nov 20 2007 ok seem I should have read the code again before posting, hope the messa...
- Bill Baxter (4/117) Nov 20 2007 I don't care how it works, but some clean way to forward function
- Tomas Lindquist Olsen (17/23) Nov 20 2007 From a users point of view the only change to the D spec would be:
- Tomas Lindquist Olsen (7/30) Nov 20 2007 Possibly also the section about "_argptr" should be changed to:
- Chad J (3/38) Nov 20 2007 Why not just make it void[] _argdata? It would save us some naming
- Tomas Lindquist Olsen (2/5) Nov 20 2007 But it would become a breaking change.
How can I delegate the variadic argument list to another variadic argument function? e.g. void myWritef( char[] frm, ... ){ writefln( frm, ??? ); } And how can I add or remove arguments to these varargs?
Nov 20 2007
Frank Benoit wrote:How can I delegate the variadic argument list to another variadic argument function? e.g. void myWritef( char[] frm, ... ){ writefln( frm, ??? ); } And how can I add or remove arguments to these varargs?You have to write a "wrapper" function that explicitly takes the hidden arguments. In the case of writefln, phobos provides OutputStream.writefx. To modify the hidden arguments, you would have to know the size of the buffer _argptr points to. I don't see how this is possible with DMD :/
Nov 20 2007
Tomas Lindquist Olsen wrote:Frank Benoit wrote:Yup, and this stinks. I don't suppose some language feature could be provided for working around this? SeanHow can I delegate the variadic argument list to another variadic argument function? e.g. void myWritef( char[] frm, ... ){ writefln( frm, ??? ); } And how can I add or remove arguments to these varargs?You have to write a "wrapper" function that explicitly takes the hidden arguments. In the case of writefln, phobos provides OutputStream.writefx.
Nov 20 2007
"Sean Kelly" <sean f4.ca> wrote in message news:fhvhck$204d$5 digitalmars.com...Tomas Lindquist Olsen wrote:It would be nice if varargs were passed instead as a reference to an array that's built on the stack out of (typeinfo, value) pairs. Problem with that, of course, is that each value can be a different size.. Tricky indeed.Frank Benoit wrote:Yup, and this stinks. I don't suppose some language feature could be provided for working around this? SeanHow can I delegate the variadic argument list to another variadic argument function? e.g. void myWritef( char[] frm, ... ){ writefln( frm, ??? ); } And how can I add or remove arguments to these varargs?You have to write a "wrapper" function that explicitly takes the hidden arguments. In the case of writefln, phobos provides OutputStream.writefx.
Nov 20 2007
Sean Kelly wrote:Tomas Lindquist Olsen wrote:It should be possible, I can't really see anything that could be a showstopper. Except using real variadic function to implement it. On x86-64 va_list is not a simple pointer to data, so the storage for the variadic arguments would have to alloca'd by the caller for this idea to work. This is exactly what I do in LLVMDC [1] btw, as implementing a variadic function is broken on x86-64 (my development platform). Only calling one works... Ok :) Here's the idea, it's very simple! The way it currently works: // --------------------------- // the function: void func(...); // really gets the prototype void func_impl(TypeInfo[], void*); // calling it like this: void func(3.0f, "hello"[]); // is implemented like this: TypeInfo[2] arg_ti = [typeid(float), typeid(char[])]; struct Tmp { float f, char[] c; } Tmp arg_val = Tmp(3.0f, "hello"); func_impl(arg_ti[], cast(void*)&arg_val); // ---------------------------- Now to be able to pass on the arguments (and possible add to them), we need another parameter: size_t _argptrLength; Further, we also need to be able to pass ... as an argument in a call expression. // --------------------------- // lets implement func2 void func2(...) { // call the first one adding some params func(42, ... , 8.0i); } // --------------------------- // now... // the function: void func2(...); // really gets the prototype void func(TypeInfo[], void*, size_t); // calling it like this: func(42, ...); // gets implemented like this: TypeInfo[] arg_ti = (cast(TypeInfo*)alloca(TypeInfo.size*(1+_arguments.length)))[0..1+_arguments.length]; arg_ti[0] = typeid(int); arg_ti[1..1+arguments.length] = _arguments[]; void* arg_val = alloca(int.sizeof + _argptrLength); *(cast(int*)arg_val) = 42; func_impl(arg_ti, arg_val); // ---------------------------- I hope this makes sense, it could be written better, but it should show the idea. All this is stuff the compiler could figure out. Thinking in terms of LLVMDC and codegen, it could be done fairly easily. I'm not sure how much work it would be to get the DMD frontend to accept the '...' token as a function argument and generate something meaningful in the AST though. Excuse all the LLVMDC references, I know nobody is using it yet (with good reason), but it's my only reference to compiler development :) Hope to get some feedback, don't think I've spent this much time on a NG post before :P - Tomas Lindquist Olsen [1] LLVMDC - LLVM D Compiler - http://www.dsource.org/projects/llvmdcFrank Benoit wrote:Yup, and this stinks. I don't suppose some language feature could be provided for working around this? SeanHow can I delegate the variadic argument list to another variadic argument function? e.g. void myWritef( char[] frm, ... ){ writefln( frm, ??? ); } And how can I add or remove arguments to these varargs?You have to write a "wrapper" function that explicitly takes the hidden arguments. In the case of writefln, phobos provides OutputStream.writefx.
Nov 20 2007
ok seem I should have read the code again before posting, hope the message comes across even with the flaws.
Nov 20 2007
Tomas Lindquist Olsen wrote:Sean Kelly wrote:I don't care how it works, but some clean way to forward function varargs that doesn't look like a clumsy afterthought would be fantastic. --bbTomas Lindquist Olsen wrote:It should be possible, I can't really see anything that could be a showstopper. Except using real variadic function to implement it. On x86-64 va_list is not a simple pointer to data, so the storage for the variadic arguments would have to alloca'd by the caller for this idea to work. This is exactly what I do in LLVMDC [1] btw, as implementing a variadic function is broken on x86-64 (my development platform). Only calling one works... Ok :) Here's the idea, it's very simple! The way it currently works: // --------------------------- // the function: void func(...); // really gets the prototype void func_impl(TypeInfo[], void*); // calling it like this: void func(3.0f, "hello"[]); // is implemented like this: TypeInfo[2] arg_ti = [typeid(float), typeid(char[])]; struct Tmp { float f, char[] c; } Tmp arg_val = Tmp(3.0f, "hello"); func_impl(arg_ti[], cast(void*)&arg_val); // ---------------------------- Now to be able to pass on the arguments (and possible add to them), we need another parameter: size_t _argptrLength; Further, we also need to be able to pass ... as an argument in a call expression. // --------------------------- // lets implement func2 void func2(...) { // call the first one adding some params func(42, ... , 8.0i); } // --------------------------- // now... // the function: void func2(...); // really gets the prototype void func(TypeInfo[], void*, size_t); // calling it like this: func(42, ...); // gets implemented like this: TypeInfo[] arg_ti = (cast(TypeInfo*)alloca(TypeInfo.size*(1+_arguments.length)))[0..1 _arguments.length]; arg_ti[0] = typeid(int); arg_ti[1..1+arguments.length] = _arguments[]; void* arg_val = alloca(int.sizeof + _argptrLength); *(cast(int*)arg_val) = 42; func_impl(arg_ti, arg_val); // ---------------------------- I hope this makes sense, it could be written better, but it should show the idea. All this is stuff the compiler could figure out. Thinking in terms of LLVMDC and codegen, it could be done fairly easily. I'm not sure how much work it would be to get the DMD frontend to accept the '...' token as a function argument and generate something meaningful in the AST though. Excuse all the LLVMDC references, I know nobody is using it yet (with good reason), but it's my only reference to compiler development :) Hope to get some feedback, don't think I've spent this much time on a NG post before :P - Tomas Lindquist Olsen [1] LLVMDC - LLVM D Compiler - http://www.dsource.org/projects/llvmdcFrank Benoit wrote:Yup, and this stinks. I don't suppose some language feature could be provided for working around this? SeanHow can I delegate the variadic argument list to another variadic argument function? e.g. void myWritef( char[] frm, ... ){ writefln( frm, ??? ); } And how can I add or remove arguments to these varargs?You have to write a "wrapper" function that explicitly takes the hidden arguments. In the case of writefln, phobos provides OutputStream.writefx.
Nov 20 2007
Bill Baxter wrote:I don't care how it works, but some clean way to forward function varargs that doesn't look like a clumsy afterthought would be fantastic. --bbFrom a users point of view the only change to the D spec would be: At the end of the section "D-style Variadic Functions" append: <<<<< The variadic arguments can be forwarded to another D-style variadic function by passing '...' as an argument. The forwarded arguments are bit-copied onto a new argument list. void foo(...) { // do something } void bar(...) { foo(1, ..., 3.0); }With this approach there is still no way to slice the argument list, for that a more high-level approach like the ones mentioned by Jarret in the "Variadic arguments and map" thread is probably needed.
Nov 20 2007
Tomas Lindquist Olsen wrote:From a users point of view the only change to the D spec would be: At the end of the section "D-style Variadic Functions" append: <<<<< The variadic arguments can be forwarded to another D-style variadic function by passing '...' as an argument. The forwarded arguments are bit-copied onto a new argument list. void foo(...) { // do something } void bar(...) { foo(1, ..., 3.0); } >>>>> With this approach there is still no way to slice the argument list, for that a more high-level approach like the ones mentioned by Jarret in the "Variadic arguments and map" thread is probably needed.Possibly also the section about "_argptr" should be changed to: "These variadic functions have a special local variable declared for them, _argptr, which is a void* pointer to the first of the variadic arguments. To access the arguments, _argptr must be cast to a pointer to the expected argument type. There is also a special local variable, _argptrLength, which holds the length in bytes of the variadic argument list" This could however just be an implementation detail.
Nov 20 2007
Tomas Lindquist Olsen wrote:Tomas Lindquist Olsen wrote:Why not just make it void[] _argdata? It would save us some naming clutter.From a users point of view the only change to the D spec would be: At the end of the section "D-style Variadic Functions" append: <<<<< The variadic arguments can be forwarded to another D-style variadic function by passing '...' as an argument. The forwarded arguments are bit-copied onto a new argument list. void foo(...) { // do something } void bar(...) { foo(1, ..., 3.0); } >>>>> With this approach there is still no way to slice the argument list, for that a more high-level approach like the ones mentioned by Jarret in the "Variadic arguments and map" thread is probably needed.Possibly also the section about "_argptr" should be changed to: "These variadic functions have a special local variable declared for them, _argptr, which is a void* pointer to the first of the variadic arguments. To access the arguments, _argptr must be cast to a pointer to the expected argument type. There is also a special local variable, _argptrLength, which holds the length in bytes of the variadic argument list" This could however just be an implementation detail.
Nov 20 2007
Chad J wrote:Why not just make it void[] _argdata? It would save us some naming clutter.But it would become a breaking change.
Nov 20 2007