diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 15:07:36 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 15:07:36 -0400 |
| commit | e30c0f06d55cd7b27c5d012a96989920f586e4a1 (patch) | |
| tree | 785c0f59ee83173867db508dbcb271adc97d1582 | |
| parent | be534f5e511a1d3836254b827cdaa2b8c309f5c4 (diff) | |
Split list compilation logic into its own file.
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | src/compile.c | 50 | ||||
| -rw-r--r-- | src/compile.h | 1 | ||||
| -rw-r--r-- | src/compile/list.c | 61 | ||||
| -rw-r--r-- | src/compile/list.h | 5 | ||||
| -rw-r--r-- | src/environment.h | 1 |
6 files changed, 71 insertions, 49 deletions
@@ -95,7 +95,7 @@ else endif EXE_FILE=tomo_$(TOMO_VERSION) -COMPILER_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c)) +COMPILER_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c src/compile/*.c)) STDLIB_OBJS=$(patsubst %.c,%.o,$(wildcard src/stdlib/*.c)) TESTS=$(patsubst test/%.tm,test/results/%.tm.testresult,$(wildcard test/*.tm)) API_YAML=$(wildcard api/*.yaml) diff --git a/src/compile.c b/src/compile.c index 262608c5..b5e22342 100644 --- a/src/compile.c +++ b/src/compile.c @@ -8,6 +8,7 @@ #include "ast.h" #include "compile.h" +#include "compile/list.h" #include "config.h" #include "enums.h" #include "environment.h" @@ -35,14 +36,11 @@ static Text_t promote_to_optional(type_t *t, Text_t code); static Text_t compile_none(type_t *t); static Text_t compile_empty(type_t *t); static Text_t compile_declared_value(env_t *env, ast_t *declaration_ast); -static Text_t compile_to_type(env_t *env, ast_t *ast, type_t *t); -static Text_t compile_typed_list(env_t *env, ast_t *ast, type_t *list_type); static Text_t compile_typed_set(env_t *env, ast_t *ast, type_t *set_type); static Text_t compile_typed_table(env_t *env, ast_t *ast, type_t *table_type); static Text_t compile_typed_allocation(env_t *env, ast_t *ast, type_t *pointer_type); static Text_t check_none(type_t *t, Text_t value); static Text_t optional_into_nonnone(type_t *t, Text_t value); -static ast_t *add_to_list_comprehension(ast_t *item, ast_t *subject); static ast_t *add_to_table_comprehension(ast_t *entry, ast_t *subject); static ast_t *add_to_set_comprehension(ast_t *item, ast_t *subject); static Text_t compile_lvalue(env_t *env, ast_t *ast); @@ -2111,6 +2109,7 @@ Text_t compile_to_pointer_depth(env_t *env, ast_t *ast, int64_t target_depth, bo return val; } +public Text_t compile_to_type(env_t *env, ast_t *ast, type_t *t) { assert(!is_incomplete_type(t)); if (ast->tag == Int && is_numeric_type(non_optional(t))) { @@ -2188,47 +2187,6 @@ Text_t compile_to_type(env_t *env, ast_t *ast, type_t *t) { code_err(ast, "I expected a ", type_to_str(t), " here, but this is a ", type_to_str(actual)); } -Text_t compile_typed_list(env_t *env, ast_t *ast, type_t *list_type) { - DeclareMatch(list, ast, List); - if (!list->items) return Text("(List_t){.length=0}"); - - type_t *item_type = Match(list_type, ListType)->item_type; - - int64_t n = 0; - for (ast_list_t *item = list->items; item; item = item->next) { - ++n; - if (item->ast->tag == Comprehension) goto list_comprehension; - } - - { - env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : env; - if (is_incomplete_type(item_type)) code_err(ast, "This list's type can't be inferred!"); - Text_t code = Texts("TypedListN(", compile_type(item_type), ", ", String(n)); - for (ast_list_t *item = list->items; item; item = item->next) { - code = Texts(code, ", ", compile_to_type(scope, item->ast, item_type)); - } - return Texts(code, ")"); - } - -list_comprehension: { - env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : fresh_scope(env); - static int64_t comp_num = 1; - const char *comprehension_name = String("list$", comp_num++); - ast_t *comprehension_var = - LiteralCode(Texts("&", comprehension_name), .type = Type(PointerType, .pointed = list_type, .is_stack = true)); - Closure_t comp_action = {.fn = add_to_list_comprehension, .userdata = comprehension_var}; - scope->comprehension_action = &comp_action; - Text_t code = Texts("({ List_t ", comprehension_name, " = {};"); - // set_binding(scope, comprehension_name, list_type, comprehension_name); - for (ast_list_t *item = list->items; item; item = item->next) { - if (item->ast->tag == Comprehension) code = Texts(code, "\n", compile_statement(scope, item->ast)); - else code = Texts(code, compile_statement(env, add_to_list_comprehension(item->ast, comprehension_var))); - } - code = Texts(code, " ", comprehension_name, "; })"); - return code; -} -} - Text_t compile_typed_set(env_t *env, ast_t *ast, type_t *set_type) { DeclareMatch(set, ast, Set); if (!set->items) return Text("((Table_t){})"); @@ -2667,10 +2625,6 @@ ast_t *add_to_table_comprehension(ast_t *entry, ast_t *subject) { .args = new (arg_ast_t, .value = e->key, .next = new (arg_ast_t, .value = e->value))); } -ast_t *add_to_list_comprehension(ast_t *item, ast_t *subject) { - return WrapAST(item, MethodCall, .name = "insert", .self = subject, .args = new (arg_ast_t, .value = item)); -} - ast_t *add_to_set_comprehension(ast_t *item, ast_t *subject) { return WrapAST(item, MethodCall, .name = "add", .self = subject, .args = new (arg_ast_t, .value = item)); } diff --git a/src/compile.h b/src/compile.h index 21176395..56b522c7 100644 --- a/src/compile.h +++ b/src/compile.h @@ -7,6 +7,7 @@ #include "environment.h" #include "stdlib/datatypes.h" +Text_t compile_to_type(env_t *env, ast_t *ast, type_t *t); Text_t expr_as_text(Text_t expr, type_t *t, Text_t color); Text_t compile_file(env_t *env, ast_t *ast); Text_t compile_file_header(env_t *env, Path_t header_path, ast_t *ast); diff --git a/src/compile/list.c b/src/compile/list.c new file mode 100644 index 00000000..01036cda --- /dev/null +++ b/src/compile/list.c @@ -0,0 +1,61 @@ +// Compilation logic for lists + +#include <gc.h> +#include <glob.h> +#include <gmp.h> +#include <uninorm.h> + +#include "../ast.h" +#include "../compile.h" +#include "../config.h" +#include "../environment.h" +#include "../stdlib/text.h" +#include "../stdlib/util.h" + +static ast_t *add_to_list_comprehension(ast_t *item, ast_t *subject) { + return WrapAST(item, MethodCall, .name = "insert", .self = subject, .args = new (arg_ast_t, .value = item)); +} + +public +Text_t compile_typed_list(env_t *env, ast_t *ast, type_t *list_type) { + DeclareMatch(list, ast, List); + if (!list->items) return Text("(List_t){.length=0}"); + + type_t *item_type = Match(list_type, ListType)->item_type; + + int64_t n = 0; + for (ast_list_t *item = list->items; item; item = item->next) { + ++n; + if (item->ast->tag == Comprehension) goto list_comprehension; + } + + { + env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : env; + if (is_incomplete_type(item_type)) code_err(ast, "This list's type can't be inferred!"); + Text_t code = Texts("TypedListN(", compile_type(item_type), ", ", String(n)); + for (ast_list_t *item = list->items; item; item = item->next) { + code = Texts(code, ", ", compile_to_type(scope, item->ast, item_type)); + } + return Texts(code, ")"); + } + +list_comprehension: { + env_t *scope = item_type->tag == EnumType ? with_enum_scope(env, item_type) : fresh_scope(env); + static int64_t comp_num = 1; + const char *comprehension_name = String("list$", comp_num++); + ast_t *comprehension_var = + LiteralCode(Texts("&", comprehension_name), .type = Type(PointerType, .pointed = list_type, .is_stack = true)); + Closure_t comp_action = {.fn = add_to_list_comprehension, .userdata = comprehension_var}; + scope->comprehension_action = &comp_action; + Text_t code = Texts("({ List_t ", comprehension_name, " = {};"); + // set_binding(scope, comprehension_name, list_type, comprehension_name); + for (ast_list_t *item = list->items; item; item = item->next) { + if (item->ast->tag == Comprehension) code = Texts(code, "\n", compile_statement(scope, item->ast)); + else code = Texts(code, compile_statement(env, add_to_list_comprehension(item->ast, comprehension_var))); + } + code = Texts(code, " ", comprehension_name, "; })"); + return code; +} +} + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/src/compile/list.h b/src/compile/list.h new file mode 100644 index 00000000..b9bf74d6 --- /dev/null +++ b/src/compile/list.h @@ -0,0 +1,5 @@ +#include "../ast.h" +#include "../environment.h" +#include "../stdlib/datatypes.h" + +Text_t compile_typed_list(env_t *env, ast_t *ast, type_t *list_type); diff --git a/src/environment.h b/src/environment.h index ca10dbae..2c646ad3 100644 --- a/src/environment.h +++ b/src/environment.h @@ -4,6 +4,7 @@ #include "stdlib/datatypes.h" #include "stdlib/print.h" +#include "stdlib/stdlib.h" #include "types.h" typedef struct { |
