diff --git a/mie/ctx.c b/mie/ctx.c index ced1cc8..1175e0d 100644 --- a/mie/ctx.c +++ b/mie/ctx.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -448,6 +450,61 @@ struct mie_type *mie_ctx_get_type( return type; } +struct mie_type *mie_ctx_get_storage_type( + struct mie_ctx *ctx, const struct mie_type **parts, size_t nr_parts) +{ + struct mie_id_builder id_builder; + mie_id_builder_begin(&id_builder, &ctx->ctx_types.map_ns_id); + mie_storage_type_build_id(&id_builder, parts, nr_parts); + mie_id id; + mie_id_builder_end(&id_builder, &id); + + mie_id *target = mie_id_map_get(&ctx->ctx_types, &id); + struct mie_type *type = b_unbox(struct mie_type, target, ty_id); + if (type) { + return type; + } + + struct mie_storage_type *new_type = mie_storage_type_create(); + for (size_t i = 0; i < nr_parts; i++) { + mie_storage_type_add_part(new_type, parts[i]); + } + + new_type->st_base.ty_id = id; + mie_id_map_put_id(&ctx->ctx_types, &new_type->st_base.ty_id); + return (struct mie_type *)new_type; +} + +struct mie_type *mie_ctx_get_function_type( + struct mie_ctx *ctx, const struct mie_type **in, size_t nr_in, + const struct mie_type **out, size_t nr_out) +{ + struct mie_id_builder id_builder; + mie_id_builder_begin(&id_builder, &ctx->ctx_types.map_ns_id); + mie_function_type_build_id(&id_builder, in, nr_in, out, nr_out); + mie_id id; + mie_id_builder_end(&id_builder, &id); + + mie_id *target = mie_id_map_get(&ctx->ctx_types, &id); + struct mie_type *type = b_unbox(struct mie_type, target, ty_id); + if (type) { + return type; + } + + struct mie_function_type *new_type = mie_function_type_create(); + for (size_t i = 0; i < nr_in; i++) { + mie_function_type_add_in_part(new_type, in[i]); + } + + for (size_t i = 0; i < nr_out; i++) { + mie_function_type_add_out_part(new_type, out[i]); + } + + new_type->func_base.ty_id = id; + mie_id_map_put_id(&ctx->ctx_types, &new_type->func_base.ty_id); + return (struct mie_type *)new_type; +} + struct mie_value *mie_ctx_get_int(struct mie_ctx *ctx, long long val, size_t nr_bits) { return (struct mie_value *)mie_int_cache_get( diff --git a/mie/include/mie/ctx.h b/mie/include/mie/ctx.h index be8ea7c..4052731 100644 --- a/mie/include/mie/ctx.h +++ b/mie/include/mie/ctx.h @@ -38,6 +38,11 @@ MIE_API struct mie_dialect_type *mie_ctx_get_dialect_type( const struct mie_ctx *ctx, const char *dialect_name, const char *type_name); MIE_API struct mie_type *mie_ctx_get_type( struct mie_ctx *ctx, const char *dialect_name, const char *type_name); +MIE_API struct mie_type *mie_ctx_get_storage_type( + struct mie_ctx *ctx, const struct mie_type **parts, size_t nr_parts); +MIE_API struct mie_type *mie_ctx_get_function_type( + struct mie_ctx *ctx, const struct mie_type **in, size_t nr_in, + const struct mie_type **out, size_t nr_out); MIE_API struct mie_value *mie_ctx_get_null(struct mie_ctx *ctx); MIE_API struct mie_value *mie_ctx_get_int( diff --git a/mie/include/mie/dialect/type.h b/mie/include/mie/dialect/type.h index 4d8e7c9..110e6c8 100644 --- a/mie/include/mie/dialect/type.h +++ b/mie/include/mie/dialect/type.h @@ -34,8 +34,7 @@ struct mie_dialect_type { enum mie_status (*ty_parse)( const struct mie_dialect_type *, struct mie_parser *, struct mie_type **); - void (*ty_init)(const struct mie_dialect_type *, struct mie_type *); - void (*ty_cleanup)(const struct mie_dialect_type *, struct mie_type *); + void (*ty_build_id)(const struct mie_type *, struct mie_id_builder *); }; MIE_API struct mie_dialect_type *mie_dialect_type_create( diff --git a/mie/include/mie/type/function.h b/mie/include/mie/type/function.h index 0dba1b2..16cd5a5 100644 --- a/mie/include/mie/type/function.h +++ b/mie/include/mie/type/function.h @@ -1,20 +1,28 @@ #ifndef MIE_TYPE_FUNCTION_H_ #define MIE_TYPE_FUNCTION_H_ +#include #include #include struct mie_function_type { struct mie_type func_base; - MIE_VECTOR_DECLARE(struct mie_type *, func_in); - MIE_VECTOR_DECLARE(struct mie_type *, func_out); + MIE_VECTOR_DECLARE(const struct mie_type *, func_in); + MIE_VECTOR_DECLARE(const struct mie_type *, func_out); }; MIE_API struct mie_function_type *mie_function_type_create(void); MIE_API void mie_function_type_add_in_part( - struct mie_function_type *ty, struct mie_type *part); + struct mie_function_type *ty, const struct mie_type *part); MIE_API void mie_function_type_add_out_part( - struct mie_function_type *ty, struct mie_type *part); + struct mie_function_type *ty, const struct mie_type *part); + +MIE_API void mie_function_type_print( + const struct mie_function_type *type, b_stream *out); +MIE_API void mie_function_type_build_id( + struct mie_id_builder *builder, const struct mie_type **in_types, + size_t nr_in_types, const struct mie_type **out_types, + size_t nr_out_types); #endif diff --git a/mie/include/mie/type/storage.h b/mie/include/mie/type/storage.h index 3f33902..e40283b 100644 --- a/mie/include/mie/type/storage.h +++ b/mie/include/mie/type/storage.h @@ -1,17 +1,24 @@ #ifndef MIE_TYPE_STORAGE_H_ #define MIE_TYPE_STORAGE_H_ +#include #include #include struct mie_storage_type { struct mie_type st_base; - MIE_VECTOR_DECLARE(struct mie_type *, st_parts); + MIE_VECTOR_DECLARE(const struct mie_type *, st_parts); }; MIE_API struct mie_storage_type *mie_storage_type_create(void); MIE_API void mie_storage_type_add_part( - struct mie_storage_type *ty, struct mie_type *part); + struct mie_storage_type *ty, const struct mie_type *part); + +MIE_API void mie_storage_type_print( + const struct mie_storage_type *type, b_stream *out); +MIE_API void mie_storage_type_build_id( + struct mie_id_builder *builder, const struct mie_type **parts, + size_t nr_parts); #endif diff --git a/mie/include/mie/type/type.h b/mie/include/mie/type/type.h index 04d4b3c..32d8735 100644 --- a/mie/include/mie/type/type.h +++ b/mie/include/mie/type/type.h @@ -1,6 +1,8 @@ #ifndef MIE_TYPE_TYPE_H_ #define MIE_TYPE_TYPE_H_ +#include +#include #include #include #include @@ -9,6 +11,16 @@ struct mie_dialect; struct mie_dialect_type; struct mie_value; +struct mie_id_builder; + +enum mie_type_category { + /* all other types */ + MIE_TYPE_OTHER = 0, + /* storage types (structs, etc) */ + MIE_TYPE_STORAGE, + /* functional types (represents the param/result types of a function) */ + MIE_TYPE_FUNCTION, +}; /* a mie_type is an instance of mie_dialect_type. * if the mie_dialect_type is a parametised type, the resulting mie_type @@ -18,18 +30,19 @@ struct mie_value; struct mie_type { /* this is NOT the same as ty_def->ty_id */ mie_id ty_id; + enum mie_type_category ty_category; - /* this pointer is optional. if it is NULL, the name of the type can - * be found in ty_def */ char *ty_name; struct mie_dialect_type *ty_def; - /* for types that can be instantiated in C (i.e. an instance that can - * be represented by a mie_value), this is the total size of the - * instance data. */ size_t ty_instance_size; }; MIE_API struct mie_type *mie_type_create(struct mie_dialect_type *type); +MIE_API void mie_type_print(const struct mie_type *type, b_stream *out); +MIE_API void mie_type_build_id( + const struct mie_type *type, struct mie_id_builder *ctx); +MIE_API void mie_type_generate_id( + const struct mie_type *type, const mie_id *ns, mie_id *out); #endif diff --git a/mie/type/function.c b/mie/type/function.c new file mode 100644 index 0000000..1689c8f --- /dev/null +++ b/mie/type/function.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +static void build_id(const struct mie_type *type, struct mie_id_builder *ctx) +{ + const struct mie_function_type *function + = (const struct mie_function_type *)type; + mie_function_type_build_id( + ctx, function->func_in.items, function->func_in.count, + function->func_out.items, function->func_out.count); +} + +static struct mie_dialect_type function_type = { + .ty_data_size = sizeof(struct mie_type), + .ty_build_id = build_id, +}; + +struct mie_function_type *mie_function_type_create(void) +{ + struct mie_function_type *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + out->func_base.ty_def = &function_type; + out->func_base.ty_category = MIE_TYPE_FUNCTION; + + return out; +} + +void mie_function_type_add_in_part( + struct mie_function_type *ty, const struct mie_type *part) +{ + mie_vector_push_back(ty->func_in, &part); +} + +void mie_function_type_add_out_part( + struct mie_function_type *ty, const struct mie_type *part) +{ + mie_vector_push_back(ty->func_out, &part); +} + +void mie_function_type_print(const struct mie_function_type *type, b_stream *out) +{ + b_stream_write_char(out, '('); + + for (size_t i = 0; i < MIE_VECTOR_COUNT(type->func_in); i++) { + if (i > 0) { + b_stream_write_string(out, ", ", NULL); + } + + mie_type_print(MIE_VECTOR_ITEM(type->func_in, i), out); + } + + b_stream_write_string(out, ") -> ", NULL); + + if (MIE_VECTOR_COUNT(type->func_out) == 1) { + mie_type_print(MIE_VECTOR_ITEM(type->func_out, 0), out); + return; + } + + b_stream_write_char(out, '('); + + for (size_t i = 0; i < MIE_VECTOR_COUNT(type->func_out); i++) { + if (i > 0) { + b_stream_write_string(out, ", ", NULL); + } + + mie_type_print(MIE_VECTOR_ITEM(type->func_out, i), out); + } + + b_stream_write_char(out, ')'); +} + +void mie_function_type_build_id( + struct mie_id_builder *ctx, const struct mie_type **in_types, + size_t nr_in_types, const struct mie_type **out_types, size_t nr_out_types) +{ + mie_id_builder_add_marker(ctx, MIE_ID_BUILDER_FUNCTION_IN_START); + for (size_t i = 0; i < nr_in_types; i++) { + mie_type_build_id(in_types[i], ctx); + } + mie_id_builder_add_marker(ctx, MIE_ID_BUILDER_FUNCTION_IN_END); + + mie_id_builder_add_marker(ctx, MIE_ID_BUILDER_FUNCTION_OUT_START); + for (size_t i = 0; i < nr_out_types; i++) { + mie_type_build_id(out_types[i], ctx); + } + mie_id_builder_add_marker(ctx, MIE_ID_BUILDER_FUNCTION_OUT_END); +} diff --git a/mie/type/storage.c b/mie/type/storage.c new file mode 100644 index 0000000..759e99f --- /dev/null +++ b/mie/type/storage.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include + +static void build_id(const struct mie_type *type, struct mie_id_builder *ctx) +{ + const struct mie_storage_type *storage + = (const struct mie_storage_type *)type; + mie_storage_type_build_id( + ctx, storage->st_parts.items, storage->st_parts.count); +} + +static struct mie_dialect_type storage_type = { + .ty_data_size = sizeof(struct mie_type), + .ty_build_id = build_id, +}; + +struct mie_storage_type *mie_storage_type_create(void) +{ + struct mie_storage_type *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + out->st_base.ty_def = &storage_type; + out->st_base.ty_category = MIE_TYPE_STORAGE; + + return out; +} + +void mie_storage_type_add_part( + struct mie_storage_type *ty, const struct mie_type *part) +{ + mie_vector_push_back(ty->st_parts, &part); +} + +void mie_storage_type_print(const struct mie_storage_type *type, b_stream *out) +{ + b_stream_write_char(out, '('); + + for (size_t i = 0; i < MIE_VECTOR_COUNT(type->st_parts); i++) { + if (i > 0) { + b_stream_write_string(out, ", ", NULL); + } + + mie_type_print(MIE_VECTOR_ITEM(type->st_parts, i), out); + } + + b_stream_write_char(out, ')'); +} + +void mie_storage_type_build_id( + struct mie_id_builder *ctx, const struct mie_type **parts, size_t nr_parts) +{ + mie_id_builder_add_marker(ctx, MIE_ID_BUILDER_STORAGE_START); + for (size_t i = 0; i < nr_parts; i++) { + mie_type_build_id(parts[i], ctx); + } + mie_id_builder_add_marker(ctx, MIE_ID_BUILDER_STORAGE_END); +} diff --git a/mie/type/type.c b/mie/type/type.c index 562266d..cef231d 100644 --- a/mie/type/type.c +++ b/mie/type/type.c @@ -1,4 +1,6 @@ #include +#include +#include #include struct mie_type *mie_type_create(struct mie_dialect_type *type) @@ -17,3 +19,52 @@ struct mie_type *mie_type_create(struct mie_dialect_type *type) return out; } + +void mie_type_print(const struct mie_type *type, b_stream *out) +{ + switch (type->ty_category) { + case MIE_TYPE_STORAGE: + mie_storage_type_print((const struct mie_storage_type *)type, out); + return; + case MIE_TYPE_FUNCTION: + mie_function_type_print((const struct mie_function_type *)type, out); + return; + default: + break; + } + + if (type->ty_name) { + b_stream_write_string(out, type->ty_name, NULL); + } else if (type->ty_def && type->ty_def->ty_print) { + type->ty_def->ty_print(type->ty_def, type, out); + } else if (type->ty_def->ty_name) { + b_stream_write_string(out, type->ty_def->ty_name, NULL); + } else { + b_stream_write_string(out, "", NULL); + } +} + +void mie_type_build_id(const struct mie_type *type, struct mie_id_builder *ctx) +{ + if (type->ty_def->ty_build_id) { + type->ty_def->ty_build_id(type, ctx); + return; + } else if (type->ty_name) { + mie_id_builder_add(ctx, type->ty_name, strlen(type->ty_name)); + } else if (type->ty_def->ty_name) { + mie_id_builder_add( + ctx, type->ty_def->ty_name, strlen(type->ty_def->ty_name)); + } else { + const char *placeholder = ""; + const size_t placeholder_len = strlen(placeholder); + mie_id_builder_add(ctx, placeholder, placeholder_len); + } +} + +void mie_type_generate_id(const struct mie_type *type, const mie_id *ns, mie_id *out) +{ + struct mie_id_builder ctx; + mie_id_builder_begin(&ctx, ns); + mie_type_build_id(type, &ctx); + mie_id_builder_end(&ctx, out); +}