diff --git a/net.c b/net.c index b6c4022..03fe02d 100644 --- a/net.c +++ b/net.c @@ -2,6 +2,134 @@ #include "net.h" #include +__attribute__((unused)) static int abs_serialize(struct Abs val, byte *buf); +__attribute__((unused)) static int abs_deserialize(struct Abs *val, const byte *buf); +__attribute__((unused)) static void abs_free(struct Abs val); +__attribute__((unused)) static int key_serialize(struct Key val, byte *buf); +__attribute__((unused)) static int key_deserialize(struct Key *val, const byte *buf); +__attribute__((unused)) static void key_free(struct Key val); +__attribute__((unused)) static int rel_serialize(struct Rel val, byte *buf); +__attribute__((unused)) static int rel_deserialize(struct Rel *val, const byte *buf); +__attribute__((unused)) static void rel_free(struct Rel val); +__attribute__((unused)) static int tag_list_serialize(struct TagList val, byte *buf); +__attribute__((unused)) static int tag_list_deserialize(struct TagList *val, const byte *buf); +__attribute__((unused)) static void tag_list_free(struct TagList val); +__attribute__((unused)) static int tag_serialize(struct Tag val, byte *buf); +__attribute__((unused)) static int tag_deserialize(struct Tag *val, const byte *buf); +__attribute__((unused)) static void tag_free(struct Tag val); + +static int abs_serialize(struct Abs val, byte *buf) { + byte * base_buf = buf; + *(uint32_t *)&buf[0] = val.min; + *(uint32_t *)&buf[4] = val.max; + *(uint32_t *)&buf[8] = val.fuzz; + *(uint32_t *)&buf[12] = val.flat; + *(uint32_t *)&buf[16] = val.res; + *(uint16_t *)&buf[20] = val.id; + buf += 24; + return (int)(buf - base_buf); +} +static int abs_deserialize(struct Abs *val, const byte *buf) { + const byte * base_buf = buf; + val->min = *(uint32_t *)&buf[0]; + val->max = *(uint32_t *)&buf[4]; + val->fuzz = *(uint32_t *)&buf[8]; + val->flat = *(uint32_t *)&buf[12]; + val->res = *(uint32_t *)&buf[16]; + val->id = *(uint16_t *)&buf[20]; + buf += 24; + return (int)(buf - base_buf); +} +static void abs_free(struct Abs val) { } + +static int key_serialize(struct Key val, byte *buf) { + byte * base_buf = buf; + *(uint16_t *)&buf[0] = val.id; + buf += 2; + return (int)(buf - base_buf); +} +static int key_deserialize(struct Key *val, const byte *buf) { + const byte * base_buf = buf; + val->id = *(uint16_t *)&buf[0]; + buf += 2; + return (int)(buf - base_buf); +} +static void key_free(struct Key val) { } + +static int rel_serialize(struct Rel val, byte *buf) { + byte * base_buf = buf; + *(uint16_t *)&buf[0] = val.id; + buf += 2; + return (int)(buf - base_buf); +} +static int rel_deserialize(struct Rel *val, const byte *buf) { + const byte * base_buf = buf; + val->id = *(uint16_t *)&buf[0]; + buf += 2; + return (int)(buf - base_buf); +} +static void rel_free(struct Rel val) { } + +static int tag_list_serialize(struct TagList val, byte *buf) { + byte * base_buf = buf; + *(uint16_t *)&buf[0] = val.tags.len; + buf += 2; + for(size_t i = 0; i < val.tags.len; i++) { + typeof(val.tags.data[i]) e0 = val.tags.data[i]; + buf += tag_serialize(e0, &buf[0]); + } + buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); + return (int)(buf - base_buf); +} +static int tag_list_deserialize(struct TagList *val, const byte *buf) { + const byte * base_buf = buf; + val->tags.len = *(uint16_t *)&buf[0]; + buf += 2; + val->tags.data = malloc(val->tags.len * sizeof(typeof(*val->tags.data))); + for(size_t i = 0; i < val->tags.len; i++) { + typeof(&val->tags.data[i]) e0 = &val->tags.data[i]; + buf += tag_deserialize(e0, &buf[0]); + } + buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); + return (int)(buf - base_buf); +} +static void tag_list_free(struct TagList val) { + for(size_t i = 0; i < val.tags.len; i++) { + typeof(val.tags.data[i]) e0 = val.tags.data[i]; + tag_free(e0); + } + free(val.tags.data); +} + +static int tag_serialize(struct Tag val, byte *buf) { + byte * base_buf = buf; + *(uint16_t *)&buf[0] = val.name.len; + buf += 2; + for(size_t i = 0; i < val.name.len; i++) { + typeof(val.name.data[i]) e0 = val.name.data[i]; + *(char *)&buf[0] = e0; + buf += 1; + } + buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); + return (int)(buf - base_buf); +} +static int tag_deserialize(struct Tag *val, const byte *buf) { + const byte * base_buf = buf; + val->name.len = *(uint16_t *)&buf[0]; + buf += 2; + val->name.data = malloc(val->name.len * sizeof(typeof(*val->name.data))); + for(size_t i = 0; i < val->name.len; i++) { + typeof(&val->name.data[i]) e0 = &val->name.data[i]; + *e0 = *(char *)&buf[0]; + buf += 1; + } + buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); + return (int)(buf - base_buf); +} +static void tag_free(struct Tag val) { + free(val.name.data); +} + int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) { const byte *base_buf = buf; if(len < 2 * MSG_MAGIC_SIZE) @@ -21,23 +149,15 @@ int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) { buf += 8; for(size_t i = 0; i < msg->info.abs.len; i++) { typeof(msg->info.abs.data[i]) e0 = msg->info.abs.data[i]; - *(uint32_t *)&buf[0] = e0.min; - *(uint32_t *)&buf[4] = e0.max; - *(uint32_t *)&buf[8] = e0.fuzz; - *(uint32_t *)&buf[12] = e0.flat; - *(uint32_t *)&buf[16] = e0.res; - *(uint16_t *)&buf[20] = e0.id; - buf += 24; + buf += abs_serialize(e0, &buf[0]); } for(size_t i = 0; i < msg->info.rel.len; i++) { typeof(msg->info.rel.data[i]) e0 = msg->info.rel.data[i]; - *(uint16_t *)&buf[0] = e0.id; - buf += 2; + buf += rel_serialize(e0, &buf[0]); } for(size_t i = 0; i < msg->info.key.len; i++) { typeof(msg->info.key.data[i]) e0 = msg->info.key.data[i]; - *(uint16_t *)&buf[0] = e0.id; - buf += 2; + buf += key_serialize(e0, &buf[0]); } buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); break; @@ -89,20 +209,7 @@ int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) { buf += 18; for(size_t i = 0; i < msg->request.requests.len; i++) { typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i]; - *(uint16_t *)&buf[0] = e0.tags.len; - buf += 2; - for(size_t i = 0; i < e0.tags.len; i++) { - typeof(e0.tags.data[i]) e1 = e0.tags.data[i]; - *(uint16_t *)&buf[0] = e1.name.len; - buf += 2; - for(size_t i = 0; i < e1.name.len; i++) { - typeof(e1.name.data[i]) e2 = e1.name.data[i]; - *(char *)&buf[0] = e2; - buf += 1; - } - buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); - } - buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); + buf += tag_list_serialize(e0, &buf[0]); } buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); break; @@ -142,23 +249,15 @@ int msg_device_deserialize(const byte *buf, size_t len, DeviceMessage *msg) { buf += 8; for(size_t i = 0; i < msg->info.abs.len; i++) { typeof(&msg->info.abs.data[i]) e0 = &msg->info.abs.data[i]; - e0->min = *(uint32_t *)&buf[0]; - e0->max = *(uint32_t *)&buf[4]; - e0->fuzz = *(uint32_t *)&buf[8]; - e0->flat = *(uint32_t *)&buf[12]; - e0->res = *(uint32_t *)&buf[16]; - e0->id = *(uint16_t *)&buf[20]; - buf += 24; + buf += abs_deserialize(e0, &buf[0]); } for(size_t i = 0; i < msg->info.rel.len; i++) { typeof(&msg->info.rel.data[i]) e0 = &msg->info.rel.data[i]; - e0->id = *(uint16_t *)&buf[0]; - buf += 2; + buf += rel_deserialize(e0, &buf[0]); } for(size_t i = 0; i < msg->info.key.len; i++) { typeof(&msg->info.key.data[i]) e0 = &msg->info.key.data[i]; - e0->id = *(uint16_t *)&buf[0]; - buf += 2; + buf += key_deserialize(e0, &buf[0]); } buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); break; @@ -210,22 +309,7 @@ int msg_device_deserialize(const byte *buf, size_t len, DeviceMessage *msg) { msg->request.requests.data = malloc(msg->request.requests.len * sizeof(typeof(*msg->request.requests.data))); for(size_t i = 0; i < msg->request.requests.len; i++) { typeof(&msg->request.requests.data[i]) e0 = &msg->request.requests.data[i]; - e0->tags.len = *(uint16_t *)&buf[0]; - buf += 2; - e0->tags.data = malloc(e0->tags.len * sizeof(typeof(*e0->tags.data))); - for(size_t i = 0; i < e0->tags.len; i++) { - typeof(&e0->tags.data[i]) e1 = &e0->tags.data[i]; - e1->name.len = *(uint16_t *)&buf[0]; - buf += 2; - e1->name.data = malloc(e1->name.len * sizeof(typeof(*e1->name.data))); - for(size_t i = 0; i < e1->name.len; i++) { - typeof(&e1->name.data[i]) e2 = &e1->name.data[i]; - *e2 = *(char *)&buf[0]; - buf += 1; - } - buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); - } - buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); + buf += tag_list_deserialize(e0, &buf[0]); } buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); if(msg->request._version != 1UL) { @@ -270,11 +354,7 @@ void msg_device_free(DeviceMessage *msg) { case DeviceTagRequest: { for(size_t i = 0; i < msg->request.requests.len; i++) { typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i]; - for(size_t i = 0; i < e0.tags.len; i++) { - typeof(e0.tags.data[i]) e1 = e0.tags.data[i]; - free(e1.name.data); - } - free(e0.tags.data); + tag_list_free(e0); } free(msg->request.requests.data); break; diff --git a/net.h b/net.h index 115064b..493a07d 100644 --- a/net.h +++ b/net.h @@ -29,13 +29,6 @@ typedef struct Rel { uint16_t id; } Rel; -typedef struct Tag { - struct { - uint16_t len; - char *data; - } name; -} Tag; - typedef struct TagList { struct { uint16_t len; @@ -43,6 +36,13 @@ typedef struct TagList { } tags; } TagList; +typedef struct Tag { + struct { + uint16_t len; + char *data; + } name; +} Tag; + // Device typedef enum DeviceTag { diff --git a/ser/codegen.c b/ser/codegen.c index 1b6c70d..7028da3 100644 --- a/ser/codegen.c +++ b/ser/codegen.c @@ -36,6 +36,8 @@ static void file_writer_format(void *w, const char *fmt, va_list args) { FileWriter *fw = (FileWriter *)w; vfprintf(fw->fd, fmt, args); } +static void null_writer_write(void *w, const char *data, size_t len) { } +static void null_writer_format(void *w, const char *fmt, va_list args) { } BufferedWriter buffered_writer_init() { CharVec buf = vec_init(); @@ -52,6 +54,9 @@ FileWriter file_writer_from_fd(FILE *fd) { return (FileWriter){.w.write = file_writer_write, .w.format = file_writer_format, .fd = fd}; } void file_writer_drop(FileWriter w) { fclose(w.fd); } +NullWriter null_writer_init() { + return (NullWriter){.w.write = null_writer_write, .w.format = null_writer_format}; +} void wt_write(Writer *w, const char *data, size_t len) { w->write(w, data, len); } void wt_format(Writer *w, const char *fmt, ...) { @@ -82,7 +87,7 @@ int struct_object_compare(const void *a, const void *b) { return strncmp(sa->name.ptr, sb->name.ptr, len); } -void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *obj)) { +void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *obj, void *), void * user_data) { Hashmap *dependencies = hashmap_init(strdeps_hash, strdeps_equal, strdeps_drop, sizeof(StructDependencies)); TypeDef *td = NULL; @@ -132,7 +137,7 @@ void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObjec for (size_t i = 0; i < to_define.len; i++) { StructObject *s = to_define.data[i]; - define(w, s); + define(w, s, user_data); hashmap_delete(dependencies, &(StructDependencies){.obj = s}); } pass++; diff --git a/ser/codegen.h b/ser/codegen.h index 4d6833f..dc2d3cd 100644 --- a/ser/codegen.h +++ b/ser/codegen.h @@ -29,17 +29,22 @@ typedef struct { FILE *fd; } FileWriter; +typedef struct { + Writer w; +} NullWriter; + BufferedWriter buffered_writer_init(); void buffered_writer_drop(BufferedWriter w); FileWriter file_writer_init(const char *path); FileWriter file_writer_from_fd(FILE *fd); void file_writer_drop(FileWriter w); +NullWriter null_writer_init(); void wt_write(Writer *w, const char *data, size_t len); void wt_format(Writer *w, const char *fmt, ...); // Define the structs of a program in the correct order (respecting direct dependencies) -void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *)); +void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *, void *), void *user_data); char *pascal_to_snake_case(StringSlice str); char *snake_case_to_screaming_snake_case(StringSlice str); diff --git a/ser/codegen_c.c b/ser/codegen_c.c index 8be3276..3ff7609 100644 --- a/ser/codegen_c.c +++ b/ser/codegen_c.c @@ -3,6 +3,8 @@ #include "vector.h" #include "vector_impl.h" +#include + #define INDENT 4 typedef enum { @@ -183,7 +185,7 @@ void write_field(Writer *w, Field f, Modifier *mods, size_t len, uint32_t indent _vec_modifier_drop(modifiers); } -void write_struct(Writer *w, StructObject *obj) { +void write_struct(Writer *w, StructObject *obj, void *_user_data) { wt_format(w, "typedef struct %.*s {\n", obj->name.len, obj->name.ptr); for (size_t i = 0; i < obj->fields.len; i++) { @@ -281,7 +283,7 @@ bool is_field_accessor_heap_array(FieldAccessor fa, TypeObject *base_type) { } void write_type_serialization( - Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth + Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth, bool always_inline ) { if (layout->fields.len == 0) return; @@ -291,6 +293,14 @@ void write_type_serialization( offset += calign_to(al, layout->fields.data[0].type->align); + if (layout->type->kind == TypeStruct && layout->type->type.struct_.has_funcs && !always_inline) { + char *name = pascal_to_snake_case(layout->type->type.struct_.name); + char *deref = ptr ? "*" : ""; + wt_format(w, "%*sbuf += %s_serialize(%s%s, &buf[%lu]);\n", indent, "", name, deref, base, offset); + free(name); + return; + } + size_t i = 0; for (; i < layout->fields.len && layout->fields.data[i].size != 0; i++) { FieldAccessor fa = layout->fields.data[i]; @@ -334,7 +344,8 @@ void write_type_serialization( (CurrentAlignment){.align = farr.type->align, .offset = 0}, layouts, indent + INDENT, - depth + 1 + depth + 1, + false ); wt_format(w, "%*s}\n", indent, ""); free(vname); @@ -347,7 +358,7 @@ void write_type_serialization( } void write_type_deserialization( - Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth + Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth, bool always_inline ) { if (layout->fields.len == 0) return; @@ -357,6 +368,14 @@ void write_type_deserialization( offset += calign_to(al, layout->fields.data[0].type->align); + if (layout->type->kind == TypeStruct && layout->type->type.struct_.has_funcs && !always_inline) { + char *name = pascal_to_snake_case(layout->type->type.struct_.name); + char *ref = ptr ? "" : "&"; + wt_format(w, "%*sbuf += %s_deserialize(%s%s, &buf[%lu]);\n", indent, "", name, ref, base, offset); + free(name); + return; + } + char *deref = ""; if (layout->type->kind == TypePrimitif) { deref = "*"; @@ -415,7 +434,8 @@ void write_type_deserialization( (CurrentAlignment){.align = farr.type->align, .offset = 0}, layouts, indent + INDENT, - depth + 1 + depth + 1, + false ); wt_format(w, "%*s}\n", indent, ""); free(vname); @@ -427,7 +447,7 @@ void write_type_deserialization( } } -int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent, size_t depth) { +int write_type_free(Writer *w, const char *base, TypeObject *type, Hashmap *layouts, size_t indent, size_t depth, bool always_inline) { if (type->kind == TypePrimitif) { return 0; } else if (type->kind == TypeArray) { @@ -446,7 +466,7 @@ int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent } char *new_base = msprintf("e%lu", depth); - total += write_type_free(w2, new_base, type->type.array.type, indent + INDENT, depth + 1); + total += write_type_free(w2, new_base, type->type.array.type, layouts, indent + INDENT, depth + 1, false); free(new_base); wt_format(w2, "%*s}\n", indent, ""); @@ -465,10 +485,24 @@ int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent StructObject *s = (StructObject *)&type->type.struct_; int total = 0; + if(type->type.struct_.has_funcs && !always_inline) { + char *name = pascal_to_snake_case(s->name); + wt_format(w, "%*s%s_free(%s);\n", indent, "", name, base); + free(name); + + Layout *layout = hashmap_get(layouts, &(Layout){.type = type}); + assert(layout != NULL, "No layout for type that has funcs defined"); + for(size_t i = 0; i < layout->fields.len; i++) { + if(layout->fields.data[i].size == 0) total++; + } + + return total; + } + for (size_t i = 0; i < s->fields.len; i++) { Field f = s->fields.data[i]; char *new_base = msprintf("%s.%.*s", base, f.name.len, f.name.ptr); - total += write_type_free(w, new_base, f.type, indent, depth); + total += write_type_free(w, new_base, f.type, layouts, indent, depth, false); free(new_base); } @@ -478,6 +512,52 @@ int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent return 0; } +void write_struct_func_decl(Writer *w, StructObject *obj, void *_user_data) { + obj->has_funcs = true; + + StringSlice sname = obj->name; + char *snake_case_name = pascal_to_snake_case(sname); + wt_format(w, "__attribute__((unused)) static int %s_serialize(struct %.*s val, byte *buf);\n", snake_case_name, sname.len, sname.ptr); + wt_format(w, "__attribute__((unused)) static int %s_deserialize(struct %.*s *val, const byte *buf);\n", snake_case_name, sname.len, sname.ptr); + wt_format(w, "__attribute__((unused)) static void %s_free(struct %.*s val);\n", snake_case_name, sname.len, sname.ptr); + free(snake_case_name); +} + +void write_struct_func(Writer *w, StructObject *obj, void *user_data) { + Hashmap *layouts = user_data; + // Retreive original TypeObject pointer from struct object pointer. + TypeObject *t = (void *)((byte *)obj - offsetof(struct TypeObject, type)); + + Layout *layout = hashmap_get(layouts, &(Layout){.type = t}); + assert(layout != NULL, "No layout found for struct"); + + StringSlice sname = obj->name; + char *snake_case_name = pascal_to_snake_case(sname); + wt_format(w, "static int %s_serialize(struct %.*s val, byte *buf) {\n", snake_case_name, sname.len, sname.ptr); + wt_format(w, "%*sbyte * base_buf = buf;\n", INDENT, ""); + write_type_serialization(w, "val", false, layout, (CurrentAlignment){.offset = 0, .align = t->align}, layouts, INDENT, 0, true); + wt_format(w, "%*sreturn (int)(buf - base_buf);\n", INDENT, ""); + wt_format(w, "}\n"); + + wt_format(w, "static int %s_deserialize(struct %.*s *val, const byte *buf) {\n", snake_case_name, sname.len, sname.ptr); + wt_format(w, "%*sconst byte * base_buf = buf;\n", INDENT, ""); + write_type_deserialization(w, "val", true, layout, (CurrentAlignment){.offset = 0, .align = t->align}, layouts, INDENT, 0, true); + wt_format(w, "%*sreturn (int)(buf - base_buf);\n", INDENT, ""); + wt_format(w, "}\n"); + + wt_format(w, "static void %s_free(struct %.*s val) {", snake_case_name, sname.len, sname.ptr); + BufferedWriter b = buffered_writer_init(); + int f = write_type_free((Writer*)&b, "val", t, layouts, INDENT, 0, true); + if(f > 0) { + wt_format(w, "\n%.*s}\n\n", b.buf.len, b.buf.data); + } else { + wt_format(w, " }\n\n"); + } + buffered_writer_drop(b); + + free(snake_case_name); +} + void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { char *uc_name = snake_case_to_screaming_snake_case((StringSlice){.ptr = name, .len = strlen(name)}); wt_format( @@ -509,7 +589,10 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { name ); - define_structs(p, header, write_struct); + define_structs(p, header, write_struct, NULL); + define_structs(p, source, write_struct_func_decl, NULL); + wt_format(source, "\n"); + define_structs(p, source, write_struct_func, p->layouts); for (size_t i = 0; i < p->messages.len; i++) { MessagesObject msgs = p->messages.data[i]; @@ -664,7 +747,8 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { (CurrentAlignment){.align = ALIGN_8, .offset = 2}, p->layouts, INDENT * 2, - 0 + 0, + false ); wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, ""); @@ -699,7 +783,6 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { wt_format(source, "%*sswitch(tag) {\n", INDENT, ""); wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, ""); - for (size_t j = 0; j < msgs.messages.len; j++) { MessageObject m = msgs.messages.data[j]; TypeObject *mtype = message_tos.data[j]; @@ -718,7 +801,8 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { (CurrentAlignment){.align = ALIGN_8, .offset = 2}, p->layouts, INDENT * 2, - 0 + 0, + false ); if (m.attributes & Attr_versioned) { wt_format(source, "%*sif(msg->%s._version != %luUL) {\n", INDENT * 2, "", snake_case_name, msgs.version); @@ -761,7 +845,7 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { char *base = msprintf("msg->%s", snake_case_name); wt_format(source, "%*scase %s%.*s: {\n", INDENT, "", tag_type, m.name.len, m.name.ptr); - write_type_free(source, base, mtype, INDENT * 2, 0); + write_type_free(source, base, mtype, p->layouts, INDENT * 2, 0, false); wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, ""); free(base); diff --git a/ser/eval.c b/ser/eval.c index 85590ff..3caeb51 100644 --- a/ser/eval.c +++ b/ser/eval.c @@ -579,6 +579,7 @@ static TypeObject *resolve_type(EvaluationContext *ctx, SpannedStringSlice name) value->kind = TypeStruct; value->type.struct_.fields = *(AnyVec *)&fields; value->type.struct_.name = name.slice; + value->type.struct_.has_funcs = false; value->align.value = 0; hashmap_set(ctx->typedefs, &(TypeDef){.name = name.slice, .value = value}); } diff --git a/ser/eval.h b/ser/eval.h index 0fbd3ce..5a6271d 100644 --- a/ser/eval.h +++ b/ser/eval.h @@ -70,6 +70,8 @@ typedef enum { struct StructObject { StringSlice name; AnyVec fields; + // Used by codegen_c + bool has_funcs; }; typedef union { @@ -97,6 +99,8 @@ VECTOR_IMPL(Field, FieldVec, field); typedef struct { StringSlice name; FieldVec fields; + // Used by codegen_c + bool has_funcs; } StructObject; void struct_drop(StructObject s);