README.md typo fixes, wording improvements
parent
e2b1fddbba
commit
6a3d38d9be
35
README.md
35
README.md
|
|
@ -24,7 +24,7 @@ The only way forward is inside out.
|
||||||
|
|
||||||
3. In any compilation unit where you are going to be C-Scripting, `#include "symbol_set.h"`.
|
3. In any compilation unit where you are going to be C-Scripting, `#include "symbol_set.h"`.
|
||||||
|
|
||||||
4. Before the header, `#define SY__MAIN` -- If you have multiple compilation units, `#define SY__MAIN` into just one of them (perhaps `main.c`).
|
4. Before the header, `#define SY__MAIN` -- If you have multiple compilation units, `#define SY__MAIN 1` into just one of them (perhaps `main.c`).
|
||||||
|
|
||||||
At this point your program should build and behave as it did before setup. If something went wrong for you when you tried, you can contact `support@mr4th.com` and I can try to help you. If it does build, then you're ready to start C-Scripting!
|
At this point your program should build and behave as it did before setup. If something went wrong for you when you tried, you can contact `support@mr4th.com` and I can try to help you. If it does build, then you're ready to start C-Scripting!
|
||||||
|
|
||||||
|
|
@ -161,9 +161,9 @@ The usefulness of having symbols in small consecutive IDs is great, but it is co
|
||||||
|
|
||||||
## 5. Introduction to the Symbol Set programming primitives.
|
## 5. Introduction to the Symbol Set programming primitives.
|
||||||
|
|
||||||
In the file `symbol_set.h` there a couple important sections. The first contains some copy pastable boilerplate. The first contains the boilerplate for setting up a symbol set.
|
In the file `symbol_set.h` the first section contains boilerplate for setting up a symbol set.
|
||||||
|
|
||||||
These first 5 line block define the symbol set itself. For instance if `MY_COMMAND` is the name of my symbol set, and `MyCommand` is the type, the code that instantiates the symbol set could be:
|
The first 5 line block defines a symbol set. For instance if `MY_COMMAND` is the name of my symbol set, and `MyCommand` is the type, the code that instantiates the symbol set could be:
|
||||||
```C
|
```C
|
||||||
#define SYMBOL_SET_DEFINE MY_COMMAND
|
#define SYMBOL_SET_DEFINE MY_COMMAND
|
||||||
#define MY_COMMAND_Type MyCommand
|
#define MY_COMMAND_Type MyCommand
|
||||||
|
|
@ -174,7 +174,7 @@ These first 5 line block define the symbol set itself. For instance if `MY_COMMA
|
||||||
|
|
||||||
The next few blocks define various patterns of helper macros for defining symbols.
|
The next few blocks define various patterns of helper macros for defining symbols.
|
||||||
|
|
||||||
The first block is how I setup macros for defining data-only symbol types.
|
The first block shows how I setup macros "data only" symbol types.
|
||||||
```C
|
```C
|
||||||
#define ZZZ_DEF(N,...) SyDefine(ZZZ, N) = { ... }
|
#define ZZZ_DEF(N,...) SyDefine(ZZZ, N) = { ... }
|
||||||
```
|
```
|
||||||
|
|
@ -189,7 +189,7 @@ And then you'd use it like:
|
||||||
SPRITE_DEFINE(Hero, "Hero.png", .x = 8, .y = 16);
|
SPRITE_DEFINE(Hero, "Hero.png", .x = 8, .y = 16);
|
||||||
```
|
```
|
||||||
|
|
||||||
The next block is how I setup macros for defining symbols with an attached function pointer:
|
The next block is how I setup macros for defining symbols with an attached function:
|
||||||
```C
|
```C
|
||||||
#define ZZZ_DEF(N,...) \
|
#define ZZZ_DEF(N,...) \
|
||||||
static void funczz##N(void*); \
|
static void funczz##N(void*); \
|
||||||
|
|
@ -210,7 +210,18 @@ MY_COMMAND_DEFINE(Foo, "Do Foo.){
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The next block shows how you can also setup symbols that don't have names.
|
I don't have a block for this in the boilerplate, but if you want to create a symbol type that wants multiple attached functions, you can do it like this:
|
||||||
|
```C
|
||||||
|
#define ZZZ_DEF(N,...) \
|
||||||
|
static void func1zz##N(void*); \
|
||||||
|
static void func2zz##N(void*); \
|
||||||
|
SyDefine(ZZZ, N) = { func1zz##N, func2zz##N, ... };
|
||||||
|
|
||||||
|
#define ZZZ_FUNC1(N) void func1zz##N(void*)
|
||||||
|
#define ZZZ_FUNC2(N) void func2zz##N(void*)
|
||||||
|
```
|
||||||
|
|
||||||
|
The final block shows how you can also setup symbols that don't have names.
|
||||||
```C
|
```C
|
||||||
#define ZZZ_DEF(...) SyDefineUnnamed(ZZZ) = { ... }
|
#define ZZZ_DEF(...) SyDefineUnnamed(ZZZ) = { ... }
|
||||||
```
|
```
|
||||||
|
|
@ -232,13 +243,13 @@ I don't really know any examples of unnamed symbols that don't rely on referenci
|
||||||
|
|
||||||
### Inter-Symbol References
|
### Inter-Symbol References
|
||||||
|
|
||||||
First, we can't just store IDs into a symbol the way we'd want, because the data we store into symbols has to be statically resolved, but the IDs aren't resolvable until after linking. What we can do is use a variable address as a constant expression. Even though that the final address of a global variable isn't resolved until link time, the language can count on the linker to fill in the gap with relocations. But relocations werent' built for fixing up IDs.
|
First, we can't just store IDs into a symbol the way we'd want, because the data we store into symbols has to be statically resolved, but the IDs aren't resolvable until after linking. What we can do is use a variable address as a constant expression. Even though the final address of a global variable isn't resolved until link time, the compiler can count on the linker to fill in the gap with relocations, and so the compiler lets you treat that as a constant expression. (Take note, we need ID relocations to do better.)
|
||||||
|
|
||||||
Instead what we do is we store the `Raw` for the symbol. The `Raw` is just the address of the global variable typed as a `SY__UAddr` an address widthed unsigned integer. Then we use `SyIDFromRaw` at init time to translate all of the `Raw`s into `ID`s in place (for this reason I put symbols in read-write memory even when I am treating them as strictly read-only after the ID fixup).
|
Instead what we do is we store the `Raw` for the symbol. The `Raw` is just the address of the global variable typed as a `SY__UAddr`. `SY__UAddr` is an address-widthed unsigned integer. We can use `SyIDFromRaw` at init time to translate all of the `Raw`s into `ID`s in place. It is for this reason that I put symbols in read-write memory even when I am treating them as strictly read-only after the ID fixup.
|
||||||
|
|
||||||
I have developed a helper in `symbol_set.init.h` that I use for managing this. You can include this header after `symbol_set.h`. It sets up a symbol set called `SY_INIT` and each element of this set is a function pointer that describes how to fixup the symbol set.
|
I have developed a helper in `symbol_set.init.h` that I use for managing this. You can include this header after `symbol_set.h`. It sets up a symbol set called `SY_INIT` and each element of this set is a function pointer that describes how to fixup the symbol set.
|
||||||
|
|
||||||
Using this helper defining a symbol that references another symbol looks like this:
|
Using this helper, you define a symbol that references another symbol in the following way:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
typedef struct MyThing{
|
typedef struct MyThing{
|
||||||
|
|
@ -259,11 +270,11 @@ SY_INIT_DEF(MY_THING){
|
||||||
#endif
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
In summary, I wrap the reference to a symbol in the helper macro to make all the symbol definitions easy on the eyes, and to ensure there that `SyRaw` is used and not `SyID`, then if this is the `SY__MAIN` unit, I define a special `SY_INIT` symbol that describes how to loop over the symbol and fixup `SyRaw`s into `SyID`s. I have to manually make sure the symbol set that I use in `SyRaw` matches the one I use in `SyIDFromRaw` or I will just get 0 ids.
|
That is, I wrap the symbol reference in the helper macro to make all the symbol definitions easy on the eyes, and to ensure there that `SyRaw` is used and not `SyID`. Then if this is the compilation unit with `#define SY__MAIN 1`, I define a special `SY_INIT` symbol that describes how to loop over the symbol set and fixup `SyRaw`s into `SyID`s. I have to manually make sure the symbol set that I use in `SyRaw` (in the definition helper macro) matches the one I use in `SyIDFromRaw` (in the `SY_INIT` id fixup). If these don't match `SyIDFromRaw` just gives 0 ids.
|
||||||
|
|
||||||
Then I just have to call `sy__run_init();` early in `main`. I don't use a run-before-main for this, because I already use run-before-mains to automate the location of the array on Windows, and you can't do fixup before you locate symbols. `SY_INIT` is like run-before-main except you decide when to run all the `SY_INIT` functions explicitly, and therefore it can be timed strictly after the initial wiring up.
|
Then I just have to call `sy__run_init();` early in `main`. I don't use a run-before-main for this, because I already use run-before-mains to automate the process of locating symbol set arrays on Windows. These fixups can't be done until after symbols are located. `SY_INIT` is like run-before-main except you decide when to run all the `SY_INIT` functions explicitly, and therefore it can be timed strictly later than the symbol locating process. (In fact, because of all this, symbols shouldn't really be trusted during the "before main" execution phase, they should be considered ready to go at `main` and not necessarily before).
|
||||||
|
|
||||||
This way of organizing the fixups feels makes the maintenance of lots of interconnected symbol sets a lot more manageable than it would be otherwise. I just consider the the ID fixup boilerplate a necessary component of defining the symbol set itself, and whenever I modify the symbol set types I try to be sure to recheck the ID fixup at the same time.
|
This way of organizing the fixups makes the maintenance of lots of interconnected symbol sets a lot more manageable than it would be otherwise. I just consider the the ID fixup boilerplate a necessary component of defining the symbol set itself, and whenever I modify the symbol set types I try to be sure to recheck the ID fixup at the same time.
|
||||||
|
|
||||||
### Symbol Set Referencing Primitives
|
### Symbol Set Referencing Primitives
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue