From 1f02ef82910f8c2b37a33cbfc0c347ebb10de9ae Mon Sep 17 00:00:00 2001 From: adamhutchings Date: Sat, 12 Nov 2022 23:51:41 -0500 Subject: [PATCH 1/4] Add empty function test --- tests/sem/func-forward.yf | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/sem/func-forward.yf diff --git a/tests/sem/func-forward.yf b/tests/sem/func-forward.yf new file mode 100644 index 0000000..0d30a14 --- /dev/null +++ b/tests/sem/func-forward.yf @@ -0,0 +1 @@ +foo(x: int): int; From 97c2f845f20ea2d02c6c0032a8437458d8518e11 Mon Sep 17 00:00:00 2001 From: adamhutchings Date: Sat, 12 Nov 2022 23:51:57 -0500 Subject: [PATCH 2/4] Handle empty function bodies properly --- src/api/cst-dump.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/api/cst-dump.c b/src/api/cst-dump.c index 0c96f2b..26646ca 100644 --- a/src/api/cst-dump.c +++ b/src/api/cst-dump.c @@ -132,7 +132,11 @@ static void yf_dump_funcdecl(struct yfcs_funcdecl * node, FILE * out) { yf_print_line(out, "return type: %s", node->ret.databuf); yf_print_line(out, "function body"); indent(); - yf_dump_cst(node->body, out); + if (node->body) { + yf_dump_cst(node->body, out); + } else { + yf_print_line(out, "[no body]"); + } dedent(); yf_print_line(out, "end function body"); dedent(); From a1756b5a84d3f63ee7145833232f815abc687d98 Mon Sep 17 00:00:00 2001 From: adamhutchings Date: Sat, 12 Nov 2022 23:52:07 -0500 Subject: [PATCH 3/4] Generate empty function bodies properly --- src/gen/gen.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gen/gen.c b/src/gen/gen.c index 43c0ee5..e27ca2d 100644 --- a/src/gen/gen.c +++ b/src/gen/gen.c @@ -138,7 +138,10 @@ static void yf_gen_funcdecl( fprintf(out, ") "); - yf_gen_node(node->body, out, i); + if (node->body == NULL) + fprintf(out, ";"); + else + yf_gen_node(node->body, out, i); } From 70f67710416e3471b8e0f17734da698002b77632 Mon Sep 17 00:00:00 2001 From: adamhutchings Date: Sat, 12 Nov 2022 23:52:24 -0500 Subject: [PATCH 4/4] Add frontend for empty function bodies --- src/parser/func.c | 11 +++++++ src/semantics/validate/validate-func.c | 41 +++++++++++++++----------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/parser/func.c b/src/parser/func.c index 0270a75..c04c4aa 100644 --- a/src/parser/func.c +++ b/src/parser/func.c @@ -88,6 +88,17 @@ int yfp_funcdecl(struct yf_parse_node * node, struct yf_lexer * lexer) { bodyp: node->type = YFCS_FUNCDECL; + + struct yf_token sctest; /* semicolon test */ + yfl_lex(lexer, &sctest); + if (sctest.type == YFT_SEMICOLON) { + /* No body for function. */ + node->funcdecl.body = NULL; + return 0; + } else { + yfl_unlex(lexer, &sctest); + } + node->funcdecl.body = yf_malloc(sizeof (struct yf_parse_node)); return yfp_bstmt(node->funcdecl.body, lexer); diff --git a/src/semantics/validate/validate-func.c b/src/semantics/validate/validate-func.c index 1195d8c..ea3679c 100644 --- a/src/semantics/validate/validate-func.c +++ b/src/semantics/validate/validate-func.c @@ -67,29 +67,36 @@ int validate_funcdecl( return 1; } - a->body = yf_malloc(sizeof (struct yf_ast_node)); - if (!a->body) - return 2; - - /* Now, validate the body. */ - if (validate_bstmt(validator, c->body, a->body, a->ret, &returns)) { - yf_free(a->body); + if (c->body == NULL) { a->body = NULL; - return 1; + } else { + a->body = yf_malloc(sizeof (struct yf_ast_node)); + if (!a->body) + return 2; + + /* Now, validate the body. */ + if (validate_bstmt(validator, c->body, a->body, a->ret, &returns)) { + yf_free(a->body); + a->body = NULL; + return 1; + } } + /* Close the scope. */ exit_scope(validator); - if (returns == 0 && a->ret->primitive.size != 0) { - YF_PRINT_ERROR( - "%s %d:%d: Function '%s' does not always return a value", - cin->loc.file, - cin->loc.line, - cin->loc.column, - c->name.name - ); - return 1; + if (a->body != NULL) { + if (returns == 0 && a->ret->primitive.size != 0) { + YF_PRINT_ERROR( + "%s %d:%d: Function '%s' does not always return a value", + cin->loc.file, + cin->loc.line, + cin->loc.column, + c->name.name + ); + return 1; + } } return 0;