コード例 #1
0
ファイル: test_typecheck_arr.c プロジェクト: refu-lang/refu
} END_TEST

START_TEST(test_array_type4) {
    static const struct RFstring s = RF_STRING_STATIC_INIT(
        "{\n"
        "a:u64[] = [1, 2, 3]\n"
        "}"
    );
    front_testdriver_new_ast_main_source(&s);
    ck_assert_typecheck_ok();

    int64_t dims[] = {3};
    struct type *t_u64 = testsupport_analyzer_type_create_elemarray(
        ELEMENTARY_TYPE_UINT_64,
        dims
    );

    struct ast_node *block = ast_node_get_child(front_testdriver_module()->node, 0);
    struct ast_node *blist = ast_binaryop_right(ast_node_get_child(block, 0));
    const struct type *blist_type = ast_node_get_type(blist);
    ck_assert_msg(blist_type, "bracket type should not be NULL");
    ck_assert_msg(
        type_compare(blist_type, t_u64, TYPECMP_GENERIC),
        "Bracket type comparison failure"
    );

    struct ast_node *vardecl = ast_binaryop_left(ast_node_get_child(block, 0));
    const struct type *vardecl_type = ast_node_get_type(vardecl);
    ck_assert_msg(vardecl_type, "bracket type should not be NULL");
    ck_assert_msg(
        type_compare(vardecl_type, t_u64, TYPECMP_IDENTICAL),
        "Bracket type comparison failure"
    );
} END_TEST
コード例 #2
0
ファイル: test_types.c プロジェクト: refu-lang/refu
} END_TEST

START_TEST(test_determine_block_type2) {
    struct ast_node *block;
    static const struct RFstring s = RF_STRING_STATIC_INIT(
        "type foo {a:i8, b:string}\n"
        "{\n"
        "a:foo\n"
        "}"
    );
    front_testdriver_new_ast_main_source(&s);
    ck_assert_typecheck_ok();

    struct type *t_i8 = testsupport_analyzer_type_create_simple_elementary(ELEMENTARY_TYPE_INT_8);
    struct type *t_string = testsupport_analyzer_type_create_simple_elementary(ELEMENTARY_TYPE_STRING);
    struct type *t_prod_1 = testsupport_analyzer_type_create_operator(TYPEOP_PRODUCT,
                                                                      t_i8,
                                                                      t_string);
    static const struct RFstring id_foo = RF_STRING_STATIC_INIT("foo");
    struct type *t_foo = testsupport_analyzer_type_create_defined(&id_foo, t_prod_1);

    block = ast_node_get_child(front_testdriver_module()->node, 1);
    ck_assert_msg(block, "Block should be the second child of the root");
    const struct type *block_type = ast_node_get_type(block);
    ck_assert_msg(block_type, "Block should have a type");
    ck_assert_msg(type_compare(block_type, t_foo, TYPECMP_IDENTICAL),
                  "Expected the block's type to be an f64");
} END_TEST
コード例 #3
0
ファイル: rir_convert.c プロジェクト: pirapira/refulangcore
bool rir_process_convertcall(const struct ast_node *n, struct rir_ctx *ctx)
{
    struct ast_node *args = ast_fncall_args(n);
    RF_ASSERT(ast_node_get_type(args)->category != TYPE_CATEGORY_OPERATOR,
              "A conversion call should only have a single argument");
    // process that argument
    const struct rir_value *argexprval = rir_process_ast_node_getreadval(args, ctx);
    if (!argexprval) {
        RF_ERROR("Could not create rir expression from conversion call argument");
        RIRCTX_RETURN_EXPR(ctx, false, NULL);
    }
    // create the conversion
    struct rir_object *obj = rir_convert_create_obj_maybeadd(
        argexprval,
        rir_type_create_from_type(ast_node_get_type(n), ctx),
        ctx
    );
    if (!obj) {
        RIRCTX_RETURN_EXPR(ctx, false, NULL);
    }
    RIRCTX_RETURN_EXPR(ctx, true, obj);
}
コード例 #4
0
ファイル: test_types.c プロジェクト: refu-lang/refu
} END_TEST

START_TEST(test_determine_block_type1) {
    struct ast_node *block;
    static const struct RFstring s = RF_STRING_STATIC_INIT(
        "{\n"
        "d:f64 = 3.14 * 0.14\n"
        "}"
    );
    front_testdriver_new_ast_main_source(&s);
    ck_assert_typecheck_ok();

    struct type *t_f64 = testsupport_analyzer_type_create_simple_elementary(ELEMENTARY_TYPE_FLOAT_64);
    block = ast_node_get_child(front_testdriver_module()->node, 0);
    ck_assert_msg(block, "Block should be the first child of the root");
    const struct type *block_type = ast_node_get_type(block);
    ck_assert_msg(block_type, "Block should have a type");
    ck_assert_msg(type_compare(block_type, t_f64, TYPECMP_IDENTICAL),
                  "Expected the block's type to be an f64");
} END_TEST
コード例 #5
0
ファイル: test_typecheck_arr.c プロジェクト: refu-lang/refu
} END_TEST

