summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Sotoudeh <matthew@masot.net>2024-03-22 23:48:16 -0400
committerMatthew Sotoudeh <matthew@masot.net>2024-03-22 23:48:16 -0400
commit61a87d12aebbcbd0b70eaa9cb0244b2faf989c91 (patch)
tree7f0043372efeab40691c152bb47cb4b88ae75fda
parent2043ff5746e0df3b2be6ff6bcf712901daa8f5e6 (diff)
improve readmes
-rw-r--r--README.txt108
-rw-r--r--c_version/README.txt13
-rw-r--r--gamma_version/README.txt20
3 files changed, 127 insertions, 14 deletions
diff --git a/README.txt b/README.txt
index 31591d5..e98b023 100644
--- a/README.txt
+++ b/README.txt
@@ -1 +1,109 @@
####### Gamma: Backwards-Compatible Templates for C #######
+Gamma is a C preprocessor designed to make simple templated data structures
+ergonomic in C.
+
+It was designed by Akshay, Matthew, and Zach.
+
+####### Selling Points #######
+Selling points include:
+
+ - It aims to be fully backwards compatible:
+
+ * Gamma is designed to be a strict superset of C, never breaking
+ currently working C code.
+
+ * Simply add CC=gc gcc and LD=gc gcc to your Makefile and everything
+ will work, including object files, static libraries, etc.
+
+ * If you have a GCC-compatible toolchain for your target architecture,
+ you can immediately wrap it in Gamma and everything works.
+
+ * Slowdown on sequential C builds (no templates) is only about 30%.
+
+ - Template definitions can be in .c files just like normal C function
+ definitions; only declarations need to be placed in header files.
+
+ - Specialization and partial specialization is supported.
+
+ - The implementation is simple, easy to hack on, and easy to understand. It
+ is arguably simpler than CPP.
+
+ - The implementation relies on almost no knowledge about the C grammar
+ except for a lightweight, best-effort lexing pass. This makes it
+ relatively easy to port as a preprocessor for other languages, e.g.,
+ Hare.
+
+####### Code Samples #######
+
+> uint32_t vector_push::[type T](struct vector::[T] *vector, T item) {
+> if ((2 * vector->count) >= vector->cap) {
+> vector->cap *= 4;
+> vector->cap = vector->cap ? vector->cap : 128;
+> vector->data = realloc(vector->data, vector->cap * sizeof(vector->data[0]));
+> }
+> vector->data[vector->count++] = item;
+> }
+>
+> T vector_pop::[type T](struct vector::[T] *vector) {
+> return vector->data[--(vector->count)];
+> }
+>
+> struct vector::[T] *vector_init::[type T]() {
+> return calloc(1, sizeof(struct vector::[T]));
+> }
+
+####### Versions & Self-Hosting #######
+There are three versions:
+
+ - `py_version` is written in Python and is the oldest & slowest. It does
+ not support the latest syntax features. It's designed to infer template
+ locations, so you can write just "foo[T]" instead of, say, "foo![T]".
+
+ - `c_version` is written in C and supports all the current features.
+
+ - `gamma_version` is written in Gamma and supports all the current
+ features. It's also faster for projects with many templates.
+
+The Gamma-in-Gamma version requires an existing Gamma compiler. It is currently
+set up to use the result of the C version, hence you must build like so:
+
+ gamma $ make -C c_version
+ gamma $ make -C gamma_version
+
+####### How it Works #######
+------- The Preprocessor
+The code is lexed and broken up into 'chunks;' each chunk is meant to represent
+one top-level C statement (i.e., a variable/function/type
+declaration/definition). Specifically, chunks are matched greedily and end once
+a top-level '}' or '}\s*;' is read.
+
+Any sequence of the form "ident::[...]" is interpreted as a template call.
+
+The last template call on the outer nesting level of a chunk is its _defining
+call_ and is used as the template pattern for that chunk.
+
+Type variables in the defining call are indicated by the prefix "type "; all
+other arguments in a defining call are assumed to be concrete types.
+
+After collecting all chunks and their calls, we solve to determine all the
+concrete template instantiations that will be needed.
+
+Then, the file is printed out with each template duplicated once for each
+instantiation needed. Type variables are replaced by their concrete
+instantiations and the template call syntax is mangled.
+
+------- The Compiler Wrapper
+When the -c flag is used, i.e., an intermediate object file compilation is
+requested, we first check if the file uses templates. If not, we build the
+object file as normal. If so, we store the preprocessed source code and the
+compile flags used in a custom '.o' file format.
+
+At link time, we read all the '.o's in our custom format and consider template
+instantiations needed by, and definitions provided by, all of them.
+
+Currently this sequentializes the compilation of Gamma files (but not pure-C
+files). In theory only the fixedpoint stage needs to be sequentialized; we are
+interested in improving this in the future.
+
+####### Security #######
+Don't compile object files with an untrusted source through Gamma.
diff --git a/c_version/README.txt b/c_version/README.txt
index 9ff18da..d836bb6 100644
--- a/c_version/README.txt
+++ b/c_version/README.txt
@@ -4,19 +4,18 @@ Why?
Zach wanted a self-hostable version
-Differences?
+Differences to the Python version?
It uses a slightly different approach to picking up chunks + templates
- Specifically, you're now *forced* to use "foo![...]" for templates
+ Specifically, you're now *forced* to use "foo![...]" or "foo::[...]" for
+ templates
On the plus side, this means you can have templated arrays and typedefs
- Static libraries (.a's) don't work yet
-
How to use?
- gamma/self-hosted $ make -B
- gamma/self-hosted $ ./build/gc gcc examples/hashmap.c
- gamma/self-hosted $ ./a.out
+ gamma/c_version $ make -B
+ gamma/c_version $ ./build/gc gcc examples/hashmap.c
+ gamma/c_version $ ./a.out
...
diff --git a/gamma_version/README.txt b/gamma_version/README.txt
index 9ff18da..348c9ff 100644
--- a/gamma_version/README.txt
+++ b/gamma_version/README.txt
@@ -1,22 +1,28 @@
-====== Gamma-C, in C ======
+====== Gamma-C, in Gamma ======
Why?
Zach wanted a self-hostable version
-Differences?
+Differences to the Python version?
It uses a slightly different approach to picking up chunks + templates
- Specifically, you're now *forced* to use "foo![...]" for templates
+ Specifically, you're now *forced* to use "foo![...]" or "foo::[...]" for
+ templates
On the plus side, this means you can have templated arrays and typedefs
- Static libraries (.a's) don't work yet
+Differences to the C version?
+
+ Because data structures become so simple, we're using a significantly more
+ efficient fixedpoint engine (i.e., a work queue instead of 'loop over
+ everything every iteration'). So, if you're compiling a project with many
+ templates, Gamma-in-Gamma is the way to go!
How to use?
- gamma/self-hosted $ make -B
- gamma/self-hosted $ ./build/gc gcc examples/hashmap.c
- gamma/self-hosted $ ./a.out
+ gamma/gamma_version $ make -B
+ gamma/gamma_version $ ./build/gc gcc examples/hashmap.c
+ gamma/gamma_version $ ./a.out
...
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback