jaf: support multiple input files

This commit is contained in:
Nunuhara Cabbage
2020-06-21 16:50:04 -07:00
parent d4f1b5ba46
commit b41275f6f4
8 changed files with 139 additions and 65 deletions
+1
View File
@@ -334,6 +334,7 @@ int ain_get_global_no(struct ain *ain, char *name);
void ain_add_initval(struct ain *ain, struct ain_initval *init);
int ain_add_function(struct ain *ain, struct ain_function *fun);
int ain_add_string(struct ain *ain, const char *str);
int ain_add_file(struct ain *ain, const char *filename);
void ain_free(struct ain *ain);
void ain_free_functions(struct ain *ain);
+7
View File
@@ -293,6 +293,13 @@ int ain_add_string(struct ain *ain, const char *str)
return i;
}
int ain_add_file(struct ain *ain, const char *filename)
{
ain->filenames = xrealloc_array(ain->filenames, ain->nr_filenames, ain->nr_filenames+1, sizeof(char*));
ain->filenames[ain->nr_filenames++] = strdup(filename);
return ain->nr_filenames - 1;
}
static const char *errtab[AIN_MAX_ERROR] = {
[AIN_SUCCESS] = "Success",
[AIN_FILE_ERROR] = "Error opening AIN file",
+7 -4
View File
@@ -91,7 +91,8 @@ int main(int argc, char *argv[])
struct ain *ain;
int err = AIN_SUCCESS;
const char *code_file = NULL;
const char *jaf_file = NULL;
unsigned nr_jaf_files = 0;
const char **jaf_files = NULL;
const char *decl_file = NULL;
const char *text_file = NULL;
const char *output_file = NULL;
@@ -133,7 +134,8 @@ int main(int argc, char *argv[])
code_file = optarg;
break;
case LOPT_JAF:
jaf_file = optarg;
jaf_files = xrealloc_array(jaf_files, nr_jaf_files, nr_jaf_files+1, sizeof(char*));
jaf_files[nr_jaf_files++] = optarg;
break;
case 'j':
case LOPT_JSON:
@@ -214,8 +216,8 @@ int main(int argc, char *argv[])
read_declarations(decl_file, ain);
}
if (jaf_file) {
jaf_compile(ain, jaf_file);
if (jaf_files) {
jaf_build(ain, jaf_files, nr_jaf_files);
}
if (code_file) {
@@ -230,6 +232,7 @@ write_ain_file:
NOTICE("Writing AIN file...");
ain_write(output_file, ain);
free(jaf_files);
ain_free(ain);
return 0;
}
+9 -3
View File
@@ -194,7 +194,8 @@ enum block_item_kind {
JAF_STMT_BREAK,
JAF_STMT_RETURN,
JAF_STMT_CASE,
JAF_STMT_DEFAULT
JAF_STMT_DEFAULT,
JAF_EOF
};
struct jaf_declaration {
@@ -251,6 +252,7 @@ struct jaf_block_item {
struct jaf_block_item *body;
} for_loop;
struct string *target; // goto
unsigned file_no; // eof
};
};
@@ -301,6 +303,7 @@ struct jaf_block *jaf_type_declaration(struct jaf_type_specifier *type);
struct jaf_block *jaf_merge_blocks(struct jaf_block *head, struct jaf_block *tail);
struct jaf_block *jaf_block(struct jaf_block_item *item);
struct jaf_block *jaf_block_append(struct jaf_block *head, struct jaf_block_item *tail);
struct jaf_block_item *jaf_compound_statement(struct jaf_block *block);
struct jaf_block_item *jaf_label_statement(struct string *label, struct jaf_block_item *stmt);
struct jaf_block_item *jaf_case_statement(struct jaf_expression *expr, struct jaf_block_item *stmt);
@@ -318,10 +321,13 @@ struct jaf_block_item *jaf_return(struct jaf_expression *expr);
void jaf_free_expr(struct jaf_expression *expr);
void jaf_free_block(struct jaf_block *block);
// jaf_compile.c
// jaf_parser.y
struct ain *jaf_ain_out;
struct jaf_block *jaf_toplevel;
void jaf_compile(struct ain *out, const char *path);
struct jaf_block *jaf_parse(struct ain *ain, const char **files, unsigned nr_files);
// jaf_compile.c
void jaf_build(struct ain *out, const char **files, unsigned nr_files);
void jaf_define_struct(struct ain *ain, struct jaf_type_specifier *type);
// jaf_eval.c
+8
View File
@@ -281,6 +281,13 @@ struct jaf_block *jaf_merge_blocks(struct jaf_block *head, struct jaf_block *tai
return head;
}
struct jaf_block *jaf_block_append(struct jaf_block *head, struct jaf_block_item *tail)
{
head->items = xrealloc_array(head->items, head->nr_items, head->nr_items+1, sizeof(struct jaf_block_item*));
head->items[head->nr_items++] = tail;
return head;
}
struct jaf_block *jaf_block(struct jaf_block_item *item)
{
struct jaf_block *block = xcalloc(1, sizeof(struct jaf_block));
@@ -504,6 +511,7 @@ void jaf_free_block_item(struct jaf_block_item *item)
free_string(item->target);
case JAF_STMT_CONTINUE:
case JAF_STMT_BREAK:
case JAF_EOF:
break;
case JAF_STMT_RETURN:
jaf_free_expr(item->expr);
+31 -56
View File
@@ -29,12 +29,6 @@
#include "jaf.h"
#include "jaf_parser.tab.h"
FILE *yyin;
int yyparse(void);
struct ain *jaf_ain_out;
struct jaf_block *jaf_toplevel;
/*
* NOTE: We need to pass some state between calls to handle
* break/continue.
@@ -53,18 +47,6 @@ struct compiler_state {
struct loop_state *loops;
};
int sym_type(char *name)
{
char *u = encode_text_to_input_format(name);
struct ain_struct *s = ain_get_struct(jaf_ain_out, u);
free(u);
if (s) {
return TYPEDEF_NAME;
}
return IDENTIFIER;
}
static void start_loop(struct compiler_state *state)
{
state->loops = xrealloc_array(state->loops, state->nr_loops, state->nr_loops+1, sizeof(struct loop_state));
@@ -805,6 +787,9 @@ static void compile_statement(struct compiler_state *state, struct jaf_block_ite
case JAF_STMT_DEFAULT:
ERROR("switch not supported");
break;
case JAF_EOF:
write_instruction1(state, _EOF, item->file_no);
break;
}
}
@@ -819,8 +804,8 @@ static void compile_function(struct compiler_state *state, struct jaf_declaratio
{
assert(decl->func_no >= 0 && decl->func_no < state->ain->nr_functions);
state->func_no = decl->func_no;
state->ain->functions[decl->func_no].address = state->out.index + 6;
write_instruction1(state, FUNC, decl->func_no);
state->ain->functions[decl->func_no].address = state->out.index;
compile_block(state, decl->body);
compile_nullexpr(state, state->ain->functions[state->func_no].return_type.data);
write_instruction0(state, RETURN);
@@ -833,6 +818,9 @@ static void compile_declaration(struct compiler_state *state, struct jaf_block_i
compile_function(state, &decl->decl);
return;
}
if (decl->kind == JAF_EOF) {
compile_statement(state, decl);
}
// TODO: global constructors/array allocations
}
@@ -858,58 +846,45 @@ static void compile_global_init_function(struct compiler_state *state)
write_instruction1(state, ENDFUNC, func_no);
}
void jaf_compile(struct ain *out, const char *path)
static void jaf_compile(struct ain *ain, struct jaf_block *toplevel)
{
out->keycode = 0x2d1f2904;
if (path) {
if (!strcmp(path, "-"))
yyin = stdin;
else
yyin = fopen(path, "rb");
if (!yyin)
ERROR("Opening input file '%s': %s", path, strerror(errno));
}
jaf_ain_out = out;
yyparse();
if (!jaf_toplevel)
ERROR("Failed to parse .jaf file");
jaf_toplevel = jaf_static_analyze(out, jaf_toplevel);
assert(toplevel->nr_items > 0);
struct compiler_state state = {
.ain = out,
.ain = ain,
.out = {
.buf = out->code,
.size = out->code_size,
.index = out->code_size
.buf = ain->code,
.size = ain->code_size,
.index = ain->code_size
}
};
for (size_t i = 0; i < jaf_toplevel->nr_items; i++) {
compile_declaration(&state, jaf_toplevel->items[i]);
for (size_t i = 0; i < toplevel->nr_items - 1; i++) {
compile_declaration(&state, toplevel->items[i]);
}
compile_global_init_function(&state);
state.ain->functions[0].address = state.out.index + 6;
// add NULL function
write_instruction1(&state, FUNC, 0);
write_instruction1(&state, _EOF, out->nr_filenames);
state.ain->functions[0].address = state.out.index;
// add filename to ain file
char *filename = strdup(path);
out->filenames = xrealloc_array(out->filenames, out->nr_filenames, out->nr_filenames+1, sizeof(char*));
out->filenames[out->nr_filenames++] = strdup(basename(filename));
free(filename);
// add final EOF
compile_declaration(&state, toplevel->items[toplevel->nr_items-1]);
free(state.loops);
out->code = state.out.buf;
out->code_size = state.out.index;
ain->code = state.out.buf;
ain->code_size = state.out.index;
// XXX: ain_add_initval adds initval to GSET section of the ain file.
// If the original ain file did not have a GSET section, init
// code needs to be added to the "0" function instead.
if (out->nr_initvals && !out->GSET.present) {
WARNING("%d global initvals ignored", out->nr_initvals);
}
if (ain->nr_initvals && !ain->GSET.present)
WARNING("%d global initvals ignored", ain->nr_initvals);
}
jaf_free_block(jaf_toplevel);
void jaf_build(struct ain *out, const char **files, unsigned nr_files)
{
struct jaf_block *toplevel;
toplevel = jaf_parse(out, files, nr_files);
toplevel = jaf_static_analyze(out, toplevel);
jaf_compile(out, toplevel);
jaf_free_block(toplevel);
}
+72 -1
View File
@@ -17,11 +17,82 @@
*/
%{
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <libgen.h>
#include <assert.h>
#include "system4.h"
#include "system4/ain.h"
#include "ainedit.h"
#include "jaf.h"
#include "jaf_parser.tab.h"
extern int yylex();
void yyerror(const char *s);
int yyparse(void);
FILE *yyin;
struct ain *jaf_ain_out;
struct jaf_block *jaf_toplevel;
static FILE *open_jaf_file(const char *file)
{
if (!strcmp(file, "-"))
return stdin;
FILE *f = fopen(file, "rb");
if (!f)
ERROR("Opening input file '%s': %s", file, strerror(errno));
return f;
}
static struct jaf_block *insert_eof(struct ain *ain, struct jaf_block *block, const char *_filename)
{
assert(block);
char *filename = xstrdup(_filename);
int file_no = ain_add_file(ain, basename(filename));
free(filename);
struct jaf_block_item *eof = xmalloc(sizeof(struct jaf_block_item));
eof->kind = JAF_EOF;
eof->file_no = file_no;
return jaf_block_append(block, eof);
}
struct jaf_block *jaf_parse(struct ain *ain, const char **files, unsigned nr_files)
{
jaf_ain_out = ain;
jaf_toplevel = NULL;
for (unsigned i = 0; i < nr_files; i++) {
// open file
yyin = open_jaf_file(files[i]);
if (yyparse())
ERROR("Failed to parse .jaf file");
if (yyin != stdin)
fclose(yyin);
jaf_toplevel = insert_eof(ain, jaf_toplevel, files[i]);
}
struct jaf_block *r = jaf_toplevel;
jaf_toplevel = NULL;
jaf_ain_out = NULL;
return r;
}
int sym_type(char *name)
{
char *u = encode_text_to_input_format(name);
struct ain_struct *s = ain_get_struct(jaf_ain_out, u);
free(u);
if (s) {
return TYPEDEF_NAME;
}
return IDENTIFIER;
}
%}
%union {
@@ -421,7 +492,7 @@ jump_statement
;
toplevel
: translation_unit { jaf_toplevel = $1; }
: translation_unit { jaf_toplevel = jaf_merge_blocks(jaf_toplevel, $1); }
;
translation_unit
+4 -1
View File
@@ -261,6 +261,7 @@ static void analyze_statement(struct jaf_env *env, struct jaf_block_item *item)
case JAF_STMT_GOTO:
case JAF_STMT_CONTINUE:
case JAF_STMT_BREAK:
case JAF_EOF:
break;
}
}
@@ -347,6 +348,7 @@ static void resolve_statement_types(struct ain *ain, struct jaf_block_item *item
case JAF_STMT_CONTINUE:
case JAF_STMT_BREAK:
case JAF_STMT_RETURN:
case JAF_EOF:
break;
}
}
@@ -429,6 +431,7 @@ static struct ain_variable *block_item_get_vars(struct ain *ain, struct jaf_bloc
case JAF_STMT_CONTINUE:
case JAF_STMT_BREAK:
case JAF_STMT_RETURN:
case JAF_EOF:
break;
case JAF_FUNDECL:
@@ -492,7 +495,7 @@ static void jaf_process_declarations(struct ain *ain, struct jaf_block *block)
if (block->items[i]->decl.name) {
if (block->items[i]->kind == JAF_FUNDECL)
add_function(ain, &block->items[i]->decl);
else
else if (block->items[i]->kind == JAF_DECLARATION)
add_global(ain, &block->items[i]->decl);
}
}