#include "cmd.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum { ARG_FILEPATH, }; static int trait_ref_print(const struct mie_trait *trait, void *arg) { fputc(' ', stdout); mie_trait_print(trait, b_stdout); return 0; } static void mie_op_arg_print(const struct mie_op_arg *arg) { enum mie_register_flags arg_flags = 0; const char *arg_name = NULL; const struct mie_type *arg_type = NULL; if (MIE_TEST_FLAGS(arg->arg_flags, MIE_OP_F_ARG_RESOLVED)) { arg_flags = arg->arg_value->reg_flags; arg_name = arg->arg_value->reg_name.n_str; arg_type = arg->arg_value->reg_type; } else { arg_flags = arg->arg_unresolved.reg_flags; arg_name = arg->arg_unresolved.reg_name; arg_type = arg->arg_unresolved.reg_type; } if (arg_flags & MIE_REGISTER_F_MACHINE) { b_printf(" [bold,red]MR"); } else { b_printf(" [bold,magenta]VR"); } printf(":("); mie_type_print(arg_type, b_stdout); b_printf(")%s[reset]", arg_name); } static void mie_op_print(const struct mie_op *op) { b_stringstream *tmp = b_stringstream_create(); printf("FLAGS:"); (op->op_flags & MIE_OP_F_OP_RESOLVED) && printf(" OP_RESOLVED"); (op->op_flags & MIE_OP_F_ARG_RESOLVED) && printf(" ARG_RESOLVED"); printf("\n"); printf("DIALECT: %s\n", op->op_dialect ? op->op_dialect->d_name : ""); printf("OP: %s\n", op->op_info ? op->op_info->op_name : ""); printf("NAME: %s\n", op->op_name ? op->op_name : ""); printf("TRAITS:"); mie_trait_table_iterate(&op->op_info->op_traits, trait_ref_print, NULL); printf("\n"); printf("ATTRIBUTES:"); for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_attrib); i++) { printf(" (%s = ", op->op_attrib.items[i].attrib_name); mie_value_print(op->op_attrib.items[i].attrib_value, b_stdout); printf(")"); } printf("\n"); printf("REGIONS: %zu\n", MIE_VECTOR_COUNT(op->op_regions)); printf("SUCCESSORS:"); for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_successors); i++) { const struct mie_op_successor *s = &op->op_successors.items[i]; if (MIE_TEST_FLAGS(s->s_flags, MIE_OP_F_SUCCESSOR_RESOLVED)) { printf(" ^%s", s->s_block->b_name.n_str); } else { printf(" ^%s?", s->s_block_name); } printf(":("); for (size_t i = 0; i < MIE_VECTOR_COUNT(s->s_args); i++) { const struct mie_op_arg *arg = &s->s_args.items[i]; mie_op_arg_print(arg); } printf(" )"); } printf("\n"); printf("ARGS:"); for (size_t i = 0; i < op->op_args.count; i++) { const struct mie_op_arg *arg = &op->op_args.items[i]; mie_op_arg_print(arg); } printf("\n"); printf("RESULT:"); for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) { const struct mie_register *reg = &op->op_result.items[i]; printf(" %s:(", (reg->reg_flags & MIE_REGISTER_F_MACHINE) ? "MR" : "VR"); mie_type_print(reg->reg_type, b_stdout); printf(")%s", reg->reg_name.n_str); } printf("\n"); } static void mie_op_definition_print(const struct mie_op_definition *op) { char id_str[MIE_ID_STRING_MAX]; mie_id_to_string(&op->op_id, id_str, sizeof id_str); b_printf( " [bold,red]Op:[reset]%-20s [dark_grey]{%s}[reset]\n", op->op_name, id_str); } static void mie_type_definition_print(const struct mie_type_definition *type) { char id_str[MIE_ID_STRING_MAX]; mie_id_to_string(&type->ty_id, id_str, sizeof id_str); b_printf( " [bold,blue]Ty:[reset]%-20s [dark_grey]{%s}[reset]\n", type->ty_name, id_str); } static void mie_trait_definition_print(const struct mie_trait_definition *trait) { char id_str[MIE_ID_STRING_MAX]; mie_id_to_string(&trait->tr_id, id_str, sizeof id_str); b_printf( " [bold,yellow]Tr:[reset]%-20s [dark_grey]{%s}[reset]\n", trait->tr_name, id_str); } static void mie_dialect_print(const struct mie_dialect *dialect) { char id_str[MIE_ID_STRING_MAX]; mie_id_to_string(&dialect->d_id, id_str, sizeof id_str); b_printf( "[bold,green]D:[reset]%-20s [dark_grey]{%s}[reset]\n", dialect->d_name, id_str); b_btree_node *node = b_btree_first(&dialect->d_ops.map_entries); while (node) { mie_id *id = b_unbox(mie_id, node, e_node); struct mie_op_definition *op = b_unbox(struct mie_op_definition, id, op_id); mie_op_definition_print(op); node = b_btree_next(node); } node = b_btree_first(&dialect->d_types.map_entries); while (node) { mie_id *id = b_unbox(mie_id, node, e_node); struct mie_type_definition *type = b_unbox(struct mie_type_definition, id, ty_id); mie_type_definition_print(type); node = b_btree_next(node); } node = b_btree_first(&dialect->d_traits.map_entries); while (node) { mie_id *id = b_unbox(mie_id, node, e_node); struct mie_trait_definition *trait = b_unbox(struct mie_trait_definition, id, tr_id); mie_trait_definition_print(trait); node = b_btree_next(node); } } static void mie_ctx_print(const struct mie_ctx *ctx) { b_btree_node *node = b_btree_first(&ctx->ctx_dialects.map_entries); while (node) { mie_id *id = b_unbox(mie_id, node, e_node); struct mie_dialect *dialect = b_unbox(struct mie_dialect, id, d_id); mie_dialect_print(dialect); node = b_btree_next(node); } } static int validate_file(const char *path, const b_arglist *args) { b_file *file = NULL; b_result result = b_file_open(NULL, B_RV_PATH(path), B_FILE_READ_ONLY, &file); if (b_result_is_error(result)) { b_throw(result); return -1; } printf("File OK\n"); struct mie_ctx *ctx = mie_ctx_create(); mie_builtin_dialect_create(ctx); mie_meta_dialect_create(ctx); mie_select_dialect_create(ctx); mie_ptr_dialect_create(ctx); mie_arith_dialect_create(ctx); mie_func_dialect_create(ctx); mie_cf_dialect_create(ctx); mie_scf_dialect_create(ctx); mie_index_dialect_create(ctx); mie_ctx_print(ctx); struct mie_type *i32 = mie_arith_int_get_type(ctx, 32); struct mie_type *str = mie_ctx_get_type(ctx, "builtin", "string"); struct mie_type *index = mie_ctx_get_type(ctx, "index", "index"); struct mie_value *i32_value = mie_ctx_get_int(ctx, 1024, 32); struct mie_value *index_value = mie_ctx_get_index(ctx, 25000); struct mie_value *str_value = mie_ctx_get_string(ctx, "Hello, world!"); const struct mie_type *storage_type_parts[] = {i32, str, index}; struct mie_type *storage_type = mie_ctx_get_storage_type( ctx, storage_type_parts, sizeof storage_type_parts / sizeof *storage_type_parts); const struct mie_type *func_in_parts[] = {i32, str}; const struct mie_type *func_out_parts[] = {index}; struct mie_type *func_type = mie_ctx_get_function_type( ctx, func_in_parts, sizeof func_in_parts / sizeof *func_in_parts, func_out_parts, sizeof func_out_parts / sizeof *func_out_parts); /* make sure storage/function type caching is working */ assert(storage_type == mie_ctx_get_storage_type( ctx, storage_type_parts, sizeof storage_type_parts / sizeof *storage_type_parts)); assert(func_type == mie_ctx_get_function_type( ctx, func_in_parts, sizeof func_in_parts / sizeof *func_in_parts, func_out_parts, sizeof func_out_parts / sizeof *func_out_parts)); char id_str[MIE_ID_STRING_MAX]; mie_id_to_string(&i32->ty_id, id_str, sizeof id_str); printf("i32 type: {%s} %s (instance of %s.%s)\n", id_str, i32->ty_name, i32->ty_def->ty_parent->d_name, i32->ty_def->ty_name); mie_id_to_string(&str->ty_id, id_str, sizeof id_str); printf("str type: {%s} %s (instance of %s.%s)\n", id_str, str->ty_name, str->ty_def->ty_parent->d_name, str->ty_def->ty_name); mie_id_to_string(&index->ty_id, id_str, sizeof id_str); printf("index type: {%s} %s (instance of %s.%s)\n", id_str, index->ty_name, index->ty_def->ty_parent->d_name, index->ty_def->ty_name); mie_id_to_string(&storage_type->ty_id, id_str, sizeof id_str); printf("storage type: {%s} ", id_str); mie_type_print(storage_type, b_stdout); printf("\n"); mie_id_to_string(&func_type->ty_id, id_str, sizeof id_str); printf("function type: {%s} ", id_str); mie_type_print(func_type, b_stdout); printf("\n"); printf("i32 value: "); mie_value_print(i32_value, b_stdout); printf("\n"); printf("index value: "); mie_value_print(index_value, b_stdout); printf("\n"); printf("str value: "); mie_value_print(str_value, b_stdout); printf("\n"); struct mie_lex *lex = mie_lex_create(file); struct mie_parser *parse = mie_parser_create(ctx, lex); struct mie_name_map *names = mie_name_map_create(NULL); struct mie_op op = {}; if (!mie_parser_parse_op(parse, names, &op)) { printf("parse failed\n"); return -1; } if (!mie_ctx_resolve_op(ctx, &op)) { printf("op resolve failed\n"); return -1; } mie_op_print(&op); #if 0 while (1) { struct mie_token *tok = mie_lex_peek(lex); if (!tok) { break; } printf("%s[%d:%d -> %d:%d]", mie_token_type_to_string(tok->tok_type), tok->tok_start.c_row, tok->tok_start.c_col, tok->tok_end.c_row, tok->tok_end.c_col); switch (tok->tok_value_type) { case MIE_TOK_V_STRING: printf(" S:%s", tok->tok_str); break; case MIE_TOK_V_INT: printf(" I:%lld", tok->tok_int); break; case MIE_TOK_V_DOUBLE: printf(" D:%lf", tok->tok_double); break; case MIE_TOK_V_SYMBOL: printf(" SYM:%s", mie_token_symbol_to_string(tok->tok_sym)); break; default: break; } printf("\n"); mie_lex_advance(lex); } #endif mie_lex_destroy(lex); b_file_unref(file); return 0; } int validate(const b_command *cmd, const b_arglist *args, const b_array *_) { b_arglist_iterator it; b_arglist_foreach_filtered(&it, args, B_COMMAND_INVALID_ID, ARG_FILEPATH) { b_arglist_value *path = it.value; if (path->val_type != B_COMMAND_ARG_STRING) { continue; } int r = validate_file(path->val_str, args); if (r != 0) { return r; } } return 0; } B_COMMAND(CMD_VALIDATE, CMD_ROOT) { B_COMMAND_NAME("validate"); B_COMMAND_SHORT_NAME('V'); B_COMMAND_DESC("validate a mie ir file."); B_COMMAND_HELP_OPTION(); B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); B_COMMAND_FUNCTION(validate); B_COMMAND_ARG(ARG_FILEPATH) { B_ARG_NAME("filepath"); B_ARG_DESC("the mie file to validate"); B_ARG_NR_VALUES(1); } B_COMMAND_HELP_OPTION(); }