From 0a7239ae0f7b92d1fc008961a67fe484c91f8d67 Mon Sep 17 00:00:00 2001 From: Nunuhara Cabbage Date: Thu, 18 Jun 2020 22:03:28 -0700 Subject: [PATCH] jaf: loops --- src/tools/ainedit/jaf_ast.c | 1 + src/tools/ainedit/jaf_compile.c | 403 +++++++++++++++--------- src/tools/ainedit/jaf_static_analysis.c | 33 +- src/tools/ainedit/jaf_types.c | 2 +- 4 files changed, 287 insertions(+), 152 deletions(-) diff --git a/src/tools/ainedit/jaf_ast.c b/src/tools/ainedit/jaf_ast.c index 2390dee..71b2e55 100644 --- a/src/tools/ainedit/jaf_ast.c +++ b/src/tools/ainedit/jaf_ast.c @@ -370,6 +370,7 @@ struct jaf_block_item *jaf_for_loop(struct jaf_block *init, struct jaf_block_ite item->for_loop.test = test->expr; item->for_loop.after = after; item->for_loop.body = body; + free(test); return item; } diff --git a/src/tools/ainedit/jaf_compile.c b/src/tools/ainedit/jaf_compile.c index dd2188f..18169ff 100644 --- a/src/tools/ainedit/jaf_compile.c +++ b/src/tools/ainedit/jaf_compile.c @@ -34,6 +34,23 @@ int yyparse(void); struct ain *jaf_ain_out; struct jaf_block *jaf_toplevel; +/* + * NOTE: We need to pass some state between calls to handle + * break/continue. + */ +struct loop_state { + size_t loop_addr; + size_t nr_breaks; + uint32_t *breaks; +}; + +struct compiler_state { + struct ain *ain; + struct buffer out; + size_t nr_loops; + struct loop_state *loops; +}; + int sym_type(char *name) { char *u = encode_text_to_input_format(name); @@ -46,32 +63,50 @@ int sym_type(char *name) return IDENTIFIER; } -static void write_opcode(struct buffer *out, uint16_t opcode) +static void start_loop(struct compiler_state *state) { - buffer_write_int16(out, opcode); + state->loops = xrealloc_array(state->loops, state->nr_loops, state->nr_loops+1, sizeof(struct loop_state)); + state->loops[state->nr_loops].loop_addr = state->out.index; + state->loops[state->nr_loops].nr_breaks = 0; + state->loops[state->nr_loops].breaks = NULL; + state->nr_loops++; } -static void write_argument(struct buffer *out, uint32_t arg) +static void end_loop(struct compiler_state *state) { - buffer_write_int32(out, arg); + struct loop_state *loop = &state->loops[--state->nr_loops]; + for (size_t i = 0; i < loop->nr_breaks; i++) { + buffer_write_int32_at(&state->out, loop->breaks[i], state->out.index); + } + free(loop->breaks); } -static void write_instruction0(struct buffer *out, uint16_t opcode) +static void write_opcode(struct compiler_state *state, uint16_t opcode) { - write_opcode(out, opcode); + buffer_write_int16(&state->out, opcode); } -static void write_instruction1(struct buffer *out, uint16_t opcode, uint32_t arg0) +static void write_argument(struct compiler_state *state, uint32_t arg) { - write_opcode(out, opcode); - write_argument(out, arg0); + buffer_write_int32(&state->out, arg); } -static void write_instruction2(struct buffer *out, uint16_t opcode, uint32_t arg0, uint32_t arg1) +static void write_instruction0(struct compiler_state *state, uint16_t opcode) { - write_opcode(out, opcode); - write_argument(out, arg0); - write_argument(out, arg1); + write_opcode(state, opcode); +} + +static void write_instruction1(struct compiler_state *state, uint16_t opcode, uint32_t arg0) +{ + write_opcode(state, opcode); + write_argument(state, arg0); +} + +static void write_instruction2(struct compiler_state *state, uint16_t opcode, uint32_t arg0, uint32_t arg1) +{ + write_opcode(state, opcode); + write_argument(state, arg0); + write_argument(state, arg1); } static uint32_t flo2int(float f) @@ -139,38 +174,39 @@ static enum opcode jaf_op_to_opcode(enum jaf_operator op, enum jaf_type type) } } -static void compile_block(struct ain *ain, struct buffer *out, struct jaf_block *block); -static void compile_expression(struct ain *ain, struct buffer *out, struct jaf_expression *expr); +static void compile_block(struct compiler_state *state, struct jaf_block *block); +static void compile_statement(struct compiler_state *state, struct jaf_block_item *item); +static void compile_expression(struct compiler_state *state, struct jaf_expression *expr); -static void compile_identifier(possibly_unused struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_identifier(struct compiler_state *state, struct jaf_expression *expr) { if (expr->ident.var_type == AIN_VAR_LOCAL) { - write_instruction0(out, PUSHLOCALPAGE); + write_instruction0(state, PUSHLOCALPAGE); } else if (expr->ident.var_type == AIN_VAR_GLOBAL) { - write_instruction0(out, PUSHGLOBALPAGE); + write_instruction0(state, PUSHGLOBALPAGE); } else { ERROR("Invalid variable type"); } - write_instruction1(out, PUSH, expr->ident.var_no); - write_instruction0(out, REF); + write_instruction1(state, PUSH, expr->ident.var_no); + write_instruction0(state, REF); } -static void compile_unary(struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_unary(struct compiler_state *state, struct jaf_expression *expr) { switch (expr->op) { case JAF_AMPERSAND: ERROR("Function types not supported"); case JAF_UNARY_PLUS: - compile_expression(ain, out, expr->expr); + compile_expression(state, expr->expr); break; case JAF_UNARY_MINUS: - write_instruction0(out, INV); + write_instruction0(state, INV); break; case JAF_BIT_NOT: - write_instruction0(out, COMPL); + write_instruction0(state, COMPL); break; case JAF_LOG_NOT: - write_instruction0(out, NOT); + write_instruction0(state, NOT); break; case JAF_PRE_INC: case JAF_PRE_DEC: @@ -182,17 +218,17 @@ static void compile_unary(struct ain *ain, struct buffer *out, struct jaf_expres } } -static void compile_lvalue(possibly_unused struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_lvalue(struct compiler_state *state, struct jaf_expression *expr) { if (expr->type == JAF_EXP_IDENTIFIER) { if (expr->ident.var_type == AIN_VAR_GLOBAL) { - write_instruction0(out, PUSHGLOBALPAGE); + write_instruction0(state, PUSHGLOBALPAGE); } else if (expr->ident.var_type == AIN_VAR_LOCAL) { - write_instruction0(out, PUSHLOCALPAGE); + write_instruction0(state, PUSHLOCALPAGE); } else { ERROR("Invalid variable type as lvalue"); } - write_instruction1(out, PUSH, expr->ident.var_no); + write_instruction1(state, PUSH, expr->ident.var_no); } else if (expr->type == JAF_EXP_MEMBER) { ERROR("struct member lvalues not supported"); } else { @@ -200,7 +236,7 @@ static void compile_lvalue(possibly_unused struct ain *ain, struct buffer *out, } } -static void compile_binary(struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_binary(struct compiler_state *state, struct jaf_expression *expr) { size_t addr[3]; switch (expr->op) { @@ -220,39 +256,39 @@ static void compile_binary(struct ain *ain, struct buffer *out, struct jaf_expre case JAF_BIT_XOR: case JAF_BIT_IOR: assert(expr->lhs->value_type.type == expr->rhs->value_type.type); - compile_expression(ain, out, expr->lhs); - compile_expression(ain, out, expr->rhs); - write_instruction0(out, jaf_op_to_opcode(expr->op, expr->value_type.type)); + compile_expression(state, expr->lhs); + compile_expression(state, expr->rhs); + write_instruction0(state, jaf_op_to_opcode(expr->op, expr->value_type.type)); break; case JAF_LOG_AND: - compile_expression(ain, out, expr->lhs); - addr[0] = out->index + 2; - write_instruction1(out, IFZ, 0); - compile_expression(ain, out, expr->rhs); - addr[1] = out->index + 2; - write_instruction1(out, IFZ, 0); - write_instruction1(out, PUSH, 1); - addr[2] = out->index + 2; - write_instruction1(out, JUMP, 0); - buffer_write_int32_at(out, addr[0], out->index); - buffer_write_int32_at(out, addr[1], out->index); - write_instruction1(out, PUSH, 0); - buffer_write_int32_at(out, addr[2], out->index); + compile_expression(state, expr->lhs); + addr[0] = state->out.index + 2; + write_instruction1(state, IFZ, 0); + compile_expression(state, expr->rhs); + addr[1] = state->out.index + 2; + write_instruction1(state, IFZ, 0); + write_instruction1(state, PUSH, 1); + addr[2] = state->out.index + 2; + write_instruction1(state, JUMP, 0); + buffer_write_int32_at(&state->out, addr[0], state->out.index); + buffer_write_int32_at(&state->out, addr[1], state->out.index); + write_instruction1(state, PUSH, 0); + buffer_write_int32_at(&state->out, addr[2], state->out.index); break; case JAF_LOG_OR: - compile_expression(ain, out, expr->lhs); - addr[0] = out->index + 2; - write_instruction1(out, IFNZ, 0); - compile_expression(ain, out, expr->rhs); - addr[1] = out->index + 2; - write_instruction1(out, IFNZ, 0); - write_instruction1(out, PUSH, 0); - addr[2] = out->index + 2; - write_instruction1(out, JUMP, 0); - buffer_write_int32_at(out, addr[0], out->index); - buffer_write_int32_at(out, addr[1], out->index); - write_instruction1(out, PUSH, 1); - buffer_write_int32_at(out, addr[2], out->index); + compile_expression(state, expr->lhs); + addr[0] = state->out.index + 2; + write_instruction1(state, IFNZ, 0); + compile_expression(state, expr->rhs); + addr[1] = state->out.index + 2; + write_instruction1(state, IFNZ, 0); + write_instruction1(state, PUSH, 0); + addr[2] = state->out.index + 2; + write_instruction1(state, JUMP, 0); + buffer_write_int32_at(&state->out, addr[0], state->out.index); + buffer_write_int32_at(&state->out, addr[1], state->out.index); + write_instruction1(state, PUSH, 1); + buffer_write_int32_at(&state->out, addr[2], state->out.index); break; case JAF_ASSIGN: case JAF_MUL_ASSIGN: @@ -266,55 +302,55 @@ static void compile_binary(struct ain *ain, struct buffer *out, struct jaf_expre case JAF_XOR_ASSIGN: case JAF_OR_ASSIGN: case JAF_REF_ASSIGN: - compile_lvalue(ain, out, expr->lhs); - compile_expression(ain, out, expr->rhs); - write_instruction0(out, jaf_op_to_opcode(expr->op, expr->value_type.type)); + compile_lvalue(state, expr->lhs); + compile_expression(state, expr->rhs); + write_instruction0(state, jaf_op_to_opcode(expr->op, expr->value_type.type)); break; default: ERROR("Invalid binary operator"); } } -static void compile_ternary(struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_ternary(struct compiler_state *state, struct jaf_expression *expr) { ERROR("Ternary operator not supported"); } -static void compile_funcall(struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_funcall(struct compiler_state *state, struct jaf_expression *expr) { for (size_t i = 0; i < expr->call.args->nr_items; i++) { - compile_expression(ain, out, expr->call.args->items[i]); + compile_expression(state, expr->call.args->items[i]); } - write_instruction1(out, CALLFUNC, expr->call.func_no); + write_instruction1(state, CALLFUNC, expr->call.func_no); } -static void compile_cast(struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_cast(struct compiler_state *state, struct jaf_expression *expr) { enum jaf_type src_type = expr->cast.expr->value_type.type; enum jaf_type dst_type = expr->cast.type; - compile_expression(ain, out, expr->cast.expr); + compile_expression(state, expr->cast.expr); if (src_type == dst_type) return; if (src_type == JAF_INT) { if (dst_type == JAF_FLOAT) { - write_instruction0(out, ITOF); + write_instruction0(state, ITOF); } else if (dst_type == JAF_STRING) { - write_instruction0(out, I_STRING); + write_instruction0(state, I_STRING); } else { goto invalid_cast; } } else if (src_type == JAF_FLOAT) { if (dst_type == JAF_INT) { - write_instruction0(out, FTOI); + write_instruction0(state, FTOI); } else if (dst_type == JAF_STRING) { - write_instruction0(out, FTOS); + write_instruction0(state, FTOS); } else { goto invalid_cast; } } else if (src_type == JAF_STRING) { if (dst_type == JAF_INT) { - write_instruction0(out, STOI); + write_instruction0(state, STOI); } else { goto invalid_cast; } @@ -324,47 +360,47 @@ invalid_cast: ERROR("Unsupported cast: %s to %s", jaf_typestr(src_type), jaf_typestr(dst_type)); } -static void compile_member(struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_member(struct compiler_state *state, struct jaf_expression *expr) { ERROR("struct member access not supported"); } -static void compile_expression(struct ain *ain, struct buffer *out, struct jaf_expression *expr) +static void compile_expression(struct compiler_state *state, struct jaf_expression *expr) { switch (expr->type) { case JAF_EXP_VOID: break; case JAF_EXP_INT: - write_instruction1(out, PUSH, expr->i); + write_instruction1(state, PUSH, expr->i); break; case JAF_EXP_FLOAT: - write_instruction1(out, F_PUSH, flo2int(expr->f)); + write_instruction1(state, F_PUSH, flo2int(expr->f)); break; case JAF_EXP_STRING: ERROR("strings not supported"); case JAF_EXP_IDENTIFIER: - compile_identifier(ain, out, expr); + compile_identifier(state, expr); break; case JAF_EXP_UNARY: - compile_unary(ain, out, expr); + compile_unary(state, expr); break; case JAF_EXP_BINARY: - compile_binary(ain, out, expr); + compile_binary(state, expr); break; case JAF_EXP_TERNARY: - compile_ternary(ain, out, expr); + compile_ternary(state, expr); break; //case JAF_EXP_SUBSCRIPT: //compile_subscript(ain, out, expr); //break; case JAF_EXP_FUNCALL: - compile_funcall(ain, out, expr); + compile_funcall(state, expr); break; case JAF_EXP_CAST: - compile_cast(ain, out, expr); + compile_cast(state, expr); break; case JAF_EXP_MEMBER: - compile_member(ain, out, expr); + compile_member(state, expr); break; //case JAF_EXP_SEQ: //compile_seq(ain, out, expr); @@ -372,32 +408,32 @@ static void compile_expression(struct ain *ain, struct buffer *out, struct jaf_e } } -static void compile_vardecl(struct ain *ain, struct buffer *out, struct jaf_declaration *decl) +static void compile_vardecl(struct compiler_state *state, struct jaf_declaration *decl) { switch (decl->type->type) { case JAF_VOID: ERROR("void variable declaration"); case JAF_INT: - write_instruction0(out, PUSHLOCALPAGE); - write_instruction1(out, PUSH, decl->var_no); + write_instruction0(state, PUSHLOCALPAGE); + write_instruction1(state, PUSH, decl->var_no); if (decl->init) { - compile_expression(ain, out, decl->init); + compile_expression(state, decl->init); } else { - write_instruction1(out, PUSH, 0); + write_instruction1(state, PUSH, 0); } - write_instruction0(out, ASSIGN); - write_instruction0(out, POP); + write_instruction0(state, ASSIGN); + write_instruction0(state, POP); break; case JAF_FLOAT: - write_instruction0(out, PUSHLOCALPAGE); - write_instruction1(out, PUSH, decl->var_no); + write_instruction0(state, PUSHLOCALPAGE); + write_instruction1(state, PUSH, decl->var_no); if (decl->init) { - compile_expression(ain, out, decl->init); + compile_expression(state, decl->init); } else { - write_instruction1(out, F_PUSH, 0); + write_instruction1(state, F_PUSH, 0); } - write_instruction0(out, F_ASSIGN); - write_instruction0(out, POP); + write_instruction0(state, F_ASSIGN); + write_instruction0(state, POP); break; case JAF_STRING: ERROR("strings not supported"); @@ -413,12 +449,103 @@ static void compile_vardecl(struct ain *ain, struct buffer *out, struct jaf_decl } } -static void compile_statement(struct ain *ain, struct buffer *out, struct jaf_block_item *item) +static void compile_if(struct compiler_state *state, struct jaf_expression *test, struct jaf_block_item *then, struct jaf_block_item *alt) +{ + uint32_t addr[3]; + compile_expression(state, test); + addr[0] = state->out.index + 2; + write_instruction1(state, IFNZ, 0); + addr[1] = state->out.index + 2; + write_instruction1(state, JUMP, 0); + buffer_write_int32_at(&state->out, addr[0], state->out.index); + compile_statement(state, then); + if (alt) { + addr[2] = state->out.index + 2; + write_instruction1(state, JUMP, 0); + buffer_write_int32_at(&state->out, addr[1], state->out.index); + compile_statement(state, alt); + buffer_write_int32_at(&state->out, addr[2], state->out.index); + } else { + buffer_write_int32_at(&state->out, addr[1], state->out.index); + } +} + +static void compile_while(struct compiler_state *state, struct jaf_expression *test, struct jaf_block_item *body) +{ + uint32_t addr; + // loop test + start_loop(state); + compile_expression(state, test); + addr = state->out.index + 2; + write_instruction1(state, IFZ, 0); + // loop body + compile_statement(state, body); + write_instruction1(state, JUMP, state->loops[state->nr_loops-1].loop_addr); + // loop end + buffer_write_int32_at(&state->out, addr, state->out.index); + end_loop(state); +} + +static void compile_do_while(struct compiler_state *state, struct jaf_expression *test, struct jaf_block_item *body) +{ + uint32_t addr[2]; + // skip loop test + addr[0] = state->out.index + 2; + write_instruction1(state, JUMP, 0); + // loop test + start_loop(state); + compile_expression(state, test); + addr[1] = state->out.index + 2; // address of address of loop end + write_instruction1(state, IFZ, 0); + // loop body + buffer_write_int32_at(&state->out, addr[0], state->out.index); + compile_statement(state, body); + write_instruction1(state, JUMP, state->loops[state->nr_loops-1].loop_addr); + // loop end + buffer_write_int32_at(&state->out, addr[1], state->out.index); + end_loop(state); +} + +static void compile_for(struct compiler_state *state, struct jaf_block *init, struct jaf_expression *test, struct jaf_expression *after, struct jaf_block_item *body) +{ + uint32_t addr[3]; + // loop init + compile_block(state, init); + // loop test + addr[0] = state->out.index; // address of loop test + compile_expression(state, test); + addr[1] = state->out.index + 2; // address of address of loop end + write_instruction1(state, IFZ, 0); + addr[2] = state->out.index + 2; // address of address of loop body + write_instruction1(state, JUMP, 0); + // loop increment + start_loop(state); + compile_expression(state, after); + write_instruction1(state, JUMP, addr[0]); + // loop body + buffer_write_int32_at(&state->out, addr[2], state->out.index); + compile_statement(state, body); + write_instruction1(state, JUMP, state->loops[state->nr_loops-1].loop_addr); + // loop end + buffer_write_int32_at(&state->out, addr[1], state->out.index); + end_loop(state); +} + +static void compile_break(struct compiler_state *state) +{ + if (state->nr_loops == 0) + ERROR("break outside of loop"); + struct loop_state *loop = &state->loops[state->nr_loops-1]; + loop->breaks = xrealloc_array(loop->breaks, loop->nr_breaks, loop->nr_breaks+1, sizeof(uint32_t)); + loop->breaks[loop->nr_breaks++] = state->out.index + 2; + write_instruction1(state, JUMP, 0); +} + +static void compile_statement(struct compiler_state *state, struct jaf_block_item *item) { - int addr[8]; switch (item->kind) { case JAF_DECLARATION: - compile_vardecl(ain, out, &item->decl); + compile_vardecl(state, &item->decl); break; case JAF_FUNDECL: ERROR("Nested functions not supported"); @@ -426,10 +553,10 @@ static void compile_statement(struct ain *ain, struct buffer *out, struct jaf_bl ERROR("Labels not supported"); break; case JAF_STMT_COMPOUND: - compile_block(ain, out, item->block); + compile_block(state, item->block); break; case JAF_STMT_EXPRESSION: - compile_expression(ain, out, item->expr); + compile_expression(state, item->expr); switch (item->expr->value_type.type) { case JAF_VOID: break; @@ -439,7 +566,7 @@ static void compile_statement(struct ain *ain, struct buffer *out, struct jaf_bl case JAF_STRUCT: // FIXME: this also needs a DELETE I think... case JAF_ENUM: case JAF_FUNCTION: - write_instruction0(out, POP); + write_instruction0(state, POP); break; // TODO: immediate ref types will need additional POP case JAF_TYPEDEF: @@ -447,46 +574,34 @@ static void compile_statement(struct ain *ain, struct buffer *out, struct jaf_bl } break; case JAF_STMT_IF: - compile_expression(ain, out, item->cond.test); - addr[0] = out->index + 2; - write_instruction1(out, IFNZ, 0); - addr[1] = out->index + 2; - write_instruction1(out, JUMP, 0); - buffer_write_int32_at(out, addr[0], out->index); - compile_statement(ain, out, item->cond.consequent); - if (item->cond.alternative) { - addr[2] = out->index + 2; - write_instruction1(out, JUMP, 0); - buffer_write_int32_at(out, addr[1], out->index); - compile_statement(ain, out, item->cond.alternative); - buffer_write_int32_at(out, addr[2], out->index); - } else { - buffer_write_int32_at(out, addr[1], out->index); - } + compile_if(state, item->cond.test, item->cond.consequent, item->cond.alternative); break; case JAF_STMT_SWITCH: ERROR("switch not supported"); break; case JAF_STMT_WHILE: - ERROR("while loops not supported"); + compile_while(state, item->while_loop.test, item->while_loop.body); break; case JAF_STMT_DO_WHILE: - ERROR("do-while loops not supported"); + compile_do_while(state, item->while_loop.test, item->while_loop.body); break; case JAF_STMT_FOR: - ERROR("for loops not supported"); + compile_for(state, item->for_loop.init, item->for_loop.test, item->for_loop.after, item->for_loop.body); break; case JAF_STMT_GOTO: ERROR("goto not supported"); case JAF_STMT_CONTINUE: + if (state->nr_loops == 0) + ERROR("continue outside of loop"); + write_instruction1(state, JUMP, state->loops[state->nr_loops-1].loop_addr); break; case JAF_STMT_BREAK: - ERROR("break not supported"); + compile_break(state); break; case JAF_STMT_RETURN: if (item->expr) - compile_expression(ain, out, item->expr); - write_instruction0(out, RETURN); + compile_expression(state, item->expr); + write_instruction0(state, RETURN); break; case JAF_STMT_CASE: ERROR("switch not supported"); @@ -497,26 +612,26 @@ static void compile_statement(struct ain *ain, struct buffer *out, struct jaf_bl } } -static void compile_block(struct ain *ain, struct buffer *out, struct jaf_block *block) +static void compile_block(struct compiler_state *state, struct jaf_block *block) { for (size_t i = 0; i < block->nr_items; i++) { - compile_statement(ain, out, block->items[i]); + compile_statement(state, block->items[i]); } } -static void compile_function(struct ain *ain, struct buffer *out, struct jaf_declaration *decl) +static void compile_function(struct compiler_state *state, struct jaf_declaration *decl) { - assert(decl->func_no >= 0 && decl->func_no < ain->nr_functions); - ain->functions[decl->func_no].address = out->index; - write_instruction1(out, FUNC, decl->func_no); - compile_block(ain, out, decl->body); - write_instruction1(out, ENDFUNC, decl->func_no); + assert(decl->func_no >= 0 && decl->func_no < state->ain->nr_functions); + state->ain->functions[decl->func_no].address = state->out.index; + write_instruction1(state, FUNC, decl->func_no); + compile_block(state, decl->body); + write_instruction1(state, ENDFUNC, decl->func_no); } -static void compile_declaration(struct ain *ain, struct buffer *code, struct jaf_block_item *decl) +static void compile_declaration(struct compiler_state *state, struct jaf_block_item *decl) { if (decl->kind == JAF_FUNDECL) { - compile_function(ain, code, &decl->decl); + compile_function(state, &decl->decl); return; } @@ -541,16 +656,20 @@ void jaf_compile(struct ain *out, const char *path) jaf_toplevel = jaf_static_analyze(out, jaf_toplevel); - struct buffer buf = { - .buf = out->code, - .size = out->code_size, - .index = out->code_size + struct compiler_state state = { + .ain = out, + .out = { + .buf = out->code, + .size = out->code_size, + .index = out->code_size + } }; for (size_t i = 0; i < jaf_toplevel->nr_items; i++) { - compile_declaration(out, &buf, jaf_toplevel->items[i]); + compile_declaration(&state, jaf_toplevel->items[i]); } - out->code = buf.buf; - out->code_size = buf.index; + free(state.loops); + out->code = state.out.buf; + out->code_size = state.out.index; // XXX: ain_add_initval adds initval to GSET section of the ain file. // If the original ain file did not have a GSET section, init diff --git a/src/tools/ainedit/jaf_static_analysis.c b/src/tools/ainedit/jaf_static_analysis.c index 530b868..24ec6e2 100644 --- a/src/tools/ainedit/jaf_static_analysis.c +++ b/src/tools/ainedit/jaf_static_analysis.c @@ -166,8 +166,27 @@ static void analyze_function(struct jaf_env *env, struct jaf_declaration *decl) free(funenv); } +static struct jaf_env *push_env(struct jaf_env *parent) +{ + struct jaf_env *newenv = xcalloc(1, sizeof(struct jaf_env)); + newenv->ain = parent->ain; + newenv->parent = parent; + newenv->func_no = parent->func_no; + newenv->fundecl = parent->fundecl; + return newenv; +} + +static struct jaf_env *pop_env(struct jaf_env *env) +{ + struct jaf_env *parent = env->parent; + free(env->locals); + free(env); + return parent; +} + static void analyze_statement(struct jaf_env *env, struct jaf_block_item *item) { + struct jaf_env *blockenv; if (!item) return; switch (item->kind) { @@ -204,10 +223,12 @@ static void analyze_statement(struct jaf_env *env, struct jaf_block_item *item) analyze_statement(env, item->while_loop.body); break; case JAF_STMT_FOR: - analyze_block(env, item->for_loop.init); + blockenv = push_env(env); + jaf_analyze_block(env, item->for_loop.init); analyze_expression(env, &item->for_loop.test); analyze_expression(env, &item->for_loop.after); analyze_statement(env, item->for_loop.body); + pop_env(blockenv); break; case JAF_STMT_RETURN: analyze_expression(env, &item->expr); @@ -233,15 +254,9 @@ static void jaf_analyze_block(struct jaf_env *env, struct jaf_block *block) static void analyze_block(struct jaf_env *env, struct jaf_block *block) { - struct jaf_env *blockenv = xcalloc(1, sizeof(struct jaf_env)); - blockenv->ain = env->ain; - blockenv->parent = env; - blockenv->func_no = env->func_no; - blockenv->fundecl = env->fundecl; - + struct jaf_env *blockenv = push_env(env); jaf_analyze_block(blockenv, block); - free(blockenv->locals); - free(blockenv); + pop_env(blockenv); } static void resolve_decl_types(struct ain *ain, struct jaf_declaration *decl) diff --git a/src/tools/ainedit/jaf_types.c b/src/tools/ainedit/jaf_types.c index bf84130..33af4b6 100644 --- a/src/tools/ainedit/jaf_types.c +++ b/src/tools/ainedit/jaf_types.c @@ -234,7 +234,7 @@ struct ain_variable *jaf_env_lookup(struct jaf_env *env, struct string *name, in char *u = encode_text_to_input_format(name->text); struct jaf_env *scope = env; while (scope) { - struct ain_variable *v = jaf_scope_lookup(env, u, var_no); + struct ain_variable *v = jaf_scope_lookup(scope, u, var_no); if (v) { free(u); return v;