Skip to content

Commit

Permalink
Array element access (reading)
Browse files Browse the repository at this point in the history
  • Loading branch information
moefh committed Aug 11, 2017
1 parent c05d5d3 commit dd96d82
Show file tree
Hide file tree
Showing 19 changed files with 196 additions and 92 deletions.
12 changes: 12 additions & 0 deletions src/lib/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ void fh_free_expr_children(struct fh_p_expr *expr)
fh_free_expr(expr->data.bin_op.right);
return;

case EXPR_INDEX:
fh_free_expr(expr->data.index.container);
fh_free_expr(expr->data.index.index);
return;

case EXPR_FUNC_CALL:
fh_free_expr(expr->data.func_call.func);
if (expr->data.func_call.args) {
Expand Down Expand Up @@ -239,6 +244,13 @@ int fh_ast_visit_expr_nodes(struct fh_p_expr *expr, int (*visit)(struct fh_p_exp
return ret;
return 0;

case EXPR_INDEX:
if ((ret = fh_ast_visit_expr_nodes(expr->data.index.container, visit, data)) != 0)
return ret;
if ((ret = fh_ast_visit_expr_nodes(expr->data.index.index, visit, data)) != 0)
return ret;
return 0;

case EXPR_FUNC_CALL:
if ((ret = fh_ast_visit_expr_nodes(expr->data.func_call.func, visit, data)) != 0)
return ret;
Expand Down
7 changes: 7 additions & 0 deletions src/lib/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ enum fh_expr_type {
EXPR_UN_OP,
EXPR_FUNC,
EXPR_FUNC_CALL,
EXPR_INDEX,
};

struct fh_p_expr_bin_op {
Expand All @@ -117,6 +118,11 @@ struct fh_p_expr_func {
struct fh_p_stmt_block body;
};

struct fh_p_expr_index {
struct fh_p_expr *container;
struct fh_p_expr *index;
};

struct fh_p_expr {
enum fh_expr_type type;
struct fh_src_loc loc;
Expand All @@ -128,6 +134,7 @@ struct fh_p_expr {
struct fh_p_expr_un_op un_op;
struct fh_p_expr_func func;
struct fh_p_expr_func_call func_call;
struct fh_p_expr_index index;
} data;
};

Expand Down
4 changes: 2 additions & 2 deletions src/lib/bytecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct fh_func *fh_get_bc_func_by_name(struct fh_program *prog, const char *name
{
stack_foreach(struct fh_func **, pf, &prog->funcs) {
struct fh_func *func = *pf;
if (func->name != NULL && strcmp(GET_OBJ_STRING(func->name), name) == 0)
if (func->name != NULL && strcmp(GET_OBJ_STRING_DATA(func->name), name) == 0)
return func;
}
return NULL;
Expand All @@ -58,5 +58,5 @@ const char *fh_get_bc_func_name(struct fh_program *prog, int num)
struct fh_func *func = *pf;
if (! func->name)
return NULL;
return GET_OBJ_STRING(func->name);
return GET_OBJ_STRING_DATA(func->name);
}
2 changes: 2 additions & 0 deletions src/lib/bytecode.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ enum fh_bc_opcode {
OPC_CMP_EQ,
OPC_CMP_LT,
OPC_CMP_LE,

OPC_INDEX,

OPC_ADD,
OPC_SUB,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/c_funcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ int fh_fn_len(struct fh_program *prog, struct fh_value *ret, struct fh_value *ar
{
if (n_args != 1)
return fh_set_error(prog, "len(): invalid number of arguments: %d", n_args);
struct fh_array *arr = fh_get_array(&args[0]);
struct fh_array *arr = GET_VAL_ARRAY(&args[0]);
if (! arr)
return fh_set_error(prog, "len(): argument must be an array");
*ret = fh_new_number(prog, arr->len);
Expand Down
78 changes: 56 additions & 22 deletions src/lib/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,6 @@ static int compile_bin_op(struct fh_compiler *c, struct fh_src_loc loc, struct f
return -1;
}
} else {
//printf("%s <- ", fh_get_ast_symbol(c->ast, expr->left->data.var));
//fh_dump_expr(c->ast, NULL, expr->right);
//printf("\n");
int tmp_reg = compile_expr(c, expr->right, dest_reg);
if (tmp_reg < 0)
return -1;
Expand Down Expand Up @@ -550,7 +547,7 @@ static int compile_bin_op(struct fh_compiler *c, struct fh_src_loc loc, struct f
return -1;
int right_reg;
if (dest_reg >= 0 && expr->right->type == EXPR_VAR) {
right_reg = get_var_reg(c, expr->left->loc, expr->right->data.var);
right_reg = get_var_reg(c, expr->right->loc, expr->right->data.var);
} else if (expr->right->type == EXPR_NUMBER) {
right_reg = add_const_number(c, loc, expr->right->data.num);
if (right_reg >= 0) right_reg += MAX_FUNC_REGS+1;
Expand Down Expand Up @@ -642,13 +639,47 @@ static int compile_func_call(struct fh_compiler *c, struct fh_src_loc loc, struc
return req_dest_reg;
}

static int compile_index(struct fh_compiler *c, struct fh_src_loc loc, struct fh_p_expr_index *expr, int dest_reg)
{
int container_reg;
if (dest_reg >= 0 && expr->container->type == EXPR_VAR) {
container_reg = get_var_reg(c, expr->container->loc, expr->container->data.var);
} else {
container_reg = compile_expr(c, expr->container, dest_reg);
}
if (container_reg < 0)
return -1;

int index_reg;
if (dest_reg >= 0 && expr->index->type == EXPR_VAR) {
index_reg = get_var_reg(c, expr->index->loc, expr->index->data.var);
} else if (expr->index->type == EXPR_NUMBER) {
index_reg = add_const_number(c, loc, expr->index->data.num);
if (index_reg >= 0) index_reg += MAX_FUNC_REGS+1;
} else {
index_reg = compile_expr(c, expr->index, -1);
}
if (index_reg < 0)
return -1;

if (dest_reg < 0) {
dest_reg = alloc_reg(c, loc, TMP_VARIABLE);
if (dest_reg < 0)
return -1;
}
if (add_instr(c, loc, MAKE_INSTR_ABC(OPC_INDEX, dest_reg, container_reg, index_reg)) < 0)
return -1;
return dest_reg;
}

static int compile_expr(struct fh_compiler *c, struct fh_p_expr *expr, int req_dest_reg)
{
switch (expr->type) {
case EXPR_VAR: return compile_var(c, expr->loc, expr->data.var, req_dest_reg);
case EXPR_BIN_OP: return compile_bin_op(c, expr->loc, &expr->data.bin_op, req_dest_reg);
case EXPR_UN_OP: return compile_un_op(c, expr->loc, &expr->data.un_op, req_dest_reg);
case EXPR_FUNC_CALL: return compile_func_call(c, expr->loc, &expr->data.func_call, req_dest_reg);
case EXPR_INDEX: return compile_index(c, expr->loc, &expr->data.index, req_dest_reg);
case EXPR_FUNC: return fh_compiler_error(c, expr->loc, "compilation of inner function implemented");
default:
break;
Expand All @@ -662,30 +693,33 @@ static int compile_expr(struct fh_compiler *c, struct fh_p_expr *expr, int req_d
}

switch (expr->type) {
case EXPR_NUMBER: {
int k = add_const_number(c, expr->loc, expr->data.num);
if (k < 0)
goto err;
if (add_instr(c, expr->loc, MAKE_INSTR_AU(OPC_LDC, dest_reg, k)) < 0)
goto err;
break;
}

case EXPR_STRING: {
int k = add_const_string(c, expr->loc, expr->data.str);
if (k < 0)
goto err;
if (add_instr(c, expr->loc, MAKE_INSTR_AU(OPC_LDC, dest_reg, k)) < 0)
goto err;
break;
}

case EXPR_NUMBER:
{
int k = add_const_number(c, expr->loc, expr->data.num);
if (k < 0)
goto err;
if (add_instr(c, expr->loc, MAKE_INSTR_AU(OPC_LDC, dest_reg, k)) < 0)
goto err;
break;
}

case EXPR_STRING:
{
int k = add_const_string(c, expr->loc, expr->data.str);
if (k < 0)
goto err;
if (add_instr(c, expr->loc, MAKE_INSTR_AU(OPC_LDC, dest_reg, k)) < 0)
goto err;
break;
}

case EXPR_NONE:
case EXPR_VAR:
case EXPR_BIN_OP:
case EXPR_UN_OP:
case EXPR_FUNC_CALL:
case EXPR_FUNC:
case EXPR_INDEX:
break;
}
return dest_reg;
Expand Down
10 changes: 10 additions & 0 deletions src/lib/dump_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ static void dump_expr(struct fh_ast *ast, struct fh_output *out, int indent, str
if (expr_needs_paren(expr->data.bin_op.right)) fh_output(out, ")");
return;

case EXPR_INDEX:
if (expr_needs_paren(expr->data.index.container)) fh_output(out, "(");
dump_expr(ast, out, indent, expr->data.index.container);
if (expr_needs_paren(expr->data.index.container)) fh_output(out, ")");
fh_output(out, " %s ", fh_get_ast_op(ast, expr->data.bin_op.op));
fh_output(out, "[");
dump_expr(ast, out, indent, expr->data.index.index);
fh_output(out, "]");
return;

case EXPR_UN_OP:
fh_output(out, "%s", fh_get_ast_op(ast, expr->data.un_op.op));
if (expr_needs_paren(expr->data.un_op.arg)) fh_output(out, "(");
Expand Down
2 changes: 2 additions & 0 deletions src/lib/dump_bytecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ void fh_dump_bc_instr(struct fh_program *prog, struct fh_output *out, int32_t ad
case OPC_MOV: fh_output(out, "mov "); dump_instr_ra_rkb(out, instr); return;
case OPC_NOT: fh_output(out, "not "); dump_instr_ra_rkb(out, instr); return;

case OPC_INDEX: fh_output(out, "index "); dump_instr_ra_rkb_rkc(out, instr); return;

case OPC_CMP_EQ: fh_output(out, "cmp.eq "); dump_instr_a_rkb_rkc(out, instr); return;
case OPC_CMP_LT: fh_output(out, "cmp.lt "); dump_instr_a_rkb_rkc(out, instr); return;
case OPC_CMP_LE: fh_output(out, "cmp.le "); dump_instr_a_rkb_rkc(out, instr); return;
Expand Down
3 changes: 1 addition & 2 deletions src/lib/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,14 @@ static void DEBUG_OBJ(const char *prefix, struct fh_object *obj)

static void sweep(struct fh_program *prog)
{
UNUSED(prog);
DEBUG_LOG("***** sweeping\n");
struct fh_object **objs = &prog->objects;
struct fh_object *cur;
while ((cur = *objs) != NULL) {
if (cur->obj.header.gc_mark) {
objs = &cur->obj.header.next;
cur->obj.header.gc_mark = 0;
DEBUG_OBJ("-> keeping", cur);
objs = &cur->obj.header.next;
} else {
*objs = cur->obj.header.next;
DEBUG_OBJ("-> FREEING", cur);
Expand Down
47 changes: 42 additions & 5 deletions src/lib/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ static int resolve_expr_stack(struct fh_parser *p, struct fh_src_loc loc, struct
//dump_opr_stack(p, oprs);
//printf("**************************************************\n");

if (fh_stack_is_empty(oprs))
if (fh_stack_size(oprs) == 0)
return 0;

struct fh_operator *op = fh_stack_top(oprs);
Expand All @@ -215,7 +215,7 @@ static int resolve_expr_stack(struct fh_parser *p, struct fh_src_loc loc, struct
switch (op_assoc) {
case FH_ASSOC_RIGHT:
case FH_ASSOC_LEFT:
if (fh_stack_count(opns) < 2) {
if (fh_stack_size(opns) < 2) {
fh_free_expr(expr);
fh_parse_error(p, loc, "syntax error");
return -1;
Expand All @@ -227,7 +227,7 @@ static int resolve_expr_stack(struct fh_parser *p, struct fh_src_loc loc, struct
break;

case FH_ASSOC_PREFIX:
if (fh_stack_count(opns) < 1) {
if (fh_stack_size(opns) < 1) {
fh_free_expr(expr);
fh_parse_error(p, loc, "syntax error");
return -1;
Expand Down Expand Up @@ -273,7 +273,7 @@ static struct fh_p_expr *parse_expr(struct fh_parser *p, bool consume_stop, char
expr = parse_expr(p, true, ")");
if (expr == NULL)
goto err;
expect_opn = 0;
expect_opn = false;
} else {
if (resolve_expr_stack(p, tok.loc, &opns, &oprs, FUNC_CALL_PREC) < 0)
goto err;
Expand Down Expand Up @@ -323,7 +323,7 @@ static struct fh_p_expr *parse_expr(struct fh_parser *p, bool consume_stop, char
goto err;
//printf("AFTER:\n"); dump_opn_stack(p, &opns); dump_opr_stack(p, &oprs);

if (fh_stack_count(&opns) > 1) {
if (fh_stack_size(&opns) > 1) {
dump_opn_stack(p, &opns);
dump_opr_stack(p, &oprs);
fh_parse_error(p, tok.loc, "syntax error (stack not empty!)");
Expand All @@ -340,6 +340,43 @@ static struct fh_p_expr *parse_expr(struct fh_parser *p, bool consume_stop, char
}
}

/* [ */
if (tok_is_punct(&tok, '[')) {
struct fh_p_expr *expr;
if (expect_opn) {
fh_parse_error(p, tok.loc, "parsing of array literal not implemented");
goto err;
} else {
if (resolve_expr_stack(p, tok.loc, &opns, &oprs, FUNC_CALL_PREC) < 0)
goto err;
struct fh_p_expr *container;
if (fh_pop(&opns, &container) < 0) {
fh_parse_error(p, tok.loc, "syntax error (no container on stack!)");
goto err;
}

expr = new_expr(p, tok.loc, EXPR_INDEX);
if (! expr) {
fh_free_expr(container);
goto err;
}
expr->data.index.container = container;
expr->data.index.index = parse_expr(p, true, "]");
if (expr->data.index.index == NULL) {
free(expr);
fh_free_expr(container);
goto err;
}
}

if (! fh_push(&opns, &expr)) {
fh_parse_error_oom(p, tok.loc);
fh_free_expr(expr);
goto err;
}
continue;
}

/* operator */
if (tok_is_op(p, &tok, NULL)) {
if (expect_opn) {
Expand Down
6 changes: 3 additions & 3 deletions src/lib/program.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ struct fh_program *fh_new_program(void)

void fh_free_program(struct fh_program *prog)
{
fh_free_stack(&prog->funcs);
fh_free_stack(&prog->c_vals);
fh_collect_garbage(prog);
fh_free_program_objects(prog);

fh_free_stack(&prog->funcs);
fh_destroy_vm(&prog->vm);
fh_destroy_compiler(&prog->compiler);
fh_destroy_parser(&prog->parser);
Expand Down Expand Up @@ -100,13 +100,13 @@ int fh_compile_file(struct fh_program *prog, const char *filename)

in = fh_open_input_file(filename);
if (! in) {
fh_set_error(prog, "ERROR: can't open '%s'", filename);
fh_set_error(prog, "can't open '%s'", filename);
goto err;
}

ast = fh_new_ast();
if (! ast) {
fh_set_error(prog, "ERROR: out of memory for AST");
fh_set_error(prog, "out of memory for AST");
goto err;
}
if (fh_parse(&prog->parser, ast, in) < 0)
Expand Down
Loading

0 comments on commit dd96d82

Please sign in to comment.