예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}