Skip to content

Instantly share code, notes, and snippets.

@theMackabu
Created March 18, 2026 23:03
Show Gist options
  • Select an option

  • Save theMackabu/bf9c4154a8f17632bd2809c7ef634a6f to your computer and use it in GitHub Desktop.

Select an option

Save theMackabu/bf9c4154a8f17632bd2809c7ef634a6f to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <math.h>
#define PREFIX 0xFFF0000000000000ULL
#define DATA_MASK 0x00007FFFFFFFFFFFULL
enum Type { T_NUM, T_STR, T_BOOL, T_NIL };
static inline uint64_t mknum(double d) { uint64_t v; memcpy(&v, &d, 8); return v; }
static inline double asnum(uint64_t v) { double d; memcpy(&d, &v, 8); return d; }
static inline uint64_t mktag(int t, uint64_t d) { return PREFIX | ((uint64_t)t << 47) | (d & DATA_MASK); }
static inline int vtag(uint64_t v) { return v > PREFIX ? (v >> 47) & 0x1F : T_NUM; }
static inline uint64_t vdata(uint64_t v) { return v & DATA_MASK; }
static inline uint64_t mkstr(uint64_t id) { return mktag(T_STR, id); }
static inline uint64_t mkbool(int b) { return mktag(T_BOOL, b); }
static inline uint64_t mknil(void) { return mktag(T_NIL, 0); }
static inline int isfalsy(uint64_t v) { return vtag(v)==T_NIL || (vtag(v)==T_BOOL && !vdata(v)) || (vtag(v)==T_NUM && asnum(v)==0); }
static char *strtab[4096]; static int nstrs;
static int intern(char *s) { for (int i = 0; i < nstrs; i++) if (!strcmp(strtab[i], s)) return i; strtab[nstrs] = strdup(s); return nstrs++; }
static uint64_t b_print(uint64_t *args, int n) {
for (int i = 0; i < n; i++) { if (i) printf(" "); switch (vtag(args[i])) {
case T_NUM: { double d = asnum(args[i]); d == (int)d ? printf("%d",(int)d) : printf("%g",d); } break;
case T_STR: printf("%s", strtab[vdata(args[i])]); break;
case T_BOOL: printf("%s", vdata(args[i]) ? "true" : "false"); break; case T_NIL: printf("nil"); break;
}} return mknil(); }
static uint64_t b_println(uint64_t *a, int n) { b_print(a, n); printf("\n"); return mknil(); }
static uint64_t b_len(uint64_t *a, int n) { (void)n; return vtag(a[0]) == T_STR ? mknum(strlen(strtab[vdata(a[0])])) : mknum(0); }
static uint64_t b_type(uint64_t *a, int n) { (void)n; const char *nm[] = {"num","str","bool","nil"}; return mkstr(intern((char*)nm[vtag(a[0])])); }
static uint64_t b_str(uint64_t *a, int n) {
(void)n; char buf[64]; switch (vtag(a[0])) {
case T_NUM: { double d=asnum(a[0]); d==(int)d ? snprintf(buf,64,"%d",(int)d) : snprintf(buf,64,"%g",d); break; }
case T_STR: return a[0]; case T_BOOL: return mkstr(intern(vdata(a[0]) ? "true" : "false"));
case T_NIL: return mkstr(intern("nil")); } return mkstr(intern(buf)); }
static uint64_t b_num(uint64_t *a, int n) {
(void)n; if (vtag(a[0]) == T_STR) return mknum(strtod(strtab[vdata(a[0])], NULL));
return vtag(a[0]) == T_BOOL ? mknum(vdata(a[0])) : a[0]; }
typedef uint64_t (*Builtin)(uint64_t*, int);
static struct { char *name; Builtin fn; } builtins[] = {
{"print", b_print}, {"println", b_println}, {"len", b_len}, {"type", b_type}, {"str", b_str}, {"num", b_num}, };
#define NBUILTINS (sizeof builtins / sizeof builtins[0])
static int find_builtin(char *name) { for (int i = 0; i < (int)NBUILTINS; i++) if (!strcmp(builtins[i].name, name)) return i; return -1; }
enum Tok { TNUM=128, TSTR, TID, TIF, TELSE, TWHILE, TTRUE, TFALSE, TNIL, TEQ, TNE, TLE, TGE, TEOF };
static char src[65536], *p; static int tok; static double toknum; static char tokstr[1024], tokname[64];
static void next(void) {
while (isspace(*p)) p++;
if (!*p) { tok = TEOF; return; }
if (*p == '/' && p[1] == '/') { while (*p && *p != '\n') p++; next(); return; }
if (isdigit(*p) || (*p == '.' && isdigit(p[1]))) { tok = TNUM; toknum = strtod(p, &p); return; }
if (*p == '"' || *p == '\'') { char q = *p++; char *s = tokstr;
while (*p && *p != q) { if (*p == '\\') { p++; *s++ = *p=='n' ? '\n' : *p=='t' ? '\t' : *p; p++; } else *s++ = *p++; }
*s = 0; if (*p == q) p++; tok = TSTR; return; }
if (isalpha(*p) || *p == '_') { char *s = tokname; while (isalnum(*p) || *p == '_') *s++ = *p++; *s = 0; tok = TID;
if (!strcmp(tokname,"if")) tok=TIF; else if (!strcmp(tokname,"else")) tok=TELSE;
else if (!strcmp(tokname,"while")) tok=TWHILE; else if (!strcmp(tokname,"true")) tok=TTRUE;
else if (!strcmp(tokname,"false")) tok=TFALSE; else if (!strcmp(tokname,"nil")) tok=TNIL; return; }
char c = *p++;
if (c=='=' && *p=='=') { p++; tok=TEQ; } else if (c=='!' && *p=='=') { p++; tok=TNE; }
else if (c=='<' && *p=='=') { p++; tok=TLE; } else if (c=='>' && *p=='=') { p++; tok=TGE; } else tok = c; }
enum Op { OPUSH, OLOAD, OSTORE, OADD, OSUB, OMUL, ODIV, OMOD, OEQ, ONE, OLT, OGT, OLE, OGE, OJMP, OJNZ, OJEZ, OHALT, ONEG, ONOT, OCALL };
enum Nd { NNUM, NSTR, NBOOL, NNIL, NID, NBINOP, NUNOP, NASSIGN, NIF, NWHILE, NCALL, NBLOCK };
typedef struct Node { int kind, op; double num; int strid, bval; char name[64];
struct Node *a, *b, *c; struct Node *args[16]; int nargs; struct Node *stmts[256]; int nstmts; } Node;
static void expect(int t) { if (tok != t) { fprintf(stderr, "expected '%c' got %d\n", t, tok); exit(1); } next(); }
static Node *mknode(int k) { Node *n = calloc(1, sizeof(Node)); n->kind = k; return n; }
static Node *expr(void);
static Node *atom(void) {
if (tok == TNUM) { Node *n = mknode(NNUM); n->num = toknum; next(); return n; }
if (tok == TSTR) { Node *n = mknode(NSTR); n->strid = intern(tokstr); next(); return n; }
if (tok == TTRUE) { Node *n = mknode(NBOOL); n->bval = 1; next(); return n; }
if (tok == TFALSE) { Node *n = mknode(NBOOL); n->bval = 0; next(); return n; }
if (tok == TNIL) { Node *n = mknode(NNIL); next(); return n; }
if (tok == TID) { char name[64]; strcpy(name, tokname); next(); if (tok == '(') {
next(); Node *n = mknode(NCALL); strcpy(n->name, name);
if (tok != ')') { n->args[n->nargs++] = expr(); while (tok == ',') { next(); n->args[n->nargs++] = expr(); } }
expect(')'); return n; } Node *n = mknode(NID); strcpy(n->name, name); return n; }
if (tok == '(') { next(); Node *n = expr(); expect(')'); return n; }
if (tok == '-') { next(); Node *n = mknode(NUNOP); n->op = '-'; n->a = atom(); return n; }
if (tok == '!') { next(); Node *n = mknode(NUNOP); n->op = '!'; n->a = atom(); return n; }
fprintf(stderr, "unexpected token %d\n", tok); exit(1); }
static Node *binop(Node*(*sub)(void), int *ops, int *toks, int n) { Node *left = sub();
for (;;) { int found = -1; for (int i = 0; i < n; i++) if (tok == toks[i]) { found = i; break; }
if (found < 0) return left; next(); Node *nd = mknode(NBINOP); nd->op = ops[found]; nd->a = left; nd->b = sub(); left = nd; } }
static Node *muldiv(void) { return binop(atom, (int[]){OMUL,ODIV,OMOD}, (int[]){'*','/','%'}, 3); }
static Node *addsub(void) { return binop(muldiv, (int[]){OADD,OSUB}, (int[]){'+','-'}, 2); }
static Node *cmp(void) { return binop(addsub, (int[]){OLT,OGT,OLE,OGE}, (int[]){'<','>',TLE,TGE}, 4); }
static Node *expr(void) { return binop(cmp, (int[]){OEQ,ONE}, (int[]){TEQ,TNE}, 2); }
static Node *stmt(void);
static Node *block(void) { Node *n = mknode(NBLOCK);
if (tok == '{') { next(); while (tok != '}') n->stmts[n->nstmts++] = stmt(); next(); }
else n->stmts[n->nstmts++] = stmt(); return n; }
static Node *stmt(void) {
if (tok == TIF) { next(); expect('('); Node *n = mknode(NIF); n->a = expr(); expect(')');
n->b = block(); if (tok == TELSE) { next(); n->c = block(); } return n; }
if (tok == TWHILE) { next(); expect('('); Node *n = mknode(NWHILE); n->a = expr(); expect(')'); n->b = block(); return n; }
if (tok == TID) { char name[64]; strcpy(name, tokname); next();
if (tok == '=') { next(); Node *n = mknode(NASSIGN); strcpy(n->name, name); n->a = expr(); expect(';'); return n; }
if (tok == '(') { next(); Node *n = mknode(NCALL); strcpy(n->name, name);
if (tok != ')') { n->args[n->nargs++] = expr(); while (tok == ',') { next(); n->args[n->nargs++] = expr(); } }
expect(')'); expect(';'); return n; } Node *id = mknode(NID); strcpy(id->name, name); expect(';'); return id;
} Node *n = expr(); expect(';'); return n; }
static uint64_t code[65536]; static int cp; static uint64_t vars_[256]; static char *varnames[256]; static int nvars;
static int varslot(char *n) { for (int i = 0; i < nvars; i++) if (!strcmp(varnames[i], n)) return i; varnames[nvars] = strdup(n); return nvars++; }
#define EMIT(o) (code[cp++] = (uint64_t)(o))
#define EMITV(v) (code[cp++] = (v))
#define PATCH(a) (code[a] = (uint64_t)cp)
static void compile(Node *n) { switch (n->kind) {
case NNUM: EMIT(OPUSH); EMITV(mknum(n->num)); break;
case NSTR: EMIT(OPUSH); EMITV(mkstr(n->strid)); break;
case NBOOL: EMIT(OPUSH); EMITV(mkbool(n->bval)); break;
case NNIL: EMIT(OPUSH); EMITV(mknil()); break;
case NID: EMIT(OLOAD); EMIT(varslot(n->name)); break;
case NASSIGN: compile(n->a); EMIT(OSTORE); EMIT(varslot(n->name)); break;
case NBINOP: compile(n->a); compile(n->b); EMIT(n->op); break;
case NUNOP: compile(n->a); EMIT(n->op == '-' ? ONEG : ONOT); break;
case NCALL: { for (int i = 0; i < n->nargs; i++) compile(n->args[i]);
int id = find_builtin(n->name); if (id < 0) { fprintf(stderr, "unknown function '%s'\n", n->name); exit(1); }
EMIT(OCALL); EMIT(id); EMIT(n->nargs); } break;
case NIF: compile(n->a); EMIT(OJEZ); { int p1 = cp; EMIT(0); compile(n->b);
if (n->c) { EMIT(OJMP); int p2 = cp; EMIT(0); PATCH(p1); compile(n->c); PATCH(p2); } else PATCH(p1); } break;
case NWHILE: { int top = cp; compile(n->a); EMIT(OJEZ); int ex = cp; EMIT(0);
compile(n->b); EMIT(OJMP); EMIT(top); PATCH(ex); } break;
case NBLOCK: for (int i = 0; i < n->nstmts; i++) compile(n->stmts[i]); break; } }
static void run(void) {
static void *dispatch[] = { [OPUSH]=&&L_PUSH, [OLOAD]=&&L_LOAD, [OSTORE]=&&L_STORE,
[OADD]=&&L_ADD, [OSUB]=&&L_SUB, [OMUL]=&&L_MUL, [ODIV]=&&L_DIV, [OMOD]=&&L_MOD,
[OEQ]=&&L_EQ, [ONE]=&&L_NE, [OLT]=&&L_LT, [OGT]=&&L_GT, [OLE]=&&L_LE, [OGE]=&&L_GE,
[OJMP]=&&L_JMP, [OJNZ]=&&L_JNZ, [OJEZ]=&&L_JEZ, [OHALT]=&&L_HALT, [ONEG]=&&L_NEG, [ONOT]=&&L_NOT, [OCALL]=&&L_CALL, };
uint64_t stack[4096]; int sp = 0, ip = 0;
#define NEXT goto *dispatch[code[ip++]]
#define POP stack[--sp]
#define PUSH(v) (stack[sp++]=(v))
#define NUMBIN(op) { double b=asnum(POP),a=asnum(POP); PUSH(mknum(a op b)); NEXT; }
#define CMPBIN(op) { double b=asnum(POP),a=asnum(POP); PUSH(mkbool(a op b)); NEXT; }
NEXT;
L_PUSH: PUSH(code[ip++]); NEXT; L_LOAD: PUSH(vars_[code[ip++]]); NEXT; L_STORE: vars_[code[ip++]] = stack[sp-1]; NEXT;
L_ADD: { uint64_t bv = POP, av = POP;
if (vtag(av)==T_STR && vtag(bv)==T_STR) { char buf[2048]; snprintf(buf, sizeof buf, "%s%s", strtab[vdata(av)], strtab[vdata(bv)]); PUSH(mkstr(intern(buf))); }
else PUSH(mknum(asnum(av)+asnum(bv))); NEXT; }
L_SUB: NUMBIN(-) L_MUL: NUMBIN(*) L_DIV: NUMBIN(/)
L_MOD: { double b=asnum(POP),a=asnum(POP); PUSH(mknum(fmod(a,b))); NEXT; }
L_EQ: CMPBIN(==) L_NE: CMPBIN(!=) L_LT: CMPBIN(<) L_GT: CMPBIN(>)
L_LE: CMPBIN(<=) L_GE: CMPBIN(>=)
L_NEG: stack[sp-1] = mknum(-asnum(stack[sp-1])); NEXT;
L_NOT: stack[sp-1] = mkbool(isfalsy(stack[sp-1])); NEXT;
L_JMP: ip = (int)code[ip]; NEXT;
L_JNZ: ip = !isfalsy(POP) ? (int)code[ip] : ip+1; NEXT;
L_JEZ: ip = isfalsy(POP) ? (int)code[ip] : ip+1; NEXT;
L_CALL: { int id = (int)code[ip++], nargs = (int)code[ip++];
uint64_t args[16]; for (int i = nargs-1; i >= 0; i--) args[i] = POP;
PUSH(builtins[id].fn(args, nargs)); NEXT; }
L_HALT: return; }
int main(int argc, char **argv) {
FILE *f = argc > 1 ? fopen(argv[1], "r"): stdin; if (!f) { perror("fopen"); return 1; }
int len = fread(src, 1, sizeof(src)-1, f); src[len] = 0; if (f != stdin) fclose(f);
p = src; next(); Node *prog = mknode(NBLOCK); while (tok != TEOF) prog->stmts[prog->nstmts++] = stmt();
compile(prog); EMIT(OHALT); run(); }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment