#pragma once #include #include #include enum node_type { N_CONS, N_IDENT, N_INTEGER, N_STRING }; struct node { enum node_type type; union { struct { struct node *car, *cdr; } n_cons; char *n_ident; char *n_string; intmax_t n_integer; }; }; static inline int cons_q(struct node *n) { return !n || n->type == N_CONS; } static inline int null_q(struct node *n) { return n == NULL; } static inline int pair_q(struct node *n) { return n && n->type == N_CONS; } static inline int ident_q(struct node *n) { return n && n->type == N_IDENT; } static inline int integer_q(struct node *n) { return n && n->type == N_INTEGER; } static inline int string_q(struct node *n) { return n && n->type == N_STRING; } static inline struct node *car(struct node *n) { assert(pair_q(n)); return n->n_cons.car; } static inline struct node *cdr(struct node *n) { assert(pair_q(n)); return n->n_cons.cdr; } static inline struct node *cadr(struct node *n) { return car(cdr(n)); } static inline struct node *caddr(struct node *n) { return car(cdr(cdr(n))); } static inline struct node *cddr(struct node *n) { return cdr(cdr(n)); } struct node *string_from_owned(char *ptr); struct node *cons(struct node *a, struct node *b); struct node *ident(const char *i); struct node *integer(intmax_t v); struct node *list(int n, ...); void vm_print(const struct node *node, int depth);