diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 16:35:01 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 16:35:01 -0400 |
| commit | e4d080f598b8528d5200deccde279ff02ac5750e (patch) | |
| tree | f3a82306e82b1d8453a3c8d02fe7a06c0e355669 /src/compile/sets.c | |
| parent | 5e82b074667627d1e6f44247396bae80f1c02fff (diff) | |
Move method calls into separate files
Diffstat (limited to 'src/compile/sets.c')
| -rw-r--r-- | src/compile/sets.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/compile/sets.c b/src/compile/sets.c index a1471a5a..7cb56fff 100644 --- a/src/compile/sets.c +++ b/src/compile/sets.c @@ -4,7 +4,11 @@ #include "../environment.h" #include "../stdlib/datatypes.h" #include "../stdlib/text.h" +#include "../typecheck.h" #include "../types.h" +#include "functions.h" +#include "optionals.h" +#include "pointers.h" #include "promotion.h" static ast_t *add_to_set_comprehension(ast_t *item, ast_t *subject) { @@ -49,3 +53,89 @@ set_comprehension: { return code; } } + +public +Text_t compile_set_method_call(env_t *env, ast_t *ast) { + DeclareMatch(call, ast, MethodCall); + type_t *self_t = get_type(env, call->self); + + int64_t pointer_depth = 0; + type_t *self_value_t = self_t; + for (; self_value_t->tag == PointerType; self_value_t = Match(self_value_t, PointerType)->pointed) + pointer_depth += 1; + + Text_t self = compile(env, call->self); +#define EXPECT_POINTER() \ + do { \ + if (pointer_depth < 1) code_err(call->self, "I expected a set pointer here, not a set value"); \ + else if (pointer_depth > 1) code_err(call->self, "I expected a set pointer here, not a nested set pointer"); \ + } while (0) + DeclareMatch(set, self_value_t, SetType); + if (streq(call->name, "has")) { + self = compile_to_pointer_depth(env, call->self, 0, false); + arg_t *arg_spec = new (arg_t, .name = "key", .type = set->item_type); + return Texts("Table$has_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", + compile_type_info(self_value_t), ")"); + } else if (streq(call->name, "add")) { + EXPECT_POINTER(); + arg_t *arg_spec = new (arg_t, .name = "item", .type = set->item_type); + return Texts("Table$set_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", NULL, ", + compile_type_info(self_value_t), ")"); + } else if (streq(call->name, "add_all")) { + EXPECT_POINTER(); + arg_t *arg_spec = + new (arg_t, .name = "items", .type = Type(ListType, .item_type = Match(self_value_t, SetType)->item_type)); + return Texts("({ Table_t *set = ", self, "; ", + "List_t to_add = ", compile_arguments(env, ast, arg_spec, call->args), "; ", + "for (int64_t i = 0; i < to_add.length; i++)\n" + "Table$set(set, to_add.data + i*to_add.stride, NULL, ", + compile_type_info(self_value_t), ");\n", "(void)0; })"); + } else if (streq(call->name, "remove")) { + EXPECT_POINTER(); + arg_t *arg_spec = new (arg_t, .name = "item", .type = set->item_type); + return Texts("Table$remove_value(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", + compile_type_info(self_value_t), ")"); + } else if (streq(call->name, "remove_all")) { + EXPECT_POINTER(); + arg_t *arg_spec = + new (arg_t, .name = "items", .type = Type(ListType, .item_type = Match(self_value_t, SetType)->item_type)); + return Texts("({ Table_t *set = ", self, "; ", + "List_t to_add = ", compile_arguments(env, ast, arg_spec, call->args), "; ", + "for (int64_t i = 0; i < to_add.length; i++)\n" + "Table$remove(set, to_add.data + i*to_add.stride, ", + compile_type_info(self_value_t), ");\n", "(void)0; })"); + } else if (streq(call->name, "clear")) { + EXPECT_POINTER(); + (void)compile_arguments(env, ast, NULL, call->args); + return Texts("Table$clear(", self, ")"); + } else if (streq(call->name, "with")) { + self = compile_to_pointer_depth(env, call->self, 0, false); + arg_t *arg_spec = new (arg_t, .name = "other", .type = self_value_t); + return Texts("Table$with(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", + compile_type_info(self_value_t), ")"); + } else if (streq(call->name, "overlap")) { + self = compile_to_pointer_depth(env, call->self, 0, false); + arg_t *arg_spec = new (arg_t, .name = "other", .type = self_value_t); + return Texts("Table$overlap(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", + compile_type_info(self_value_t), ")"); + } else if (streq(call->name, "without")) { + self = compile_to_pointer_depth(env, call->self, 0, false); + arg_t *arg_spec = new (arg_t, .name = "other", .type = self_value_t); + return Texts("Table$without(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", + compile_type_info(self_value_t), ")"); + } else if (streq(call->name, "is_subset_of")) { + self = compile_to_pointer_depth(env, call->self, 0, false); + arg_t *arg_spec = + new (arg_t, .name = "other", .type = self_value_t, + .next = new (arg_t, .name = "strict", .type = Type(BoolType), .default_val = FakeAST(Bool, false))); + return Texts("Table$is_subset_of(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", + compile_type_info(self_value_t), ")"); + } else if (streq(call->name, "is_superset_of")) { + self = compile_to_pointer_depth(env, call->self, 0, false); + arg_t *arg_spec = + new (arg_t, .name = "other", .type = self_value_t, + .next = new (arg_t, .name = "strict", .type = Type(BoolType), .default_val = FakeAST(Bool, false))); + return Texts("Table$is_superset_of(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ", + compile_type_info(self_value_t), ")"); + } else code_err(ast, "There is no '", call->name, "' method for tables"); +} |