START_TEST(test_array_type3) {
    static const struct RFstring s = RF_STRING_STATIC_INIT(
        "a:u64[42][13][24]\n"
    );
    front_testdriver_new_ast_main_source(&s);
    ck_assert_typecheck_ok();

    int64_t dims[] = {42, 13, 24};
    struct type *t_u64 = testsupport_analyzer_type_create_elemarray(
        ELEMENTARY_TYPE_UINT_64,
        dims
    );
    struct ast_node *typedesc = ast_node_get_child(front_testdriver_module()->node, 0);
    const struct type *n_type = ast_node_get_type(typedesc);
    ck_assert_msg(n_type, "Type should not be NULL");
    ck_assert_msg(
        type_compare(n_type, t_u64, TYPECMP_IDENTICAL),
        "Node type comparison failure"
    );
} END_TEST
コード例 #6
0
ファイル: typecheck_functions.c プロジェクト: refu-lang/refu
enum traversal_cb_res typecheck_function_call(
    struct ast_node *n,
    struct analyzer_traversal_ctx *ctx)
{
    const struct RFstring *fn_name;
    const struct type *fn_type;
    const struct type *fn_declared_args_type;
    const struct type *fn_found_args_type;
    struct ast_node *fn_call_args = ast_fncall_args(n);

    // check for existence of function
    fn_name = ast_fncall_name(n);
    fn_type = type_lookup_identifier_string(fn_name, ctx->current_st);

    if (!fn_type || !type_is_callable(fn_type)) {
        analyzer_err(ctx->m, ast_node_startmark(n),
                     ast_node_endmark(n),
                     "Undefined function call \""RFS_PF"\" detected",
                     RFS_PA(fn_name));
        goto fail;
    }

    // create the arguments ast node array
    ast_fncall_arguments(n);

    // also check the ast node of the function declaration to get more
    // information if it's not a conversion
    if (!type_is_explicitly_convertable_elementary(fn_type)) {
        const struct ast_node *fndecl = symbol_table_lookup_node(
            ctx->current_st,
            fn_name,
            NULL
        );
        RF_ASSERT(fndecl, "Since fn_type was found so should fndecl be found here");
        if (fndecl->fndecl.position == FNDECL_PARTOF_FOREIGN_IMPORT) {
            n->fncall.type = AST_FNCALL_FOREIGN;
        }
    }

    fn_found_args_type = (fn_call_args)
        ? ast_node_get_type(fn_call_args)
        : type_elementary_get_type(ELEMENTARY_TYPE_NIL);

    if (!fn_found_args_type) { // argument typechecking failed
        goto fail;
    }

    if (type_is_explicitly_convertable_elementary(fn_type)) {
        // silly way to check if it's only 1 argument. Maybe figure out safer way?
        if (!fn_call_args || fn_found_args_type->category == TYPE_CATEGORY_OPERATOR) {
            analyzer_err(
                ctx->m,
                ast_node_startmark(n),
                ast_node_endmark(n),
                "Invalid arguments for explicit conversion to \""
                RFS_PF"\".",
                RFS_PA(fn_name)
            );
            goto fail;
        }

        // check if the explicit conversion is valid
        if (!type_compare(fn_found_args_type, fn_type, TYPECMP_EXPLICIT_CONVERSION)) {
            analyzer_err(ctx->m, ast_node_startmark(n), ast_node_endmark(n),
                         "Invalid explicit conversion. "RFS_PF".",
                         RFS_PA(typecmp_ctx_get_error()));
            goto fail;
        }
        n->fncall.type = AST_FNCALL_EXPLICIT_CONVERSION;
    } else {
        //check that the types of its arguments do indeed match
        fn_declared_args_type = type_callable_get_argtype(fn_type);
        n->fncall.declared_type = fn_declared_args_type;
        if (type_is_sumop(fn_declared_args_type)) {
            n->fncall.type = AST_FNCALL_SUM;
        }
        typecmp_ctx_set_flags(TYPECMP_FLAG_FUNCTION_CALL);
        if (!type_compare(
                fn_found_args_type,
                fn_declared_args_type,
                n->fncall.type == AST_FNCALL_SUM
                    ? TYPECMP_PATTERN_MATCHING :
                    TYPECMP_IMPLICIT_CONVERSION)) {
            RFS_PUSH();
            analyzer_err(
                ctx->m, ast_node_startmark(n), ast_node_endmark(n),
                RFS_PF" "RFS_PF"() is called with argument type of \""RFS_PF
                "\" which does not match the expected "
                "type of \""RFS_PF"\"%s"RFS_PF".",
                RFS_PA(type_callable_category_str(fn_type)),
                RFS_PA(fn_name),
                RFS_PA(type_str_or_die(fn_found_args_type, TSTR_DEFAULT)),
                RFS_PA(type_str_or_die(fn_declared_args_type, TSTR_DEFINED_ONLY_CONTENTS)),
                typecmp_ctx_have_error() ? ". " : "",
                RFS_PA(typecmp_ctx_get_error())
            );
            RFS_POP();
            goto fail;
        }
        // the function call's matched type should be either a specific sum type
        // that may have matched or the entirety of the called arguments
        if (!(n->fncall.params_type = typemp_ctx_get_matched_type())) {
            n->fncall.params_type = fn_found_args_type;
        }
    }

    traversal_node_set_type(n, type_callable_get_rettype(fn_type), ctx);
    return TRAVERSAL_CB_OK;

fail:
    traversal_node_set_type(n, NULL, ctx);
    return TRAVERSAL_CB_ERROR;
}