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 "net.h"
#include <stdio.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) { int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) {
const byte *base_buf = buf; const byte *base_buf = buf;
if(len < 2 * MSG_MAGIC_SIZE) if(len < 2 * MSG_MAGIC_SIZE)
@ -21,23 +149,15 @@ int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) {
buf += 8; buf += 8;
for(size_t i = 0; i < msg->info.abs.len; i++) { for(size_t i = 0; i < msg->info.abs.len; i++) {
typeof(msg->info.abs.data[i]) e0 = msg->info.abs.data[i]; typeof(msg->info.abs.data[i]) e0 = msg->info.abs.data[i];
*(uint32_t *)&buf[0] = e0.min; buf += abs_serialize(e0, &buf[0]);
*(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;
} }
for(size_t i = 0; i < msg->info.rel.len; i++) { for(size_t i = 0; i < msg->info.rel.len; i++) {
typeof(msg->info.rel.data[i]) e0 = msg->info.rel.data[i]; typeof(msg->info.rel.data[i]) e0 = msg->info.rel.data[i];
*(uint16_t *)&buf[0] = e0.id; buf += rel_serialize(e0, &buf[0]);
buf += 2;
} }
for(size_t i = 0; i < msg->info.key.len; i++) { for(size_t i = 0; i < msg->info.key.len; i++) {
typeof(msg->info.key.data[i]) e0 = msg->info.key.data[i]; typeof(msg->info.key.data[i]) e0 = msg->info.key.data[i];
*(uint16_t *)&buf[0] = e0.id; buf += key_serialize(e0, &buf[0]);
buf += 2;
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
break; break;
@ -89,20 +209,7 @@ int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) {
buf += 18; buf += 18;
for(size_t i = 0; i < msg->request.requests.len; i++) { for(size_t i = 0; i < msg->request.requests.len; i++) {
typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i]; typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i];
*(uint16_t *)&buf[0] = e0.tags.len; buf += tag_list_serialize(e0, &buf[0]);
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 = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
break; break;
@ -142,23 +249,15 @@ int msg_device_deserialize(const byte *buf, size_t len, DeviceMessage *msg) {
buf += 8; buf += 8;
for(size_t i = 0; i < msg->info.abs.len; i++) { for(size_t i = 0; i < msg->info.abs.len; i++) {
typeof(&msg->info.abs.data[i]) e0 = &msg->info.abs.data[i]; typeof(&msg->info.abs.data[i]) e0 = &msg->info.abs.data[i];
e0->min = *(uint32_t *)&buf[0]; buf += abs_deserialize(e0, &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;
} }
for(size_t i = 0; i < msg->info.rel.len; i++) { for(size_t i = 0; i < msg->info.rel.len; i++) {
typeof(&msg->info.rel.data[i]) e0 = &msg->info.rel.data[i]; typeof(&msg->info.rel.data[i]) e0 = &msg->info.rel.data[i];
e0->id = *(uint16_t *)&buf[0]; buf += rel_deserialize(e0, &buf[0]);
buf += 2;
} }
for(size_t i = 0; i < msg->info.key.len; i++) { for(size_t i = 0; i < msg->info.key.len; i++) {
typeof(&msg->info.key.data[i]) e0 = &msg->info.key.data[i]; typeof(&msg->info.key.data[i]) e0 = &msg->info.key.data[i];
e0->id = *(uint16_t *)&buf[0]; buf += key_deserialize(e0, &buf[0]);
buf += 2;
} }
buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
break; 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))); 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++) { for(size_t i = 0; i < msg->request.requests.len; i++) {
typeof(&msg->request.requests.data[i]) e0 = &msg->request.requests.data[i]; typeof(&msg->request.requests.data[i]) e0 = &msg->request.requests.data[i];
e0->tags.len = *(uint16_t *)&buf[0]; buf += tag_list_deserialize(e0, &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 = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3);
if(msg->request._version != 1UL) { if(msg->request._version != 1UL) {
@ -270,11 +354,7 @@ void msg_device_free(DeviceMessage *msg) {
case DeviceTagRequest: { case DeviceTagRequest: {
for(size_t i = 0; i < msg->request.requests.len; i++) { for(size_t i = 0; i < msg->request.requests.len; i++) {
typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i]; typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i];
for(size_t i = 0; i < e0.tags.len; i++) { tag_list_free(e0);
typeof(e0.tags.data[i]) e1 = e0.tags.data[i];
free(e1.name.data);
}
free(e0.tags.data);
} }
free(msg->request.requests.data); free(msg->request.requests.data);
break; break;

14
net.h
View File

@ -29,13 +29,6 @@ typedef struct Rel {
uint16_t id; uint16_t id;
} Rel; } Rel;
typedef struct Tag {
struct {
uint16_t len;
char *data;
} name;
} Tag;
typedef struct TagList { typedef struct TagList {
struct { struct {
uint16_t len; uint16_t len;
@ -43,6 +36,13 @@ typedef struct TagList {
} tags; } tags;
} TagList; } TagList;
typedef struct Tag {
struct {
uint16_t len;
char *data;
} name;
} Tag;
// Device // Device
typedef enum DeviceTag { 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; FileWriter *fw = (FileWriter *)w;
vfprintf(fw->fd, fmt, args); 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() { BufferedWriter buffered_writer_init() {
CharVec buf = vec_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}; return (FileWriter){.w.write = file_writer_write, .w.format = file_writer_format, .fd = fd};
} }
void file_writer_drop(FileWriter w) { fclose(w.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_write(Writer *w, const char *data, size_t len) { w->write(w, data, len); }
void wt_format(Writer *w, const char *fmt, ...) { 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); 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)); Hashmap *dependencies = hashmap_init(strdeps_hash, strdeps_equal, strdeps_drop, sizeof(StructDependencies));
TypeDef *td = NULL; 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++) { for (size_t i = 0; i < to_define.len; i++) {
StructObject *s = to_define.data[i]; StructObject *s = to_define.data[i];
define(w, s); define(w, s, user_data);
hashmap_delete(dependencies, &(StructDependencies){.obj = s}); hashmap_delete(dependencies, &(StructDependencies){.obj = s});
} }
pass++; pass++;

View File

@ -29,17 +29,22 @@ typedef struct {
FILE *fd; FILE *fd;
} FileWriter; } FileWriter;
typedef struct {
Writer w;
} NullWriter;
BufferedWriter buffered_writer_init(); BufferedWriter buffered_writer_init();
void buffered_writer_drop(BufferedWriter w); void buffered_writer_drop(BufferedWriter w);
FileWriter file_writer_init(const char *path); FileWriter file_writer_init(const char *path);
FileWriter file_writer_from_fd(FILE *fd); FileWriter file_writer_from_fd(FILE *fd);
void file_writer_drop(FileWriter w); void file_writer_drop(FileWriter w);
NullWriter null_writer_init();
void wt_write(Writer *w, const char *data, size_t len); void wt_write(Writer *w, const char *data, size_t len);
void wt_format(Writer *w, const char *fmt, ...); void wt_format(Writer *w, const char *fmt, ...);
// Define the structs of a program in the correct order (respecting direct dependencies) // 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 *pascal_to_snake_case(StringSlice str);
char *snake_case_to_screaming_snake_case(StringSlice str); char *snake_case_to_screaming_snake_case(StringSlice str);

View File

@ -3,6 +3,8 @@
#include "vector.h" #include "vector.h"
#include "vector_impl.h" #include "vector_impl.h"
#include <stddef.h>
#define INDENT 4 #define INDENT 4
typedef enum { 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); _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); wt_format(w, "typedef struct %.*s {\n", obj->name.len, obj->name.ptr);
for (size_t i = 0; i < obj->fields.len; i++) { 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( 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) if (layout->fields.len == 0)
return; return;
@ -291,6 +293,14 @@ void write_type_serialization(
offset += calign_to(al, layout->fields.data[0].type->align); 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; size_t i = 0;
for (; i < layout->fields.len && layout->fields.data[i].size != 0; i++) { for (; i < layout->fields.len && layout->fields.data[i].size != 0; i++) {
FieldAccessor fa = layout->fields.data[i]; FieldAccessor fa = layout->fields.data[i];
@ -334,7 +344,8 @@ void write_type_serialization(
(CurrentAlignment){.align = farr.type->align, .offset = 0}, (CurrentAlignment){.align = farr.type->align, .offset = 0},
layouts, layouts,
indent + INDENT, indent + INDENT,
depth + 1 depth + 1,
false
); );
wt_format(w, "%*s}\n", indent, ""); wt_format(w, "%*s}\n", indent, "");
free(vname); free(vname);
@ -347,7 +358,7 @@ void write_type_serialization(
} }
void write_type_deserialization( 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) if (layout->fields.len == 0)
return; return;
@ -357,6 +368,14 @@ void write_type_deserialization(
offset += calign_to(al, layout->fields.data[0].type->align); 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 = ""; char *deref = "";
if (layout->type->kind == TypePrimitif) { if (layout->type->kind == TypePrimitif) {
deref = "*"; deref = "*";
@ -415,7 +434,8 @@ void write_type_deserialization(
(CurrentAlignment){.align = farr.type->align, .offset = 0}, (CurrentAlignment){.align = farr.type->align, .offset = 0},
layouts, layouts,
indent + INDENT, indent + INDENT,
depth + 1 depth + 1,
false
); );
wt_format(w, "%*s}\n", indent, ""); wt_format(w, "%*s}\n", indent, "");
free(vname); 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) { if (type->kind == TypePrimitif) {
return 0; return 0;
} else if (type->kind == TypeArray) { } 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); 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); free(new_base);
wt_format(w2, "%*s}\n", indent, ""); 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_; StructObject *s = (StructObject *)&type->type.struct_;
int total = 0; 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++) { for (size_t i = 0; i < s->fields.len; i++) {
Field f = s->fields.data[i]; Field f = s->fields.data[i];
char *new_base = msprintf("%s.%.*s", base, f.name.len, f.name.ptr); 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); free(new_base);
} }
@ -478,6 +512,52 @@ int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent
return 0; 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) { 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)}); char *uc_name = snake_case_to_screaming_snake_case((StringSlice){.ptr = name, .len = strlen(name)});
wt_format( wt_format(
@ -509,7 +589,10 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) {
name 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++) { for (size_t i = 0; i < p->messages.len; i++) {
MessagesObject msgs = p->messages.data[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}, (CurrentAlignment){.align = ALIGN_8, .offset = 2},
p->layouts, p->layouts,
INDENT * 2, INDENT * 2,
0 0,
false
); );
wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, ""); 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, "%*sswitch(tag) {\n", INDENT, "");
wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, ""); wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, "");
for (size_t j = 0; j < msgs.messages.len; j++) { for (size_t j = 0; j < msgs.messages.len; j++) {
MessageObject m = msgs.messages.data[j]; MessageObject m = msgs.messages.data[j];
TypeObject *mtype = message_tos.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}, (CurrentAlignment){.align = ALIGN_8, .offset = 2},
p->layouts, p->layouts,
INDENT * 2, INDENT * 2,
0 0,
false
); );
if (m.attributes & Attr_versioned) { if (m.attributes & Attr_versioned) {
wt_format(source, "%*sif(msg->%s._version != %luUL) {\n", INDENT * 2, "", snake_case_name, msgs.version); 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); char *base = msprintf("msg->%s", snake_case_name);
wt_format(source, "%*scase %s%.*s: {\n", INDENT, "", tag_type, m.name.len, m.name.ptr); 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, ""); wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, "");
free(base); free(base);

