about summary refs log tree commit diff
path: root/boot/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot/tree.c')
-rw-r--r--boot/tree.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/boot/tree.c b/boot/tree.c
index ea8ed69..dc22bfd 100644
--- a/boot/tree.c
+++ b/boot/tree.c
@@ -572,6 +572,104 @@ type_node_is_none(const struct Type_Node* type_node)
     return type_node->type == TYPE_NODE_NONE;
 }
 
+enum Pragma_Type
+{
+    PRAGMA_NONE,
+    PRAGMA_UNKNOWN,
+    PRAGMA_C_HEADER,
+    // TODO: further pragma types.
+
+    // NOTE: there would be plenty of use for user-defined pragmas,
+    // acting similar to attributes in other languages or #[derive] macros
+    // in Rust. for now we only support out hard-coded pragmas,
+    // but it's something to definitely consider in the future.
+};
+
+#define PRAGMA_ARGUMENT_MAX 3
+
+struct Pragma_Argument
+{
+    enum Pragma_Argument_Type
+    {
+        PRAGMA_ARGUMENT_NONE,
+        PRAGMA_ARGUMENT_NAME_OR_STRING,
+        PRAGMA_ARGUMENT_NUMBER,
+        PRAGMA_ARGUMENT_DECIMAL,
+    } type;
+
+    union Pragma_Argument_Value
+    {
+        struct String name_or_string;
+        int64 number;
+        float64 decimal;
+    } value;
+};
+
+// a "pragma" is what we call compiler hints used for giving almost every piece of information
+// the compiler might require to compile your code.
+// you can recognize a pragma by the '|' token, like in '| c_header "stdio.h"'.
+// their use ranges from setting alignment/padding for structures, defining default copy or move
+// behaviour, to including different C compilation units and other catskill modules.
+// pragmas are parsed as lone statements in the source code at first, but are then
+// "attached" to the relevant nodes of the type the pragma is relevant to.
+struct Pragma_Node
+{
+    enum Pragma_Type type;
+    struct Pragma_Argument arguments[PRAGMA_ARGUMENT_MAX];
+    uint argument_count;
+
+    struct Span span;
+    struct Cursor location;
+
+    struct Pragma_Node* next; // further pragmas on the same line.
+};
+
+REGION(struct Pragma_Node, pragma_node)
+
+struct Pragma_Node*
+pragma_node_new(enum Pragma_Type type, struct Span span, struct Cursor location)
+{
+    check(region_pragma_node_cursor < REGION_SIZE, "out of pragma node memory");
+    struct Pragma_Node* pragma = &region_pragma_node[region_pragma_node_cursor++];
+    *pragma = (struct Pragma_Node){
+        .type = type,
+        .arguments = {},
+        .argument_count = 0,
+        .span = span,
+        .location = location,
+        .next = nil,
+    };
+    return pragma;
+}
+
+enum Pragma_Type
+pragma_type_from_string(struct String name)
+{
+    // look up hash values with:
+    // `echo -ne "string to hash" | cksum`
+    uint32 hash = crc32_posix(name);
+    switch (hash) {
+    case 2852954401: // "c_header"
+        return PRAGMA_C_HEADER;
+    default:
+        return PRAGMA_UNKNOWN;
+    }
+}
+
+const ascii*
+pragma_type_to_string(enum Pragma_Type type)
+{
+    switch (type) {
+    case PRAGMA_C_HEADER:
+        return "c_header";
+    case PRAGMA_UNKNOWN:
+        return "unknown";
+    default:
+        failure("unexpected pragma type passed to `pragma_type_to_string`");
+        return nil;
+    }
+}
+
 enum Expression_Kind
 {
     EXPRESSION_NONE,
@@ -742,6 +840,8 @@ enum Statement_Kind
     STATEMENT_BREAK,
     STATEMENT_CONTINUE,
     STATEMENT_DEFER,
+
+    STATEMENT_PRAGMA,
 };
 
 struct Statement_Value_Expression
@@ -828,6 +928,11 @@ struct Statement_Value_Defer
     struct Block_Node block;
 };
 
+struct Statement_Value_Pragma
+{
+    struct Pragma_Node* inner;
+};
+
 union Statement_Value
 {
     struct Statement_Value_Expression expression;
@@ -837,6 +942,7 @@ union Statement_Value
     struct Statement_Value_Loop loop;
     struct Statement_Value_Return return_value;
     struct Statement_Value_Defer defer;
+    struct Statement_Value_Pragma pragma;
 };
 
 struct Statement