From 93093f5a220582ade7e51008d6c234a508381089 Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum
toc
improves on C’s syntax (and semantics) in many ways,
+
toc
improves on C's syntax (and semantics) in many ways,
To declare x
as an integer and set it to 5,
you can do:
-x := 5; // Declare x and set x to 5 (infer type)
-x : int = 5; // Explicitly make the type int.
-x : int; x = 5; // Declare x as an integer, then set it to 5.
+x := 5; // Declare x and set x to 5 (infer type)
+x : int = 5; // Explicitly make the type int.
+x : int; x = 5; // Declare x as an integer, then set it to 5.
toc
is statically typed and has many of C’s features, but
+
toc
is statically typed and has many of C's features, but
it is nearly as fast in theory.
See docs
for more information (in progress).
toc
compiles to C for three reasons:
toc
Source Codetoc
is set up as a unity build, meaning that there is only one translation unit. So, main.c
#include
s toc.c
, which #include
s all of toc
’s files.
toc
is set up as a unity build, meaning that there is only one translation unit. So, main.c
#include
s toc.c
, which #include
s all of toc
's files.
This improves compilation speeds (especially from scratch), since you don’t have to include headers a bunch of times for each translation unit. This is more of a problem in C++, where, for example, doing #include <map>
ends up turning into 25,000 lines after preprocessing. All of toc’s source code, which includes most of the C standard library, at the time of this writing (Dec 2019) is only 22,000 lines after preprocessing; imagine including all of that once for each translation unit which includes map
. It also obviates the need for fancy build systems like CMake.
This improves compilation speeds (especially from scratch), since you don't have to include headers a bunch of times for each translation unit. This is more of a problem in C++, where, for example, doing #include <map>
ends up turning into 25,000 lines after preprocessing. All of toc's source code, which includes most of the C standard library, at the time of this writing (Dec 2019) is only 22,000 lines after preprocessing; imagine including all of that once for each translation unit which includes map
. It also obviates the need for fancy build systems like CMake.
Here are all the C99 features which toc
depends on (I might have forgotten some…):
Here are all the C99 features which toc
depends on (I might have forgotten some...):
The last three of those could all be removed fairly easily (assuming the system actually has 8-, 16-, 32-, and 64-bit signed and unsigned types).
And here are all of its C11 features:
max_align_t
and alignof
- It can still compile without these but it won’t technically be standard-compliantmax_align_t
and alignof
- It can still compile without these but it won't technically be standard-compliantSee main.c
for a bit more information.
Here are the major versions of toc
.
Version | -Description | -Date | -
---|---|---|
0.0 | -Initial version. | -2019 Dec 6 | -
0.1 | -Constant parameter inference. | -2019 Dec 15 | -
Version | Description | Date |
0.0 | Initial version. | 2019 Dec 6 |
0.1 | Constant parameter inference. | 2019 Dec 15 |
0.1.1 | Better constant parameter inference. | 2019 Dec 16 |
If you find a bug, you can report it through GitHub’s issue tracker, or by emailing pommicket@gmail.com.
+If you find a bug, you can report it through GitHub's issue tracker, or by emailing pommicket@gmail.com.
-Just send me the toc
source code which results in the bug, and I’ll try to fix it.
Just send me the toc
source code which results in the bug, and I'll try to fix it.
Is completely fine. x
will hold an unspecified value after the jump (but it isn’t used so it doesn’t really matter). Apparently, in C++, this is an ill-formed program. This is a bit ridiculous since
Is completely fine. x
will hold an unspecified value after the jump (but it isn't used so it doesn't really matter). Apparently, in C++, this is an ill-formed program. This is a bit ridiculous since
int main() {
@@ -145,5 +125,4 @@ int main() {
}
-
-is fine. So that’s an interesting little “fun fact”: int x = 5;
isn’t always the same as int x; x = 5;
in C++.
is fine. So that's an interesting little "fun fact": int x = 5;
isn't always the same as int x; x = 5;
in C++.
Version | Description | Date |
---|---|---|
0.0 | Initial version. | 2019 Dec 6 |
0.1 | Constant parameter inference. | 2019 Dec 15 |
0.1.1 | Better constant parameter inference. | 2019 Dec 16 |
int
, whereas 0.0
defaults to a float
.
-Here are all of toc’s builtin types and their ranges of values:
+Here are all of toc's builtin types and their ranges of values:
int
- A 64-bit signed integer (always), -9223372036854775808 to 9223372036854775807float
.
char
- A character. The specific values are technically platform-dependent, but usually there are 256 of them.At the moment, it is not technically guaranteed that f32
/float
is actually 32-bit and that f64
is actually 64-bit; they are platform dependent. Perhaps someday there will be a version of toc which does not compile to C, where that could be guaranteed.
To make declarations constant, use ::
instead of :
. e.g.
-x ::= 5+3;
+x ::= 5+3;
y :: float = 5.123;
Here, “constant” means constant at compile time, not read-only as it does in C. One interesting thing about toc is that normal functions can run at compile time, so pretty much any expression is a valid initializer for a constant, e.g. doing x ::= some_function();
runs some_function
at compile time, not at run time.
Here, "constant" means constant at compile time, not read-only as it does in C. One interesting thing about toc is that normal functions can run at compile time, so pretty much any expression is a valid initializer for a constant, e.g. doing x ::= some_function();
runs some_function
at compile time, not at run time.
It declares a constant, main
, which is a function with an empty body. Note that the syntax for declaring functions is the same as the syntax for declaring constants (it isn’t something like fn main() { ... }
).
It declares a constant, main
, which is a function with an empty body. Note that the syntax for declaring functions is the same as the syntax for declaring constants (it isn't something like fn main() { ... }
).
Assuming you have compiled the compiler (see README.md
for instructions about that), you can compile it with
You will get a file called out.c
, which you can then put through your C compiler to get an executable file which does nothing. Congratulations! You’ve written your first toc program.
You will get a file called out.c
, which you can then put through your C compiler to get an executable file which does nothing. Congratulations! You've written your first toc program.