diff options
author | pommicket <pommicket@gmail.com> | 2022-02-07 15:16:26 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-02-07 15:16:26 -0500 |
commit | 4b6fe5266a60951a7acde77031541c7b4670c503 (patch) | |
tree | 3fb748b0504e567a1016e94a0e85dfc25cb86b09 | |
parent | 9372a72d433d511dda6c40ddf40b4b8367cb85b8 (diff) |
cleanup - declaring functions without defining them, etc.
-rw-r--r-- | 05/main.b | 4 | ||||
-rw-r--r-- | 05/main.c | 13 | ||||
-rw-r--r-- | 05/parse.b | 64 |
3 files changed, 51 insertions, 30 deletions
@@ -49,9 +49,7 @@ global output_file_data ; ident list of global variables. each one is stored as ; (type << 32) | address global global_variables -; ident list of functions. each entry is a pointer two statements -; - the first one is a STATEMENT_LOCAL_DECLARATION (with dat2=dat3=dat4=0), which is only there to set rsp properly because of parameters -; - the second one is the function body (a STATEMENT_BLOCK) +; ident list of functions. each entry is a pointer to a statement (specifically, a STATEMENT_BLOCK) global function_statements ; ident list mapping function names to function types (TYPE_FUNCTION {...}) global function_types @@ -1,17 +1,24 @@ /* static int g; */ +int G; + int f(int a, float x[], double y, ...) { } -float * g() { -} +float * g(void); int main() { int b[] = {1,2,3}; - int a = f(1, 17, b, 36, 55.0, 22.3f); + int a = f(G, 17, b, 36, 55.0, 22.3f); float *f = g(17.2, b); + int *y; + y = b; } +float *g () { + float j; + return &j; +} /* int f(int x, int y[3]) { */ /* int z = 17 +x; */ /* int g[]={1,2,3,4,5}; */ @@ -137,8 +137,22 @@ function parse_toplevel_declaration rwdata_end_addr <= 3 token = suffix_end - if *1token == SYMBOL_LBRACE goto parse_function_definition - if is_extern != 0 goto parse_tl_decl_cont ; ignore external variable declarations + p = types + type + if *1p == TYPE_FUNCTION goto parse_function_declaration + + ; ignore external variable declarations + ; @NONSTANDARD: this means we don't handle + ; extern int X; + ; int main() { printf("%d\n", X); } + ; int X; + ; correctly. There is no (good) way for us to handle this properly without two passes. + ; Consider: + ; extern int X[]; /* how many bytes to allocate? */ + ; int Y = 123; /* where do we put this? */ + ; int main() { printf("%d\n", Y); } + ; int X[] = {1, 2, 3, 4}; /* 16 bytes (but it's too late) */ + if is_extern != 0 goto parse_tl_decl_cont + ; deal with the initializer if there is one if *1token == SYMBOL_SEMICOLON goto parse_tld_no_initializer if *1token == SYMBOL_COMMA goto parse_tld_no_initializer @@ -159,7 +173,7 @@ function parse_toplevel_declaration :tl_decl_loop_done token += 16 ; skip semicolon goto parse_tld_ret - + :tl_decl_no_ident token_error(prefix_end, .str_tl_decl_no_ident) :str_tl_decl_no_ident @@ -170,9 +184,18 @@ function parse_toplevel_declaration :str_tld_bad_stuff_after_decl string Declarations should be immediately followed by a comma or semicolon. byte 0 + :parse_function_declaration + b = ident_list_lookup(function_types, name) + if b != 0 goto function_decl_have_type ; e.g. function declared then defined + ident_list_add(function_types, name, type) + :function_decl_have_type + if *1token == SYMBOL_LBRACE goto parse_function_definition + if *1token == SYMBOL_SEMICOLON goto parse_tl_decl_cont + token_error(token, .str_bad_fdecl_suffix) + :str_bad_fdecl_suffix + string Expected semicolon or { after function declaration. + byte 0 :parse_tld_no_initializer - p = types + type - if *1p == TYPE_FUNCTION goto parse_tl_decl_cont ; ignore function declarations -- we do two passes anyways b = ident_list_lookup(static_vars, name) if b != 0 goto global_redefinition c = type < 32 @@ -215,7 +238,6 @@ function parse_toplevel_declaration out = function_stmt_data + function_stmt_data_bytes_used out0 = out ident_list_add(function_statements, name, out) - ident_list_add(function_types, name, type) ; deal with function parameters p = type + 1 @@ -237,24 +259,18 @@ function parse_toplevel_declaration name += 1 goto fn_params_loop :fn_params_loop_end - - write_statement_header(out, STATEMENT_LOCAL_DECLARATION, token) - out += 8 - *8out = local_var_rbp_offset - out += 32 - + ; NOTE: it's the caller's responsibility to properly set rsp to accomodate all the arguments. + ; it needs to be this way because of varargs functions (the function doesn't know how many arguments there are). parse_statement(&token, &out) - if block_depth != 0 goto stmtdepth_internal_err + if block_depth != 0 goto blockdepth_internal_err function_stmt_data_bytes_used = out - function_stmt_data print_statement(out0) - out0 += 40 - print_statement(out0) goto parse_tld_ret - :stmtdepth_internal_err - token_error(token, .str_stmtdepth_internal_err) - :str_stmtdepth_internal_err - string Internal compiler error: parse_stmt_depth is not 0 after parsing function body. + :blockdepth_internal_err + token_error(token, .str_blockdepth_internal_err) + :str_blockdepth_internal_err + string Internal compiler error: block_depth is not 0 after parsing function body. byte 0 :lbrace_after_declaration token_error(token, .str_lbrace_after_declaration) @@ -2941,7 +2957,7 @@ function parse_expression ; it must be a function c = ident_list_lookup(function_types, a) - if c == 0 goto undeclared_function + if c == 0 goto undeclared_variable *1out = EXPRESSION_FUNCTION out += 4 *4out = c @@ -2949,11 +2965,11 @@ function parse_expression *8out = a out += 8 return out - :undeclared_function + :undeclared_variable ; @NONSTANDARD: C89 allows calling functions without declaring them - token_error(in, .str_undeclared_function) - :str_undeclared_function - string Undeclared function. + token_error(in, .str_undeclared_variable) + :str_undeclared_variable + string Undeclared variable. byte 0 :found_local_variable |