--- /dev/null
+\#+TITLE: Using `#assign` to Construct Sets and Lists in the C Preprocessor
+\#+AUTHOR: Thomas Walker Lynch
+\#+DATE: 2025-05-06
+\#+OPTIONS: toc\:nil num\:nil
+\#+LANGUAGE: en
+
+The `#assign` directive allows the programmer to perform runtime macro redefinitions within the C preprocessor. This facility introduces mutability and symbolic indirection, enabling set and list representations not possible with static `#define`s alone.
+
+* Introduction
+
+Normally, the C preprocessor (`cpp`) operates as a single-pass, immutable macro expander. Once a macro is defined, it cannot be updated or re-bound without manual `#undef` intervention, and even then only in certain contexts. `#assign`, by design, bypasses this constraint.
+
+It enables symbolic mutation. With this, we can simulate associative data structures: sets, lists, cons cells, even environments.
+
+* Representing Sets with `#assign`
+
+In a conventional C macro environment, a set cannot be constructed dynamically because macro definitions are static. However, with `#assign`, we can model a set as a collection of defined macro names.
+
+\*\* Membership Test
+
+To test whether `X` is in a set:
+
+\#+begin\_src c
+\#ifndef \_SET\_\_X
+\#define NOT\_MEMBER
+\#else
+\#define MEMBER
+\#endif
+\#+end\_src
+
+We treat the existence of the macro `_SET__X` as a membership marker.
+
+\*\* Adding to the Set
+
+We can define an element by assigning an empty macro:
+
+\#+begin\_src c
+\#assign (\_SET\_\_X, )
+\#+end\_src
+
+This simulates inserting `X` into the set.
+
+\*\* Properties
+
+* Sets are /existence-based/: their content is inferred by symbol presence, not enumeration.
+* There is /no inherent order/ to the elements.
+* You /cannot enumerate/ the contents of the set without external bookkeeping.
+
+- Representing Lists with `#assign`
+
+Lists can be represented as chained macros where each node is a pair (a cons cell):
+
+\#+begin\_src c
+\#define c0 (a, b)
+\#define c1 (c, d)
+\#assign (SECOND(c0), c1)
+\#define c2 (e, f)
+\#assign (SECOND(c1), c2)
+\#+end\_src
+
+This forms a chain:
+
+\#+begin\_src
+c0 → (a, c1)
+c1 → (c, c2)
+c2 → (e, f)
+\#+end\_src
+
+Each assignment updates the /cdr/ or /tail/ of the previous node.
+
+\*\* Appending to a List
+
+Given a head macro `LIST`, we can append by updating its tail pointer:
+
+\#+begin\_src c
+\#assign (LIST, CAT(LIST, COMMA, NEW\_ELEMENT))
+\#+end\_src
+
+This mutates the list structure dynamically.
+
+\*\* Traversal
+
+Traversal is only possible if a symbolic walk is encoded or if a confederate macro is prepared to test known elements. This is limited and requires foreknowledge of the structure.
+
+* Sideways Lists (Symbol Table Indexed)
+
+An alternative to comma-based lists is to use macro names as nodes — each symbol representing a cons cell.
+
+You define each cons cell:
+
+\#+begin\_src c
+\#assign (\_cons\_a, (A, \_cons\_b))
+\#assign (\_cons\_b, (B, \_cons\_c))
+\#assign (\_cons\_c, (C, NIL))
+\#+end\_src
+
+Now `_cons_a` is the symbolic head. Each macro name points to a `(car, cdr)` pair.
+
+This format mirrors the representation of linked lists in Lisp, and mutation is achieved by re-assigning the `cdr` field via `#assign`.
+
+* Mutability
+
+What makes this all possible is that `#assign` allows redefinition. It effectively simulates mutable variables:
+
+\#+begin\_src c
+\#assign (X, 5)
+\#assign (X, 7)
+\#+end\_src
+
+Later macro expansions of `X` now yield `7`, not `5`. This is unlike `#define`, which would have required an `#undef` first and would have affected macro hygiene.
+
+* Limitations
+
+- No native enumeration of keys in the symbol table.
+- No stack or heap — only symbolic references.
+- No scoped environments unless explicitly constructed via naming schemes.
+- Risk of name collisions.
+
+* Conclusion
+
+The `#assign` directive reimagines the C preprocessor as a mutable symbolic computation engine. It opens the door to implementing symbolic sets, lists, and even cons structures within macro space, turning what is normally a static templating tool into a dynamic environment for structured symbolic logic.
+
+Future extensions could include associative maps, recursive evaluators, or stack machines — all using nothing but macro indirection and symbolic mutation.
--- /dev/null
+
+typedef long unsigned int size_t;
+typedef __builtin_va_list __gnuc_va_list;
+typedef unsigned char __u_char;
+typedef unsigned short int __u_short;
+typedef unsigned int __u_int;
+typedef unsigned long int __u_long;
+typedef signed char __int8_t;
+typedef unsigned char __uint8_t;
+typedef signed short int __int16_t;
+typedef unsigned short int __uint16_t;
+typedef signed int __int32_t;
+typedef unsigned int __uint32_t;
+typedef signed long int __int64_t;
+typedef unsigned long int __uint64_t;
+typedef __int8_t __int_least8_t;
+typedef __uint8_t __uint_least8_t;
+typedef __int16_t __int_least16_t;
+typedef __uint16_t __uint_least16_t;
+typedef __int32_t __int_least32_t;
+typedef __uint32_t __uint_least32_t;
+typedef __int64_t __int_least64_t;
+typedef __uint64_t __uint_least64_t;
+typedef long int __quad_t;
+typedef unsigned long int __u_quad_t;
+typedef long int __intmax_t;
+typedef unsigned long int __uintmax_t;
+typedef unsigned long int __dev_t;
+typedef unsigned int __uid_t;
+typedef unsigned int __gid_t;
+typedef unsigned long int __ino_t;
+typedef unsigned long int __ino64_t;
+typedef unsigned int __mode_t;
+typedef unsigned long int __nlink_t;
+typedef long int __off_t;
+typedef long int __off64_t;
+typedef int __pid_t;
+typedef struct { int __val[2]; } __fsid_t;
+typedef long int __clock_t;
+typedef unsigned long int __rlim_t;
+typedef unsigned long int __rlim64_t;
+typedef unsigned int __id_t;
+typedef long int __time_t;
+typedef unsigned int __useconds_t;
+typedef long int __suseconds_t;
+typedef long int __suseconds64_t;
+typedef int __daddr_t;
+typedef int __key_t;
+typedef int __clockid_t;
+typedef void * __timer_t;
+typedef long int __blksize_t;
+typedef long int __blkcnt_t;
+typedef long int __blkcnt64_t;
+typedef unsigned long int __fsblkcnt_t;
+typedef unsigned long int __fsblkcnt64_t;
+typedef unsigned long int __fsfilcnt_t;
+typedef unsigned long int __fsfilcnt64_t;
+typedef long int __fsword_t;
+typedef long int __ssize_t;
+typedef long int __syscall_slong_t;
+typedef unsigned long int __syscall_ulong_t;
+typedef __off64_t __loff_t;
+typedef char *__caddr_t;
+typedef long int __intptr_t;
+typedef unsigned int __socklen_t;
+typedef int __sig_atomic_t;
+typedef struct
+{
+ int __count;
+ union
+ {
+ unsigned int __wch;
+ char __wchb[4];
+ } __value;
+} __mbstate_t;
+typedef struct _G_fpos_t
+{
+ __off_t __pos;
+ __mbstate_t __state;
+} __fpos_t;
+typedef struct _G_fpos64_t
+{
+ __off64_t __pos;
+ __mbstate_t __state;
+} __fpos64_t;
+struct _IO_FILE;
+typedef struct _IO_FILE __FILE;
+struct _IO_FILE;
+typedef struct _IO_FILE FILE;
+struct _IO_FILE;
+struct _IO_marker;
+struct _IO_codecvt;
+struct _IO_wide_data;
+typedef void _IO_lock_t;
+struct _IO_FILE
+{
+ int _flags;
+ char *_IO_read_ptr;
+ char *_IO_read_end;
+ char *_IO_read_base;
+ char *_IO_write_base;
+ char *_IO_write_ptr;
+ char *_IO_write_end;
+ char *_IO_buf_base;
+ char *_IO_buf_end;
+ char *_IO_save_base;
+ char *_IO_backup_base;
+ char *_IO_save_end;
+ struct _IO_marker *_markers;
+ struct _IO_FILE *_chain;
+ int _fileno;
+ int _flags2;
+ __off_t _old_offset;
+ unsigned short _cur_column;
+ signed char _vtable_offset;
+ char _shortbuf[1];
+ _IO_lock_t *_lock;
+ __off64_t _offset;
+ struct _IO_codecvt *_codecvt;
+ struct _IO_wide_data *_wide_data;
+ struct _IO_FILE *_freeres_list;
+ void *_freeres_buf;
+ size_t __pad5;
+ int _mode;
+ char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
+};
+typedef __gnuc_va_list va_list;
+typedef __off_t off_t;
+typedef __ssize_t ssize_t;
+typedef __fpos_t fpos_t;
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+extern int remove (const char *__filename) __attribute__ ((__nothrow__ , __leaf__));
+extern int rename (const char *__old, const char *__new) __attribute__ ((__nothrow__ , __leaf__));
+extern int renameat (int __oldfd, const char *__old, int __newfd,
+ const char *__new) __attribute__ ((__nothrow__ , __leaf__));
+extern int fclose (FILE *__stream);
+extern FILE *tmpfile (void)
+ __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (fclose, 1))) ;
+extern char *tmpnam (char[20]) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern char *tmpnam_r (char __s[20]) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern char *tempnam (const char *__dir, const char *__pfx)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (__builtin_free, 1)));
+extern int fflush (FILE *__stream);
+extern int fflush_unlocked (FILE *__stream);
+extern FILE *fopen (const char *__restrict __filename,
+ const char *__restrict __modes)
+ __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (fclose, 1))) ;
+extern FILE *freopen (const char *__restrict __filename,
+ const char *__restrict __modes,
+ FILE *__restrict __stream) ;
+extern FILE *fdopen (int __fd, const char *__modes) __attribute__ ((__nothrow__ , __leaf__))
+ __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (fclose, 1))) ;
+extern FILE *fmemopen (void *__s, size_t __len, const char *__modes)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (fclose, 1))) ;
+extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__ , __leaf__))
+ __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (fclose, 1))) ;
+extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__ , __leaf__));
+extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,
+ int __modes, size_t __n) __attribute__ ((__nothrow__ , __leaf__));
+extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
+ size_t __size) __attribute__ ((__nothrow__ , __leaf__));
+extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+extern int fprintf (FILE *__restrict __stream,
+ const char *__restrict __format, ...);
+extern int printf (const char *__restrict __format, ...);
+extern int sprintf (char *__restrict __s,
+ const char *__restrict __format, ...) __attribute__ ((__nothrow__));
+extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
+ __gnuc_va_list __arg);
+extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);
+extern int vsprintf (char *__restrict __s, const char *__restrict __format,
+ __gnuc_va_list __arg) __attribute__ ((__nothrow__));
+extern int snprintf (char *__restrict __s, size_t __maxlen,
+ const char *__restrict __format, ...)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4)));
+extern int vsnprintf (char *__restrict __s, size_t __maxlen,
+ const char *__restrict __format, __gnuc_va_list __arg)
+ __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0)));
+extern int vdprintf (int __fd, const char *__restrict __fmt,
+ __gnuc_va_list __arg)
+ __attribute__ ((__format__ (__printf__, 2, 0)));
+extern int dprintf (int __fd, const char *__restrict __fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+extern int fscanf (FILE *__restrict __stream,
+ const char *__restrict __format, ...) ;
+extern int scanf (const char *__restrict __format, ...) ;
+extern int sscanf (const char *__restrict __s,
+ const char *__restrict __format, ...) __attribute__ ((__nothrow__ , __leaf__));
+extern int fscanf (FILE *__restrict __stream, const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf") ;
+extern int scanf (const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf") ;
+extern int sscanf (const char *__restrict __s, const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__ , __leaf__));
+extern int vfscanf (FILE *__restrict __s, const char *__restrict __format,
+ __gnuc_va_list __arg)
+ __attribute__ ((__format__ (__scanf__, 2, 0))) ;
+extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg)
+ __attribute__ ((__format__ (__scanf__, 1, 0))) ;
+extern int vsscanf (const char *__restrict __s,
+ const char *__restrict __format, __gnuc_va_list __arg)
+ __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__format__ (__scanf__, 2, 0)));
+extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf")
+ __attribute__ ((__format__ (__scanf__, 2, 0))) ;
+extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf")
+ __attribute__ ((__format__ (__scanf__, 1, 0))) ;
+extern int vsscanf (const char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf") __attribute__ ((__nothrow__ , __leaf__))
+ __attribute__ ((__format__ (__scanf__, 2, 0)));
+extern int fgetc (FILE *__stream);
+extern int getc (FILE *__stream);
+extern int getchar (void);
+extern int getc_unlocked (FILE *__stream);
+extern int getchar_unlocked (void);
+extern int fgetc_unlocked (FILE *__stream);
+extern int fputc (int __c, FILE *__stream);
+extern int putc (int __c, FILE *__stream);
+extern int putchar (int __c);
+extern int fputc_unlocked (int __c, FILE *__stream);
+extern int putc_unlocked (int __c, FILE *__stream);
+extern int putchar_unlocked (int __c);
+extern int getw (FILE *__stream);
+extern int putw (int __w, FILE *__stream);
+extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
+ __attribute__ ((__access__ (__write_only__, 1, 2)));
+extern __ssize_t __getdelim (char **__restrict __lineptr,
+ size_t *__restrict __n, int __delimiter,
+ FILE *__restrict __stream) ;
+extern __ssize_t getdelim (char **__restrict __lineptr,
+ size_t *__restrict __n, int __delimiter,
+ FILE *__restrict __stream) ;
+extern __ssize_t getline (char **__restrict __lineptr,
+ size_t *__restrict __n,
+ FILE *__restrict __stream) ;
+extern int fputs (const char *__restrict __s, FILE *__restrict __stream);
+extern int puts (const char *__s);
+extern int ungetc (int __c, FILE *__stream);
+extern size_t fread (void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) ;
+extern size_t fwrite (const void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __s);
+extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream) ;
+extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size,
+ size_t __n, FILE *__restrict __stream);
+extern int fseek (FILE *__stream, long int __off, int __whence);
+extern long int ftell (FILE *__stream) ;
+extern void rewind (FILE *__stream);
+extern int fseeko (FILE *__stream, __off_t __off, int __whence);
+extern __off_t ftello (FILE *__stream) ;
+extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos);
+extern int fsetpos (FILE *__stream, const fpos_t *__pos);
+extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+extern int feof (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern int ferror (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern void perror (const char *__s);
+extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern int pclose (FILE *__stream);
+extern FILE *popen (const char *__command, const char *__modes)
+ __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (pclose, 1))) ;
+extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__))
+ __attribute__ ((__access__ (__write_only__, 1)));
+extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
+extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
+extern int __uflow (FILE *);
+extern int __overflow (FILE *, int);
+
+int main(){
+ printf("X %d" ,A(C));
+}