diff --git a/src/api/cst-dump.c b/src/api/cst-dump.c index 39f18c0..82dc098 100644 --- a/src/api/cst-dump.c +++ b/src/api/cst-dump.c @@ -121,6 +121,7 @@ static void yf_dump_vardecl(struct yfcs_vardecl * node, FILE * out) { static void yf_dump_funcdecl(struct yfcs_funcdecl * node, FILE * out) { yf_print_line(out, "funcdecl"); indent(); + yf_print_line(out, "name: %s", node->name.name); if (node->extc) yf_print_line(out, "[extc]"); yf_print_line(out, "params"); diff --git a/src/api/sym.h b/src/api/sym.h index 325060b..7807308 100644 --- a/src/api/sym.h +++ b/src/api/sym.h @@ -67,7 +67,7 @@ struct yfsn_param { struct yfs_fn { char * name; - struct yfs_type * rtype; /* "return type" */ + struct yfs_type rtype; /* "return type" */ struct yf_list params; /* list of param */ }; diff --git a/src/driver/compile.c b/src/driver/compile.c index 9400869..61ac2dc 100644 --- a/src/driver/compile.c +++ b/src/driver/compile.c @@ -421,7 +421,7 @@ static int yfc_validate_compile( if (yf_ensure_entry_point(pdata)) { return 1; } - retval = yf_backend_generate_code(adata); + retval = yf_backend_generate_code(pdata, adata); } return retval; diff --git a/src/driver/compiler-backend.c b/src/driver/compiler-backend.c index 0948e35..a348ea0 100644 --- a/src/driver/compiler-backend.c +++ b/src/driver/compiler-backend.c @@ -116,8 +116,9 @@ static int create_output_file_name( * Generate C code */ static int yf_gen_c( + struct yf_compilation_data * data, struct yf_compile_analyse_job * fdata, struct yf_gen_info * info) { - return yfg_gen(fdata, info); + return yfg_gen(data, fdata, info); } /** @@ -289,14 +290,14 @@ int yf_ensure_entry_point( } if (total_entries != 1) - YF_PRINT_ERROR("total 'main' functions found: %d\n", total_entries); + YF_PRINT_ERROR("total 'main' functions found: %d", total_entries); return total_entries != 1; } int yf_backend_generate_code( - struct yf_compile_analyse_job * data + struct yf_compilation_data * cdata, struct yf_compile_analyse_job * data ) { struct yf_gen_info ginfo = { .yf_prefix = data->unit_info->file_prefix, @@ -305,5 +306,5 @@ int yf_backend_generate_code( create_formatted_prefix( ginfo.yf_prefix, ginfo.gen_prefix, 256 ); - return yf_gen_c(data, &ginfo); + return yf_gen_c(cdata, data, &ginfo); } diff --git a/src/driver/compiler-backend.h b/src/driver/compiler-backend.h index fab7ece..e6daf7b 100644 --- a/src/driver/compiler-backend.h +++ b/src/driver/compiler-backend.h @@ -34,7 +34,7 @@ int yf_backend_add_link_job( ); int yf_backend_generate_code( - struct yf_compile_analyse_job * + struct yf_compilation_data*, struct yf_compile_analyse_job * ); /** diff --git a/src/gen/gen.c b/src/gen/gen.c index 89677d3..fc5a003 100644 --- a/src/gen/gen.c +++ b/src/gen/gen.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -102,7 +103,7 @@ static void yf_gen_funcdecl( struct yf_ast_node * child; int argct = 0; char typebuf[256]; - yfg_ctype(256, typebuf, node->name->fn.rtype); + yfg_ctype(256, typebuf, &node->name->fn.rtype); /* Hacky fix -- but it should work. */ /* We need to check if the function is called "main" because the C compiler @@ -119,12 +120,17 @@ static void yf_gen_funcdecl( fprintf( out, "%s /* %s */ %s$$%s", typebuf, - node->name->fn.rtype->name, + node->name->fn.rtype.name, i->gen_prefix, node->name->fn.name ); } } else { + if (node->extc) { + YF_PRINT_ERROR("'main' function may not be declared extc"); + /* TODO check this in semantic analysis */ + /* return 1; */ + } fprintf(out, "int main"); } @@ -261,7 +267,10 @@ static int create_all_parent_dirs(char * path) { return 0; } -int yfg_gen(struct yf_compile_analyse_job * data, struct yf_gen_info * info) { +int yfg_gen( + struct yf_compilation_data * cdata, + struct yf_compile_analyse_job * data, struct yf_gen_info * info +) { create_all_parent_dirs(data->unit_info->output_file); @@ -275,6 +284,8 @@ int yfg_gen(struct yf_compile_analyse_job * data, struct yf_gen_info * info) { fprintf(out, "/* Generated by yfc. */\n\n"); fprintf(out, "#include \n\n"); + yfg_output_syms(cdata, data, out); + yf_gen_node(&data->ast_tree, out, info); fclose(out); diff --git a/src/gen/gen.h b/src/gen/gen.h index fb837c6..8f4f021 100644 --- a/src/gen/gen.h +++ b/src/gen/gen.h @@ -8,6 +8,9 @@ #include #include -int yfg_gen(struct yf_compile_analyse_job * data, struct yf_gen_info * info); +int yfg_gen( + struct yf_compilation_data * cdata, + struct yf_compile_analyse_job * data, struct yf_gen_info * info +); #endif /* GEN_GEN_H */ diff --git a/src/gen/symgen.c b/src/gen/symgen.c new file mode 100644 index 0000000..3b5735d --- /dev/null +++ b/src/gen/symgen.c @@ -0,0 +1,43 @@ +#include "symgen.h" + +#include + +static int dump_symbol( + FILE * out, + struct yf_sym * sym +) { + /* TODO */ + return 0; +} + +int yfg_output_syms( + struct yf_compilation_data * cdata, + struct yf_compile_analyse_job * data, + FILE * out +) { + + struct yfh_cursor cursor; + struct yfs_symtab * fsymtab; + + /* We iterate through all symtabs and dump all decls into the file */ + for (yfh_cursor_init(&cursor, &cdata->symtables); !yfh_cursor_next(&cursor); ) { + + yfh_cursor_get(&cursor, NULL, (void **)&fsymtab); + + struct yfh_cursor inner_cursor; + struct yf_sym * sym; + int fail; + + for (yfh_cursor_init(&inner_cursor, &fsymtab->table); !yfh_cursor_next(&cursor); ) { + yfh_cursor_get(&inner_cursor, NULL, (void **)&sym); + if ((fail = dump_symbol(out, sym))) { + YF_PRINT_ERROR("gen: panic: error in dumping symbol"); + return fail; + } + } + + } + + return 0; + +} diff --git a/src/gen/symgen.h b/src/gen/symgen.h new file mode 100644 index 0000000..6ecdb3c --- /dev/null +++ b/src/gen/symgen.h @@ -0,0 +1,19 @@ +/** + * For projects -- dumping all symbols from other files as forward declarations + * in the current file. + */ + +#ifndef GEN_SYMGEN_H +#define GEN_SYMGEN_H + +#include /* FILE */ + +#include + +int yfg_output_syms( + struct yf_compilation_data * cdata, + struct yf_compile_analyse_job * data, + FILE * out +); + +#endif /* GEN_SYMGEN_H */ diff --git a/src/semantics/symtab.c b/src/semantics/symtab.c index 9571b2a..318493d 100644 --- a/src/semantics/symtab.c +++ b/src/semantics/symtab.c @@ -1,11 +1,16 @@ #include "symtab.h" +#include + #include +#include #include #include -static int yfs_add_var(struct yf_hashmap * symtab, struct yf_parse_node *); -static int yfs_add_fn(struct yf_hashmap * symtab, struct yf_parse_node *); +static int yfs_add_var(struct yf_compile_analyse_job *, +struct yf_hashmap * symtab, struct yf_parse_node *); +static int yfs_add_fn(struct yf_compile_analyse_job *, +struct yf_hashmap * symtab, struct yf_parse_node *); int yfs_build_symtab(struct yf_compile_analyse_job * data) { @@ -18,16 +23,19 @@ int yfs_build_symtab(struct yf_compile_analyse_job * data) { YF_PRINT_ERROR("symtab: failed to allocate table"); return 3; /* Memory error */ } + + yfh_init(&data->types.table); + yfv_add_builtin_types(data); ret = 0; YF_LIST_FOREACH(data->parse_tree.program.decls, node) { switch (node->type) { case YFCS_VARDECL: - if (yfs_add_var(&data->symtab.table, node)) + if (yfs_add_var(data, &data->symtab.table, node)) ret = 1; break; case YFCS_FUNCDECL: - if (yfs_add_fn(&data->symtab.table, node)) + if (yfs_add_fn(data, &data->symtab.table, node)) ret = 1; break; default: @@ -40,7 +48,10 @@ int yfs_build_symtab(struct yf_compile_analyse_job * data) { } -static int yfs_add_var(struct yf_hashmap * symtab, struct yf_parse_node * n) { +static int yfs_add_var( + struct yf_compile_analyse_job * data, + struct yf_hashmap * symtab, struct yf_parse_node * n +) { struct yfcs_vardecl * v = &n->vardecl; struct yf_sym * vsym, * dupl; @@ -68,7 +79,10 @@ static int yfs_add_var(struct yf_hashmap * symtab, struct yf_parse_node * n) { } -static int yfs_add_fn(struct yf_hashmap * symtab, struct yf_parse_node * f) { +static int yfs_add_fn( + struct yf_compile_analyse_job * udata, struct yf_hashmap * symtab, + struct yf_parse_node * f +) { struct yfcs_funcdecl * fn = &f->funcdecl; @@ -102,6 +116,9 @@ static int yfs_add_fn(struct yf_hashmap * symtab, struct yf_parse_node * f) { } + /* TODO -- actually look up custom types once those exist. */ + fsym->fn.rtype = *yfv_get_type_s(udata, fn->ret.databuf); + yfh_set(symtab, fsym->fn.name, fsym); return 0; diff --git a/src/semantics/types.c b/src/semantics/types.c index 830bd35..1021e6e 100644 --- a/src/semantics/types.c +++ b/src/semantics/types.c @@ -1,5 +1,45 @@ #include "types.h" +void yft_add_type( + struct yf_compile_analyse_job * udata, + char * name, int size, enum yfpt_format fmt +) { + + struct yfs_type * type = yf_malloc(sizeof (struct yfs_type)); + type->primitive.size = size; + type->kind = YFS_T_PRIMITIVE; + type->primitive.type = fmt; + type->name = name; + yfv_add_type(udata, type); + +} + +void yfv_add_builtin_types(struct yf_compile_analyse_job * udata) { + + /* All types are signed for now - unsigned types are not yet supported. */ + + /* "standard" types. */ + yft_add_type(udata, "char", 8, YFS_F_INT ); + yft_add_type(udata, "short", 16, YFS_F_INT ); + yft_add_type(udata, "int", 32, YFS_F_INT ); + yft_add_type(udata, "long", 64, YFS_F_INT ); + yft_add_type(udata, "void", 0, YFS_F_NONE ); + yft_add_type(udata, "float", 32, YFS_F_FLOAT); + yft_add_type(udata, "double", 64, YFS_F_FLOAT); + + /* Convenience types. */ + yft_add_type(udata, "i16", 16, YFS_F_INT ); + yft_add_type(udata, "i32", 32, YFS_F_INT ); + yft_add_type(udata, "i64", 64, YFS_F_INT ); + yft_add_type(udata, "f16", 16, YFS_F_FLOAT); + yft_add_type(udata, "f32", 32, YFS_F_FLOAT); + yft_add_type(udata, "f64", 64, YFS_F_FLOAT); + + /* We're considering bool to be one bit for conversion purposes. */ + yft_add_type(udata, "bool", 1, YFS_F_INT ); + +} + enum yfs_conversion_allowedness yfs_is_safe_conversion( struct yfs_type * from, struct yfs_type * to ) { @@ -93,7 +133,7 @@ struct yfs_type * yfse_get_expr_type( } break; case YFA_E_FUNCCALL: - return expr->as.call.name->fn.rtype; + return &expr->as.call.name->fn.rtype; } } diff --git a/src/semantics/types.h b/src/semantics/types.h index 7a2b37e..0ecd62f 100644 --- a/src/semantics/types.h +++ b/src/semantics/types.h @@ -11,6 +11,13 @@ #include #include +void yft_add_type( + struct yf_compile_analyse_job * udata, + char * name, int size, enum yfpt_format fmt +); + +void yfv_add_builtin_types(struct yf_compile_analyse_job * udata); + enum yfs_conversion_allowedness { YFS_CONVERSION_OK, YFS_CONVERSION_LOSSY, /* like i64 -> bool */ diff --git a/src/semantics/validate/validate-func.c b/src/semantics/validate/validate-func.c index 3266dd0..13f3350 100644 --- a/src/semantics/validate/validate-func.c +++ b/src/semantics/validate/validate-func.c @@ -24,7 +24,9 @@ int validate_funcdecl( return 2; } - if ((a->name->fn.rtype = yfv_get_type_t( + struct yfs_type * ty; + + if ((ty = yfv_get_type_t( validator->udata, c->ret )) == NULL) { YF_PRINT_ERROR( @@ -36,6 +38,8 @@ int validate_funcdecl( return 2; } + a->name->fn.rtype = *ty; + /* Now, validate the argument list. */ /* Also, open a new scope for arguments. */ enter_scope(validator, &a->param_scope); diff --git a/src/semantics/validate/validate.c b/src/semantics/validate/validate.c index aa6168d..cff97f9 100644 --- a/src/semantics/validate/validate.c +++ b/src/semantics/validate/validate.c @@ -4,53 +4,11 @@ #include #include -static void add_type( - struct yf_compile_analyse_job * udata, - char * name, int size, enum yfpt_format fmt -) { - - struct yfs_type * type = yf_malloc(sizeof (struct yfs_type)); - type->primitive.size = size; - type->kind = YFS_T_PRIMITIVE; - type->primitive.type = fmt; - type->name = name; - yfv_add_type(udata, type); - -} - -static void yfv_add_builtin_types(struct yf_compile_analyse_job * udata) { - - /* All types are signed for now - unsigned types are not yet supported. */ - - /* "standard" types. */ - add_type(udata, "char", 8, YFS_F_INT ); - add_type(udata, "short", 16, YFS_F_INT ); - add_type(udata, "int", 32, YFS_F_INT ); - add_type(udata, "long", 64, YFS_F_INT ); - add_type(udata, "void", 0, YFS_F_NONE ); - add_type(udata, "float", 32, YFS_F_FLOAT); - add_type(udata, "double", 64, YFS_F_FLOAT); - - /* Convenience types. */ - add_type(udata, "i16", 16, YFS_F_INT ); - add_type(udata, "i32", 32, YFS_F_INT ); - add_type(udata, "i64", 64, YFS_F_INT ); - add_type(udata, "f16", 16, YFS_F_FLOAT); - add_type(udata, "f32", 32, YFS_F_FLOAT); - add_type(udata, "f64", 64, YFS_F_FLOAT); - - /* We're considering bool to be one bit for conversion purposes. */ - add_type(udata, "bool", 1, YFS_F_INT ); - -} - int yfs_validate( struct yf_compile_analyse_job * udata, struct yf_compilation_data * pdata ) { - yfh_init(&udata->types.table); - yfv_add_builtin_types(udata); struct yfv_validator validator = { /* Root symbol table is the global scope of the program. */ .current_scope = &udata->symtab, diff --git a/tests/sem/misc.yf b/tests/sem/misc.yf new file mode 100644 index 0000000..d974d48 --- /dev/null +++ b/tests/sem/misc.yf @@ -0,0 +1,3 @@ +main() { + +}