-
Notifications
You must be signed in to change notification settings - Fork 162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New compiler: Initializers for global classic arrays and structs #2662
base: ags4
Are you sure you want to change the base?
New compiler: Initializers for global classic arrays and structs #2662
Conversation
A `char[]` is considered an empty string whenever a '\0' is in its first byte, but a `std::string` cannot be handled that way: → use `clear()` and `empty()`. Some strings in the interface of the compiler have been converted from `char[]` into `std::string`. Update the handling within the parser to account for that.
These tests are often run in parallel, and then 'ccSetOption()' calls that happen concurrently clobber each other's effect. Convert to the 4-parameter function 'cc_compile()' of the new compiler, which has a dedicated parameter for the compiler options.
Recently, a lot of `char[]` in the interface to the compiler have been converted to `std::string`. Rewrite the functions that generate bytecode tests or that compare interface components to match. Also provide code to compare and check the `scrip.globaldata` that the compiler generates. Make some library functions `static`, as suggested by the MSVS compiler.
Add Googletest for the new function
This sounds great! I shall test this soon.
Are these technically possible and may they be planned for the future, or not at all? Personally, I believe that having a ordered struct initializer will be very convenient for simple structs and also consistent with the function argument list syntax (where you can pass arguments either ordered or named). Local initialization: in theory these can be done by preallocating a struct and then filling them with results of expressions inside initializer. But also, since they are executed at runtime, these may contain non-constexpr expressions, like function calls and |
Yes, it's doable: The fields are ordered in the symbol table: They come in the order in which they were defined. If the struct has been extended, then the ancester fields and perhaps the fields of their ancesters etc. must be considered, too. We can define a sequence from that, e.g., ‘first the fields of the ancester's ancester, then the added fields of the ancester, then the added fields of the struct proper’ – and then an initializer list (From a practical perspective of the user-programmer, a sequence list saves some typing in comparison to a named list, but when the fields in the struct get moved around afterwards for some reason then it's very error-prone to find and change around the respective initializations. I've been there. 😀 But that's an aside.)
Yes, that's also doable. It would be a different piece of code that would have to be added to another place in the compiler than where the globals are initialized, but it can definitely be done. I'm not against doing those two in principle, it's just that I haven't implemented them for now. |
- `struct` components uninitialized after construction - Refer to data of a vector v as `&v[0]` instead of `v.data()` - LINUM directives left out or generated erroneously
Fixes #2152
I've implemented the possibility to initialize global structs and global classic arrays, using a similar syntax as we (now) have for parameters.
Background
Global variables can be initialized at compile time: The compiler essentially prepares in a byte buffer an image of all the global variables with the initial values already set so that the variables can be used at run time without any further processing. (Managed variables can only be initialized to
null
this way.)Of course, this can only work when the compiler knows what initial values those global variables should have. Previously, there was no way of specifying the initial values for
struct
variables and for classic arrays. Now there is a way.I've implemented the following initializations:
Initializer for non-managed
struct
variablesNotes:
HasAirbags
is set to binary zeros, i.e., tofalse
struct
may have managed fields such asString
s, but the only value that you can initialize them to isnull
.struct A
extends astruct B
and you initialize a variable of typeA
, then you can initialize all the fields fromA
andB
by just naming them:fieldname : value
. You cannot simply list the values without the fieldnames in some sequential order (I haven't implemented that for now).struct
variable can have a field that is anotherstruct
. In this case, the initializers are nested:Initializers for classic (i.e., non-dynamic) array variables
I provide several ways:
Sequence initialization
Notes:
int
andfloat
expressions that can be evaluated at compile timeNamed initialization
Notes:
{ 1, 2, [5]: 99 }
or{ [0]: 2, [1]: 3, 5, 7, }
Multi-dimensional classic arrays
An
int Foo[2][3]
is treated as2
arrays, each of which has3
values. So this is how the array is initialized:Notes:
C++
offers the possibility to omit all the inner braces and simply list all the values. I have not implemented that. For instance, you cannot defineint Spreadsheet[2][3] = { 1, 2, 3, 4, 5, 6);
Special case: Classic one-dimensional
char
arraysThese can also be initialized by a string literal.
Notes:
\0
must be at most as long as the array, otherwise the compiler will balk. This is a safeguard attempt for when this array is passed as an argument to a function (e.g.,Display(SafeCode);
)Local
struct
s and local classic arraysUnfortunately, not supported for now. If you define an array within a function, you'll have to initialize its values the old-fashioned way. These initializations need to happen at runtime, anyway.