Folks working on the Smalltalk to C Translator:
I agree with what Andrew says below. But as the guy who designed and implemented Slang in the first place, I can't resist throwing in a few additional words about its history and design philosophy. :->
First, one can always add features. But it takes a great deal of restraint and good taste to NOT add every feature you can think of. One the secrets to the portability of Squeak is that the Smalltalk to C translator started off nearly as minimal as it could possibly be (only about 3 dozen rules). In many cases, it seemed better to modify the Smalltalk code to be translated rather than adding additional features to the translator. Although we are now using the translator to build primitives in addition to building the VM itself, I still think it is reasonable to balance the cost of modifying the code to be translated against the cost of adding (and maintaining) translator features. I'm not arguing against progress, here, just pointining out that there are several paths to the desired goal.
We were very conservative about the dialect of C that the translator generates. We stuck entirely to the ANSI C standard and in at least one case (right shifts) tried to do the least ambiguous thing even though the spec itself does not fully define the operation. This conservative approach has been a huge success and we should be careful not to introduce any new feature which is not 100% ANSI C. The question is what your compiler or my compiler does, but what the ANSI C spec says *ALL* C compilers should do. Some C compilers have an ANSI compatible switch; if so, that can be used to verify that we aren't generating non-conforming code. But the safest thing is to follow the spec. I use the Kernighan and Ritchie C manual, Second Edition.
Thanks for the recent work on the Smalltalk-to-C translator, expecially the combined efforts of Stephan Rudlof and Andrew Greenberg.
Happy Holidays!
-- John
At 12:29 PM -0500 12/25/99, Andrew C. Greenberg wrote:
I'm not a compiler specialist, but couldn't the compiler recognize if there are control structures like 'for' or 'while' which aren't allowed in C construct like (expr) ? (commaSeparatedStmtList, expr) : (commaSeparatedStmtList, expr); ? Then it could generate an error.
I'm sure it could, but what is the virtue, if any, of having a compiler with such peculiar semantics? In particular, of compiling
var := condition ifTrue: [expression].
but not
var := cond1 ifTrue: [[cond2] whileTrue: [stmts]. expression]
? To my mind, it would be far less funky to have (as C has) either two separate syntactic constructs for the control structure and the conditional expression, or simply to forego the conditional expression. No one denies that the Slang subset isn't a complete Smalltalk. The question is whether any extensions are more beneficial than costly on all relevant fronts. As "ugly" as having a separate #exprIfTrue:#exprIfFalse construct for translation to the C conditional expression may seem at first blush, I think to the extent the functionality is necessary, it may be the clearest way to distinguish the two without confusing users. (Also, compiling "?:" and "," everwhere in lieu of "if()" and ";", while still providing a capacity to have control statements inside a conditional, when the conditional is not itself part of an expression will substantially complicate the compiler, but more important, would make cCode highly unreadable, IMHO.)
Again, the issue is whether the benefits outweigh the costs. One of the reasons that many of the more important changes you have requested thus far have been so quickly implemented derives in large part from the simplicity and elegance of the CCodeGenerator design. That simplicity has some costs, of course. I just don't think the cost of rewriting the two expression above as
condition ifTrue: [var := expression].
cond1 ifTrue: [[cond2] whileTrue: [stmts]. var := expr]
is all that bad as compared to the cost of having the more "Smalltalk-like" expression semantics widely available. And even if it was really necessary to support conditional expressions, you could always write the first expression above as:
var := condition exprIfTrue: [expression].
after implementing the builtin, a substantially easier task than the one you suggested. To me, however, the status quo feels just fine.
My C compiler accepts constructs like:
void vf( int arg) { printf("\nvf( %d)", arg); } double df( int arg) { printf("\ndf( %d)", arg); return arg; }
void main() { int k; k = 0 == 0 ? vf(1), df(2) : df(3), df(4); printf("\nk: %d", k); k = 0 == 1 ? vf(1), df(2) : df(3), df(4); printf("\nk: %d", k); // interpreted as: ( k = (0 == num) ? (vf(1), df(2)) : df(3) ), df(4); // so it makes sense to use more braces... }
This begs the question, of course.
, so it is possible to use - not control - statements inside expressions.
Function calls are most certainly C expressions.
The point of CCompiler is not to implement Smalltalk, but just a subset sufficient to express a hunk-o-code.
But it is as easier to write plugins as more ST constructs are eaten by the ST2C compiler...;-)
It also gets confusing when "the same" construct works sometimes but not others.
P.S.: To avoid misunderstandings: This is not a criticism of your work (it is great!), but a suggestion for - possible and nice, but not necessary - improvements!
The CCodeGenerator was not my work, but that of SqueakCentral, and Slang was one of the fundamental inventions that begat Squeak. My work has been focused on tweaking it from time to time, and adding the ability to specify primitives.
squeak-dev@lists.squeakfoundation.org