Namespacing
How Tomo organizes code into namespaces to avoid name collisions and interoperate cleanly with C.
In order to work with C’s namespace limitations, I’ve designed the
following system, which makes use of a C language extension
-fdollars-in-identifiers that lets you use dollar signs in
identifiers. This extension is supported by GCC, TinyCC, and Clang.
Unique File Suffixes
Each file gets a unique suffix with the format
$<filename>_XXXXXXXX, where the Xs are 8 randomly chosen
identifier characters and <filename> includes only valid
identifier characters up to the first period.
For example, in a file called hello-world.tm, a variable like
foo would become foo$helloworld_VEDjfzDs. This helps
avoid namespace conflicts between two files that define the same symbol.
Namespaces
Dollar signs in identifiers provide 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 or Foo_Baz.
Example
For this Tomo code:
// File: foo.tm
my_var := 123
struct Baz(x:Int)
member := 5
func frob(b:Baz -> Int)
return b.x
func main() passThe generated C source code will look like this:
// File: .build/foo.tm.h
...
typedef struct Baz$$struct$foo_VEDjfzDs Baz$$type$foo_VEDjfzDs;
struct Baz$$struct$foo_VEDjfzDs {
Int_t x;
};
DEFINE_OPTIONAL_TYPE(struct Baz$$struct$foo_VEDjfzDs, 8,$OptionalBaz$$type$foo_VEDjfzDs);
extern const TypeInfo_t Baz$$info$foo_VEDjfzDs;
extern Int_t Baz$member$foo_VEDjfzDs;
Int_t Baz$frob$foo_VEDjfzDs(struct Baz$$struct$foo_VEDjfzDs _$b);
extern Int_t my_var$foo_VEDjfzDs;
void main$foo_VEDjfzDs();
...// File: .build/foo.tm.c
...
public Int_t my_var$foo_VEDjfzDs = I_small(123);
public const TypeInfo_t Baz$$info$foo_VEDjfzDs = {...};
public Int_t Baz$member$foo_VEDjfzDs = I_small(5);
public Int_t Baz$frob$foo_VEDjfzDs(struct Baz$$struct$foo_VEDjfzDs _$b) {
return (_$b).x;
}
public void main$foo_VEDjfzDs() {
}
...