diff options
| author | Mel <mel@rnrd.eu> | 2025-06-12 17:14:12 +0200 |
|---|---|---|
| committer | Mel <mel@rnrd.eu> | 2025-06-12 17:14:12 +0200 |
| commit | 9676d1ca61b025af9e52506f8aec1f9c0792f51c (patch) | |
| tree | 1992a522d86019e87363c2b0de2ce37368d27789 /boot/tree.c | |
| parent | 8b655fe0f1d6589c9216a6244c067aec1d866be7 (diff) | |
| download | catskill-9676d1ca61b025af9e52506f8aec1f9c0792f51c.tar.zst catskill-9676d1ca61b025af9e52506f8aec1f9c0792f51c.zip | |
Parse most primitive types into tree
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/tree.c')
| -rw-r--r-- | boot/tree.c | 296 |
1 files changed, 270 insertions, 26 deletions
diff --git a/boot/tree.c b/boot/tree.c index 39a1de4..449f4e6 100644 --- a/boot/tree.c +++ b/boot/tree.c @@ -394,24 +394,247 @@ struct Block_Node void block_node_print(const struct Block_Node* block); -enum Type_Type +// a function header, describing the parameters and return type of function. +// used both as a type and in full function definitions. +struct Function_Header_Node { - TYPE_NONE, - TYPE_NAME, + // linked list of parameters. + // name, if given, is included in the type node. + struct Type_Node* parameters_type_and_name; + struct Type_Node* return_type; + + struct Span span; +}; + +void function_header_node_print(const struct Function_Header_Node* header); + +enum Type_Node_Type +{ + TYPE_NODE_NONE, + + TYPE_NODE_NAME, + TYPE_NODE_ARRAY, // an array of a type, `[int]`. + TYPE_NODE_REFERENCE, // a reference to a type, `&int`. + TYPE_NODE_MAYBE, // a type that may be null, `int?`. + TYPE_NODE_TUPLE, // a tuple type, `(int string)`. + TYPE_NODE_MAP, // a map type, `[string = int]`. + + TYPE_NODE_FUNCTION, // a function type, `fun (int) int`. + TYPE_NODE_STRUCTURE, // a struct, invoked either with `type` or with `{}` when a type is inline. + TYPE_NODE_VARIANT, // a tagged union. + TYPE_NODE_CLASS, // a class of types, a.k.a. an interface. +}; + +struct Type_Node_Name +{ + struct String name; +}; + +struct Type_Node_Array +{ + struct Type_Node* element_type; +}; + +struct Type_Node_Reference +{ + struct Type_Node* referenced_type; +}; + +struct Type_Node_Maybe +{ + struct Type_Node* inner_type; +}; + +struct Type_Node_Tuple +{ + struct Type_Node* head; // the first type in the tuple, if any. +}; + +struct Type_Node_Map +{ + struct Type_Node* key_type; + struct Type_Node* value_type; +}; + +struct Type_Node_Function +{ + struct Function_Header_Node header; +}; + +struct Type_Node_Structure +{ + // the fields of the structure, linked list of types and (required) names. + struct Type_Node* fields; +}; + +struct Type_Node_Variant +{ + // the variants of the tagged union, linked list of (required) variant names and backing types. + // if a variant has no backing type, it is TYPE_NODE_NONE. + struct Type_Node* variants; +}; + +struct Type_Node_Class +{ + // linked list of the types of methods required to implement the class. + // each node is required to have a name and be of TYPE_NODE_FUNCTION. + struct Type_Node* methods; +}; + +union Type_Node_Value +{ + struct Type_Node_Name name; + struct Type_Node_Array array; + struct Type_Node_Reference reference; + struct Type_Node_Maybe maybe; + struct Type_Node_Tuple tuple; + struct Type_Node_Map map; + struct Type_Node_Function function; + struct Type_Node_Structure structure; + struct Type_Node_Variant variant; + struct Type_Node_Class class; }; // a type node represents a type in the syntax tree. // currently, we only support types that are simple names. // or null types. +// also includes the name of the field, member, parameter, etc., for which +// the type is defined. struct Type_Node { - enum Type_Type type; + enum Type_Node_Type type; + union Type_Node_Value value; // note: we could also just include the token here i think? - struct String name; struct Span span; struct Cursor location; + + // usually a type is preceded by the name of the binding + // it is assigned to, e.g. `x int`, `string y`, etc. + // this is the name of that binding, for ease of listing. + struct String value_name; + + // if type is within a group of multiple types, + // points to the next type within the group. + struct Type_Node* next; }; +REGION(struct Type_Node, type_node) + +// allocates a new type node in the global type node region. +struct Type_Node* +type_node_new( + enum Type_Node_Type type, union Type_Node_Value value, struct Span span, struct Cursor location) +{ + check(region_type_node_cursor < REGION_SIZE, "out of type node memory"); + struct Type_Node* type_node = ®ion_type_node[region_type_node_cursor++]; + *type_node = (struct Type_Node){ + .type = type, + .value = value, + .span = span, + .location = location, + + .value_name = string_empty(), + .next = nil, + }; + return type_node; +} + +// allocates a new type node with no value, used for `none` types. +// this is used for types that are not specified, note that it is still +// fully allocated and can be used in the syntax tree. +struct Type_Node* +type_node_none(struct Span span, struct Cursor location) +{ + return type_node_new(TYPE_NODE_NONE, (union Type_Node_Value){ 0 }, span, location); +} + +bool +type_node_is_none(const struct Type_Node* type_node) +{ + return type_node->type == TYPE_NODE_NONE; +} + +void +type_node_print(const struct Type_Node* type_node) +{ + printf("(type "); + switch (type_node->type) { + case TYPE_NODE_NONE: + printf("none"); + break; + case TYPE_NODE_NAME: + printf("name %s", type_node->value.name.name.data); + break; + case TYPE_NODE_ARRAY: + printf("array of "); + type_node_print(type_node->value.array.element_type); + break; + case TYPE_NODE_REFERENCE: + printf("reference to "); + type_node_print(type_node->value.reference.referenced_type); + break; + case TYPE_NODE_MAYBE: + printf("maybe "); + type_node_print(type_node->value.maybe.inner_type); + break; + case TYPE_NODE_TUPLE: { + printf("tuple"); + FOR_EACH(struct Type_Node*, current, type_node->value.tuple.head) + { + printf(" "); + type_node_print(current); + } + break; + } + case TYPE_NODE_MAP: + printf("map "); + type_node_print(type_node->value.map.key_type); + printf(" = "); + type_node_print(type_node->value.map.value_type); + break; + case TYPE_NODE_FUNCTION: { + printf("function "); + function_header_node_print(&type_node->value.function.header); + break; + } + case TYPE_NODE_STRUCTURE: { + printf("structure"); + FOR_EACH(struct Type_Node*, current, type_node->value.structure.fields) + { + printf(" (field %s) ", current->value_name.data); + type_node_print(current); + } + break; + } + case TYPE_NODE_VARIANT: { + printf("variant"); + FOR_EACH(struct Type_Node*, current, type_node->value.variant.variants) + { + if (type_node_is_none(current)) { + printf(" (variant %s)", current->value_name.data); + } else { + printf(" (variant %s of ", current->value_name.data); + type_node_print(current); + printf(")"); + } + } + break; + } + case TYPE_NODE_CLASS: + printf("class"); + FOR_EACH(struct Type_Node*, current, type_node->value.class.methods) + { + check(current->type == TYPE_NODE_FUNCTION, + "expected class method type node to be a function type"); + printf(" (method %s ", current->value_name.data); + function_header_node_print(¤t->value.function.header); + printf(")"); + } + break; + } + printf(")"); +} + enum Expression_Kind { EXPRESSION_NONE, @@ -503,18 +726,9 @@ struct Expression_Increment_Decrement enum Increment_Decrement_Operation operation; }; -#define EXPRESSION_FUNCTION_MAX_PARAMS 32 - struct Expression_Function { - struct Expression_Function_Parameter - { - struct String name; - struct Type_Node type; - } parameters[EXPRESSION_FUNCTION_MAX_PARAMS]; - uint parameter_count; - - struct Type_Node return_type; + struct Function_Header_Node header; struct Block_Node body; }; @@ -568,6 +782,28 @@ expression_new( } void +function_header_node_print(const struct Function_Header_Node* header) +{ + FOR_EACH(struct Type_Node*, current, header->parameters_type_and_name) + { + if (current != header->parameters_type_and_name) printf(" "); + + if (!string_is_empty(current->value_name)) + printf("(param %s) ", current->value_name.data); + else + printf("(param) "); + + type_node_print(current); + } + + if (header->return_type) { + printf(" (returns "); + type_node_print(header->return_type); + printf(")"); + } +} + +void expression_print(const struct Expression* expression) { printf("(expr "); @@ -641,13 +877,8 @@ expression_print(const struct Expression* expression) } case EXPRESSION_FUNCTION: { const struct Expression_Function* fun = &expression->value.function; - printf("(function"); - for (uint i = 0; i < fun->parameter_count; ++i) { - const struct Expression_Function_Parameter* param = &fun->parameters[i]; - printf(" (param %s)", param->name.data); - if (param->type.type != TYPE_NONE) { printf(" (type %s)", param->type.name.data); } - } - if (fun->return_type.type != TYPE_NONE) printf(" (returns %s)", fun->return_type.name.data); + printf("(function "); + function_header_node_print(&fun->header); printf(" "); block_node_print(&fun->body); printf(")"); @@ -673,6 +904,7 @@ enum Statement_Kind STATEMENT_BREAK, STATEMENT_CONTINUE, STATEMENT_DEFER, + STATEMENT_TYPE, }; struct Statement_Value_Expression @@ -684,7 +916,7 @@ struct Statement_Value_Declaration { struct String_Array names; struct Expression* initializer; - struct Type_Node type; + struct Type_Node* type; }; struct Statement_Value_Block @@ -731,6 +963,12 @@ struct Statement_Value_Defer struct Block_Node block; }; +struct Statement_Value_Type +{ + struct Type_Node* type; + struct String name; +}; + union Statement_Value { struct Statement_Value_Expression expression; @@ -740,6 +978,7 @@ union Statement_Value struct Statement_Value_Loop loop; struct Statement_Value_Return return_value; struct Statement_Value_Defer defer; + struct Statement_Value_Type type; }; struct Statement @@ -807,9 +1046,9 @@ statement_print(const struct Statement* statement) { printf("%s ", name.data); } - if (statement->value.declaration.type.type != TYPE_NONE) { - printf("(type %s) ", statement->value.declaration.type.name.data); - } + if (type_node_is_none(statement->value.declaration.type)) + type_node_print(statement->value.declaration.type); + if (statement->value.declaration.initializer) { printf("(initializer "); expression_print(statement->value.declaration.initializer); @@ -889,6 +1128,11 @@ statement_print(const struct Statement* statement) printf(")"); break; } + case STATEMENT_TYPE: { + printf("(type name %s) ", statement->value.type.name.data); + type_node_print(statement->value.type.type); + break; + } default: failure("unexpected statement kind passed to `statement_print`"); break; |
