Thread overview | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 16, 2002 D and real Macros | ||||
---|---|---|---|---|
| ||||
Attachments: | 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 was > simple 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 **/ - #: concatenation of names. - 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 @@mkargline arg#0 #FOR ??i = 1, ??i < %%dim, ??i++ ///I think you guess what #FOR/#ENDM macro-directive do #DEFINE @@mkargline @@mkargline#sep#arg#??i #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++ arg#??i op val; #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++ left_arg#??i op right_arg#??i#close_right_arg; #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 ??vect Vector_#%%dim#_#type inline int operator#op(const ??vect& a, const ??vect& b) { #DEFINE ??line (a.coord0#op#b.coord0) #FOR ??i = 1, ??i < %%dim, ??i++ #DEFINE ??line ??line && ( a.coord#??i#op#b.coord#??i ) #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 ??vect Vector_#%%dim#_#type 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 ??vect Vector_#%%dim#_#type 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 ??vect Vector_#%%dim#_#type inline ??vect operator#op(const ??vect& a, const ??vect& b) { ??vect temp; #FOR ??i = 0, ??i < %%dim, ??i++ temp.coord#??i = a.coord#??i op b; #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 ??vect Vector_#%%dim#_#type inline ??vect operator#op(const ??vect& a, const ??vect& b) { ??vect temp; #FOR ??i = 0, ??i < %%dim, ??i++ temp.coord#??i = a.coord#??i op b.coord#??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 Vector_#??dim#_#type ///vector already defined: exit #EXITM #ENDIF #DEFINE ??cvect Vector_#??dim#_#type ///??cvect is easier to write and read than Vector_#??dim#_#type #DEFINE ??pvect Vector_#??pdim#_#type ///??pvect is easier to write and read than Vector_#??pdim#_#type ///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ///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 type coord#??pdim; ///the last dimension: coord<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), coord#??pdim(lp) { ///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 |
April 17, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roland | 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 was > > simple 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> |
April 17, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roland | 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. |
April 17, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | "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 C# programs have access to this info at run time, by bloating it's 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) |
April 17, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to DrWhat? |
DrWhat? a écrit :
> > Example of pseudo-code using masm style macro.
>
> One word : Ewwwwwww!
>
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.
roland
|
April 17, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | "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. > > Sean > you 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 |
April 17, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roland | All those ?? and # are really ugly as well... surely there would be a way to 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) printf(" U field #%d named %s is type %s\n", i, U.fields[i].name, 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) printf(" U element #%d is %s\n", i, uparm[i].tostring); } 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... > > <SNIP unreadable macro example code> > > really so horrible ? > hope you read the .H with an idde that highlight the preprocessor directives. > > roland |
April 17, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roland | "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 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. 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. |
April 18, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to Roland | Roland wrote: > > > DrWhat? a écrit : > >> > Example of pseudo-code using masm style macro. >> >> One word : Ewwwwwww! >> > > 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. Yes, that is why I suggested using this style for a SEPERATE (and generic) preprocessor. > 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 |
April 18, 2002 Re: D and real Macros | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | "Sean L. Palmer" a écrit : > All those ?? and # are really ugly as well... surely there would be a way to 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) > printf(" U field #%d named %s is type %s\n", i, U.fields[i].name, > 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) > printf(" U element #%d is %s\n", i, uparm[i].tostring); > } > 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 > you got the idea. now is it interesting enough to search for a syntax ? for me yes roland |
Copyright © 1999-2021 by the D Language Foundation