From 916b5c28355b848b3df52087231e675535c67b44 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Tue, 21 Oct 2014 22:20:55 -0400 Subject: [PATCH] Reworked codegenerator to generate to file or standard output --- source/sclpl/codegen.c | 174 +++++++++++++++++++++-------------------- source/sclpl/main.c | 116 +++++++++++++++++++++++---- 2 files changed, 189 insertions(+), 101 deletions(-) diff --git a/source/sclpl/codegen.c b/source/sclpl/codegen.c index 14ac332..31d2865 100644 --- a/source/sclpl/codegen.c +++ b/source/sclpl/codegen.c @@ -79,185 +79,187 @@ static size_t get_fn_id(vec_t* funcs, tree_t* fn) { /*****************************************************************************/ -static void print_indent(int depth) { +static void print_indent(FILE* file, int depth) { for(int i = 0; i < (4 * depth); i++) - printf("%c", ' '); + fprintf(file, "%c", ' '); } -static void print_char(char ch) { +static void print_char(FILE* file, char ch) { switch (ch) { - case '\r': printf("__char('\\r')"); break; - case '\n': printf("__char('\\n')"); break; - case '\t': printf("__char('\\t')"); break; - case '\v': printf("__char('\\v')"); break; - default: printf("__char('%c')", ch); break; + case '\r': fprintf(file, "__char('\\r')"); break; + case '\n': fprintf(file, "__char('\\n')"); break; + case '\t': fprintf(file, "__char('\\t')"); break; + case '\v': fprintf(file, "__char('\\v')"); break; + default: fprintf(file, "__char('%c')", ch); break; } } -static void print_string(const char* str) { - printf("__string(\""); +static void print_string(FILE* file, const char* str) { + fprintf(file, "__string(\""); while('\0' != str[0]) { switch (str[0]) { - case '\r': printf("\\r"); break; - case '\n': printf("\\n"); break; - case '\t': printf("\\t"); break; - case '\v': printf("\\v"); break; - default: printf("%c", str[0]); break; + case '\r': fprintf(file, "\\r"); break; + case '\n': fprintf(file, "\\n"); break; + case '\t': fprintf(file, "\\t"); break; + case '\v': fprintf(file, "\\v"); break; + default: fprintf(file, "%c", str[0]); break; } str++; } - printf("\")"); + fprintf(file, "\")"); } /*****************************************************************************/ -static void emit_header(void) { - puts("#include \n"); +static void emit_header(FILE* file) { + fputs("#include \n\n", file); } -static void emit_fn_signature(char* name, tree_t* fnval) { - printf("_Value %s(", name); +static void emit_fn_signature(FILE* file, char* name, tree_t* fnval) { + fprintf(file, "_Value %s(", name); vec_t* params = get_child(fnval, 1)->ptr.vec; for (size_t i = 0; i < vec_size(params); i++) { - printf("_Value %s", (char*)get_val((tree_t*)vec_at(params,i))); + fprintf(file, "_Value %s", (char*)get_val((tree_t*)vec_at(params,i))); if (i+1 < vec_size(params)) - printf(", "); + fprintf(file, ", "); } - printf(")"); + fprintf(file, ")"); } -static void emit_def_placeholders(vec_t* prgrm) { +static void emit_def_placeholders(FILE* file, vec_t* prgrm) { for (size_t idx = 0; idx < vec_size(prgrm); idx++) { tree_t* p_tree = (tree_t*)vec_at(prgrm, idx); if (is_formtype(p_tree, "def")) { - printf("_Value %s;\n", (char*)get_child_val(p_tree,1)); + fprintf(file, "_Value %s;\n", (char*)get_child_val(p_tree,1)); } } - puts(""); + fputs("\n", file); } -static void emit_expression(vec_t* fnlst, tree_t* p_tree, int depth) { +static void emit_expression(FILE* file, vec_t* fnlst, tree_t* p_tree, int depth) { if (p_tree->tag == ATOM) { lex_tok_t* tok = p_tree->ptr.tok; switch (tok->type) { - case T_STRING: print_string(((char*)tok->value)); break; - case T_CHAR: print_char(((char)(int)tok->value)); break; - case T_INT: printf("__int(%ld)", *((long int*)tok->value)); break; - case T_FLOAT: printf("__float(%f)", *((double*)tok->value)); break; - case T_BOOL: printf("__bool(%s)", ((int)tok->value)?"true":"false"); break; - case T_VAR: printf("%s", ((char*)tok->value)); break; - default: break; + case T_STRING: print_string(file, ((char*)tok->value)); break; + case T_CHAR: print_char(file, ((char)(int)tok->value)); break; + case T_INT: fprintf(file, "__int(%ld)", *((long int*)tok->value)); break; + case T_FLOAT: fprintf(file, "__float(%f)", *((double*)tok->value)); break; + case T_BOOL: fprintf(file, "__bool(%s)", ((int)tok->value)?"true":"false"); break; + case T_VAR: fprintf(file, "%s", ((char*)tok->value)); break; + default: break; } } else if (is_formtype(p_tree, "if")) { - printf("IF ("); - emit_expression(fnlst, get_child(p_tree, 1), depth); - printf(")\n"); - print_indent(depth+1); - emit_expression(fnlst, get_child(p_tree, 2), depth+1); - printf("\n"); - print_indent(depth); - printf("ELSE\n"); - print_indent(depth+1); + fprintf(file, "IF ("); + emit_expression(file, fnlst, get_child(p_tree, 1), depth); + fprintf(file, ")\n"); + print_indent(file, depth+1); + emit_expression(file, fnlst, get_child(p_tree, 2), depth+1); + fprintf(file, "\n"); + print_indent(file, depth); + fprintf(file, "ELSE\n"); + print_indent(file, depth+1); if (vec_size(p_tree->ptr.vec) > 3) { - emit_expression(fnlst, get_child(p_tree, 4), depth+1); + emit_expression(file, fnlst, get_child(p_tree, 4), depth+1); } else { - printf("NIL"); + fprintf(file, "__nil"); } } else if (is_formtype(p_tree, "fn")) { - printf("__func(&fn%d)", (int)get_fn_id(fnlst, p_tree)); + fprintf(file, "__func(&fn%d)", (int)get_fn_id(fnlst, p_tree)); } else { vec_t* vec = p_tree->ptr.vec; int nargs = vec_size(vec)-1; /* Determine the calling convention based on number of args */ if (0 == nargs) - printf("__call0(%s", (char*)get_val(vec_at(vec,0))); + fprintf(file, "__call0(%s", (char*)get_val(vec_at(vec,0))); else if (nargs < 16) - printf("__calln(%s, %d, ", (char*)get_val(vec_at(vec,0)), (int)nargs); + fprintf(file, "__calln(%s, %d, ", (char*)get_val(vec_at(vec,0)), (int)nargs); else - printf("__calln(%s, n, ", (char*)get_val(vec_at(vec,0))); + fprintf(file, "__calln(%s, n, ", (char*)get_val(vec_at(vec,0))); /* Print out the arguments */ for (size_t idx = 1; idx < vec_size(vec); idx++) { - emit_expression(fnlst, (tree_t*)vec_at(vec,idx), depth); + emit_expression(file, fnlst, (tree_t*)vec_at(vec,idx), depth); if (idx+1 < vec_size(vec)) - printf(", "); + fprintf(file, ", "); } - printf(")"); + fprintf(file, ")"); } } -static void emit_fn_declarations(vec_t* fnlst) { +static void emit_fn_declarations(FILE* file, vec_t* fnlst) { char name[64]; for (size_t idx = 0; idx < vec_size(fnlst); idx++) { sprintf(name,"fn%d", (int)idx); - printf("static "); - emit_fn_signature(name, (tree_t*)vec_at(fnlst,idx)); - puts(";"); + fprintf(file, "static "); + emit_fn_signature(file, name, (tree_t*)vec_at(fnlst,idx)); + fputs(";\n", file); } - puts(""); + fputs("\n", file); } -static void emit_fn_definitions(vec_t* fnlst) { +static void emit_fn_definitions(FILE* file, vec_t* fnlst) { char name[64]; for (size_t idx = 0; idx < vec_size(fnlst); idx++) { tree_t* func = (tree_t*)vec_at(fnlst,idx); sprintf(name,"fn%d", (int)idx); - printf("static "); - emit_fn_signature(name, func); - puts(" {"); + fprintf(file, "static "); + emit_fn_signature(file, name, func); + fputs(" {\n", file); vec_t* body = (vec_t*)func->ptr.vec; for (size_t i = 2; i < vec_size(body); i++) { - printf(" "); + fprintf(file, " "); if (i+1 == vec_size(body)) - printf("return "); - emit_expression(fnlst, (tree_t*)vec_at(body,i), 1); - printf(";\n"); + fprintf(file, "return "); + emit_expression(file, fnlst, (tree_t*)vec_at(body,i), 1); + fprintf(file, ";\n"); } - puts("}\n"); + fputs("}\n", file); } + fputs("\n", file); } -static void emit_toplevel(vec_t* fnlst, vec_t* prgrm) { - puts("void toplevel(void) {"); +static void emit_toplevel(FILE* file, vec_t* fnlst, vec_t* prgrm) { + fputs("void toplevel(void) {\n", file); for (size_t idx = 0; idx < vec_size(prgrm); idx++) { tree_t* p_tree = (tree_t*)vec_at(prgrm, idx); if (is_formtype(p_tree, "require")) { - printf(" extern void %s_toplevel(void);\n", (char*)get_child_val(p_tree,1)); - printf(" %s_toplevel();\n", (char*)get_child_val(p_tree,1)); + fprintf(file, " extern void %s_toplevel(void);\n", (char*)get_child_val(p_tree,1)); + fprintf(file, " %s_toplevel();\n", (char*)get_child_val(p_tree,1)); } else if (is_formtype(p_tree, "def")) { - printf(" %s = ", (char*)get_child_val(p_tree,1)); - emit_expression(fnlst, get_child(p_tree, 2), 0); - printf(";\n"); + fprintf(file, " %s = ", (char*)get_child_val(p_tree,1)); + emit_expression(file, fnlst, get_child(p_tree, 2), 0); + fprintf(file, ";\n"); } else { - printf(" (void)("); - emit_expression(fnlst, p_tree, 1); - printf(");\n"); + fprintf(file, " (void)("); + emit_expression(file, fnlst, p_tree, 1); + fprintf(file, ");\n"); } } - puts("}"); + fputs("}\n", file); } -static void emit_footer(void) { - puts( +static void emit_footer(FILE* file) { + fputs( "\nint main(int argc, char** argv) {" "\n (void)argc;" "\n (void)argv;" "\n toplevel();" "\n return 0;" - "\n}" + "\n}\n", + file ); } void codegen_csource(FILE* file, vec_t* program) { (void)file; - emit_header(); - emit_def_placeholders(program); + emit_header(file); + emit_def_placeholders(file, program); vec_t* funcs = find_fn_literals(program); - emit_fn_declarations(funcs); - emit_fn_definitions(funcs); - emit_toplevel(funcs, program); + emit_fn_declarations(file, funcs); + emit_fn_definitions(file, funcs); + emit_toplevel(file, funcs, program); mem_release(funcs); - emit_footer(); + emit_footer(file); } diff --git a/source/sclpl/main.c b/source/sclpl/main.c index 6ebb8f5..0b92afa 100644 --- a/source/sclpl/main.c +++ b/source/sclpl/main.c @@ -2,6 +2,8 @@ #include #include #include "opts.h" +#include "str.h" +#include "list.h" #include "grammar.h" #include "parser.h" #include "lexer.h" @@ -99,6 +101,92 @@ tree_t* convert_to_ast(tree_t* p_tree) { return p_newtree; } +/* Options Helpers + *****************************************************************************/ +bool file_exists(const char* name) { + bool ret = false; + FILE* file = fopen(name,"r"); + if (NULL != file) { + fclose(file); + ret = true; + } + return ret; +} + +list_t* input_files(void) { + list_t* infiles = list_new(); + const char** files = opts_arguments(); + while (NULL != files[0]) { + if (!file_exists(files[0])) { + mem_release(infiles); + fprintf(stderr, "Error: no such file or directory: %s\n", files[0]); + exit(1); + } + list_push_front(infiles, str_new(files[0])); + files++; + } + mem_release(list_pop_front(infiles)); + return infiles; +} + +/* Utility Functions + *****************************************************************************/ +typedef enum { + CSOURCE, + OBJECT, + PROGRAM, + STATICLIB, + SHAREDLIB +} file_type_t; + +str_t* get_filename(file_type_t ftype, str_t* infile) { + str_t* ext_ind = str_new("."); + size_t index = str_rfind(infile, ext_ind); + str_t* rawname = str_substr(infile, 0, str_size(infile)-index); + str_t* ext; + switch (ftype) { + case CSOURCE: ext = str_new(".c"); break; + case OBJECT: ext = str_new(".o"); break; + case PROGRAM: ext = str_new(""); break; + case STATICLIB: ext = str_new(".a"); break; + case SHAREDLIB: ext = str_new(".lib"); break; + } + str_t* fname = str_concat(rawname, ext); + mem_release(ext_ind); + mem_release(rawname); + mem_release(ext); + return fname; +} + +int translate(str_t* in, str_t* out) { + int ret = 0; + FILE* input = (NULL == in) ? stdin : fopen(str_cstr(in), "r"); + FILE* output = (NULL == out) ? stdout : fopen(str_cstr(out), "w"); + + parser_t* p_parser = parser_new(NULL, input); + vec_t* p_vec = vec_new(0); + while(!parser_eof(p_parser)) { + tree_t* p_tree = grammar_toplevel(p_parser); + if (NULL != p_tree) { + tree_t* p_ast = convert_to_ast(p_tree); + mem_release(p_tree); + vec_push_back(p_vec, p_ast); + } else { + parser_resume(p_parser); + ret = 1; + } + } + if (0 == ret) + codegen_csource(output, p_vec); + mem_release(p_vec); + mem_release(p_parser); + + fclose(input); + fclose(output); + mem_release(out); + return ret; +} + /* Driver Modes *****************************************************************************/ static int emit_tokens(void) { @@ -133,23 +221,19 @@ static int emit_tree(void) { static int emit_csource(void) { int ret = 0; - parser_t* p_parser = parser_new(NULL, stdin); - vec_t* p_vec = vec_new(0); - while(!parser_eof(p_parser)) { - tree_t* p_tree = grammar_toplevel(p_parser); - if (NULL != p_tree) { - tree_t* p_ast = convert_to_ast(p_tree); - mem_release(p_tree); - vec_push_back(p_vec, p_ast); - } else { - parser_resume(p_parser); - ret = 1; + list_t* files = input_files(); + size_t size = list_size(files); + if (0 == size) { + translate(NULL, NULL); + } else { + list_node_t* node = NULL; + while (NULL != (node = list_pop_front(files))) { + str_t* fname = (str_t*)node->contents; + ret = translate(fname, get_filename(CSOURCE, fname)); + mem_release(node); } } - if (0 == ret) - codegen_csource(stdout, p_vec); - mem_release(p_vec); - mem_release(p_parser); + mem_release(files); return ret; } @@ -194,6 +278,8 @@ static int emit_program(void) { int main(int argc, char **argv) { opts_parse( Options_Config, argc, argv ); + mem_release(input_files()); + if (!opts_is_set(NULL,"mode")) { print_usage(); } else if(opts_equal(NULL, "mode", "repl")) { -- 2.52.0