/* Copyright (C) 2025 Aryadev Chavali * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License Version 2 for * details. * You may distribute and modify this code under the terms of the GNU General * Public License Version 2, which you should have received a copy of along with * this program. If not, please go to . * Created: 2025-04-06 * Description: */ #ifndef TAG_H #define TAG_H #include #include #include // Opaque structure to make tagged pointers a separate type from general // pointers typedef struct Obj lisp_t; #define NIL NULL enum Tag { TAG_NIL = 0b00000000, // Atomic types TAG_INT = 0b00000001, // special so we can encode 63 bit integers TAG_SYM = 0b00000100, TAG_SSYM = 0b00001000, TAG_CHAR = 0b00001100, TAG_BOOL = 0b00010000, TAG_FLOAT = 0b00010100, TAG_CONS = 0b00000010, // Container types TAG_VEC = 0b00000110, TAG_STR = 0b00001010, NUM_TAGS = 9, }; enum Shift { SHIFT_INT = 1, SHIFT_SSYM = 5, SHIFT_CHAR = 8, SHIFT_SYM = 8, SHIFT_BOOL = 8, SHIFT_FLOAT = 8, SHIFT_CONS = 8, SHIFT_VEC = 8, SHIFT_STR = 8, }; enum Mask { MASK_INT = 0b00000001, MASK_SSYM = 0b00011111, MASK_SYM = 0b11111111, MASK_CHAR = 0b11111111, MASK_BOOL = 0b11111111, MASK_FLOAT = 0b11111111, MASK_CONS = 0b11111111, MASK_VEC = 0b11111111, MASK_STR = 0b11111111, }; #define TAG(PTR, TYPE) ((lisp_t *)(((PTR) << SHIFT_##TYPE) | TAG_##TYPE)) #define IS_TAG(PTR, TYPE) (((u64)(PTR) & MASK_##TYPE) == TAG_##TYPE) #define UNTAG(PTR, TYPE) (((u64)PTR) >> SHIFT_##TYPE) enum Tag tag_get(lisp_t *ptr); lisp_t *tag_int(i64 i); lisp_t *tag_char(u32 codepoint); lisp_t *tag_sym(void *ptr); lisp_t *tag_ssym(const char *data, size_t size); lisp_t *tag_bool(bool b); lisp_t *tag_vec(void *ptr); lisp_t *tag_str(void *ptr); lisp_t *tag_cons(void *ptr); #define INT_MAX ((1L << 62) - 1) #define INT_MIN (-(1L << 62)) #endif