gbdev / rgbds

Rednex Game Boy Development System - An assembly toolchain for the Nintendo Game Boy and Game Boy Color
https://rgbds.gbdev.io
MIT License
1.33k stars 175 forks source link

[Feature request] File-local defines #342

Open aaaaaa123456789 opened 5 years ago

aaaaaa123456789 commented 5 years ago

Some projects are a hairy mess of file inclusions. It happens, and there's not much we can do about it after some time.

The consequence of this is that, after resolving all the inclusions (imagine a rgbasm option equivalent to gcc -E), the actually assembled file is tens of thousands (or hundreds of thousands) of lines long. Anything defined anywhere through this chain of includes is visible anywhere afterwards, including in the parent, things included by the parent, and so on. This is often desirable (think of a constants file), but not always.

Thus, what I'm requesting are equivalents to EQU, EQUS and MACRO (and any other similar keywords you can think of) that don't traverse file inclusions — whatever they define is local to the file, isn't inherited by included files, and is purged automatically when the file ends. This would make it a lot simpler to define local constants, etc., without having to end files with a long stream of PURGE commands.

Thoughts? Comments?

mid-kid commented 5 years ago

I'm sorry, I just don't see how this is any different from what we currently have: Symbols in one translation unit aren't visible by other translation units unless you export them or include them from a "shared includes" file (or more than one file, up to you).

Furthermore, what happens with the symbols when one file is included in the middle of another file? Will the included file inherit the parent's "local symbols"? Will the parent's "local symbols" be restored when the included file ends? If so, I guess we also need a "local symbol hash table" stack. Also, what happens to regular labels, should they also have a new keyword to be file-local?

I don't know, I guess more ways to do something aren't always bad, but this is just something we already have... This would just emulate objects and a linker script with additional keywords and INCLUDEs.

aaaaaa123456789 commented 5 years ago

Symbols in one translation unit aren't visible by other translation units unless you export them or include them from a "shared includes" file (or more than one file, up to you).

When you include hundreds of files into a single "main" file, they become a single translation unit. This is a common pattern for a lot of reasons. (Hence my opening line in the OP.)

Furthermore, what happens with the symbols when one file is included in the middle of another file?

This is exactly what I'm asking these new keywords to change:

Will the included file inherit the parent's "local symbols"?

No, that's why they are local.

Will the parent's "local symbols" be restored when the included file ends?

Yes; local symbols would have file scope.

If so, I guess we also need a "local symbol hash table" stack.

Probably.

Also, what happens to regular labels, should they also have a new keyword to be file-local?

This would be amazing, as it would help reduce source code duplication when there are actual reasons to have duplicated code in the output binary (one immediate use case I can think of is pokered's audio engine, which is included several times (I think three) into the ROM — right now they just have three identical copies of the code, but with file-local labels, they could just include the same file three times). I thought it would be far more work than equates and macros, though, which is why I didn't ask for this at first.

this is just something we already have

It isn't, because the current system has no way of dealing with file inclusion webs. INCLUDE is pretty much the same as C's #include, so everything that is limited to "the current translation unit", much like in C, will cross inclusion boundaries freely.

AntonioND commented 5 years ago

I don't think this is a good idea. This looks like a project-specific problem that could (maybe) be fixed by organizing includes better from the start.

In any case, the best reason to not implement your proposal is that it would behave in a different way as the C includes. The behaviour of the tools should be easily understood by the users, and everyone knows how include works in C. Changing this behaviour in this toolchain would go against the knowledge of most people, which is: Include inserts the code of that file into the current file, and nothing more.

aaaaaa123456789 commented 5 years ago

Changing this behaviour in this toolchain would go against the knowledge of most people

That's why I'd never suggest that. Instead, I'm asking for completely new keywords that have local behavior.

ISSOtm commented 4 years ago

This was brought up again when discussing how wonky PURGE is—one of its largest uses is trying to keep outer scopes clean when calling macros.

The implementation I would suggest is: any symbol whose first character is an @ will die (implicit PURGE) at the end of the scope it's defined in. Scopes being includes, macros, and REPTs.

ISSOtm commented 4 years ago

The discussion in #492 brought up that such "local" symbols should not be allowed to be externally referenced. (Neither should they be exported, either.)

ISSOtm commented 4 years ago

More discussion: it would be interesting for such a symbol to live as long as the scope it's defined in. Children scopes would inherit the symbols, but if they were to re-define them, then the new definition would "shadow" the parent one until the end of its life. @aaaaaa123456789 paralleled this to the behavior of C variables.

I understand the interest as far as "constant" symbols go, but I'm much less sure about labels.

ISSOtm commented 3 years ago

Since 0.4.2 is late enough imo, I'll be postponing this to 0.4.3 (hopefully.)

Rangi42 commented 3 years ago

any symbol whose first character is an @ will die (implicit PURGE) at the end of the scope it's defined in.

Would this include local symbols like .@foo? That would be useful for not cluttering .sym files with arbitrary \@-generated labels; one could use something like .@temp\@ in a macro.

Rangi42 commented 3 years ago

If the scope of a FOR includes its own symbol, then FOR @IDX, 1, N+1 would be convenient to purge @IDX.

Rangi42 commented 3 years ago

The unusual characters @ and # are allowed in identifiers. If @foo will be local, how about making #foo global/exported?

Rangi42 commented 3 years ago

RASM also allows local labels prefixed with @.