aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-10-05 16:24:59 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-10-05 16:24:59 -0400
commit9738b3454639ddf3ae46186a5c6ba671fe9a6861 (patch)
tree3b9d300b4d2cae1479c013bdb154b1eb7e16780f /src
parent76d3008d98cf9cd6ed60a9aa66a87f854965f0ab (diff)
Add serialization and deserialization by coercion to/from [Byte]
Diffstat (limited to 'src')
-rw-r--r--src/compile/expressions.c6
-rw-r--r--src/compile/promotions.c15
-rw-r--r--src/stdlib/integers.c2
-rw-r--r--src/types.c3
4 files changed, 23 insertions, 3 deletions
diff --git a/src/compile/expressions.c b/src/compile/expressions.c
index 098ed4ca..4e6c720f 100644
--- a/src/compile/expressions.c
+++ b/src/compile/expressions.c
@@ -12,8 +12,10 @@
public
Text_t compile_maybe_incref(env_t *env, ast_t *ast, type_t *t) {
if (is_idempotent(ast) && can_be_mutated(env, ast)) {
- if (t->tag == ListType) return Texts("LIST_COPY(", compile_to_type(env, ast, t), ")");
- else if (t->tag == TableType) return Texts("TABLE_COPY(", compile_to_type(env, ast, t), ")");
+ type_t *actual = get_type(env, ast);
+ if (t->tag == ListType && type_eq(t, actual)) return Texts("LIST_COPY(", compile_to_type(env, ast, t), ")");
+ else if (t->tag == TableType && type_eq(t, actual))
+ return Texts("TABLE_COPY(", compile_to_type(env, ast, t), ")");
}
return compile_to_type(env, ast, t);
}
diff --git a/src/compile/promotions.c b/src/compile/promotions.c
index d453b764..68b4f64c 100644
--- a/src/compile/promotions.c
+++ b/src/compile/promotions.c
@@ -25,6 +25,21 @@ bool promote(env_t *env, ast_t *ast, Text_t *code, type_t *actual, type_t *neede
type_t *more_complete = most_complete_type(actual, needed);
if (more_complete) return true;
+ // Serialization/deserialization:
+ if (type_eq(needed, Type(ListType, Type(ByteType)))) {
+ *code = Texts("generic_serialize((", compile_declaration(actual, Text("[1]")), "){", *code, "}, ",
+ compile_type_info(actual), ")");
+ return true;
+ } else if (type_eq(actual, Type(ListType, Type(ByteType)))) {
+ *code = Texts("({ ", compile_declaration(needed, Text("deserialized")),
+ ";\n"
+ "generic_deserialize(",
+ *code, ", &deserialized, ", compile_type_info(needed),
+ ");\n"
+ "deserialized; })");
+ return true;
+ }
+
// Optional promotion:
if (needed->tag == OptionalType && type_eq(actual, Match(needed, OptionalType)->type)) {
*code = promote_to_optional(actual, *code);
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c
index e7a58ef3..962c97cf 100644
--- a/src/stdlib/integers.c
+++ b/src/stdlib/integers.c
@@ -27,7 +27,7 @@ int Int$print(FILE *f, Int_t i) {
}
}
-static inline Text_t _int64_to_text(int64_t n) {
+static Text_t _int64_to_text(int64_t n) {
if (n == INT64_MIN) return Text("-9223372036854775808");
char buf[21] = {[20] = 0}; // Big enough for INT64_MIN + '\0'
diff --git a/src/types.c b/src/types.c
index ff86ab8f..900588f5 100644
--- a/src/types.c
+++ b/src/types.c
@@ -274,6 +274,9 @@ PUREFUNC bool can_promote(type_t *actual, type_t *needed) {
// No promotion necessary:
if (type_eq(actual, needed)) return true;
+ // Serialization/deserialization
+ if (type_eq(actual, Type(ListType, Type(ByteType))) || type_eq(needed, Type(ListType, Type(ByteType)))) return true;
+
if (actual->tag == NumType && needed->tag == IntType) return false;
if (actual->tag == IntType && (needed->tag == NumType || needed->tag == BigIntType)) return true;