Ben Bacarisse said:
This point and the last one suggest that you are generating code at what
I'd be tempted to call the wrong level. I.e. rather than a compiler it
sounds like a translator.
It originally targeted ASM, so I guess it's a compiler. Maybe I could
generate C from the AST instead of intermediate code, and it might be
possible to create more structured C that way than the 'flat' C I'm creating
now. But I don't think that would solve too many of my current problems, and
would probably create new ones!
If your source language pointers are type
agnostic and use bytes offsets, I'd expect them all to appear as
unsigned char pointer in the C output. C's rules for pointer
compatibility and arithmetic won't then come into it.
My pointers are typed, but I just use byte offsets which are more flexible.
As an example of the type issues I have to deal with in C, take this program
in my source language (to do with the function casts I was asking about).
Not C-like, but hopefully clear:
ref int pcptr
proc disploop=
ref ref proc() fnptr @ pcptr
do
fnptr^^()
od
end
This is the C code generated (in the above code, fnptr and pcptr are the
same memory location, that needs to be emulated in C):
static void disploop(void);
static int (*pcptr);
void disploop(void) {
/* void (*(*fnptr)) (void) @pcptr */
L2:
(*((void (*(*)) (void))pcptr))();
goto L2;
}
And this is the x86 code that I might generate instead, just the function
body:
disploop:
L3:
mov esi,[pcptr]
mov eax,[esi]
call eax
jmp L3
retn
Notice this doesn't involve asterisks, parentheses or voids that have to be
in exactly the right pattern! Although the generated C could have been
tidied up a bit, I don't see how this stuff can be avoided, no matter how
the C is generated.
Surely all your source-language names are kept in a separate space? You
can then use an "escape" convention to capture case: source name func
maps to srcfunc__ and Func to, say, src_func__. I can't see how a
reserved word can be a problem unless you are trying to some sort of
minimal source-level translation rather than what would be more normally
termed compilation.
If, on the other hand, you've decided that C functions should be
callable with no wrappers at all, then I think you've just made a rod
for your own back.
Maybe. Some problems can solved by writing wrapper functions *in C*. But I'm
trying to avoid that (you can't tell someone using the language and trying
to call an imported C function, to switch to another language!). As a silly
example, take this program in my source language:
stop
which is translated to a call to a runtime function, also in the source
language, which happens to call the imported C function exit(). However
'exit' is a reserved word in my language! So I call a wrapper function in C,
which calls exit() for me.