D - Suggestion: "if" outside of function blocks (and much more)
- Norbert Nemec (36/36) Jan 17 2003 Hi there,
- Evan McClanahan (18/67) Jan 17 2003 This seems like the mechanism already in place, I don't really see the
- Norbert Nemec (24/73) Jan 17 2003 There's no win at that point. Just that the language definition becomes
- Mike Wynn (56/92) Jan 17 2003 this is something I have been thinking about, allowing D to be used for
- Norbert Nemec (15/26) Jan 17 2003 Well, part of it is present in many languages. C++ allows a const to be
- Mike Wynn (34/58) Jan 17 2003 special
- Norbert Nemec (16/17) Jan 18 2003 Be careful on how far you take the concept. My suggestions were tiny, ea...
- Mike Wynn (37/52) Jan 18 2003 the think is parts are already there
- Daniel Yokomiso (21/128) Jan 17 2003 values
- Mike Wynn (6/26) Jan 18 2003 I must read that more fully, but looks very much along the lines I was
- Sean L. Palmer (4/5) Jan 18 2003 Yes; this feature of Boost::mpl is extremely handy.
Hi there, just a quick and dirty suggestion: How about allowing "if"-"else"-blocks outside of function blocks? Of course, the argument will have to be computable at compile time. This simple construct will allow several things: * "version" could become a boolean expression instead of a block statement. version(...) { } would become if(version(...)) { } with the added possibily of logic constructions. * Together with integers as template parameters, the data fields of a template class could be dependant on those parameters. The addition should be absolutely straightforward. Anyhow a few more additions would make it even more powerful: * Define "compile-time-value" as any value that can be deduced by the compiler. * Define "function without side-effects" (should be an attribute of some kind) * Require the compiler to be able to run such functions at compile time if the arguments are compile-time-value Now, every expression made up of constants, basic operators and functions without side-effects are compile-time-values. This all taken together would perhaps give us all the compile-time-computing-power we need to put really heavy optimization into a library. One more detail: There should be an argument for function arguments to be specified as compile-time-values. This way, the function can only be called with a compile-time-value provided at that point, and inside the function, the value can be used, p.e. as a template parameter. And a last thought: it might prove useful to provide a larger set of expressions for handling types, like comparing them, etc. so these can be used in compile-time decisions within a template library. Ciao, Nobbi
Jan 17 2003
Comments embedded. Norbert Nemec wrote:Hi there, just a quick and dirty suggestion: How about allowing "if"-"else"-blocks outside of function blocks? Of course, the argument will have to be computable at compile time. This simple construct will allow several things: * "version" could become a boolean expression instead of a block statement. version(...) { } would become if(version(...)) { } with the added possibily of logic constructions.This seems like the mechanism already in place, I don't really see the win there. Unless I'm wrong and you can't do version(..1) { } version(..2) { } else { } in which case I see where you're going and approve.* Together with integers as template parameters, the data fields of a template class could be dependant on those parameters. The addition should be absolutely straightforward. Anyhow a few more additions would make it even more powerful: * Define "compile-time-value" as any value that can be deduced by the compiler. * Define "function without side-effects" (should be an attribute of some kind) * Require the compiler to be able to run such functions at compile time if the arguments are compile-time-valuehard to do, chews up keywords. Hard to make guarantees in those respects, I think. It would also be *really* annoying to maintain. But then, I'm not really interested in writing libraries, so if it didn't intrude much, I'd not really complain.Now, every expression made up of constants, basic operators and functions without side-effects are compile-time-values. This all taken together would perhaps give us all the compile-time-computing-power we need to put really heavy optimization into a library. One more detail: There should be an argument for function arguments to be specified as compile-time-values. This way, the function can only be called with a compile-time-value provided at that point, and inside the function, the value can be used, p.e. as a template parameter. And a last thought: it might prove useful to provide a larger set of expressions for handling types, like comparing them, etc. so these can be used in compile-time decisions within a template library. Ciao, Nobbi
Jan 17 2003
Evan McClanahan wrote:Comments embedded. Norbert Nemec wrote:There's no win at that point. Just that the language definition becomes simpler if "version" is not an additional block statement, but simply a expression evaluating to a boolean. And my generalized "if" is by far more powerful, and maybe even easier to understand, than the current "version"-block statement. The language definition gets tidier and the result is far more expressive.Hi there, just a quick and dirty suggestion: How about allowing "if"-"else"-blocks outside of function blocks? Of course, the argument will have to be computable at compile time. This simple construct will allow several things: * "version" could become a boolean expression instead of a block statement. version(...) { } would become if(version(...)) { } with the added possibily of logic constructions.This seems like the mechanism already in place, I don't really see the win there. Unless I'm wrong and you can't do version(..1) { } version(..2) { } else { } in which case I see where you're going and approve.???!!! "const" is there already. One keyword for "function without side-effects" would have to be found (suggestions?). That's it.* Define "compile-time-value" as any value that can be deduced by the compiler. * Define "function without side-effects" (should be an attribute of some kind) * Require the compiler to be able to run such functions at compile time if the arguments are compile-time-valueshard to do, chews up keywords.Hard to make guarantees in those respects, I think. It would also be *really* annoying to maintain. But then, I'm not really interested in writing libraries, so if it didn't intrude much, I'd not really complain.What do you mean? Maintain the code? Nothing special to do there. I just propose the additional possibility to give a special attribute to some functions so they can be used in places where the result has to be know at compile time. This doesn't restrict the use of the function, just what you can do within. And since, usually, you would't want to do expensive computations at compile-time anyway, it is mainly meant for tiny, simple functions after all. So where's the problem? Of course, the compiler needs some additional intelligence, but about all that is needed is there already for optimization. Basically, what I'm talking about, is constant folding and inlining. About every reasonable compiler has those, so the extra effort is not that bad. What is needed, is to define what exactly is allowed in a function without side-effects and assure that the compiler can do those things at compile time. Ciao, Nobbi
Jan 17 2003
this is something I have been thinking about, allowing D to be used for runtime and compile time code. allowing sections of code, and variables to exists at compile time (a D interpreter as part of the D compile, the ast/dag could be interpreted instead of compiled) you can perform all the features of C preprocessor macros and inline functions etc; I think allowing a clear distinction between runtime and compile time values and code may seem odd to C/C++ programmers and is a feature I've not seen in any languages (has anyone?), but is something I've wanted in several. compiletime { .... compile time executed D ... } so to create a static array of constants Object[] foo; // may have to be compiletime(visible) Object[] foo; // might be compiletime( only ) { // or compiletime( eval ) { compiletime { /// perfroms the same op as c++ [cost] Object[] = { { 1, 2 }, { 2, 4, } ..... }; but with more flexability /// will actually create a "snap shot" in rom/code/ram of the compiled object mesh. foo = new MyObject[5]; for ( int i = 0; i < 5; i++ ) { foo[i] = new MyObject( i, myFunc( i*2 ) ); } } compiletime int min( int a, int b ) { return a < b ? a : b ; } would only compile if a and b are determinable at compile time, in the current context etc and so on it would be good if templates could have parameter arrays too template foo ( T, P ) { T myFunc( P ) { compiletime { if ( cast( ctParams[]) P ) { if ( !(P[0].hasoperator( +, T ) ) ) throw new CompileTimeError( "Param 0 must have and operator + for foo.MyFunc to work" ); runtime { T = compileTime P[0] + compileTime P[1]; } } else throw CompileTimeError( "P must be a param list type " ); } } } "Norbert Nemec" <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> wrote in message news:b090su$2qf4$1 digitaldaemon.com...Hi there, just a quick and dirty suggestion: How about allowing "if"-"else"-blocks outside of function blocks? Ofcourse,the argument will have to be computable at compile time. This simple construct will allow several things: * "version" could become a boolean expression instead of a blockstatement.version(...) { } would become if(version(...)) { } with the added possibily of logic constructions. * Together with integers as template parameters, the data fields of a template class could be dependant on those parameters. The addition should be absolutely straightforward. Anyhow a few more additions would make it even more powerful: * Define "compile-time-value" as any value that can be deduced by the compiler. * Define "function without side-effects" (should be an attribute of some kind) * Require the compiler to be able to run such functions at compile time if the arguments are compile-time-value Now, every expression made up of constants, basic operators and functions without side-effects are compile-time-values. This all taken together would perhaps give us all the compile-time-computing-power we need to put really heavy optimization into a library. One more detail: There should be an argument for function arguments to be specified as compile-time-values. This way, the function can only becalledwith a compile-time-value provided at that point, and inside the function, the value can be used, p.e. as a template parameter. And a last thought: it might prove useful to provide a larger set of expressions for handling types, like comparing them, etc. so these can be used in compile-time decisions within a template library. Ciao, Nobbi
Jan 17 2003
Mike Wynn wrote:this is something I have been thinking about, allowing D to be used for runtime and compile time code. allowing sections of code, and variables to exists at compile time (a D interpreter as part of the D compile, the ast/dag could be interpreted instead of compiled) you can perform all the features of C preprocessor macros and inline functions etc; I think allowing a clear distinction between runtime and compile time values and code may seem odd to C/C++ programmers and is a feature I've not seen in any languages (has anyone?), but is something I've wanted in several.Well, part of it is present in many languages. C++ allows a const to be calculated as an expression of other consts. I never thought of any special "compiletime" functions, but just of functions that are allowed in such a constant expression. Many language features (like pointer handling etc.) would have to be prohibited in those restricted functions, but otherwise they are just plain functions usuable at any point in the code. The only point where the whole thing goes beyond plain constant folding is, that via "if" statements outside of functions, there can be arbitrary decisions made at compile time about the code that is to be produced. Anyhow, the idea of a "CompileTimeError" is something I missed. Of course this would be necessary - although I don't think "throw" should be used for it. It should rather be done by a separate statement. Ciao, Nobbi
Jan 17 2003
"Norbert Nemec" <Nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> wrote in message news:b0a9i8$jm6$1 digitaldaemon.com...Mike Wynn wrote:specialthis is something I have been thinking about, allowing D to be used for runtime and compile time code. allowing sections of code, and variables to exists at compile time (a D interpreter as part of the D compile, the ast/dag could be interpreted instead of compiled) you can perform all the features of C preprocessor macros and inline functions etc; I think allowing a clear distinction between runtime and compile time values and code may seem odd to C/C++ programmers and is a feature I've not seen in any languages (has anyone?), but is something I've wanted in several.Well, part of it is present in many languages. C++ allows a const to be calculated as an expression of other consts. I never thought of any"compiletime" functions, but just of functions that are allowed in such a constant expression. Many language features (like pointer handling etc.) would have to be prohibited in those restricted functions, but otherwise they are just plain functions usuable at any point in the code. The only point where the whole thing goes beyond plain constant folding is, thatvia"if" statements outside of functions, there can be arbitrary decisionsmadeat compile time about the code that is to be produced.exactly my point, parts are present in other langs, but not the concept that code can be run at either compile time or runtime explicitly. why stop at 'if', if you have if, you need to have expressions, many statements can be written as expressions; infact many programs can be rewritten to be one expression, so not why go that extra step; this allows manual control over constant folding allows you to write lookuptables in the same code as the program; think of it this way, you can write a sin lookuptable (float ->fixed compile time conversion) that is build by the compiler to run on a platform without floats, but without having to write two programs. no more writing programs to generate source code, for the compiler to compile, you write is all in one program, easy to maintain, easy to modify when things change 0..360 deg lookup not 0..256 all the consts that the lookuptable gen code sees are all the same values that the final code sees pointers to static data are known at compile time (or enough is know about them to link later) so why not allow compile time new that allocate in the final code/rom image ?Anyhow, the idea of a "CompileTimeError" is something I missed. Of course this would be necessary - although I don't think "throw" should be usedforit. It should rather be done by a separate statement.Why ? that's what exceptions are for, I can not continue along this code path - goto somewhere (anywhere) that can deal with the problem. seem simple and logical (to me). why add yet another keyword/feature when there is a perfect solution already there. all though I do see a problem with 'new' which would create the exception object in the final image, but thats o.k. because the compile is being terminated, if the exception is caught, that's also o.k. the new'ed objects would only need one gc mark-sweep cycle to remove unreachables before comitting the data to the object file image. Mike.
Jan 17 2003
Mike Wynn wrote:why stop at 'if'...Be careful on how far you take the concept. My suggestions were tiny, easy to implement extensions to the current language. Of course, one can always start dreaming, but in the end, the whole suggestion will just be to invading and complex to be realistic. D is not a language to experiment with great, new ideas, but to stay in well-known terrain and make the best out of it. I think, my few suggestions were pretty straightforward and one can about estimate their overall effects on the overall language, but once you get beyond that point, there's the danger that many more extensions have to be added to compensate effects you never dreamed of. Just think of templates in C++. They were a pretty revolutionary concept when they were invented, and that is the cause for most of the problems of complexity they introduce. Ciao, Nobbi
Jan 18 2003
"Norbert Nemec" <Nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> wrote in message news:b0bdua$185s$1 digitaldaemon.com...Mike Wynn wrote:the think is parts are already there consider bit a = (SOME_CONST < 5) || (SOMEOTHER>600); which is infact bit a; if ( SOME_CONST < 5 ) { a = true;} else if (SOMEOTHER>600){ a = true } else { a = false; } more fun, D has the C comma operator; I must try out const int a = 3; int b; int c = (b = (a+3)), a+5; it does not work (not that I'm suprised) const int a = 3; int b; int c = (b = a); gives "test.d(6): non-constant expression b = 3" but int d = a+5; bit e = (a<3)||(a>67); compile finewhy stop at 'if'...Be careful on how far you take the concept. My suggestions were tiny, easy to implement extensions to the current language. Of course, one can always start dreaming, but in the end, the whole suggestion will just be to invading and complex to be realistic. D is not a language to experiment with great, new ideas, but to stay in well-known terrain and make the best out of it.I think, my few suggestions were pretty straightforward and one can about estimate their overall effects on the overall language, but once you get beyond that point, there's the danger that many more extensions have to be added to compensate effects you never dreamed of.your right, but conditional compilation exists in D with the use of 'version( foo ) { ... }' and I've realised that what I realy want in const functions and constructors; that is a function whose output is ONLY determined by its inputs and has no effect on anything other than its locals and return value. the same for constructors, which only effect the object, and could only call const constructors of members. this means that as long as the params are fully determinable at compile time, the return of the function or the consturcted object would also be fully determinable at compile time.Just think of templates in C++. They were a pretty revolutionary concept when they were invented, and that is the cause for most of the problems of complexity they introduce.and for all their faults and complex probems they introduce they are now a standard feature that people expect a new language to have.
Jan 18 2003
"Mike Wynn" <mike.wynn l8night.co.uk> escreveu na mensagem news:b09ou3$9jj$1 digitaldaemon.com...this is something I have been thinking about, allowing D to be used for runtime and compile time code. allowing sections of code, and variables to exists at compile time (a D interpreter as part of the D compile, the ast/dag could be interpreted instead of compiled) you can perform all the features of C preprocessor macros and inline functions etc; I think allowing a clear distinction between runtime and compile timevaluesand code may seem odd to C/C++ programmers and is a feature I've not seeninany languages (has anyone?), but is something I've wanted in several.Syntax definitions in Scheme are macro expanded at compile-time but accessing the entire environment while doing so. http://www.scheme.com/tspl2d/ and http://www.schemers.org/Documents/Standards/R5RS/ can give you directions. They're different from normal function definitions, but can be used as language primitives.compiletime { .... compile time executed D ... } so to create a static array of constants Object[] foo; // may have to be compiletime(visible) Object[] foo; // might be compiletime( only ) { // or compiletime( eval ) { compiletime { /// perfroms the same op as c++ [cost] Object[] = { { 1, 2 }, { 2, 4, } ..... }; but with more flexability /// will actually create a "snap shot" in rom/code/ram of the compiled object mesh. foo = new MyObject[5]; for ( int i = 0; i < 5; i++ ) { foo[i] = new MyObject( i, myFunc( i*2 ) ); } } compiletime int min( int a, int b ) { return a < b ? a : b ; } would only compile if a and b are determinable at compile time, in the current context etc and so on it would be good if templates could have parameter arrays too template foo ( T, P ) { T myFunc( P ) { compiletime { if ( cast( ctParams[]) P ) { if ( !(P[0].hasoperator( +, T ) ) ) throw new CompileTimeError( "Param 0 must have and operator + for foo.MyFunc to work" ); runtime { T = compileTime P[0] + compileTime P[1]; } } else throw CompileTimeError( "P must be a param list type " ); } } } "Norbert Nemec" <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM>wrotein message news:b090su$2qf4$1 digitaldaemon.com...ifHi there, just a quick and dirty suggestion: How about allowing "if"-"else"-blocks outside of function blocks? Ofcourse,the argument will have to be computable at compile time. This simple construct will allow several things: * "version" could become a boolean expression instead of a blockstatement.version(...) { } would become if(version(...)) { } with the added possibily of logic constructions. * Together with integers as template parameters, the data fields of a template class could be dependant on those parameters. The addition should be absolutely straightforward. Anyhow a few more additions would make it even more powerful: * Define "compile-time-value" as any value that can be deduced by the compiler. * Define "function without side-effects" (should be an attribute of some kind) * Require the compiler to be able to run such functions at compile timefunctionsthe arguments are compile-time-value Now, every expression made up of constants, basic operators andintowithout side-effects are compile-time-values. This all taken together would perhaps give us all the compile-time-computing-power we need to put really heavy optimizationbea library. One more detail: There should be an argument for function arguments tofunction,specified as compile-time-values. This way, the function can only becalledwith a compile-time-value provided at that point, and inside thebethe value can be used, p.e. as a template parameter. And a last thought: it might prove useful to provide a larger set of expressions for handling types, like comparing them, etc. so these can--- Outgoing mail is certified Virus Free. Checked by AVG anti-virus system (http://www.grisoft.com). Version: 6.0.443 / Virus Database: 248 - Release Date: 11/1/2003used in compile-time decisions within a template library. Ciao, Nobbi
Jan 17 2003
"Mike Wynn" <mike.wynn l8night.co.uk> escreveu na mensagem news:b09ou3$9jj$1 digitaldaemon.com...seenthis is something I have been thinking about, allowing D to be used for runtime and compile time code. allowing sections of code, and variables to exists at compile time (a D interpreter as part of the D compile, the ast/dag could be interpreted instead of compiled) you can perform all the features of C preprocessor macros and inline functions etc; I think allowing a clear distinction between runtime and compile timevaluesand code may seem odd to C/C++ programmers and is a feature I've notinI must read that more fully, but looks very much along the lines I was thinking about. I would like scheme if it is was not for the prolific use of brackets, and the lack of list indexed access (all those cddar's cry out for c[2] in my mind (wrote some gimp scripts, that was enough scheme for me)).any languages (has anyone?), but is something I've wanted in several.Syntax definitions in Scheme are macro expanded at compile-time but accessing the entire environment while doing so. http://www.scheme.com/tspl2d/ and http://www.schemers.org/Documents/Standards/R5RS/ can give you directions. They're different from normal function definitions, but can be used as language primitives.
Jan 18 2003
Yes; this feature of Boost::mpl is extremely handy. Sean "Mike Wynn" <mike.wynn l8night.co.uk> wrote in message news:b09ou3$9jj$1 digitaldaemon.com...it would be good if templates could have parameter arrays too
Jan 18 2003