aboutsummaryrefslogtreecommitdiff
path: root/tag.h
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2025-05-09 18:29:52 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2025-05-09 18:29:52 +0100
commitba5c0a4579ece5d53c009a14d00e683e70b982f4 (patch)
treead7e6788b8ce634172f9a5cdee0a1a9ac08c7788 /tag.h
parent576bf0f3085022e9117d78e3b4e19971c82a61d6 (diff)
downloadoats-ba5c0a4579ece5d53c009a14d00e683e70b982f4.tar.gz
oats-ba5c0a4579ece5d53c009a14d00e683e70b982f4.tar.bz2
oats-ba5c0a4579ece5d53c009a14d00e683e70b982f4.zip
Initial implementation
Diffstat (limited to 'tag.h')
-rw-r--r--tag.h90
1 files changed, 90 insertions, 0 deletions
diff --git a/tag.h b/tag.h
new file mode 100644
index 0000000..dab1fa0
--- /dev/null
+++ b/tag.h
@@ -0,0 +1,90 @@
+/* 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 <https://www.gnu.org/licenses/>.
+
+ * Created: 2025-04-06
+ * Description:
+ */
+
+#ifndef TAG_H
+#define TAG_H
+
+#include "./base.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+// Opaque structure to make tagged pointers a separate type from general
+// pointers
+typedef struct Obj lisp_t;
+
+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