jaf: loops

This commit is contained in:
Nunuhara Cabbage
2020-06-18 22:03:28 -07:00
parent f46f3ac28a
commit 0a7239ae0f
4 changed files with 287 additions and 152 deletions
+1
View File
@@ -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;
}
+261 -142
View File
@@ -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
+24 -9
View File
@@ -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)
+1 -1
View File
@@ -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;