struct ast_node *parser_acc_fnimpl(struct parser *p) { struct ast_node *n; struct ast_node *decl; struct ast_node *body; struct token *tok; decl = parser_acc_fndecl(p, FNDECL_PARTOF_IMPL); if (!decl) { return NULL; } tok = lexer_lookahead(p->lexer, 1); if (!tok) { goto fail_free_decl; } if (tok->type == TOKEN_SM_OCBRACE) { // normal function body body = parser_acc_block(p, true); if (!body) { parser_synerr(p, ast_node_endmark(decl), NULL, "Expected a body for \""RF_STR_PF_FMT"\" function " "implementation", RF_STR_PF_ARG(ast_fndecl_name_str(decl))); goto fail_free_decl; } } else { // attempt to find a headless match expression as the function body body = parser_acc_matchexpr(p, false, true); if (!body) { parser_synerr(p, ast_node_endmark(decl), NULL, "Expected a body for \""RF_STR_PF_FMT"\" function " "implementation", RF_STR_PF_ARG(ast_fndecl_name_str(decl))); goto fail_free_decl; } // now set the matchexpr's fn_args since this is a headless matchexpr ast_matchexpr_set_fnargs(body, ast_fndecl_args_get(decl)); } n = ast_fnimpl_create(ast_node_startmark(decl), ast_node_endmark(body), decl, body); if (!n) { RF_ERRNOMEM(); ast_node_destroy(body); ast_node_destroy(decl); return NULL; } return n; fail_free_decl: ast_node_destroy(decl); return NULL; }
static bool analyzer_symbol_table_add_fndecl(struct analyzer_traversal_ctx *ctx, struct ast_node *n) { struct symbol_table_record *rec; const struct RFstring *fn_name; fn_name = ast_fndecl_name_str(n); rec = symbol_table_lookup_record(ctx->current_st, fn_name, NULL); if (rec && type_is_function(rec->data)) { analyzer_err(ctx->m, ast_node_startmark(n), ast_node_endmark(n), "Function \""RF_STR_PF_FMT"\" was already declared " "at "INPLOCATION_FMT, RF_STR_PF_ARG(fn_name), INPLOCATION_ARG( module_get_file(ctx->m), ast_node_location(symbol_table_record_node(rec)))); return false; } if (!symbol_table_add_node(ctx->current_st, ctx->m, fn_name, n)) { RF_ERROR("Could not add a function node to a symbol table"); return false; } // function's arguments are added to the symbol table by type creation return true; }
enum traversal_cb_res typecheck_fndecl( struct ast_node *n, struct analyzer_traversal_ctx *ctx) { const struct type *t; t = type_lookup_identifier_string(ast_fndecl_name_str(n), ctx->current_st); if (!t) { RF_ERROR( "Function declaration name not found in the symbol table at " "impossible point" ); return TRAVERSAL_CB_ERROR; } traversal_node_set_type(n, t, ctx); return TRAVERSAL_CB_OK; }