yangtau/hedgehog

only find variable in the same scope

Closed this issue · 1 comments

only find variable in the same scope

need some tests

// TODO: only find variable in the same scope

}

static int compile_ast_node_args(struct compiler_context* ctx, void* _args) {
    struct ast_node_array* args = _args;

    int rc = 0;
    for (size_t i = 0; i < args->len; i++) {
        // push inversely
        rc |= compile_ast_node(ctx, args->arr[i]);
    }
    return rc;
}

static int compile_define_vars(struct compiler_context* ctx, void* _vars) {
    struct ast_node_array* vars = _vars;

    int rc = 0;

    for (size_t i = 0; i < vars->len; i++) {
        struct hg_value* id = vars->arr[i]->node;

        int loc;
        bool islocal;
        // TODO: only find variable in the same scope
        //       need some tests
        if ((loc = find_variable(ctx, *id, &islocal)) != -1) {
            fprintf(stderr, "redefine variable: ");
            hg_value_write(*id, stderr, true);
            fprintf(stderr, "\n");
            return -1;
        } else if (ctx->scope_depth == 0) {
            // define global var
            loc = chunk_add_static(ctx->chk, VAL_UNDEF());
            hash_map_put(&ctx->global_vars, *id, VAL_INT(loc));

            chunk_write(ctx->chk, OP_SET_STATIC);
            chunk_write_word(ctx->chk, loc);
        } else {
            // define local var
            add_local(ctx, ((struct hg_string*)VAL_AS_OBJ(*id))->str);
        }
    }
    return rc;
}

static int compile_set_vars(struct compiler_context* ctx, void* _vars) {
    struct ast_node_array* vars = _vars;

    int rc = 0;

    for (int i = vars->len - 1; i >= 0; i--) {
        struct hg_value* id = vars->arr[i]->node;

        int loc;
        bool islocal;
        if ((loc = find_variable(ctx, *id, &islocal)) != -1) {
            chunk_write(ctx->chk, islocal ? OP_SET_LOCAL : OP_SET_STATIC);
            chunk_write_word(ctx->chk, loc);
        } else {
            fprintf(stderr, "compile error: reference before definition: ");
            hg_value_write(*id, stderr, true);
            fprintf(stderr, "\n");
            rc |= -1;
        }
    }
    return rc;
}

static int compile_ast_node_assign(struct compiler_context* ctx,
                                   void* _assign) {
    struct ast_node_assign* node = _assign;
    // check if args.len == vars.len
    struct ast_node_array* args = node->args->node;
    struct ast_node_array* vars = node->vars->node;

    int rc = 0;

    if (args->len != vars->len) {
        fprintf(stderr,
                "compiler error: expect %ld on the left of assignment but got "
                "%ld\n",
                vars->len, args->len);
        return -1;
    }

    rc |= compile_ast_node(ctx, node->args);
    rc |= compile_set_vars(ctx, node->vars->node);
    return rc;
}

static int compile_ast_node_let(struct compiler_context* ctx, void* _assign) {
    struct ast_node_assign* node = _assign;
    // check if args.len == vars.len
    struct ast_node_array* args = node->args->node;
    struct ast_node_array* vars = node->vars->node;

    if (args->len != vars->len) {
        fprintf(stderr,
                "compiler error: expect %ld on the left of assignment but got "
                "%ld\n",
                vars->len, args->len);
        return -1;
    }

    int rc = 0;
    rc |= compile_ast_node(ctx, node->args);

    rc |= compile_define_vars(ctx, node->vars->node);
    return rc;
}

/* IF-ELSE-IF-ELSE:

8d88864f154f0ae376ed79fdfbf21889d18f0184