aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-09-21 22:55:03 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-09-21 22:55:03 -0400
commit0d36812c6af951a41caac77d5f312949f3bc521f (patch)
treeae0f545805c524ffa467b925687bf70e88e2bc58 /src
parentfa7a0ddc0963deb387f0cae7bb22ca968ee9146f (diff)
Deprecate binary ops (other than ++) for tables. Instead use proper
methods: t.with(other), t.without(other), t.intersection(other), t.difference(other)
Diffstat (limited to 'src')
-rw-r--r--src/compile/binops.c11
-rw-r--r--src/compile/tables.c20
-rw-r--r--src/stdlib/tables.c16
-rw-r--r--src/stdlib/tables.h8
-rw-r--r--src/typecheck.c18
5 files changed, 39 insertions, 34 deletions
diff --git a/src/compile/binops.c b/src/compile/binops.c
index 0bff98c0..acf1e031 100644
--- a/src/compile/binops.c
+++ b/src/compile/binops.c
@@ -160,8 +160,6 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
return Texts("(", lhs, " + ", rhs, ")");
}
case Minus: {
- if (overall_t->tag == TableType)
- return Texts("Table$minus(", lhs, ", ", rhs, ", ", compile_type_info(overall_t), ")");
if (overall_t->tag != IntType && overall_t->tag != NumType && overall_t->tag != ByteType)
code_err(ast,
"Math operations are only supported for values of the same "
@@ -204,8 +202,6 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
case And: {
if (overall_t->tag == BoolType) return Texts("(", lhs, " && ", rhs, ")");
else if (overall_t->tag == IntType || overall_t->tag == ByteType) return Texts("(", lhs, " & ", rhs, ")");
- else if (overall_t->tag == TableType)
- return Texts("Table$and(", lhs, ", ", rhs, ", ", compile_type_info(overall_t), ")");
else
code_err(ast, "The 'and' operator isn't supported between ", type_to_text(lhs_t), " and ",
type_to_text(rhs_t), " values");
@@ -218,8 +214,6 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
return Texts("(", lhs, " || ", rhs, ")");
} else if (overall_t->tag == IntType || overall_t->tag == ByteType) {
return Texts("(", lhs, " | ", rhs, ")");
- } else if (overall_t->tag == TableType) {
- return Texts("Table$or(", lhs, ", ", rhs, ", ", compile_type_info(overall_t), ")");
} else {
code_err(ast, "The 'or' operator isn't supported between ", type_to_text(lhs_t), " and ",
type_to_text(rhs_t), " values");
@@ -229,8 +223,6 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
// TODO: support optional values in `xor` expressions
if (overall_t->tag == BoolType || overall_t->tag == IntType || overall_t->tag == ByteType)
return Texts("(", lhs, " ^ ", rhs, ")");
- else if (overall_t->tag == TableType)
- return Texts("Table$xor(", lhs, ", ", rhs, ", ", compile_type_info(overall_t), ")");
else
code_err(ast, "The 'xor' operator isn't supported between ", type_to_text(lhs_t), " and ",
type_to_text(rhs_t), " values");
@@ -245,6 +237,9 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) {
return Texts("List$concat(", lhs, ", ", rhs, ", sizeof(",
compile_type(Match(overall_t, ListType)->item_type), "))");
}
+ case TableType: {
+ return Texts("Table$with(", lhs, ", ", rhs, ", ", compile_type_info(overall_t), ")");
+ }
default:
code_err(ast, "Concatenation isn't supported between ", type_to_text(lhs_t), " and ", type_to_text(rhs_t),
" values");
diff --git a/src/compile/tables.c b/src/compile/tables.c
index b6efdecd..814d81f5 100644
--- a/src/compile/tables.c
+++ b/src/compile/tables.c
@@ -139,5 +139,25 @@ Text_t compile_table_method_call(env_t *env, ast_t *ast) {
self = compile_to_pointer_depth(env, call->self, 0, false);
arg_t *arg_spec = new (arg_t, .name = "fallback", .type = Type(OptionalType, self_value_t));
return Texts("Table$with_fallback(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ")");
+ } else if (streq(call->name, "intersection")) {
+ 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$intersection(", self, ", ", compile_arguments(env, ast, arg_spec, call->args), ", ",
+ compile_type_info(self_value_t), ")");
+ } 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, "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, "difference")) {
+ 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$difference(", 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");
}
diff --git a/src/stdlib/tables.c b/src/stdlib/tables.c
index bda55375..6698dea3 100644
--- a/src/stdlib/tables.c
+++ b/src/stdlib/tables.c
@@ -577,9 +577,9 @@ Table_t Table$from_entries(List_t entries, const TypeInfo_t *type) {
return t;
}
-// And is "set intersection" in formal terms
+// "set intersection" in formal terms
public
-Table_t Table$and(Table_t a, Table_t b, const TypeInfo_t *type) {
+Table_t Table$intersection(Table_t a, Table_t b, const TypeInfo_t *type) {
// Return a table such that t[k]==a[k] for all k such that a.has(k), b.has(k), and a[k]==b[k]
Table_t result = {};
const size_t offset = value_offset(type);
@@ -595,9 +595,9 @@ Table_t Table$and(Table_t a, Table_t b, const TypeInfo_t *type) {
return result;
}
-// Or is "set union" in formal terms
+// "set union" in formal terms
public
-Table_t Table$or(Table_t a, Table_t b, const TypeInfo_t *type) {
+Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type) {
// return a table such that t[k]==b[k] for all k such that b.has(k), and t[k]==a[k] for all k such that a.has(k) and
// not b.has(k)
Table_t result = {};
@@ -617,9 +617,9 @@ Table_t Table$or(Table_t a, Table_t b, const TypeInfo_t *type) {
return result;
}
-// Xor is "disjunctive union" or "symmetric difference" in formal terms
+// "disjunctive union" or "symmetric difference" in formal terms
public
-Table_t Table$xor(Table_t a, Table_t b, const TypeInfo_t *type) {
+Table_t Table$difference(Table_t a, Table_t b, const TypeInfo_t *type) {
// return a table with elements in `a` or `b`, but not both
Table_t result = {};
const size_t offset = value_offset(type);
@@ -638,9 +638,9 @@ Table_t Table$xor(Table_t a, Table_t b, const TypeInfo_t *type) {
return result;
}
-// Minus is "set difference" in formal terms
+// "without" is "set difference" in formal terms
public
-Table_t Table$minus(Table_t a, Table_t b, const TypeInfo_t *type) {
+Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type) {
// Return a table such that t[k]==a[k] for all k such that not b.has(k) or b[k] != a[k]
Table_t result = {};
const size_t offset = value_offset(type);
diff --git a/src/stdlib/tables.h b/src/stdlib/tables.h
index 4364530a..f4870f80 100644
--- a/src/stdlib/tables.h
+++ b/src/stdlib/tables.h
@@ -91,10 +91,10 @@ void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type);
Table$remove(t, &k, type); \
})
-Table_t Table$and(Table_t a, Table_t b, const TypeInfo_t *type);
-Table_t Table$or(Table_t a, Table_t b, const TypeInfo_t *type);
-Table_t Table$minus(Table_t a, Table_t b, const TypeInfo_t *type);
-Table_t Table$xor(Table_t a, Table_t b, const TypeInfo_t *type);
+Table_t Table$intersection(Table_t a, Table_t b, const TypeInfo_t *type);
+Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type);
+Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type);
+Table_t Table$difference(Table_t a, Table_t b, const TypeInfo_t *type);
Table_t Table$with_fallback(Table_t t, OptionalTable_t fallback);
void Table$clear(Table_t *t);
diff --git a/src/typecheck.c b/src/typecheck.c
index 6cd87289..0f720faa 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -1033,6 +1033,10 @@ type_t *get_type(env_t *env, ast_t *ast) {
else if (streq(call->name, "set")) return Type(VoidType);
else if (streq(call->name, "sorted")) return self_value_t;
else if (streq(call->name, "with_fallback")) return self_value_t;
+ else if (streq(call->name, "without")) return self_value_t;
+ else if (streq(call->name, "intersection")) return self_value_t;
+ else if (streq(call->name, "difference")) return self_value_t;
+ else if (streq(call->name, "with")) return self_value_t;
code_err(ast, "There is no '", call->name, "' method for ", type_to_text(self_value_t), " tables");
}
default: {
@@ -1152,9 +1156,6 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *lhs_t = get_type(env, binop.lhs);
type_t *rhs_t = get_type(env, binop.rhs);
- type_t *lhs_val = value_type(lhs_t), *rhs_val = value_type(rhs_t);
- if (type_eq(lhs_val, rhs_val) && lhs_val->tag == TableType) return lhs_val;
-
if (binop.lhs->tag == Int && is_int_type(rhs_t)) return rhs_t;
else if (binop.rhs->tag == Int && is_int_type(lhs_t)) return lhs_t;
@@ -1198,9 +1199,6 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *lhs_t = get_type(env, binop.lhs);
type_t *rhs_t = get_type(env, binop.rhs);
- type_t *lhs_val = value_type(lhs_t), *rhs_val = value_type(rhs_t);
- if (type_eq(lhs_val, rhs_val) && lhs_val->tag == TableType) return lhs_val;
-
if (binop.lhs->tag == Int && is_int_type(rhs_t)) return rhs_t;
else if (binop.rhs->tag == Int && is_int_type(lhs_t)) return lhs_t;
@@ -1231,9 +1229,6 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *lhs_t = get_type(env, binop.lhs);
type_t *rhs_t = get_type(env, binop.rhs);
- type_t *lhs_val = value_type(lhs_t), *rhs_val = value_type(rhs_t);
- if (type_eq(lhs_val, rhs_val) && lhs_val->tag == TableType) return lhs_val;
-
if (binop.lhs->tag == Int && is_int_type(rhs_t)) return rhs_t;
else if (binop.rhs->tag == Int && is_int_type(lhs_t)) return lhs_t;
@@ -1291,11 +1286,6 @@ type_t *get_type(env_t *env, ast_t *ast) {
type_t *lhs_t = get_type(env, binop.lhs);
type_t *rhs_t = get_type(env, binop.rhs);
- if (ast->tag == Minus) {
- type_t *lhs_val = value_type(lhs_t), *rhs_val = value_type(rhs_t);
- if (type_eq(lhs_val, rhs_val) && lhs_val->tag == TableType) return lhs_val;
- }
-
if (ast->tag == LeftShift || ast->tag == UnsignedLeftShift || ast->tag == RightShift
|| ast->tag == UnsignedRightShift) {
if (!is_int_type(rhs_t))