diff options
| author | Mustafa Quraish <[email protected]> | 2022-02-05 05:47:52 -0500 |
|---|---|---|
| committer | Mustafa Quraish <[email protected]> | 2022-02-05 08:56:15 -0500 |
| commit | 2ca7824bedade35a08da5c037b8dc999a54e84f1 (patch) | |
| tree | 281421602911828b060f43a540862517c19370b3 /src/parser.c | |
| parent | Handle command-line arguments properly on linux (diff) | |
| download | cup-2ca7824bedade35a08da5c037b8dc999a54e84f1.tar.xz cup-2ca7824bedade35a08da5c037b8dc999a54e84f1.zip | |
Allow function declarations without a definition
Diffstat (limited to 'src/parser.c')
| -rw-r--r-- | src/parser.c | 50 |
1 files changed, 36 insertions, 14 deletions
diff --git a/src/parser.c b/src/parser.c index 9f66060..0294dc2 100644 --- a/src/parser.c +++ b/src/parser.c @@ -896,18 +896,34 @@ void parse_func_args(Lexer *lexer, Node *func) Node *parse_func(Lexer *lexer) { - Token token; - token = assert_token(Lexer_next(lexer), TOKEN_FN); - - token = assert_token(Lexer_next(lexer), TOKEN_IDENTIFIER); - if (identifier_exists(&token)) - die_location(token.loc, "Function name already exists as an identifier"); + assert_token(Lexer_next(lexer), TOKEN_FN); + Token token = assert_token(Lexer_next(lexer), TOKEN_IDENTIFIER); Node *func = Node_new(AST_FUNC); - push_new_function(func); + Node *dfunc = func; // The pointer to a declaration node + func->func.name = token.value.as_string; + // If the identifier exists, there's 3 possible cases: + // 1. It's another variable / struct, which is an error. + // 2. It's a function that's been defined, which is an error. + // 3. It's a function that's been declared (but not defined), which is OK + if (identifier_exists(&token)) { + dfunc = find_function_definition(&token); + // Case 1 + if (dfunc == NULL) + die_location(token.loc, "Function name already exists as an identifier"); + // Case 2 + if (dfunc->func.is_defined) + die_location(token.loc, "Function already defined earlier"); + + // Case 3 (No error, just set the current function correctly) + current_function = func; + } else { + // We don't have a declaration yet, push this. + push_new_function(func); + } - func->func.name = token.value.as_string; + // TODO: IMPORTANT: Make sure that args match the declaration, if any. parse_func_args(lexer, func); token = Lexer_peek(lexer); @@ -920,12 +936,18 @@ Node *parse_func(Lexer *lexer) func->func.return_type = type_new(TYPE_VOID); } - // Make sure there's no funny business with the stack offset - assert(cur_stack_offset == 0); - assert(block_stack_count == 0); - func->func.body = parse_block(lexer); - assert(block_stack_count == 0); - assert(cur_stack_offset == 0); + token = Lexer_peek(lexer); + if (token.type != TOKEN_SEMICOLON) { + // Make sure there's no funny business with the stack offset + assert(cur_stack_offset == 0); + assert(block_stack_count == 0); + func->func.body = parse_block(lexer); + assert(block_stack_count == 0); + assert(cur_stack_offset == 0); + + // Mark the declaration as defined. + dfunc->func.is_defined = true; + } // Reset current function current_function = NULL; |