diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-03-18 13:06:38 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-03-18 13:06:38 -0400 |
| commit | a8e328c015c71f7f835b5b863413d0667fa29327 (patch) | |
| tree | ce79fe0e91f3491bfe318d84b9abfc20c6df80b9 | |
| parent | f4593bff6c242a9feead2ccefc7412b089ce6e1c (diff) | |
Add namespacing doc
| -rw-r--r-- | docs/namespacing.md | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/docs/namespacing.md b/docs/namespacing.md new file mode 100644 index 00000000..e4d023ec --- /dev/null +++ b/docs/namespacing.md @@ -0,0 +1,61 @@ +# Namespacing + +In order to work with C's namespace limitations, I've designed the following +system: + +## Namespaces + +In C, there is a GCC extension (also supported by clang and TCC) to allow for +dollar signs in identifiers. This provides a way to have compiled C code which +segments its imports into different namespaces. For example `Foo$Baz` would be +the identifier `Baz` in the namespace `Foo`, and would be guaranteed to not +collide with a user-chosen name like `FooBaz`. + +``` +// File: foo.nl +struct Baz(x:Int) + member := 5 + func frob(b:Baz)->Int + return b.x + +qux := "Loaded!" +say(qux) + +// File: foo.nl.h +... +typedef struct foo$Baz_s foo$Baz_t; +#define foo$Baz(...) (foo$Baz_t){__VA_ARGS__} +struct foo$Baz_s { + Int_t x; +}; +extern Int_t foo$Baz$member; +Int_t foo$Baz$frob(foo$Baz_t b); +... + +// File: foo.nl.c +#include "foo.nl.h" +Int_t foo$Baz$member = 5; + +Int_t foo$Baz$frob(foo$Baz_t b) { + return b.x; +} + +void use$foo(void) { + static enum {UNLOADED, LOADING, LOADED} $state = UNLOADED; + if ($state == LOADING) + fail("Circular import"); + else if ($state == LOADED) + return; + + $state = LOADING; + { // Top-level code: + Str qux = "Loaded!"; + say(qux); + } + $state = LOADED; +} +``` + +And on the usage site, the code `use ./foo.tm` compiles to `#include +"./foo.tm.h"` in the header and `use$foo()` in the code that is executed. + |
