ser c frontend and c backend finished, + conversion, needs python backend

This commit is contained in:
viandoxdev 2023-05-09 23:27:42 +02:00
parent f6c5e749a6
commit 7335df0711
No known key found for this signature in database
GPG Key ID: AF1410C5BC10AA25
7 changed files with 259 additions and 80 deletions

194
net.c
View File

@ -2,6 +2,134 @@
#include "net.h"
#include <stdio.h>
__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;

14
net.h
View File

@ -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 {

View File

@ -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++;

View File

@ -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);

View File

@ -3,6 +3,8 @@
#include "vector.h"
#include "vector_impl.h"
#include <stddef.h>
#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);

View File

@ -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});
}

View File

@ -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);