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.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/boot/tree.c b/boot/tree.c
new file mode 100644
index 0000000..339f12c
--- /dev/null
+++ b/boot/tree.c
@@ -0,0 +1,340 @@
+/*
+ * abstract syntax tree types for a catskill source.
+ */
+
+enum Unary_Operation
+{
+    UNARY_MINUS,
+    UNARY_NOT,
+
+    UNARY_BITWISE_NOT,
+};
+
+const ascii*
+unary_operation_to_string(enum Unary_Operation operation)
+{
+    switch (operation) {
+    case UNARY_MINUS:
+        return "-";
+    case UNARY_NOT:
+        return "!";
+    case UNARY_BITWISE_NOT:
+        return "~";
+
+    default:
+        return "unknown";
+    }
+}
+
+enum Binary_Operation
+{
+    BINARY_PLUS,
+    BINARY_MINUS,
+    BINARY_MULTIPLY,
+    BINARY_DIVIDE,
+    BINARY_MODULO,
+
+    BINARY_EQUAL,
+    BINARY_NOT_EQUAL,
+    BINARY_GREATER_THAN,
+    BINARY_GREATER_THAN_EQUAL,
+    BINARY_LESS_THAN,
+    BINARY_LESS_THAN_EQUAL,
+    BINARY_AND,
+    BINARY_OR,
+
+    BINARY_BITWISE_AND,
+    BINARY_BITWISE_OR,
+    BINARY_BITWISE_XOR,
+    BINARY_BITWISE_LEFT_SHIFT,
+    BINARY_BITWISE_RIGHT_SHIFT,
+};
+
+const ascii*
+binary_operation_to_string(enum Binary_Operation operation)
+{
+    switch (operation) {
+    case BINARY_PLUS:
+        return "+";
+    case BINARY_MINUS:
+        return "-";
+    case BINARY_MULTIPLY:
+        return "*";
+    case BINARY_DIVIDE:
+        return "/";
+    case BINARY_MODULO:
+        return "%";
+
+    case BINARY_EQUAL:
+        return "==";
+    case BINARY_NOT_EQUAL:
+        return "!=";
+    case BINARY_GREATER_THAN:
+        return ">";
+    case BINARY_GREATER_THAN_EQUAL:
+        return ">=";
+    case BINARY_LESS_THAN:
+        return "<";
+    case BINARY_LESS_THAN_EQUAL:
+        return "<=";
+    case BINARY_AND:
+        return "&&";
+    case BINARY_OR:
+        return "||";
+
+    case BINARY_BITWISE_AND:
+        return "&";
+    case BINARY_BITWISE_OR:
+        return "|";
+    case BINARY_BITWISE_XOR:
+        return "^";
+    case BINARY_BITWISE_LEFT_SHIFT:
+        return "<<";
+    case BINARY_BITWISE_RIGHT_SHIFT:
+        return ">>";
+
+    default:
+        return "unknown";
+    }
+}
+
+enum Expression_Kind
+{
+    EXPRESSION_NONE,
+
+    EXPRESSION_INTEGER_LITERAL,
+    EXPRESSION_FLOAT_LITERAL,
+    EXPRESSION_STRING_LITERAL,
+    EXPRESSION_BOOLEAN_LITERAL,
+    EXPRESSION_NAME,
+
+    EXPRESSION_UNARY_OPERATION,
+    EXPRESSION_BINARY_OPERATION,
+
+    EXPRESSION_GROUP,
+    EXPRESSION_CALL,
+    EXPRESSION_SUBSCRIPT,
+    EXPRESSION_MEMBER,
+};
+
+struct Expression_Integer_Literal
+{
+    int64 value; // might not fit entire number given in source.
+};
+
+struct Expression_Float_Literal
+{
+    float64 value;
+};
+
+struct Expression_String_Literal
+{
+    struct String value;
+};
+
+struct Expression_Bool_Literal
+{
+    bool value;
+};
+
+struct Expression_Name
+{
+    struct String name;
+};
+
+struct Expression_Unary_Operator
+{
+    enum Unary_Operation operation;
+    struct Expression* operand;
+};
+
+struct Expression_Binary_Operator
+{
+    enum Binary_Operation operation;
+    struct Expression* left_operand;
+    struct Expression* right_operand;
+};
+
+struct Expression_Group
+{
+    struct Expression* inner_expression;
+};
+
+struct Expression_Call
+{
+    struct Expression* subject;
+    struct Expression* arguments; // linked list of expressions.
+};
+
+struct Expression_Subscript
+{
+    struct Expression* subject;
+    struct Expression* index;
+};
+
+struct Expression_Member
+{
+    struct Expression* subject;
+    struct String name;
+};
+
+union Expression_Value
+{
+    struct Expression_Integer_Literal integer_literal;
+    struct Expression_Float_Literal float_literal;
+    struct Expression_String_Literal string_literal;
+    struct Expression_Bool_Literal bool_literal;
+    struct Expression_Name name;
+    struct Expression_Unary_Operator unary_operator;
+    struct Expression_Binary_Operator binary_operator;
+    struct Expression_Group group;
+    struct Expression_Call call;
+    struct Expression_Subscript subscript;
+    struct Expression_Member member;
+};
+
+struct Expression
+{
+    enum Expression_Kind kind;
+    union Expression_Value value;
+
+    struct Span span;
+    struct Cursor location;
+
+    // if expression is within a group of multiple expressions,
+    // points to the next expression within it.
+    struct Expression* next;
+};
+
+REGION(struct Expression, expression)
+
+void
+expression_print(const struct Expression* expression)
+{
+    printf("(expr ");
+    switch (expression->kind) {
+    case EXPRESSION_NONE:
+        printf("none");
+        break;
+    case EXPRESSION_INTEGER_LITERAL:
+        printf("%ld", expression->value.integer_literal.value);
+        break;
+    case EXPRESSION_FLOAT_LITERAL:
+        printf("%lf", expression->value.float_literal.value);
+        break;
+    case EXPRESSION_STRING_LITERAL:
+        printf("\"%s\"", expression->value.string_literal.value.data);
+        break;
+    case EXPRESSION_BOOLEAN_LITERAL:
+        printf("%s", expression->value.bool_literal.value ? "true" : "false");
+        break;
+    case EXPRESSION_NAME:
+        printf("(name %s)", expression->value.name.name.data);
+        break;
+    case EXPRESSION_UNARY_OPERATION:
+        printf("(unary %s ", unary_operation_to_string(expression->value.unary_operator.operation));
+        expression_print(expression->value.unary_operator.operand);
+        printf(")");
+        break;
+    case EXPRESSION_BINARY_OPERATION:
+        printf(
+            "(binary %s ", binary_operation_to_string(expression->value.binary_operator.operation));
+        expression_print(expression->value.binary_operator.left_operand);
+        printf(" ");
+        expression_print(expression->value.binary_operator.right_operand);
+        printf(")");
+        break;
+    case EXPRESSION_GROUP:
+        printf("(group ");
+        expression_print(expression->value.group.inner_expression);
+        printf(")");
+        break;
+    case EXPRESSION_CALL:
+        printf("(call ");
+        expression_print(expression->value.call.subject);
+        FOR_EACH(struct Expression*, argument, expression->value.call.arguments)
+        {
+            printf(" ");
+            expression_print(argument);
+        }
+        printf(")");
+        break;
+    case EXPRESSION_SUBSCRIPT:
+        printf("(subscript ");
+        expression_print(expression->value.subscript.subject);
+        printf(" ");
+        expression_print(expression->value.subscript.index);
+        printf(")");
+        break;
+    case EXPRESSION_MEMBER:
+        printf("(member ");
+        expression_print(expression->value.member.subject);
+        printf(")");
+        break;
+    default:
+        break;
+    }
+    printf(")");
+}
+
+enum Statement_Kind
+{
+    STATEMENT_NONE,
+    STATEMENT_EXPRESSION,
+};
+
+union Statement_Value
+{
+    struct Expression* expression;
+};
+
+struct Statement
+{
+    enum Statement_Kind kind;
+    union Statement_Value value;
+
+    struct Span span;
+    struct Cursor location;
+
+    // if statement is within a group of multiple statements,
+    // points to the next statement within it.
+    struct Statement* next;
+};
+
+REGION(struct Statement, statement)
+
+void
+statement_print(const struct Statement* statement)
+{
+    printf("(stmt ");
+    switch (statement->kind) {
+    case STATEMENT_NONE:
+        printf("none");
+        break;
+    case STATEMENT_EXPRESSION: {
+        const struct Expression* expression = statement->value.expression;
+        expression_print(expression);
+        break;
+    }
+    default:
+        printf("unknown");
+        break;
+    }
+    printf(")");
+}
+
+// the top-level tree of a single catskill source file.
+struct Tree
+{
+    struct Statement* top_level_statements;
+};
+
+void
+tree_print(const struct Tree* tree)
+{
+    FOR_EACH(struct Statement*, statement, tree->top_level_statements)
+    {
+        statement_print(statement);
+        printf("\n");
+    }
+}
\ No newline at end of file