See Vs. See
- Posted by Mike The Spike <mtsreborn at yahoo.com> Feb 07, 2001
- 444 views
And then the fly whent on to drink the blood boiled in the mediaval stadium gathered from amputated breasts and shot with the flare gun into the car's back seat... Zzzz... Zzzzz..... Heh wha who huh??? Oh, yeah... Err, sorry bout that, sleaping... Anyways, I've being studying Eu To C for quite some time now, and have found that it's not as fast as it ought to be. And I don't see any ways of optimising the code directly, by changing the code produced. Therefore, we should look at WHAT is produced instead. >From a single Euphoria line, what will the C lines look like? To illustarte my point, ie. why the translator is slow, I wrote a few quicky untested C listings, one produced by the translator, and one written by hand. Here we go, pay close attention, eventhough you don't know any C. -----------------A Simple Math Demo In C-------------- #include <stdio.h> #include <stdlib.h> void main() { int a, b, c, d; float fa, fb, fc, fd; a = 50; b = a + 10; c = b * 2 - 1; d = a + b + c * 4 / 2; fa = 3.14; fb = fa * 2; fc = fa + fb / 12.0; fd = fa * fb + fc * 5.5; printf("%d %d %d %d %f %f %f %f",a,b,c,d,fa,fb,fc,fd); } --------------The Above Program In Euphoria---------- integer a, b, c, d atom fa, fb, fc, fd a = 50 b = a + 10 c = b * 2 - 1 d = a + b + c * 4 / 2 fa = 3.14 fb = fa * 2 fc = fa + fb / 12.0 fd = fa * fb + fc * 5.5 printf(1,"%d %d %d %d %f %f %f %f",{a,b,c,d,fa,fb,fc,fd}) -----------Above Program Translated To C------------- void __stdcall WinMain(void *hInstance, void *hPrevInstance, char *szCmdLine, int iCmdShow) { int _21 = 0; int _26 = 0; int _0, _1, _2, _3; int argc; char **argv; argc = 1; argv = make_arg_cv(szCmdLine, &argc); winInstance = hInstance; eu_startup(_00, 0, (int)CLOCKS_PER_SEC, (int)CLOCKS_PER_SEC); init_literal(); shift_args(argc, argv); _0a = 50; _0b = _0a + 10; _21 = _0b + _0b; if (_21 + HIGH_BITS >= 0) _21 = NewDouble((double)_21); if (IS_ATOM_INT(_21)) { _0c = _21 - 1; } else { _0c = NewDouble(DBL_PTR(_21)->dbl - (double)1); } if (!IS_ATOM_INT(_0c)) { _1 = (long)(DBL_PTR(_0c)->dbl); DeRefDS(_0c); _0c = _1; } _0 = _21; _21 = _0a + _0b; if (_21 + HIGH_BITS >= 0) _21 = NewDouble((double)_21); DeRef(_0); if (_0c == (short)_0c && 4 <= INT15 && 4 >= -INT15) _26 = _0c * 4; else _26 = NewDouble(_0c * (double)4); _0 = _26; if (IS_ATOM_INT(_26)) { if (_26 & 1) { _26 = NewDouble((_26 >> 1) + 0.5); } else _26 = _26 >> 1; } else { _26 = binary_op(DIVIDE, _26, 2); } DeRef(_0); if (IS_ATOM_INT(_21) && IS_ATOM_INT(_26)) { _0d = _21 + _26; } else { if (IS_ATOM_INT(_21)) { _0d = NewDouble((double)_21 + DBL_PTR(_26)->dbl); } else { if (IS_ATOM_INT(_26)) { _0d = NewDouble(DBL_PTR(_21)->dbl + (double)_26); } else _0d = NewDouble(DBL_PTR(_21)->dbl + DBL_PTR(_26)->dbl); } } if (!IS_ATOM_INT(_0d)) { _1 = (long)(DBL_PTR(_0d)->dbl); DeRefDS(_0d); _0d = _1; } RefDS(_29); DeRef(_0fa); _0fa = _29; _0 = _0fb; if (IS_ATOM_INT(_0fa) && IS_ATOM_INT(_0fa)) { _0fb = _0fa + _0fa; if (_0fb + HIGH_BITS >= 0) _0fb = NewDouble((double)_0fb); } else { if (IS_ATOM_INT(_0fa)) { _0fb = NewDouble((double)_0fa + DBL_PTR(_0fa)->dbl); } else { if (IS_ATOM_INT(_0fa)) { _0fb = NewDouble(DBL_PTR(_0fa)->dbl + (double)_0fa); } else _0fb = NewDouble(DBL_PTR(_0fa)->dbl + DBL_PTR(_0fa)->dbl); } } DeRef(_0); _0 = _26; if (IS_ATOM_INT(_0fb)) { _26 = NewDouble((double)_0fb / DBL_PTR(_31)->dbl); } else { _26 = NewDouble(DBL_PTR(_0fb)->dbl / DBL_PTR(_31)->dbl); } DeRef(_0); _0 = _0fc; if (IS_ATOM_INT(_0fa) && IS_ATOM_INT(_26)) { _0fc = _0fa + _26; if (_0fc + HIGH_BITS >= 0) _0fc = NewDouble((double)_0fc); } else { if (IS_ATOM_INT(_0fa)) { _0fc = NewDouble((double)_0fa + DBL_PTR(_26)->dbl); } else { if (IS_ATOM_INT(_26)) { _0fc = NewDouble(DBL_PTR(_0fa)->dbl + (double)_26); } else _0fc = NewDouble(DBL_PTR(_0fa)->dbl + DBL_PTR(_26)->dbl); } } DeRef(_0); _0 = _26; if (IS_ATOM_INT(_0fa) && IS_ATOM_INT(_0fb)) { if (_0fa == (short)_0fa && _0fb <= INT15 && _0fb >= -INT15) _26 = _0fa * _0fb; else _26 = NewDouble(_0fa * (double)_0fb); } else { if (IS_ATOM_INT(_0fa)) { _26 = NewDouble((double)_0fa * DBL_PTR(_0fb)->dbl); } else { if (IS_ATOM_INT(_0fb)) { _26 = NewDouble(DBL_PTR(_0fa)->dbl * (double)_0fb); } else _26 = NewDouble(DBL_PTR(_0fa)->dbl * DBL_PTR(_0fb)->dbl); } } DeRef(_0); _0 = _21; if (IS_ATOM_INT(_0fc)) { _21 = NewDouble((double)_0fc * DBL_PTR(_35)->dbl); } else { _21 = NewDouble(DBL_PTR(_0fc)->dbl * DBL_PTR(_35)->dbl); } DeRef(_0); _0 = _0fd; if (IS_ATOM_INT(_26)) { _0fd = NewDouble((double)_26 + DBL_PTR(_21)->dbl); } else { _0fd = NewDouble(DBL_PTR(_26)->dbl + DBL_PTR(_21)->dbl); } DeRef(_0); _0 = _21; _1 = NewS1(8); _2 = (int)((s1_ptr)_1)->first; *((int *)(_2+0)) = _0a; *((int *)(_2+4)) = _0b; *((int *)(_2+8)) = _0c; *((int *)(_2+12)) = _0d; Ref(_0fa); *((int *)(_2+16)) = _0fa; Ref(_0fb); *((int *)(_2+20)) = _0fb; Ref(_0fc); *((int *)(_2+24)) = _0fc; Ref(_0fd); *((int *)(_2+28)) = _0fd; _21 = MAKE_SEQ(_1); DeRef(_0); EPrintf(1, _38, _21); Cleanup(0); } -----------------End Of Examples------------------- Now, did you see the difference between the hand-coded C version and the generated C version? Robert told me his goal is to get to hand-coded C as close as possible with the translator. Then, I wounder, why he didn't code the translator to translate the Euphoria version listed here, to C like this; #include <stdio.h> #include <stdlib.h> void main() { int a, b, c, d; float fa, fb, fc, fd; a = 50; b = a + 10; c = b * 2 - 1; d = a + b + c * 4 / 2; fa = 3.14; fb = fa * 2; fc = fa + fb / 12.0; fd = fa * fb + fc * 5.5; printf("%d %d %d %d %f %f %f %f",a,b,c,d,fa,fb,fc,fd); } Instead of all that crap listed above. Then you wounder why it's slow... The translator should be smart, and try to map Euphoria to C as close as possible. One line of Euphoria code should be translated to about one line of C code, two at the most. When atoms are used in a program, wich get assigned floating point values, yet aren't used anywhere else in the program, the atoms should be translated to 'float' or 'double' in C. 'integer' should be 'int' in C, and that's it. Sequences, objects, etc. can remain how they are implemented. For example, say you have the following Eu code; procedure docrap(integer a, integer b) printf(1,"a+b = %d!!!",a+b) end procedure Then it should be translated to C like this; void docrap(int a, int b) { printf("a+b = %d!!!",a+b) } Untill the EUphoria To C Translator works like this, we will always lag seriously behind hand-coded C. "Sure!" You might say. "You give easy Euphoria programs as example!". Well, here's a complex one, and how it *should* be translated to C (for maximum speed, readability and portability); -----Eu Version include get.e include file.e integer fptr fptr = open("crap.txt","w") procedure writecrap(integer where) for i = 1 to 5000 do puts(where,"YOU SUCK WHITE ASS!!!\n") end for end procedure writecrap(fptr) close(fptr) -- C Version #include <stdio.h> #include <stdlib.h> void writecrap(FILE *where) { int i; for(i = 0; i < 5000; i++) puts("YOU SUCK WHITE ASS!!!"); } main() { FILE * fptr; fptr = fopen("crap.txt","w"); writecrap(fptr); fclose(fptr); } Now *THAT'S* "Translating To C". What EC.EXE does is more "Outputting A C Version", not *Translating* to C. The translator shouldn't slap 300 lines of C code where a 6 line Euphoria program used to be, it should slap out 6 to 8 lines of C code where that program used to be. We're waiting, Rob ;) Mike The Spike