aboutsummaryrefslogtreecommitdiff
path: root/src/compile/sets.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-08-24 16:35:01 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-08-24 16:35:01 -0400
commite4d080f598b8528d5200deccde279ff02ac5750e (patch)
treef3a82306e82b1d8453a3c8d02fe7a06c0e355669 /src/compile/sets.c
parent5e82b074667627d1e6f44247396bae80f1c02fff (diff)
Move method calls into separate files
Diffstat (limited to 'src/compile/sets.c')
-rw-r--r--src/compile/sets.c90
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");
+}