D - D and real Macros
- Roland (412/414) Apr 16 2002 DMACROS
- Sean L. Palmer (12/54) Apr 17 2002 Powerful. Fast. And Oh My God so utterly incomprehensible to someone w...
- Richard Krehbiel (32/38) Apr 17 2002 I still believe D would benefit from a real macro language.
- Roland (5/9) Apr 17 2002 really so horrible ?
- Sean L. Palmer (52/56) Apr 17 2002 All those ?? and # are really ugly as well... surely there would be a wa...
- Roland (22/71) Apr 18 2002 ok, I could have choosen a more appealing syntax.
- Marius S. (13/106) Apr 22 2002 I don't like the idea of separate syntax for the macro language.
- Sean L. Palmer (4/17) Apr 22 2002 So what, then, is the difference between a macro and an inlined function...
- Marius S. (2/24) Apr 23 2002
- Richard Krehbiel (13/37) Apr 23 2002 Preeee-cisely. :-)
- Walter (7/13) Apr 23 2002 program
- Richard Krehbiel (17/30) Apr 24 2002 can
- Russ Lewis (25/34) Apr 24 2002 Maybe 15 years (?) ago, the first single-pass compiler (Turbo C?) came o...
- Richard Krehbiel (20/31) Apr 24 2002 odd
- Russell Borogove (10/29) Apr 25 2002 Among other things. Walter did say tools to "view, debug,
- Georg Wrede (25/25) Apr 26 2002 Maybe we should consider the roles macros play separately?
- Walter (8/12) Apr 26 2002 There will always be a place for text generation. Interestingly, I find ...
- Roland (44/64) Apr 23 2002 right.
- Marius S. (6/87) Apr 23 2002 I'd say arg coud be typed too and i think there should be some type
- DrWhat? (29/44) Apr 16 2002 powerful - yes, though most of this could be done another way (it may b...
- Roland (17/19) Apr 17 2002 I was sure you will say that.
- Walter (10/16) Apr 17 2002 understand.
- C.R.Chafer (13/38) Apr 17 2002 Yes, that is why I suggested using this style for a SEPERATE (and generi...
DMACROS There is still a domain not already specified in D is replacement for macros / Templates. I think D cannot afford not to study MASM style of macros (oops i mean ABEL HDL style of course). Questions are: 1- is it usefull / powerfull ? no hesitation: the answer is yes. be sure it can do the job, and much more you think. 2- is it readable / easy to maintain ? Those questions are one of the main reason why a brainstorm is necessary. My opinion can't count as I fell down the masm macro pot when i was a baby. You, the poors who never felt the power of what _real_ macros are, i understand it could be a little dificult at the beginning. but it worth the effort. Below an example of a vector implementation, any type, any dimension, using masm/abel style of macros. To compare, please create the same in C++ using templates and send me it <> It will be double the size, and, at least for me, not more readable 3- is it easy to implement/parse ? implementation: A while ago, Walter wrote:Yeah, the Abel macro language was far more advanced than the C one(and wassimple to implement, too <g>).Ok, so lets do the hard work and let Walter do the easy part <> Just i hope it can be done in only one compiler pass, else i'm sure he will hate me for the rest of his life. parsing: i'm not competent on that. Just i know compilers are not natural langage traducers and we must avoid context dependent syntax and ambiguities. I did my best but my version is probably not parsable at all. 4- is it easy to debug ? expanded macro must be easily displayed to the user. depend on the IDE i guess. not a good point here. lets see later. ///================================================================================= Example of pseudo-code using masm style macro. Not C++, not D. sorry: inspired by C++. The goal is to automaticaly create vector classes of any type, any dimension. - each vector of a type and of dimension n should inherit from the vector of the same type and dimension n-1, - vector functions need to be fast, - must be castable to an array of the vector dimension size: no other data. IMPORTANT: dmacros.h is attached with this post. read it with the idde: it will be more comfortable you can NOT evaluate readeabily of what folows without doing so ///--------------------------------------------------------------------------------- some basis: - i start all macro name with ' ' charactere. i think there must be a way to global search macros. - symbol declaration: #DEFINE, #DEFINE= #DEFINE= evaluates the expression to a number before assigning it to the symbol - the #LOCAL directive creates a unique name for use in macro. the name is defined only inside the macro. no need to undef it symbols names beginning with ?? are valid if they are names defined with #LOCAL. it help identifie temporary symbols - literal text operator: ^^literal text^^ - expression operator: %%expression: evaluates the expression to a number.(must evaluate to a number) - comment end of line: /// - comment: /** and **/ - args are substituted as soon as possible ///--------------------------------------------------------------------------------- ///tools #MACRO mkargline dim,arg,sep ///create a line ///for example: mkargline 3,p,= replace mkargline with its expanded value: p0=p1=p2 #LOCAL ??i #DEFINE #FOR ??i = 1, ??i < %%dim, ??i++ ///I think you guess what #FOR/#ENDM macro-directive do #DEFINE mkargline mkargline#sep#arg #ENDM #ENDM #MACRO opargval dim,arg,op,val ///op a value to eache arg ///for example opargval 3,coord,=,NAN expand: /// coord0 = NAN; /// coord1 = NAN; /// coord2 = NAN #LOCAL ??i #FOR ??i = 0, ??i < %%dim, ??i++ #ENDM #ENDM #MACRO opargarg dim,left_arg,op,right_arg,close_right_arg ///op right_arg to eache left_arg ///for example opargarg 3,coord,=,parray[,] expand: /// coord0 = parray[0]; /// coord1 = parray[1]; /// coord2 = parray[2]; #LOCAL ??i #FOR ??i = 0, ??i < %%dim, ??i++ #ENDM #ENDM #MACRO mkcmpop dim,type,op /** example: mkcmpop 3,int,== expand like: inline int operator==(const Vector_3_int& a, const Vector_3_int& b) { return ( ( a.coord0==b.coord0 ) && ( a.coord1==b.coord1 ) && ( a.coord2==b.coord2 ) ); } i assume its faster than for (i=0; i<dim; i++) { if (a.coord[i]!=b.coord[i] break; } return (i>=dim); or something like that. **/ #LOCAL ??vect,??line,??i #DEFINE inline int operator#op(const ??vect& a, const ??vect& b) { #DEFINE ??line (a.coord0#op#b.coord0) #FOR ??i = 1, ??i < %%dim, ??i++ #DEFINE #ENDM return ( ??line ); } #ENDM #MACRO mkopeq1 dim,type,op /** example: mkopeq1 3,int,+= expand like: inline Vector_3_int& operator+=(Vector_3_int& a, const int b) { a.coord0+=b; a.coord1+=b; a.coord2+=b; return a; } **/ #LOCAL ??vect #DEFINE inline ??vect& operator#op(??vect& a, const type b) { opargval %%dim,a.coord,op,b return a; } #ENDM #MACRO mkopeq2 dim,type,op /** example: mkopeq2 3,int,+= expand like: inline Vector_3_int& operator+=(Vector_3_int& a, const Vector_3_int& b) { a.coord0+=b.coord0; a.coord1+=b.coord1; a.coord2+=b.coord2; return a; } **/ #LOCAL ??vect #DEFINE inline ??vect& operator#op(??vect& a, const ??vect& b) { opargarg %%dim,a.coord,op,b.coord return a; } #ENDM #MACRO mkop1 dim,type,op /** example: mkop1 3,int,+ expand like: inline Vector_3_int operator+(const Vector_3_int& a, const int b) { Vector_3_int temp; temp.coord0 = a.coord0 + b; temp.coord1 = a.coord1 + b; temp.coord2 = a.coord2 + b; return temp; } **/ #LOCAL ??vect,??i #DEFINE inline ??vect operator#op(const ??vect& a, const ??vect& b) { ??vect temp; #FOR ??i = 0, ??i < %%dim, ??i++ #ENDM return temp; } #ENDM #MACRO mkop2 dim,type,op /** example: mkop2 3,int,+ expand like: inline Vector_3_int operator+(const Vector_3_int& a, const Vector_3_int& b) { Vector_3_int temp; temp.coord0 = a.coord0 + b.coord0; temp.coord1 = a.coord1 + b.coord1; temp.coord2 = a.coord2 + b.coord2; return temp; } **/ #LOCAL ??vect,??i #DEFINE inline ??vect operator#op(const ??vect& a, const ??vect& b) { ??vect temp; #FOR ??i = 0, ??i < %%dim, ??i++ #ENDM return temp; } #ENDM ///--------------------------------------------------------------------------------- ///now the main macro #MACRO DefVector dim,type #LOCAL ??i,??dim,??pdim, ??cvect,??pvect ///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ///some defines #DEFINE= ??dim dim ///evaluate dim in case it is an expression. #DEFINE= ??pdim ??dim-1 ///same for previous dimension #IF (??dim < 2) ///discare vector one or negative(?) dimension #ERROR_MESSAGE " DefVector: dim must be >= 2" #EXITM ///exit #ENDIF #IFDEF #EXITM #ENDIF #DEFINE #DEFINE ///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ///now create the struct #IF (??dim == 2) struct ??cvect { type coord0; //vector 2 dimension: create the 2 axis type coord1; #ELSE DefVector ??pdim,type ///create vector dimension dim-1, dim-2..2 if they don't already exists struct ??cvect: ??pvect { ///dim vector inherits from vector dim-1 #ENDIF ///#IF (??dim == 2) //constructors ??cvect() { ///default constructor: nop for int vectors, NAN for float vectors #IF type.isfloat opargval ??dim,coord,=,NAN #ENDIF } ??cvect( mkargline ??dim,const type p,^^,^^ ) { //space before ')': can't be passed as an argument to mkargline ///example: for Vector_3_int, create constructor Vector_3_int(int p0, int p1, int p2); opargarg ??dim,coord,=,p } ??cvect(const ??pvect& pp, const type lp): ??pvect(pp), ///example: for Vector_3_double, create constructor Vector_3_double(Vector_2_double& pp, double lp); } ??cvect(const type* parray) { ///example: for Vector_3_double, create constructor Vector_3_double(double* parray) ///!! not safe: no check on parray size. opargarg ??dim,coord,=,parray[,] } ??cvect(const ??cvect& p) { ///copy constructor ///useless if you keep ??cvect(type* parray) constructor ///hope the compiler can choose this one before choosing ??cvect(type* parray) associated with ///type* operator below opargarg ??dim,coord,=,p.coord } #IF type.isinteger ??cvect(const double* parray) { ///conversion from a double array to the int vector ///!! not safe: no check on parray size. opargarg ??dim,coord,=,rndtonl(p,) } #ENDIF ///#IF type.isinteger #IF type.isfloat ??cvect(const int* parray) { ///conversion from a int array to the float vector ///!! not safe: no check on parray size. opargarg ??dim,coord,=,parray[,] } #ENDIF ///#IF type.isfloat ///operators operator type*() { ///hope would not create a lot of ambiguities. return &coord0; } #IFNDEF NDEBUG type& operator[](const int i) { ///if debug, use this one: check i ///else, use operator type* ///hope no ambiguity with operator type* assert(i>=0) && (i<??dim)); // <--- here return (&coord0)[i]; } #ENDIF ///#IFNDEF NDEBUG ///other methodes static int ^^dim^^() { //^^dim^^: here do NOT replace 'dim' with macro arg dim return ??dim; } }; ///end struct ??cvect ///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ///now create operator functions: //int operator==(const ??cvect& a, const ??cvect& b); //int operator!=(const ??cvect& a, const ??cvect& b); //int operator>=(const ??cvect& a, const ??cvect& b); //int operator<=(const ??cvect& a, const ??cvect& b); //int operator>(const ??cvect& a, const ??cvect& b); //int operator<(const ??cvect& a, const ??cvect& b); #IRP ??op,(==,!=,>=,<=,>,<) ///#IRP/#ENDM macro-directive: for each operator in the list, put it in ??op and "call" mkcmpop mkcmpop ??dim,type,??op #ENDM //??cvect& operator-=(??cvect& a, const type b); //??cvect& operator+=(??cvect& a, const type b); //??cvect& operator*=(??cvect& a, const type b); //??cvect& operator/=(??cvect& a, const type b); #IRP ??op,(-=,+=,*=,/=) mkopeq1 ??dim,type,??op #ENDM //??cvect& operator-=(??cvect& a, const ??cvect& b); //??cvect& operator+=(??cvect& a, const ??cvect& b); //??cvect& operator*=(??cvect& a, const ??cvect& b); //??cvect& operator/=(??cvect& a, const ??cvect& b); #IRP ??op,(-=,+=,*=,/=) mkopeq2 ??dim,type,??op #ENDM #IF type.isinteger ??cvect& operator>>=(??cvect& a, const int b) { opargval ??dim,a.coord,>>=,b return a; } ??cvect& operator<<=(??cvect& a, const int b) { opargval ??dim,a.coord,<<=,b return a; } #ENDIF ///#IF type.isinteger ??cvect operator-(const ??cvect& a) { ??cvect temp; opargarg temp.coord,=-,a.coord return temp; } //??cvect operator-(const ??cvect& a, const type b); //??cvect operator+(const ??cvect& a, const type b); //??cvect operator*(const ??cvect& a, const type b); //??cvect operator/(const ??cvect& a, const type b); #IRP ??op,(-,+,*,/) mkop1 ??dim,type,??op #ENDM //??cvect operator-(const ??cvect& a, ??cvect& b); //??cvect operator+(const ??cvect& a, ??cvect& b); //??cvect operator*(const ??cvect& a, ??cvect& b); //??cvect operator/(const ??cvect& a, ??cvect& b); #IRP ??op,(-,+,*,/) mkop2 ??dim,type,??op #ENDM #IF type.isinteger ??cvect operator>>(const ??cvect& a, const int b) { ??ctype temp; opargarg ??dim,temp.coord,=,a.coord,>>b return temp; } ??cvect operator<<(const ??cvect& a, const int b) { ??ctype temp; opargarg ??dim,temp.coord,=,a.coord,<<b return temp; } #ENDIF ///#IF type.isinteger ///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ///other function: ??cvect abs(const ??cvect& a) { ??ctype temp; #IF type.isinteger opargarg ??dim,temp.coord,=,abs(a.coord,) #ENDIF #IF type.isfloat opargarg ??dim,temp.coord,=,fabs(a.coord,) #ENDIF return temp; } #IF type.isfloat ??cvect ceil(const ??cvect& a) { ??ctype temp; opargarg ??dim,temp.coord,=,ceil(a.coord,) return temp; } ??cvect floor(const ??cvect& a) { ??ctype temp; opargarg ??dim,temp.coord,=,floor(a.coord,) return temp; } ??cvect round(const ??cvect& a) { ??ctype temp; opargarg ??dim,temp.coord,=,round(a.coord,) return temp; } #ENDIF ///#IF type.isfloat . . exercice: create the vector matrix, create function for scalar product, vectorial product, etc..etc.. . . #ENDM ///#MACRO DefVector dim,type ///--------------------------------------------------------------------------------- Thank you for your attention roland
Apr 16 2002
Powerful. Fast. And Oh My God so utterly incomprehensible to someone who didn't write the code. Nightmarish to maintain or debug. I for one am glad Walter doesn't like macros. I'd rather have a compiler that had a really good optimizer than have a language with macro support. And as everyone keeps bringing up, you can always use an external macro processing tool to preprocess your source files. Sean "Roland" <rv ronetech.com> wrote in message news:3CBC7C3D.C9ADB732 ronetech.com...DMACROS There is still a domain not already specified in D is replacement for macros / Templates. I think D cannot afford not to study MASM style of macros (oops i mean ABEL HDL style of course). Questions are: 1- is it usefull / powerfull ? no hesitation: the answer is yes. be sure it can do the job, and much more you think. 2- is it readable / easy to maintain ? Those questions are one of the main reason why a brainstorm is necessary. My opinion can't count as I fell down the masm macro pot when i was a baby. You, the poors who never felt the power of what _real_ macros are, i understand it could be a little dificult at the beginning. but it worth the effort. Below an example of a vector implementation, any type, any dimension, using masm/abel style of macros. To compare, please create the same in C++ using templates and send me it <> It will be double the size, and, at least for me, not more readable 3- is it easy to implement/parse ? implementation: A while ago, Walter wrote:///========================================================================= ========Yeah, the Abel macro language was far more advanced than the C one(and wassimple to implement, too <g>).Ok, so lets do the hard work and let Walter do the easy part <> Just i hope it can be done in only one compiler pass, else i'm sure he will hate me for the rest of his life. parsing: i'm not competent on that. Just i know compilers are not natural langage traducers and we must avoid context dependent syntax and ambiguities. I did my best but my version is probably not parsable at all. 4- is it easy to debug ? expanded macro must be easily displayed to the user. depend on the IDE i guess. not a good point here. lets see later.Example of pseudo-code using masm style macro.<SNIP unreadable macro example code>
Apr 17 2002
"Sean L. Palmer" <spalmer iname.com> wrote in message news:a9jhho$2vjn$1 digitaldaemon.com...Powerful. Fast. And Oh My God so utterly incomprehensible to someone who didn't write the code. Nightmarish to maintain or debug. I for one am glad Walter doesn't like macros. I'd rather have a compiler that had a really good optimizer than have a language with macro support. And as everyone keeps bringing up, you can always use an external macro processing tool to preprocess your source files.I still believe D would benefit from a real macro language. I have a bullet list of features: 1. Scriptable; macros that you can really *program*, with control flow structures like while, if/else, switch, etc. For an example, consider embedded PHP in an HTML web page. 2. Similarity to the language being compiled. A D macro script should have syntax and semantics as similar as possible to a regular D function. 3. Access to the symbol tables of the program being compiled. That means that a macro can query variable types, enumerate the members of structures and classes, etc. In CPP, you can't say "#if sizeof(var) == 4" because the stupid preprocessor doesn't have a clue about program variables. Java and executables with loads of object type information; I mean to do it at compile time. 4. The ability for a macro to escape source language syntax constraints. I'd like to code a macro to be used thus: "print(a, b, c:16);" Notice the print width specifier on c. (Also notice that the macro senses the types of the arguments.) Or this: "EXEC SQL INSERT INTO TABLE1 ( COL1 ) VALUES :var );" The macro is EXEC, and it parsed and dealt with an SQL statement, including a binding to a D language variable. I got this crazy idea in my head that I could write the preprocessor that can do this - and actually, it would mostly be a D language interpreter with some extra features. I started working on the YACC grammar for D (I'm better with YACC than open-coded parsers like Walter's doing), but it's slow going, partly because the grammer info on the web page is incomplete, but mostly because my life affords me precious little time. I wish somebody could afford to pay me to do this full time... -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 comcast.net (personal)
Apr 17 2002
"Sean L. Palmer" a écrit :And as everyone keeps bringing up, you can always use an external macro processing tool to preprocess your source files. Seanyou are probably right<SNIP unreadable macro example code>really so horrible ? hope you read the .H with an idde that highlight the preprocessor directives. roland
Apr 17 2002
do it without so many wierd symbols everywhere. Listen, I can figure out your macros, I've written many assembler macros in my time. And I kinda like the idea of automatically-generated code. But your example is basically unreadable because of all the symbols. I'm actually more in favor of something like forced-inline functions combined with generics, and language features that enable the generics to deal with unknown types nicely, such as bool Foo(type T : IComparable tparm, type uparm) // whatever you pass for T must be derived from IComparable; uparm can be anything { typealias U = typeof(uparm); U ucopy = uparm; // declare new variable same type as uparm T tcopy = tparm; // tparm's type was named in the declaration // the following checks compile time constant properties of the type to determine what kind of code to generate // blocks controlled by constant compile time false are never evaluated sematically thus won't cause compile errors. printf("U is of type %s",U.name); if (U.isstruct) { printf("U is a struct\n"); for (int i=0; i<U.numfields; ++i) U.fields[i].type.name); } else if (U.isclass) { printf("U is a class derived from %s\n",U.type.ancestor); } else if (U.isarray) { printf("U is an array %d elements\n",uparm.size); for (int i=0; i<U.numfields; ++i) } else if (U.isenum) printf("U is an enum %s\n",uparm.tostring); else if (U.isintegral) printf("U is a integral %l\n",long(uparm)); else if (U.isreal) printf("U is a real %f\n",extended(uparm)); else printf("dunno how to deal with type U\n"); assert(T.derivesfrom(IComparable)); // just to give a meaningful error message; without the assert it still would fail to compile return tcopy.CompareWith(ucopy); // type T must provide this function overloaded for type U or a compile error will result during expansion. } Since most of the stuff in there is known at compile time, quite a bit of compile time optimization is possible. And I'm sure people could come up with more stuff that would enable even cooler tricks. Sean "Roland" <rv ronetech.com> wrote in message news:3CBDBA40.B61E6445 ronetech.com...directives.<SNIP unreadable macro example code>really so horrible ? hope you read the .H with an idde that highlight the preprocessorroland
Apr 17 2002
"Sean L. Palmer" a écrit :do it without so many wierd symbols everywhere.ok, I could have choosen a more appealing syntax. one problem is that i like a separate syntax for directive and statement. I'm just understanding it is not necessary if you have a good optimizer. now i understand why in this example (C++ sorry): template <class T, int SIZE> class Toto { int afunc() { //you write if (SIZE==2) { //instead of #if (SIZE==2) { //as it always seems logical to me . . } } };Listen, I can figure out your macros, I've written many assembler macros in my time. And I kinda like the idea of automatically-generated code. But your example is basically unreadable because of all the symbols. I'm actually more in favor of something like forced-inline functions combined with generics, and language features that enable the generics to deal with unknown types nicely, such as bool Foo(type T : IComparable tparm, type uparm) // whatever you pass for T must be derived from IComparable; uparm can be anything { typealias U = typeof(uparm); U ucopy = uparm; // declare new variable same type as uparm T tcopy = tparm; // tparm's type was named in the declaration // the following checks compile time constant properties of the type to determine what kind of code to generate // blocks controlled by constant compile time false are never evaluated sematically thus won't cause compile errors. printf("U is of type %s",U.name); if (U.isstruct) { printf("U is a struct\n"); for (int i=0; i<U.numfields; ++i) U.fields[i].type.name); } else if (U.isclass) { printf("U is a class derived from %s\n",U.type.ancestor); } else if (U.isarray) { printf("U is an array %d elements\n",uparm.size); for (int i=0; i<U.numfields; ++i) } else if (U.isenum) printf("U is an enum %s\n",uparm.tostring); else if (U.isintegral) printf("U is a integral %l\n",long(uparm)); else if (U.isreal) printf("U is a real %f\n",extended(uparm)); else printf("dunno how to deal with type U\n"); assert(T.derivesfrom(IComparable)); // just to give a meaningful error message; without the assert it still would fail to compile return tcopy.CompareWith(ucopy); // type T must provide this function overloaded for type U or a compile error will result during expansion. } Since most of the stuff in there is known at compile time, quite a bit of compile time optimization is possible. And I'm sure people could come up with more stuff that would enable even cooler tricks. Seanyou got the idea. now is it interesting enough to search for a syntax ? for me yes roland
Apr 18 2002
I don't like the idea of separate syntax for the macro language. I think it would be more convenient to have similar syntax to D and special statements indicating macros. For example something like this: macro void test(int arg) { printf("a = %d;\n", arg); } what do you think? you then could write "macro a" or "macro{ a b }" and maybe "macro: a" (like "public") just a thought... :) Roland wrote:"Sean L. Palmer" a écrit :do it without so many wierd symbols everywhere.ok, I could have choosen a more appealing syntax. one problem is that i like a separate syntax for directive and statement. I'm just understanding it is not necessary if you have a good optimizer. now i understand why in this example (C++ sorry): template <class T, int SIZE> class Toto { int afunc() { //you write if (SIZE==2) { //instead of #if (SIZE==2) { //as it always seems logical to me . . } } };Listen, I can figure out your macros, I've written many assembler macros in my time. And I kinda like the idea of automatically-generated code. But your example is basically unreadable because of all the symbols. I'm actually more in favor of something like forced-inline functions combined with generics, and language features that enable the generics to deal with unknown types nicely, such as bool Foo(type T : IComparable tparm, type uparm) // whatever you pass for T must be derived from IComparable; uparm can be anything { typealias U = typeof(uparm); U ucopy = uparm; // declare new variable same type as uparm T tcopy = tparm; // tparm's type was named in the declaration // the following checks compile time constant properties of the type to determine what kind of code to generate // blocks controlled by constant compile time false are never evaluated sematically thus won't cause compile errors. printf("U is of type %s",U.name); if (U.isstruct) { printf("U is a struct\n"); for (int i=0; i<U.numfields; ++i) U.fields[i].type.name); } else if (U.isclass) { printf("U is a class derived from %s\n",U.type.ancestor); } else if (U.isarray) { printf("U is an array %d elements\n",uparm.size); for (int i=0; i<U.numfields; ++i) } else if (U.isenum) printf("U is an enum %s\n",uparm.tostring); else if (U.isintegral) printf("U is a integral %l\n",long(uparm)); else if (U.isreal) printf("U is a real %f\n",extended(uparm)); else printf("dunno how to deal with type U\n"); assert(T.derivesfrom(IComparable)); // just to give a meaningful error message; without the assert it still would fail to compile return tcopy.CompareWith(ucopy); // type T must provide this function overloaded for type U or a compile error will result during expansion. } Since most of the stuff in there is known at compile time, quite a bit of compile time optimization is possible. And I'm sure people could come up with more stuff that would enable even cooler tricks. Seanyou got the idea. now is it interesting enough to search for a syntax ? for me yes roland
Apr 22 2002
So what, then, is the difference between a macro and an inlined function? Sean "Marius S." <mars centras.lt> wrote in message news:3CC4A2FB.3000403 centras.lt...I don't like the idea of separate syntax for the macro language. I think it would be more convenient to have similar syntax to D and special statements indicating macros. For example something like this: macro void test(int arg) { printf("a = %d;\n", arg); } what do you think? you then could write "macro a" or "macro{ a b }" and maybe "macro: a" (like "public") just a thought... :) Roland wrote:
Apr 22 2002
macro is compile-time function :) Sean L. Palmer wrote:So what, then, is the difference between a macro and an inlined function? Sean "Marius S." <mars centras.lt> wrote in message news:3CC4A2FB.3000403 centras.lt...I don't like the idea of separate syntax for the macro language. I think it would be more convenient to have similar syntax to D and special statements indicating macros. For example something like this: macro void test(int arg) { printf("a = %d;\n", arg); } what do you think? you then could write "macro a" or "macro{ a b }" and maybe "macro: a" (like "public") just a thought... :)
Apr 23 2002
"Marius S." <mars centras.lt> wrote in message news:3CC51C12.8030902 centras.lt...macro is compile-time function :)Preeee-cisely. :-) A macro is a function that is executed at compile time. It has the program source code as an input stream, and output it writes is input to the compiler. It intimate with the compiler's current context, so that it can discover variable and expression types, it can interrogate class and struct membership, and it can do, well, whatever else might be useful (read and write files; issue database queries; perform socket/Internet transactions).Sean L. Palmer wrote:function?So what, then, is the difference between a macro and an inlined-- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 comcast.net (personal)Sean "Marius S." <mars centras.lt> wrote in message news:3CC4A2FB.3000403 centras.lt...I don't like the idea of separate syntax for the macro language. I think it would be more convenient to have similar syntax to D and special statements indicating macros. For example something like this: macro void test(int arg) { printf("a = %d;\n", arg); } what do you think? you then could write "macro a" or "macro{ a b }" and maybe "macro: a" (like "public") just a thought... :)
Apr 23 2002
"Richard Krehbiel" <rich kastle.com> wrote in message news:aa3jr9$2pka$1 digitaldaemon.com...A macro is a function that is executed at compile time. It has theprogramsource code as an input stream, and output it writes is input to the compiler. It intimate with the compiler's current context, so that it can discover variable and expression types, it can interrogate class andstructmembership, and it can do, well, whatever else might be useful (read and write files; issue database queries; perform socket/Internettransactions). Macros are great, but they make it impractical to separate the tokenizing step from the semantic processing.
Apr 23 2002
"Walter" <walter digitalmars.com> wrote in message news:aa4svh$19ia$1 digitaldaemon.com..."Richard Krehbiel" <rich kastle.com> wrote in message news:aa3jr9$2pka$1 digitaldaemon.com...canA macro is a function that is executed at compile time. It has theprogramsource code as an input stream, and output it writes is input to the compiler. It intimate with the compiler's current context, so that itUm... why is this important? Here's my understanding of compiler phases: Once upon a time, when 4K machines were being asked to compile FORTRAN, it was crucial to be able to separate lexical analysis from syntactic, syntactic from semantic, semantic from optimization, optimization from assembly, etc so that the individual phases could fit into core, and each phase would forward their results to the next phase in intermediate files. No longer. Today's compiler does everything but linking in one step, and everything fits in memory (and if not in real memory, then virtual). So what if it's not easy to make a token stream from your input source? I'm afraid I don't get it. -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 comcast.net (personal)discover variable and expression types, it can interrogate class andstructmembership, and it can do, well, whatever else might be useful (read and write files; issue database queries; perform socket/Internettransactions). Macros are great, but they make it impractical to separate the tokenizing step from the semantic processing.
Apr 24 2002
Richard Krehbiel wrote:Um... why is this important? Here's my understanding of compiler phases: Once upon a time, when 4K machines were being asked to compile FORTRAN, it was crucial to be able to separate lexical analysis from syntactic, syntactic from semantic, semantic from optimization, optimization from assembly, etc so that the individual phases could fit into core, and each phase would forward their results to the next phase in intermediate files. No longer. Today's compiler does everything but linking in one step, and everything fits in memory (and if not in real memory, then virtual).Maybe 15 years (?) ago, the first single-pass compiler (Turbo C?) came out, and the point of doing it all in one pass was to increase performance. However, any time that you tightly integrate two very different parts of the code (i.e. token parsing with semantic analysis, or semantic analysis with compilation), you make things more complex and harder to debug. That means that compilers are harder to write, harder to "prove correct," and therefore more likely to have subtle errors. Errors in compilers, or having a wide variety of compilers with differing levels of support for various features, is a Bad Thing. One of D's stated objectives is to make it easy to write a correct compiler that implements all of the features. By keeping the phases separate, this is much easier to do. Similarly, it allows people to write tools to view, debug, or perhaps even rearrange D code without having to parse all of the import files to find odd macros. Thus, you can bet that MY_THING *[]*foo; is the declaration of a variable called foo, and that MY_THING is a user type declared elsewhere - you don't have to parse for macros and find out that MY_THING is some weird alternate expansion. -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Apr 24 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3CC6DFC0.F01424E6 deming-os.org...Richard Krehbiel wrote:oddUm... why is this important?[ ... ] Similarly, it allows people to write tools to view, debug, or perhaps even rearrange D code without having to parse all of the import files to findmacros. Thus, you can bet that MY_THING *[]*foo; is the declaration of a variable called foo, and that MY_THING is a usertypedeclared elsewhere - you don't have to parse for macros and find out that MY_THING is some weird alternate expansion.Oh, I think I get it. The simpler a language is to parse, the more IDE-able it is. I'm thinking of the Visual Studio IDE, where you type along: struct a { int z; double y; } var; var. ...and upon typing the "." the editor gives you a pop-up to choose among the struct members. The editor has interpreted the struct definition in real time. A package of fancy macros could certainly defeat that. Indeed, the simple macros of CPP defeat Visual Studio's editor quite handily. So a language with powerful macros would need a more powerful IDE. (And here was I, wondering what use is a 2.4GHz processor to a plain text editor - why, it's running a full compile behind every keystroke...) -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 comcast.net (personal)
Apr 24 2002
Richard Krehbiel wrote:"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3CC6DFC0.F01424E6 deming-os.org...Among other things. Walter did say tools to "view, debug, or ... rearrange" code. This includes, say, putting it through a Perl script that looks for certain constructs and replaces them with other constructs. I've tried to do this in C++ and been stymied by its syntactical insanities, and usually wound up with "well, it works mostly, but I'll have to manually fix about 100 lines of code... or spend another day improving my script." -Russell BRichard Krehbiel wrote:oddUm... why is this important?[ ... ] Similarly, it allows people to write tools to view, debug, or perhaps even rearrange D code without having to parse all of the import files to findmacros. [snip]Oh, I think I get it. The simpler a language is to parse, the more IDE-able it is.
Apr 25 2002
"Russell Borogove" <kaleja estarcion.com> wrote in message news:3CC8325C.8090607 estarcion.com...Among other things. Walter did say tools to "view, debug, or ... rearrange" code. This includes, say, putting it through a Perl script that looks for certain constructs and replaces them with other constructs. I've tried to do this in C++ and been stymied by its syntactical insanities, and usually wound up with "well, it works mostly, but I'll have to manually fix about 100 lines of code... or spend another day improving my script."The existence of the preprocessor in C++ essentially prevents syntax directed editors, pretty printers, formatters, and various simple parsers (such as wizards) from working 100% reliably. You cannot know what anything is unless you know exactly what the compiler predefined symbols are, what the arguments to the compiler are, what the include path is, what all the include files are, etc. What those simple parsers do is make assumptions about the way most programmers use macros. That will work 98% of the time, but they cannot work 100% of the time. Struggling with that last 2% consumes endless time and frustration. With D, a simple parser can be made that will work reliably 100% of the time. The compiler even comes with the source to the lexer and parser you can use as a guide to how to do it right.
Apr 26 2002
Walter a écrit :"Russell Borogove" <kaleja estarcion.com> wrote in message news:3CC8325C.8090607 estarcion.com...It seems D is made for an external and optional macro preprocessor, and/or a idde that help the programmer in function parameter passing or struct field choice like in vba. If i understand well, you can't have both fonctionality at the same time. In the prévision of a future macro preprocessor, it's good to keep some keyword/keychar reserved like rolandAmong other things. Walter did say tools to "view, debug, or ... rearrange" code. This includes, say, putting it through a Perl script that looks for certain constructs and replaces them with other constructs. I've tried to do this in C++ and been stymied by its syntactical insanities, and usually wound up with "well, it works mostly, but I'll have to manually fix about 100 lines of code... or spend another day improving my script."The existence of the preprocessor in C++ essentially prevents syntax directed editors, pretty printers, formatters, and various simple parsers (such as wizards) from working 100% reliably. You cannot know what anything is unless you know exactly what the compiler predefined symbols are, what the arguments to the compiler are, what the include path is, what all the include files are, etc. What those simple parsers do is make assumptions about the way most programmers use macros. That will work 98% of the time, but they cannot work 100% of the time. Struggling with that last 2% consumes endless time and frustration. With D, a simple parser can be made that will work reliably 100% of the time. The compiler even comes with the source to the lexer and parser you can use as a guide to how to do it right.
Apr 26 2002
Maybe we should consider the roles macros play separately? As I see, preprocessor macros are used to - save typing - compensate for language (or compiler) deficiecies - create new constructs or try new languages or syntaxes - facilitate making different versions of output - easy creation of debugging runtimes from same source - facilitate compiling in different environments What else? Should we refactor this list so everyone first agrees on it, and then examine the issues in separate news-threads? Save typing here includes faster writing, less errors, and at times clearer code. Language deficiencies here means also the need for gathering and ordering input from files (#includes). The other categories are self explanatory. D seems to already take care of the last three of them. Formidably, I might add. Suppose you regularly end up in a situation where writing a macro saves more time coding than writing the macro takes, can we take that prima facie meaning that the language has deficiencies? (Unless, of course, you are doing something where you should use another language to begin with!) Georg
Apr 26 2002
"Georg Wrede" <georg iki.fi> wrote in message news:3CC91DE8.35E415AF iki.fi...Suppose you regularly end up in a situation where writing a macro saves more time coding than writing the macro takes, can we take that prima facie meaning that the language has deficiencies?There will always be a place for text generation. Interestingly, I find the C preprocessor quite inadequate for generating text. Look at impcnvgen.c and idgen.c in the compiler source - both are programs that write source which is then compiled into the compiler. I think such things, however, are properly not part of the language. Use any text processing macro program to generate D source you like.
Apr 26 2002
"Sean L. Palmer" a écrit :So what, then, is the difference between a macro and an inlined function? Sean "Marius S." <mars centras.lt> wrote in message news:3CC4A2FB.3000403 centras.lt...right. to be usefull, arg must not be typed: macro void test(arg) { . . } so what is the difference with template function ? none exept that it could be parcical to have some more directives like symbole name concatenation, repeat statement directive, local symbole names, etc.. macro void opeq(dim,p,op,a) { int i; for (i=0; i<dim; i++) { //dim is a constant. compiler may unfold the loop p.coord#i p.coord1 op a... } } now what does it do ? example: void afunction(point3d& p; const int a) { . . opeq(3,p,-=,a); . . } expand like void afunction(point3d& p; const int a) { . . p.coord0 -= a; p.coord1 -= a; p.coord2 -= a; . . } ??????? personaly i made my mind: complex macros should be processed externally from the compiler. just i have to find a good preprocessor for that. any suggestions ? rolandI don't like the idea of separate syntax for the macro language. I think it would be more convenient to have similar syntax to D and special statements indicating macros. For example something like this: macro void test(int arg) { printf("a = %d;\n", arg); } what do you think? you then could write "macro a" or "macro{ a b }" and maybe "macro: a" (like "public") just a thought... :) Roland wrote:
Apr 23 2002
Roland wrote:"Sean L. Palmer" a écrit :I'd say arg coud be typed too and i think there should be some type which matches all types (like "var" in java script).So what, then, is the difference between a macro and an inlined function? Sean "Marius S." <mars centras.lt> wrote in message news:3CC4A2FB.3000403 centras.lt...right. to be usefull, arg must not be typed: macro void test(arg) { . . }I don't like the idea of separate syntax for the macro language. I think it would be more convenient to have similar syntax to D and special statements indicating macros. For example something like this: macro void test(int arg) { printf("a = %d;\n", arg); } what do you think? you then could write "macro a" or "macro{ a b }" and maybe "macro: a" (like "public") just a thought... :) Roland wrote:so what is the difference with template function ? none exept that it could be parcical to have some more directives like symbole name concatenation, repeat statement directive, local symbole names, etc.. macro void opeq(dim,p,op,a) { int i; for (i=0; i<dim; i++) { //dim is a constant. compiler may unfold the loop p.coord#i p.coord1 op a... } }It could be more powerfull (but maybe less right) if its output would be compiled, then you could generate more flexible source code with it :) ...like PHP in HTML... no, i think that's not right :) sorry.now what does it do ? example: void afunction(point3d& p; const int a) { . . opeq(3,p,-=,a); . . } expand like void afunction(point3d& p; const int a) { . . p.coord0 -= a; p.coord1 -= a; p.coord2 -= a; . . } ??????? personaly i made my mind: complex macros should be processed externally from the compiler. just i have to find a good preprocessor for that. any suggestions ? roland
Apr 23 2002
Roland wrote:DMACROS There is still a domain not already specified in D is replacement for macros / Templates. I think D cannot afford not to study MASM style of macros (oops i mean ABEL HDL style of course). Questions are: 1- is it usefull / powerfull ?powerful - yes, though most of this could be done another way (it may be your example and macros may be the only way to do some things - though I cannot think of any examples.2- is it readable / easy to maintain ?No - it took me 3 passes before I understood it (and I have written these style of things before). More importantly it does not match well with the style of D coding. Consistancy is the first step towards a good language.3- is it easy to implement/parse ?Yes if written from scratch - adding this functionality to the current D parser may not be so easy.4- is it easy to debug ?As the code is not easy to read I would say no. Further more relating generated code to macro definitions is a none trivial task. ///=================================================================================Example of pseudo-code using masm style macro.One word : Ewwwwwww! Though if implemented as a entirely seperate preprocessor / translator which knows nothing about D or any other language (or maybe even built into an integrated development environment) it could could find a useful niche - for example this could be very helpful when writing assembler - especially as syntax between assembler an the macros is not very different. Such a seperate preprocessor could help generate repetitive blocks of code - may be writing one in D as an example of a complex project may be a good idea. I would not recommend such macros to be added to D - in my opinion the times when they are useful are far outweighed by both the additional complexity and their difficulty to learn. Their addition would be a major feature, though I think an infrequently used one. C 2002/4/16 PS: #FOR ??i = 1, ??i < %%dim, ??i++ ///I think you guess what #FOR/#ENDM macro-directive do I am guessing this is like the VHDL / Ada for .. generate statement.
Apr 16 2002
DrWhat? a écrit :I was sure you will say that. That mean difficult isn't it ? (hope you read the .H with an idde that highlight the preprocessor directives) Even if for me it is reasonably readeable, i understand it is difficult to understand. I didnt bet on the succes of this suggestion. Even i'm not sure I would favor this for D. Just i think that is a possibility among other to do the job that has to be taken in consideration for its power and compacity. It is an other phylosophie. That code expand a lot. Me, I prefer to hurt my brain with few lines of complicate code than use my eyes on a lot of line of simple code. In fact, if not easier, it is faster to write, and, i pretend it is easier to fix. rolandExample of pseudo-code using masm style macro.One word : Ewwwwwww!
Apr 17 2002
"Roland" <rv ronetech.com> wrote in message news:3CBDB98F.718A29B5 ronetech.com...Even if for me it is reasonably readeable, i understand it is difficult tounderstand.I didnt bet on the succes of this suggestion. Even i'm not sure I wouldfavor this forD. Just i think that is a possibility among other to do the job that has tobe taken inconsideration for its power and compacity.I see no problem with writing a macro processor that generates D as output. A text processing macro language will not work within D, however, because of the requirement of separation of passes. Having a macro expansion assemble a token, for example, breaks this. It will also break the feature that D can be pre-tokenized.
Apr 17 2002
Roland wrote:DrWhat? a écrit :Yes, that is why I suggested using this style for a SEPERATE (and generic) preprocessor.I was sure you will say that. That mean difficult isn't it ? (hope you read the .H with an idde that highlight the preprocessor directives) Even if for me it is reasonably readeable, i understand it is difficult to understand. I didnt bet on the succes of this suggestion. Even i'm not sure I would favor this for D. Just i think that is a possibility among other to do the job that has to be taken in consideration for its power and compacity.Example of pseudo-code using masm style macro.One word : Ewwwwwww!It is an other phylosophie.No problem with that - if we did not try different philosophies we would never improve out current position.That code expand a lot. Me, I prefer to hurt my brain with few lines of complicate code than use my eyes on a lot of line of simple code.I tend to aggree though a few lines of complicated code may often mushroom into a lot of lines of complex code.In fact, if not easier, it is faster to write, and, i pretend it is easier to fix.Due to the thinking time involved to verify it is correct - I find the two either complex or simple styles similar with respect to production time. Though frequently the complex styles execute faster - however this is not the case with macro processors and therefore the implementation of such a processor should have simple syntax. C 2002/4/18
Apr 17 2002