#include #include #include #include #include #include "assembler.h" extern struct assembler_scope_type class_scope_type; extern struct assembler_scope_type lambda_scope_type; extern struct assembler_scope_type msgh_scope_type; extern struct assembler_scope_type constpool_scope_type; static const struct assembler_scope_type *scope_types[] = { [IVY_ASM_SCOPE_CLASS] = &class_scope_type, [IVY_ASM_SCOPE_LAMBDA] = &lambda_scope_type, [IVY_ASM_SCOPE_MSGH] = &msgh_scope_type, [IVY_ASM_SCOPE_CONSTPOOL] = &constpool_scope_type, }; static const size_t nr_scope_types = sizeof scope_types / sizeof scope_types[0]; struct ivy_assembler { FILE *as_fp; struct assembler_scope *as_scope; }; enum ivy_static ivy_assembler_create(FILE *fp, struct ivy_assembler **as) { struct ivy_assembler *out = malloc(sizeof *out); if (!out) { return IVY_ERR_NO_MEMORY; } memset(out, 0x0, sizeof *out); out->as_fp = fp; *as = out; return IVY_OK; } void ivy_assembler_destroy(struct ivy_assembler *as) { free(as); } enum ivy_status ivy_assembler_begin_scope( struct ivy_assembler *as, enum ivy_assembler_scope_type type) { if (type < 0 || type >= nr_scope_types) { return IVY_ERR_NOT_SUPPORTED; } const struct assembler_scope_type *type_info = scope_types[type]; if (!type_info) { return IVY_ERR_NOT_SUPPORTED; } if (as->as_scope) { return IVY_ERR_NOT_SUPPORTED; } struct assembler_scope *scope = malloc(type_info->s_scope_size); if (!scope) { return IVY_ERR_NO_MEMORY; } scope->s_type = type; as->as_scope = scope; if (type_info->s_init_scope) { type_info->s_init_scope(as, scope); } return IVY_OK; } enum ivy_status ivy_assembler_end_scope(struct ivy_assembler *as) { if (!as->as_scope) { return IVY_ERR_NOT_SUPPORTED; } const struct assembler_scope_type *type_info = as->as_scope->s_ops; if (!type_info) { return IVY_ERR_NOT_SUPPORTED; } if (type_info->s_finish_scope) { type_info->s_finish_scope(as, as->as_scope); } free(as->as_scope); as->as_scope = NULL; return IVY_OK; } enum ivy_status ivy_assembler_put_string( struct ivy_assembler *as, int index, const char *s) { struct assembler_scope *scope = as->as_scope; if (!scope) { return IVY_ERR_NOT_SUPPORTED; } const struct assembler_scope_type *type_info = scope->s_ops; if (!type_info || !type_info->s_put_string) { return IVY_ERR_NOT_SUPPORTED; } return type_info->s_put_string(as, scope, index, s); } enum ivy_status ivy_assembler_put_ident( struct ivy_assembler *as, int index, const char *s) { struct assembler_scope *scope = as->as_scope; if (!scope) { return IVY_ERR_NOT_SUPPORTED; } const struct assembler_scope_type *type_info = scope->s_ops; if (!type_info || !type_info->s_put_string) { return IVY_ERR_NOT_SUPPORTED; } return type_info->s_put_string(as, scope, index, s); } enum ivy_status ivy_assembler_put_atom( struct ivy_assembler *as, int index, const char *s) { struct assembler_scope *scope = as->as_scope; if (!scope) { return IVY_ERR_NOT_SUPPORTED; } const struct assembler_scope_type *type_info = scope->s_ops; if (!type_info || !type_info->s_put_atom) { return IVY_ERR_NOT_SUPPORTED; } return type_info->s_put_atom(as, scope, index, s); } enum ivy_status ivy_assembler_put_selector( struct ivy_assembler *as, int index, struct ivy_selector *sel) { struct assembler_scope *scope = as->as_scope; if (!scope) { return IVY_ERR_NOT_SUPPORTED; } const struct assembler_scope_type *type_info = scope->s_ops; if (!type_info || !type_info->s_put_selector) { return IVY_ERR_NOT_SUPPORTED; } return type_info->s_put_selector(as, scope, index, sel); } enum ivy_status ivy_assembler_put_mvar( struct ivy_assembler *as, int index, const char *name) { struct assembler_scope *scope = as->as_scope; if (!scope) { return IVY_ERR_NOT_SUPPORTED; } const struct assembler_scope_type *type_info = scope->s_ops; if (!type_info || !type_info->s_put_mvar) { return IVY_ERR_NOT_SUPPORTED; } return type_info->s_put_mvar(as, scope, index, name); } enum ivy_status ivy_assembler_put_instr( struct ivy_assembler *as, const struct ivy_instr *i) { struct assembler_scope *scope = as->as_scope; if (!scope) { return IVY_ERR_NOT_SUPPORTED; } const struct assembler_scope_type *type_info = scope->s_ops; if (!type_info || !type_info->s_put_instr) { return IVY_ERR_NOT_SUPPORTED; } return type_info->s_put_instr(as, scope, i); }