2024-11-18 09:55:02 +00:00
|
|
|
#include "../debug.h"
|
|
|
|
|
#include "../line-ed/line-ed.h"
|
2024-11-01 21:41:44 +00:00
|
|
|
#include "cmd.h"
|
|
|
|
|
|
|
|
|
|
#include <blue/cmd.h>
|
2024-11-18 09:55:02 +00:00
|
|
|
#include <blue/term.h>
|
2024-11-23 19:28:26 +00:00
|
|
|
#include <ivy/lang/ast.h>
|
2025-04-14 12:25:49 +01:00
|
|
|
#include <ivy/lang/codegen.h>
|
2024-11-26 13:09:57 +00:00
|
|
|
#include <ivy/lang/lex.h>
|
2025-04-14 20:15:41 +01:00
|
|
|
#include <mie/convert.h>
|
2025-04-28 15:47:24 +01:00
|
|
|
#include <mie/ctx.h>
|
2025-04-14 20:15:41 +01:00
|
|
|
#include <mie/value.h>
|
2024-11-18 09:55:02 +00:00
|
|
|
#include <stdbool.h>
|
2025-04-14 12:25:49 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2024-11-18 09:55:02 +00:00
|
|
|
|
2024-11-23 19:28:26 +00:00
|
|
|
enum {
|
2024-12-06 20:24:50 +00:00
|
|
|
OPT_SHOW_LEX_TOKENS = 100,
|
|
|
|
|
OPT_SHOW_AST_NODES,
|
2025-04-16 21:59:32 +01:00
|
|
|
OPT_SHOW_IR,
|
2024-11-23 19:28:26 +00:00
|
|
|
};
|
|
|
|
|
|
2025-04-14 09:46:36 +01:00
|
|
|
struct repl {
|
2025-04-16 21:59:32 +01:00
|
|
|
bool r_show_lex, r_show_ast, r_show_ir;
|
2025-04-28 15:47:24 +01:00
|
|
|
struct mie_ctx *r_mie;
|
2025-04-14 12:25:49 +01:00
|
|
|
struct line_ed *r_ed;
|
|
|
|
|
struct ivy_lexer *r_lex;
|
|
|
|
|
struct ivy_parser *r_parse;
|
|
|
|
|
struct ivy_codegen *r_codegen;
|
2025-04-14 20:15:41 +01:00
|
|
|
struct mie_ir_converter *r_converter;
|
2025-04-14 09:46:36 +01:00
|
|
|
};
|
|
|
|
|
|
2024-11-23 19:28:26 +00:00
|
|
|
static void skip_line(struct ivy_lexer *lex)
|
|
|
|
|
{
|
|
|
|
|
while (ivy_lexer_tokens_available(lex)) {
|
|
|
|
|
struct ivy_token *tok = ivy_lexer_read(lex);
|
|
|
|
|
bool line_end = (tok->t_type == IVY_TOK_LINEFEED);
|
2024-11-26 13:09:57 +00:00
|
|
|
|
2024-11-23 19:28:26 +00:00
|
|
|
ivy_token_destroy(tok);
|
2024-11-26 13:09:57 +00:00
|
|
|
|
2024-11-23 19:28:26 +00:00
|
|
|
if (line_end) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 20:15:41 +01:00
|
|
|
static enum ivy_status add_node_to_codegen(
|
|
|
|
|
struct ivy_ast_node *node, enum ivy_ast_iteration_type iteration_type,
|
|
|
|
|
struct ivy_ast_node_iterator *it, void *arg)
|
|
|
|
|
{
|
2025-04-16 21:59:32 +01:00
|
|
|
if (iteration_type != IVY_AST_ITERATION_PRE) {
|
|
|
|
|
return IVY_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 20:15:41 +01:00
|
|
|
struct repl *repl = arg;
|
2025-04-16 21:59:32 +01:00
|
|
|
return ivy_codegen_push_node(repl->r_codegen, node, node->n_it.it_depth);
|
2025-04-14 20:15:41 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-14 09:46:36 +01:00
|
|
|
static int repl_eval_node(struct repl *repl, struct ivy_ast_node *node)
|
|
|
|
|
{
|
|
|
|
|
struct ivy_ast_node_iterator it = {0};
|
|
|
|
|
|
|
|
|
|
if (repl->r_show_ast) {
|
2025-04-22 15:31:51 +01:00
|
|
|
struct print_ast_node_args args = {
|
|
|
|
|
.indent = true,
|
|
|
|
|
.postorder = false,
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
ivy_ast_node_iterate(node, &it, print_ast_node, &args);
|
2025-04-22 15:31:51 +01:00
|
|
|
#if 0
|
2025-04-16 21:59:32 +01:00
|
|
|
printf("------\n");
|
|
|
|
|
args.indent = false;
|
|
|
|
|
args.postorder = true;
|
|
|
|
|
ivy_ast_node_iterate(node, &it, print_ast_node, &args);
|
2025-04-22 15:31:51 +01:00
|
|
|
#endif
|
2025-04-14 09:46:36 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-16 21:59:32 +01:00
|
|
|
if (!repl->r_show_ir) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum ivy_status status = ivy_ast_node_iterate(
|
|
|
|
|
(struct ivy_ast_node *)node, &it, add_node_to_codegen, repl);
|
2025-04-14 20:15:41 +01:00
|
|
|
if (status != IVY_OK) {
|
2025-04-16 21:59:32 +01:00
|
|
|
printf("codegen error: %s\n", ivy_status_to_string(status));
|
2025-04-14 20:15:41 +01:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-16 21:59:32 +01:00
|
|
|
ivy_codegen_push_eof(repl->r_codegen);
|
|
|
|
|
|
2025-04-14 20:15:41 +01:00
|
|
|
struct mie_module *mod = ivy_codegen_get_current_module(repl->r_codegen);
|
|
|
|
|
mie_ir_converter_set_src_value(repl->r_converter, MIE_VALUE(mod));
|
|
|
|
|
mie_ir_converter_process(repl->r_converter);
|
2025-04-14 09:46:36 +01:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
static void repl_destroy(struct repl *repl)
|
|
|
|
|
{
|
2025-04-14 20:15:41 +01:00
|
|
|
if (repl->r_converter) {
|
|
|
|
|
mie_ir_converter_destroy(repl->r_converter);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
if (repl->r_codegen) {
|
|
|
|
|
ivy_codegen_destroy(repl->r_codegen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (repl->r_parse) {
|
2025-04-17 23:16:16 +01:00
|
|
|
ivy_parser_destroy(repl->r_parse, NULL);
|
2025-04-14 12:25:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (repl->r_lex) {
|
|
|
|
|
ivy_lexer_destroy(repl->r_lex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (repl->r_ed) {
|
|
|
|
|
line_ed_destroy(repl->r_ed);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-28 15:47:24 +01:00
|
|
|
if (repl->r_mie) {
|
|
|
|
|
mie_ctx_destroy(repl->r_mie);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
free(repl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum ivy_status repl_create(struct repl **out)
|
|
|
|
|
{
|
|
|
|
|
struct repl *repl = malloc(sizeof *repl);
|
|
|
|
|
if (!repl) {
|
|
|
|
|
return IVY_ERR_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(repl, 0x0, sizeof *repl);
|
|
|
|
|
|
2025-04-28 15:47:24 +01:00
|
|
|
repl->r_mie = mie_ctx_create();
|
|
|
|
|
if (!repl->r_mie) {
|
|
|
|
|
repl_destroy(repl);
|
|
|
|
|
return IVY_ERR_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
repl->r_ed = line_ed_create();
|
|
|
|
|
if (!repl->r_ed) {
|
|
|
|
|
repl_destroy(repl);
|
|
|
|
|
return IVY_ERR_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
line_ed_set_flags(repl->r_ed, LINE_ED_REMOVE_CONTINUATIONS);
|
|
|
|
|
|
|
|
|
|
enum ivy_status status = ivy_lexer_create(&repl->r_lex);
|
|
|
|
|
if (status != IVY_OK) {
|
|
|
|
|
repl_destroy(repl);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivy_lexer_set_source(repl->r_lex, &repl->r_ed->l_line_source);
|
|
|
|
|
|
|
|
|
|
status = ivy_parser_create(&repl->r_parse);
|
|
|
|
|
if (status != IVY_OK) {
|
|
|
|
|
repl_destroy(repl);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-28 15:47:24 +01:00
|
|
|
status = ivy_codegen_create(repl->r_mie, &repl->r_codegen);
|
2025-04-14 12:25:49 +01:00
|
|
|
if (status != IVY_OK) {
|
|
|
|
|
repl_destroy(repl);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-28 15:47:24 +01:00
|
|
|
repl->r_converter
|
|
|
|
|
= mie_ir_converter_create(repl->r_mie, MIE_IR_MEM, MIE_IR_TEXT);
|
2025-04-14 20:15:41 +01:00
|
|
|
if (!repl->r_converter) {
|
|
|
|
|
repl_destroy(repl);
|
|
|
|
|
return IVY_ERR_NO_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mie_ir_converter_set_dest_file(repl->r_converter, stdout);
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
*out = repl;
|
|
|
|
|
return IVY_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-26 13:09:57 +00:00
|
|
|
int repl(const b_command *cmd, const b_arglist *args, const b_array *_)
|
2024-11-23 19:28:26 +00:00
|
|
|
{
|
2025-04-15 11:00:48 +01:00
|
|
|
#if 0
|
2025-04-14 09:46:36 +01:00
|
|
|
b_printf(
|
|
|
|
|
"[bold,bright_red]error[[E0384][reset,bold,white]: cannot "
|
|
|
|
|
"assign twice to immutable variable `i`[reset]\n");
|
2024-12-07 19:32:35 +00:00
|
|
|
b_printf("[bold,bright_blue] -->[reset] src/main.rs:7:3\n");
|
|
|
|
|
b_printf("[bold,bright_blue] |[reset]\n");
|
|
|
|
|
b_printf("[bold,bright_blue]4 |[reset] let i = 0;\n");
|
|
|
|
|
b_printf("[bold,bright_blue] | -[reset]\n");
|
|
|
|
|
b_printf("[bold,bright_blue] | |[reset]\n");
|
2025-04-14 09:46:36 +01:00
|
|
|
b_printf(
|
|
|
|
|
"[bold,bright_blue] | first assignment to "
|
|
|
|
|
"`i`[reset]\n");
|
|
|
|
|
b_printf(
|
|
|
|
|
"[bold,bright_blue] | help: make this binding "
|
|
|
|
|
"mutable: `mut i`[reset]\n");
|
2024-12-07 19:32:35 +00:00
|
|
|
b_printf("[bold,bright_blue]...[reset]\n");
|
|
|
|
|
b_printf("[bold,bright_blue]7 |[reset] i += 1;\n");
|
2025-04-14 09:46:36 +01:00
|
|
|
b_printf(
|
|
|
|
|
"[bold,bright_blue] |[bold,bright_red] ^^^^^^ cannot "
|
|
|
|
|
"assign twice to immutable variable[reset]\n");
|
2025-04-15 11:00:48 +01:00
|
|
|
#endif
|
2025-04-14 09:46:36 +01:00
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
struct repl *repl = NULL;
|
|
|
|
|
enum ivy_status status = repl_create(&repl);
|
2024-11-23 19:28:26 +00:00
|
|
|
if (status != IVY_OK) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
repl->r_show_lex = b_arglist_get_count(
|
|
|
|
|
args, OPT_SHOW_LEX_TOKENS, B_COMMAND_INVALID_ID)
|
|
|
|
|
> 0;
|
|
|
|
|
repl->r_show_ast = b_arglist_get_count(
|
|
|
|
|
args, OPT_SHOW_AST_NODES, B_COMMAND_INVALID_ID)
|
|
|
|
|
> 0;
|
2025-04-16 21:59:32 +01:00
|
|
|
repl->r_show_ir
|
|
|
|
|
= b_arglist_get_count(args, OPT_SHOW_IR, B_COMMAND_INVALID_ID) > 0;
|
2024-11-23 19:28:26 +00:00
|
|
|
|
|
|
|
|
while (true) {
|
2025-04-14 12:25:49 +01:00
|
|
|
struct ivy_token *tok = ivy_lexer_read(repl->r_lex);
|
|
|
|
|
status = ivy_lexer_get_status(repl->r_lex);
|
2024-11-23 19:28:26 +00:00
|
|
|
if (status == IVY_ERR_EOF) {
|
2024-11-18 09:55:02 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-23 19:28:26 +00:00
|
|
|
if (status != IVY_OK) {
|
|
|
|
|
b_err("lex error (%s)",
|
2025-04-14 12:25:49 +01:00
|
|
|
ivy_status_to_string(
|
|
|
|
|
ivy_lexer_get_status(repl->r_lex)));
|
2024-11-18 09:55:02 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
if (repl->r_show_lex) {
|
2024-12-06 20:24:50 +00:00
|
|
|
print_lex_token(tok);
|
2024-11-26 13:09:57 +00:00
|
|
|
}
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
status = ivy_parser_push_token(repl->r_parse, tok);
|
2024-11-18 09:55:02 +00:00
|
|
|
|
2024-11-23 19:28:26 +00:00
|
|
|
if (status != IVY_OK) {
|
2024-11-26 13:09:57 +00:00
|
|
|
b_err("parse error (%s)", ivy_status_to_string(status));
|
2024-11-23 19:28:26 +00:00
|
|
|
ivy_token_destroy(tok);
|
2025-04-14 12:25:49 +01:00
|
|
|
skip_line(repl->r_lex);
|
2024-11-23 19:28:26 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2024-11-24 16:12:49 +00:00
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
if (ivy_lexer_tokens_available(repl->r_lex)) {
|
2024-11-24 16:12:49 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-16 21:59:32 +01:00
|
|
|
struct ivy_ast_node *unit = ivy_parser_root_node(repl->r_parse);
|
2025-04-22 15:31:51 +01:00
|
|
|
struct mie_module *mod = NULL;
|
|
|
|
|
|
|
|
|
|
ivy_codegen_start_module(repl->r_codegen);
|
2025-04-16 21:59:32 +01:00
|
|
|
repl_eval_node(repl, unit);
|
2025-04-22 15:31:51 +01:00
|
|
|
ivy_codegen_end_module(repl->r_codegen, &mod);
|
|
|
|
|
|
|
|
|
|
mie_value_destroy(MIE_VALUE(mod));
|
2024-12-06 20:24:50 +00:00
|
|
|
|
2025-04-16 21:59:32 +01:00
|
|
|
#if 0
|
2025-04-14 12:25:49 +01:00
|
|
|
while ((child = ivy_parser_dequeue_node(repl->r_parse))) {
|
|
|
|
|
repl_eval_node(repl, child);
|
2025-04-14 09:46:36 +01:00
|
|
|
ivy_ast_node_destroy(child);
|
2024-12-06 20:24:50 +00:00
|
|
|
}
|
2025-04-16 21:59:32 +01:00
|
|
|
#endif
|
2024-11-18 09:55:02 +00:00
|
|
|
}
|
|
|
|
|
|
2025-04-14 12:25:49 +01:00
|
|
|
repl_destroy(repl);
|
2024-11-18 09:55:02 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
B_COMMAND(CMD_REPL, CMD_ROOT)
|
|
|
|
|
{
|
|
|
|
|
B_COMMAND_NAME("shell");
|
|
|
|
|
B_COMMAND_SHORT_NAME('S');
|
|
|
|
|
B_COMMAND_DESC("start an interactive Ivy shell.");
|
|
|
|
|
B_COMMAND_HELP_OPTION();
|
|
|
|
|
B_COMMAND_FUNCTION(repl);
|
2024-11-23 19:28:26 +00:00
|
|
|
|
2024-12-06 20:24:50 +00:00
|
|
|
B_COMMAND_OPTION(OPT_SHOW_LEX_TOKENS)
|
|
|
|
|
{
|
|
|
|
|
B_OPTION_LONG_NAME("show-lex");
|
|
|
|
|
B_OPTION_SHORT_NAME('l');
|
|
|
|
|
B_OPTION_DESC(
|
|
|
|
|
"print the lexical tokens generated from the input.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
B_COMMAND_OPTION(OPT_SHOW_AST_NODES)
|
2024-11-26 13:09:57 +00:00
|
|
|
{
|
2024-12-06 20:24:50 +00:00
|
|
|
B_OPTION_LONG_NAME("show-ast");
|
|
|
|
|
B_OPTION_SHORT_NAME('a');
|
2024-11-26 13:09:57 +00:00
|
|
|
B_OPTION_DESC(
|
2024-12-06 20:24:50 +00:00
|
|
|
"print the abstract syntax tree generated from the "
|
2024-11-26 13:09:57 +00:00
|
|
|
"input.");
|
2024-11-23 19:28:26 +00:00
|
|
|
}
|
2025-04-16 21:59:32 +01:00
|
|
|
|
|
|
|
|
B_COMMAND_OPTION(OPT_SHOW_IR)
|
|
|
|
|
{
|
|
|
|
|
B_OPTION_LONG_NAME("show-ir");
|
|
|
|
|
B_OPTION_SHORT_NAME('i');
|
|
|
|
|
B_OPTION_DESC("print the Mie IR generated from the input.");
|
|
|
|
|
}
|
2024-11-18 09:55:02 +00:00
|
|
|
}
|