From 6bebcbfdf624804f9ac62162e980b2e5841601f7 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 16 Mar 2026 12:03:02 +0000 Subject: [PATCH] scf: implement print/parse for for, if, yield --- mie/dialect/scf/op/for.c | 269 ++++++++++++++++++++++++++++++++++++- mie/dialect/scf/op/if.c | 4 +- mie/dialect/scf/op/yield.c | 77 ++++++++++- 3 files changed, 347 insertions(+), 3 deletions(-) diff --git a/mie/dialect/scf/op/for.c b/mie/dialect/scf/op/for.c index 184d97c..e52fe4f 100644 --- a/mie/dialect/scf/op/for.c +++ b/mie/dialect/scf/op/for.c @@ -1,14 +1,281 @@ +#include +#include #include +#include #include +#include +#include #include +#include +#include +#include +#include static enum mie_status print(struct mie_printer *printer, const struct mie_op *op) { + struct mie_region *body = mie_op_get_first_region(op); + struct mie_block *entry = NULL; + struct mie_register *iv = NULL; + struct mie_op_arg *lb = NULL, *ub = NULL, *step = NULL; + + if (!body) { + return MIE_ERR_BAD_STATE; + } + + entry = mie_region_get_first_block(body); + if (!entry) { + return MIE_ERR_BAD_STATE; + } + + if (MIE_VECTOR_COUNT(op->op_args) < 3) { + return MIE_ERR_BAD_STATE; + } + + if (MIE_VECTOR_COUNT(entry->b_params) < 1) { + return MIE_ERR_BAD_STATE; + } + + iv = &entry->b_params.items[0]; + lb = &op->op_args.items[0]; + ub = &op->op_args.items[1]; + step = &op->op_args.items[2]; + + b_stream_write_char(printer->p_stream, ' '); + mie_printer_print_register(printer, iv, 0); + b_stream_write_string(printer->p_stream, " = ", NULL); + mie_printer_print_op_arg(printer, lb, 0); + b_stream_write_string(printer->p_stream, " to ", NULL); + mie_printer_print_op_arg(printer, ub, 0); + b_stream_write_string(printer->p_stream, " step ", NULL); + mie_printer_print_op_arg(printer, step, 0); + + if (MIE_VECTOR_COUNT(entry->b_params) > 1) { + b_stream_write_string(printer->p_stream, " iter-args(", NULL); + for (size_t i = 1; i < MIE_VECTOR_COUNT(entry->b_params); i++) { + if (i > 1) { + b_stream_write_string(printer->p_stream, ", ", NULL); + } + + mie_printer_print_register( + printer, &entry->b_params.items[i], 0); + b_stream_write_string(printer->p_stream, " = ", NULL); + mie_printer_print_op_arg( + printer, &op->op_args.items[i + 2], false); + } + b_stream_write_char(printer->p_stream, ')'); + } + + if (MIE_VECTOR_COUNT(op->op_result) > 0) { + b_stream_write_string(printer->p_stream, " -> ", NULL); + if (MIE_VECTOR_COUNT(op->op_result) > 1) { + b_stream_write_char(printer->p_stream, '('); + } + + for (size_t i = 0; i < MIE_VECTOR_COUNT(op->op_result); i++) { + mie_printer_print_type( + printer, op->op_result.items[i].reg_type); + } + + if (MIE_VECTOR_COUNT(op->op_result) > 1) { + b_stream_write_char(printer->p_stream, ')'); + } + } + + b_stream_write_char(printer->p_stream, ' '); + mie_printer_print_region( + printer, body, MIE_PRINT_F_EXCLUDE_FIRST_BLOCK_HEADER); + return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static bool parse_result_type( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out, struct mie_block *entry) { + const struct mie_type *type = NULL; + struct mie_file_span span; + if (!mie_parser_parse_type(parser, "loop result type", &type, &span)) { + return false; + } + + const struct mie_type **types; + size_t nr_types; + + if (mie_type_is_storage(type)) { + const struct mie_storage_type *storage + = (const struct mie_storage_type *)type; + + types = storage->st_parts.items; + nr_types = storage->st_parts.count; + } else if (!mie_type_is_function(type)) { + types = &type; + nr_types = 1; + } else { + mie_parser_report_error_simple( + parser, "builtin", MIE_BUILTIN_E_INVALID_TYPE, + MIE_BUILTIN_MSG_CANNOT_USE_FUNCTION_TYPE_HERE, &span); + } + + if (MIE_VECTOR_COUNT(out->op_result) != nr_types) { + mie_parser_report_error_simple( + parser, "builtin", MIE_BUILTIN_E_INCORRECT_NUMBER_OF_TYPES, + MIE_BUILTIN_MSG_OP_NR_TYPES_DOESNT_MATCH_NR_RESULTS, + &span); + return false; + } + + for (size_t i = 0; i < nr_types; i++) { + out->op_result.items[i].reg_type = types[i]; + } + + return true; +} + +static bool parse_iter_arg( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out, struct mie_block *entry) +{ + struct mie_register *reg = mie_block_add_param(entry); + struct mie_op_arg *arg = mie_op_add_arg(out); + + if (!mie_parser_parse_register( + parser, scope, "iterator parameter name", reg)) { + return false; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_EQUAL)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_EQUAL, "iterator parameter"); + return false; + } + + if (!mie_parser_parse_parameter( + parser, false, arg, "iterator parameter value")) { + return false; + } + + struct mie_register *value = mie_parser_scope_find_value( + scope, arg->arg_unresolved.reg_name); + if (value) { + reg->reg_type = value->reg_type; + } + + return true; +} + +static bool parse_iter_args( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out, struct mie_block *entry) +{ + if (!mie_parser_parse_keyword(parser, "iter-args", NULL)) { + return true; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_LEFT_PAREN)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_LEFT_PAREN, "iterator parameter list"); + return false; + } + + if (!parse_iter_arg(parser, scope, out, entry)) { + return false; + } + + while (1) { + if (mie_parser_parse_symbol(parser, MIE_SYM_RIGHT_PAREN)) { + break; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_COMMA)) { + struct mie_parser_item expected[] = { + MIE_PARSE_ITEM_TOKEN(MIE_SYM_COMMA), + MIE_PARSE_ITEM_TOKEN(MIE_SYM_RIGHT_PAREN), + MIE_PARSE_ITEM_NONE, + }; + mie_parser_report_unexpected_token_v( + parser, expected, "iterator parameter list"); + return false; + } + + if (!parse_iter_arg(parser, scope, out, entry)) { + return false; + } + } + + return true; +} + +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out) +{ + struct mie_region *body = mie_op_add_region(out); + struct mie_block *entry = mie_region_add_block(body); + struct mie_register *iv = mie_block_add_param(entry); + + mie_parser_scope_put_name(scope, &entry->b_name, "for.entry", 0); + + if (!mie_parser_parse_register(parser, scope, "induction variable", iv)) { + return MIE_ERR_BAD_SYNTAX; + } + + iv->reg_type = mie_ctx_get_type( + mie_parser_get_mie_ctx(parser), "builtin", "index"); + + if (!mie_parser_parse_symbol(parser, MIE_SYM_EQUAL)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_EQUAL, "for-loop"); + return MIE_ERR_BAD_SYNTAX; + } + + struct mie_op_arg *lb = mie_op_add_arg(out); + if (!mie_parser_parse_parameter(parser, false, lb, "lower bound")) { + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_keyword(parser, "to", NULL)) { + mie_parser_report_unexpected_token_s(parser, "to", "for-loop"); + return MIE_ERR_BAD_SYNTAX; + } + + struct mie_op_arg *ub = mie_op_add_arg(out); + if (!mie_parser_parse_parameter(parser, false, ub, "upper bound")) { + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_keyword(parser, "step", NULL)) { + mie_parser_report_unexpected_token_s(parser, "step", "for-loop"); + return MIE_ERR_BAD_SYNTAX; + } + + struct mie_op_arg *step = mie_op_add_arg(out); + if (!mie_parser_parse_parameter(parser, false, step, "step")) { + return MIE_ERR_BAD_SYNTAX; + } + + if (!parse_iter_args(parser, scope, out, entry)) { + return MIE_ERR_BAD_SYNTAX; + } + + if (mie_parser_parse_symbol(parser, MIE_SYM_HYPHEN_RIGHT_ANGLE)) { + if (!parse_result_type(parser, scope, out, entry)) { + return MIE_ERR_BAD_SYNTAX; + } + } else if (MIE_VECTOR_COUNT(out->op_result) > 0) { + struct mie_file_span span; + mie_op_get_results_span(out, &span); + mie_parser_report_error_simple( + parser, "builtin", + MIE_BUILTIN_E_INCORRECT_NUMBER_OF_RESULTS, + MIE_BUILTIN_MSG_OP_NR_TYPES_DOESNT_MATCH_NR_RESULTS, + &span); + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_region(parser, out, body, entry)) { + return MIE_ERR_BAD_SYNTAX; + } + return MIE_SUCCESS; } diff --git a/mie/dialect/scf/op/if.c b/mie/dialect/scf/op/if.c index 4449c55..52cbc9a 100644 --- a/mie/dialect/scf/op/if.c +++ b/mie/dialect/scf/op/if.c @@ -46,7 +46,9 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *names, + struct mie_op *out) { return MIE_SUCCESS; } diff --git a/mie/dialect/scf/op/yield.c b/mie/dialect/scf/op/yield.c index 3f9e18f..cf66be9 100644 --- a/mie/dialect/scf/op/yield.c +++ b/mie/dialect/scf/op/yield.c @@ -1,8 +1,10 @@ +#include #include #include #include #include #include +#include #include static enum mie_status print(struct mie_printer *printer, const struct mie_op *op) @@ -30,8 +32,81 @@ static enum mie_status print(struct mie_printer *printer, const struct mie_op *o return MIE_SUCCESS; } -static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) +static enum mie_status parse( + struct mie_parser *parser, struct mie_parser_scope *scope, + struct mie_op *out) { + if (!mie_parser_parse_parameter_list( + parser, false, MIE_VECTOR_REF(out->op_args), + "yield value(s)")) { + return MIE_ERR_BAD_SYNTAX; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_COLON)) { + mie_parser_report_unexpected_token( + parser, MIE_SYM_COLON, "yield value type(s)"); + return MIE_ERR_BAD_SYNTAX; + } + + MIE_VECTOR_DEFINE(const struct mie_type *, types); + const struct mie_type *tmp = NULL; + struct mie_file_span first_span, last_span; + + if (!mie_parser_parse_type( + parser, "yield value type(s)", &tmp, &first_span)) { + return MIE_ERR_BAD_SYNTAX; + } + + mie_vector_push_back(types, &tmp, NULL); + bool ok = true; + + while (1) { + if (mie_parser_peek_type(parser) == MIE_TOK_LINEFEED) { + break; + } + + if (!mie_parser_parse_symbol(parser, MIE_SYM_COMMA)) { + struct mie_parser_item expected[] = { + MIE_PARSE_ITEM_TOKEN(MIE_SYM_COMMA), + MIE_PARSE_ITEM_TOKEN(MIE_TOK_LINEFEED), + MIE_PARSE_ITEM_NONE, + }; + + mie_parser_report_unexpected_token_v( + parser, expected, "yield value type list"); + ok = false; + break; + } + + if (!mie_parser_parse_type( + parser, "yield value type", &tmp, &last_span)) { + ok = false; + break; + } + + mie_vector_push_back(types, &tmp, NULL); + } + + if (!ok) { + mie_vector_destroy(types, NULL); + return MIE_ERR_BAD_SYNTAX; + } + + if (MIE_VECTOR_COUNT(types) != MIE_VECTOR_COUNT(out->op_args)) { + struct mie_file_span span = { + .s_start = first_span.s_start, + .s_end = last_span.s_end, + }; + mie_parser_report_error_simple( + parser, "builtin", MIE_BUILTIN_E_INCORRECT_NUMBER_OF_TYPES, + MIE_BUILTIN_MSG_OP_NR_TYPES_DOESNT_MATCH_NR_ARGS, &span); + return MIE_ERR_BAD_SYNTAX; + } + + for (size_t i = 0; i < MIE_VECTOR_COUNT(types); i++) { + out->op_args.items[i].arg_unresolved.reg_type = types.items[i]; + } + return MIE_SUCCESS; }