View File

@ -579,6 +579,7 @@ static TypeObject *resolve_type(EvaluationContext *ctx, SpannedStringSlice name)
value->kind = TypeStruct; value->kind = TypeStruct;
value->type.struct_.fields = *(AnyVec *)&fields; value->type.struct_.fields = *(AnyVec *)&fields;
value->type.struct_.name = name.slice; value->type.struct_.name = name.slice;
value->type.struct_.has_funcs = false;
value->align.value = 0; value->align.value = 0;
hashmap_set(ctx->typedefs, &(TypeDef){.name = name.slice, .value = value}); hashmap_set(ctx->typedefs, &(TypeDef){.name = name.slice, .value = value});
} }

View File

@ -70,6 +70,8 @@ typedef enum {
struct StructObject { struct StructObject {
StringSlice name; StringSlice name;
AnyVec fields; AnyVec fields;
// Used by codegen_c
bool has_funcs;
}; };
typedef union { typedef union {
@ -97,6 +99,8 @@ VECTOR_IMPL(Field, FieldVec, field);
typedef struct { typedef struct {
StringSlice name; StringSlice name;
FieldVec fields; FieldVec fields;
// Used by codegen_c
bool has_funcs;
} StructObject; } StructObject;
void struct_drop(StructObject s); void struct_drop(StructObject s);