frontend: assemble: convert input file to output assembly

This commit is contained in:
2024-12-13 12:26:32 +00:00
parent 5fe1a21978
commit 3bb94aa36e

View File

@@ -3,9 +3,11 @@
#include <blue/cmd.h>
#include <blue/term.h>
#include <blue/object/string.h>
#include <errno.h>
#include <ivy/file.h>
#include <ivy/asm/lex.h>
#include <ivy/asm/parse.h>
#include <ivy/asm/assembler.h>
#include <stdio.h>
@@ -15,26 +17,63 @@ enum {
ARG_OUT_FILE,
};
#if 0
static int assemble_file(const char *path)
static int assemble_file(const char *in_path, const char *out_path)
{
FILE *fp = fopen(path, "r");
if (!fp) {
b_err("cannot open source file '%s'", path);
FILE *in = fopen(in_path, "r");
if (!in) {
b_err("cannot open source file '%s'", in_path);
b_i("reason: %s", strerror(errno));
return -1;
}
struct ivy_file *src = ivy_file_from_fp(fp);
FILE *out = fopen(out_path, "wb");
if (!out) {
b_err("cannot open output file '%s'", out_path);
b_i("reason: %s", strerror(errno));
return -1;
}
struct ivy_assembler *as = NULL;
enum ivy_status status = ivy_assembler_create(out, &as);
if (status != IVY_OK) {
b_err("failed to initialise Ivy assembler");
b_i("reason: %s", ivy_status_to_string(status));
fclose(in);
fclose(out);
return -1;
}
struct ivy_file *src = ivy_file_from_fp(in);
struct ivy_asm_lexer *lex;
if (ivy_asm_lexer_create(&lex) != IVY_OK) {
status = ivy_asm_lexer_create(&lex);
if (status != IVY_OK) {
b_err("failed to initialise Ivy assembly lexer");
b_i("reason: %s", ivy_status_to_string(status));
ivy_file_close(src);
fclose(out);
ivy_assembler_finish(as);
return -1;
}
struct ivy_asm_parser *parser;
status = ivy_asm_parser_create(&parser);
if (status != IVY_OK) {
b_err("failed to initialise Ivy assembly parser");
b_i("reason: %s", ivy_status_to_string(status));
ivy_asm_lexer_destroy(lex);
ivy_file_close(src);
fclose(out);
ivy_assembler_finish(as);
return -1;
}
ivy_asm_lexer_set_source(lex, &src->f_base);
enum ivy_status status = IVY_OK;
ivy_asm_parser_set_assembler(parser, as);
while (true) {
struct ivy_asm_token *tok = ivy_asm_lexer_read(lex);
@@ -44,41 +83,109 @@ static int assemble_file(const char *path)
}
if (status != IVY_OK) {
b_err("failed to parse '%s'", path);
b_err("failed to parse '%s'", in_path);
b_i("reason: lex error (%s)",
ivy_status_to_string(ivy_asm_lexer_get_status(lex)));
break;
}
print_asm_lex_token(tok);
status = ivy_asm_parser_push_token(parser, tok);
if (status != IVY_OK) {
b_err("failed to parse '%s'", in_path);
b_i("reason: parse error (%s)",
ivy_status_to_string(status));
break;
}
}
int r = (status == IVY_OK || status == IVY_ERR_EOF) ? 0 : -1;
ivy_asm_parser_destroy(parser);
ivy_assembler_finish(as);
ivy_file_close(src);
fclose(out);
ivy_asm_lexer_destroy(lex);
return r;
}
#endif
static int assemble(const b_command *cmd, const b_arglist *args, const b_array *_)
static b_string *get_source_filename(const char *src_path)
{
#if 0
b_arglist_iterator it;
b_arglist_foreach_filtered(&it, args, B_COMMAND_INVALID_ID, ARG_SOURCE_FILE)
{
b_arglist_value *path = it.value;
if (path->val_type != B_COMMAND_ARG_STRING) {
b_string *name = b_string_create();
for (unsigned int i = 0; src_path[i]; i++) {
if (src_path[i] == '/' || src_path[i] == '\\') {
b_string_clear(name);
continue;
}
printf("%s\n", path->val_str);
int r = assemble_file(path->val_str);
if (r != 0) {
return r;
}
char s[] = { src_path[i], 0 };
b_string_append_cstr(name, s);
}
#endif
if (b_string_get_size(name, B_STRLEN_NORMAL) == 0) {
b_string_release(name);
name = NULL;
}
return name;
}
static b_string *generate_object_filename(const char *src_filename)
{
b_string *name = b_string_create();
for (unsigned int i = 0; src_filename[i]; i++) {
if (src_filename[i] == '.') {
break;
}
char s[] = { src_filename[i], 0 };
b_string_append_cstr(name, s);
}
if (b_string_get_size(name, B_STRLEN_NORMAL) == 0) {
b_string_append_cstr(name, "out");
}
b_string_append_cstr(name, ".io");
return name;
}
static int assemble(const b_command *cmd, const b_arglist *args, const b_array *_)
{
const char *in_path = NULL;
const char *out_path = NULL;
b_string *in_name = NULL;
b_string *out_name = NULL;
b_arglist_get_string(args, B_COMMAND_INVALID_ID, ARG_SOURCE_FILE, 0, &in_path);
if (!in_path) {
b_err("no source file specified.");
return -1;
}
in_name = get_source_filename(in_path);
if (!in_path) {
b_err("source filepath is not a file.");
return -1;
}
b_arglist_get_string(args, OPT_OUT_FILE, ARG_OUT_FILE, 0, &out_path);
if (!out_path) {
out_name = generate_object_filename(b_string_ptr(in_name));
out_path = b_string_ptr(out_name);
}
int r = assemble_file(in_path, out_path);
b_string_release(in_name);
b_string_release(out_name);
return r;
#if 0
const char *path = NULL;
b_arglist_get_string(args, OPT_OUT_FILE, ARG_OUT_FILE, 0, &path);
@@ -98,6 +205,10 @@ static int assemble(const b_command *cmd, const b_arglist *args, const b_array *
return -1;
}
ivy_assembler_begin_scope(as, IVY_ASM_SCOPE_CONSTPOOL, NULL);
ivy_assembler_put_pval(as, IVY_ASM_PVAL_STRING, 0, "Hello, world!");
ivy_assembler_end_scope(as);
ivy_assembler_attrib_table attrib = {
[IVY_ASM_ATTRIB_IDENT] = 32,
};
@@ -111,7 +222,7 @@ static int assemble(const b_command *cmd, const b_arglist *args, const b_array *
ivy_assembler_finish(as);
fclose(out);
#endif
return 0;
}
@@ -127,8 +238,8 @@ B_COMMAND(CMD_ASSEMBLE, CMD_ROOT)
B_COMMAND_ARG(ARG_SOURCE_FILE)
{
B_ARG_NAME("source file");
B_ARG_DESC("the .iasm assembly files to compile.");
B_ARG_NR_VALUES(B_ARG_1_OR_MORE_VALUES);
B_ARG_DESC("the .iasm assembly file to compile.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_OPTION(OPT_OUT_FILE)