Files
mie/tool/cmd/validate.c

401 lines
11 KiB
C
Raw Normal View History

#include "cmd.h"
#include <assert.h>
#include <blue/cmd.h>
#include <blue/io/file.h>
#include <blue/io/path.h>
#include <blue/term.h>
#include <mie/ctx.h>
#include <mie/dialect/arith.h>
#include <mie/dialect/builtin.h>
#include <mie/dialect/cf.h>
#include <mie/dialect/dialect.h>
#include <mie/dialect/func.h>
#include <mie/dialect/index.h>
#include <mie/dialect/meta.h>
#include <mie/dialect/ptr.h>
#include <mie/dialect/scf.h>
#include <mie/dialect/select.h>
#include <mie/ir/block.h>
#include <mie/ir/op-definition.h>
#include <mie/ir/op.h>
#include <mie/ir/region.h>
#include <mie/ir/register.h>
#include <mie/name.h>
#include <mie/parse/lex.h>
#include <mie/parse/parse.h>
#include <mie/parse/token.h>
#include <mie/trait/trait-definition.h>
#include <mie/trait/trait.h>
#include <mie/type/type-definition.h>
#include <mie/type/type.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
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 : "<unknown>");
printf("OP: %s\n", op->op_info ? op->op_info->op_name : "<unknown>");
printf("NAME: %s\n", op->op_name ? op->op_name : "<unknown>");
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();
}