Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support variable declaration in for loop setup #117

Merged
merged 1 commit into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#define MAX_FIELDS 32
#define MAX_FUNCS 512
#define MAX_FUNC_TRIES 2160
#define MAX_BLOCKS 1150
#define MAX_BLOCKS 2048
#define MAX_TYPES 64
#define MAX_IR_INSTR 36864
#define MAX_BB_PRED 128
Expand Down
94 changes: 73 additions & 21 deletions src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2326,60 +2326,110 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)

lex_expect(T_open_bracket);

/* synthesize for loop block */
block_t *blk = add_block(parent, parent->func, parent->macro);
add_ph1_ir(OP_block_start);

/* setup - execute once */
basic_block_t *setup = bb_create(blk);
bb_connect(bb, setup, NEXT);

if (!lex_accept(T_semicolon)) {
lex_peek(T_identifier, token);
read_body_assignment(token, parent, OP_generic, &bb);
if (!lex_peek(T_identifier, token))
error("Unexpected token");

int find_type_flag = lex_accept(T_struct) ? 2 : 1;
type = find_type(token, find_type_flag);
if (type) {
var = require_var(blk);
read_full_var_decl(var, 0, 0);
add_insn(blk, setup, OP_allocat, var, NULL, NULL, 0, NULL);
add_symbol(setup, var);
if (lex_accept(T_assign)) {
read_expr(blk, &setup);
read_ternary_operation(blk, &setup);

ph1_ir = add_ph1_ir(OP_assign);
ph1_ir->src0 = opstack_pop();
ph1_ir->dest = var;
add_insn(blk, setup, OP_assign, ph1_ir->dest, ph1_ir->src0,
NULL, 0, NULL);
}
while (lex_accept(T_comma)) {
var_t *nv;

/* add sequence point at T_comma */
perform_side_effect(blk, setup);

/* multiple (partial) declarations */
nv = require_var(blk);
read_partial_var_decl(nv, var); /* partial */
add_insn(blk, setup, OP_allocat, nv, NULL, NULL, 0, NULL);
add_symbol(setup, nv);
if (lex_accept(T_assign)) {
read_expr(blk, &setup);

ph1_ir = add_ph1_ir(OP_assign);
ph1_ir->src0 = opstack_pop();
ph1_ir->dest = nv;
add_insn(blk, setup, OP_assign, ph1_ir->dest,
ph1_ir->src0, NULL, 0, NULL);
}
}
} else {
read_body_assignment(token, blk, OP_generic, &setup);
}

lex_expect(T_semicolon);
}

basic_block_t *cond_ = bb_create(parent);
basic_block_t *cond_ = bb_create(blk);
basic_block_t *for_end = bb_create(parent);
break_bb[break_exit_idx] = for_end;
bb_connect(bb, cond_, NEXT);
bb_connect(setup, cond_, NEXT);
bb_connect(cond_, for_end, ELSE);

/* condition - check before the loop */
ph1_ir = add_ph1_ir(OP_label);
var_condition = require_var(parent);
var_condition = require_var(blk);
strcpy(var_condition->var_name, cond);
ph1_ir->src0 = var_condition;
if (!lex_accept(T_semicolon)) {
read_expr(parent, &cond_);
read_expr(blk, &cond_);
lex_expect(T_semicolon);
} else {
/* always true */
ph1_ir = add_ph1_ir(OP_load_constant);
vd = require_var(parent);
vd = require_var(blk);
vd->init_val = 1;
strcpy(vd->var_name, gen_name());
ph1_ir->dest = vd;
opstack_push(vd);
add_insn(parent, cond_, OP_load_constant, ph1_ir->dest, NULL, NULL,
0, NULL);
add_insn(blk, cond_, OP_load_constant, ph1_ir->dest, NULL, NULL, 0,
NULL);
}

ph1_ir = add_ph1_ir(OP_branch);
ph1_ir->dest = opstack_pop();
vd = require_var(parent);
vd = require_var(blk);
strcpy(vd->var_name, body);
ph1_ir->src0 = vd;
vd = require_var(parent);
vd = require_var(blk);
strcpy(vd->var_name, end);
ph1_ir->src1 = vd;
add_insn(parent, cond_, OP_branch, NULL, ph1_ir->dest, NULL, 0, NULL);
add_insn(blk, cond_, OP_branch, NULL, ph1_ir->dest, NULL, 0, NULL);

var_break = require_var(parent);
var_break = require_var(blk);
strcpy(var_break->var_name, end);

break_exit[break_exit_idx++] = var_break;

basic_block_t *inc_ = bb_create(parent);
basic_block_t *inc_ = bb_create(blk);
continue_bb[continue_pos_idx] = inc_;

/* increment after each loop */
ph1_ir = add_ph1_ir(OP_label);
var_inc = require_var(parent);
var_inc = require_var(blk);
strcpy(var_inc->var_name, inc);
ph1_ir->src0 = var_inc;

Expand All @@ -2391,25 +2441,25 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)
else if (lex_accept(T_decrement))
prefix_op = OP_sub;
lex_peek(T_identifier, token);
read_body_assignment(token, parent, prefix_op, &inc_);
read_body_assignment(token, blk, prefix_op, &inc_);
lex_expect(T_close_bracket);
}

/* jump back to condition */
ph1_ir = add_ph1_ir(OP_jump);
vd = require_var(parent);
vd = require_var(blk);
strcpy(vd->var_name, cond);
ph1_ir->dest = vd;

/* loop body */
ph1_ir = add_ph1_ir(OP_label);
vd = require_var(parent);
vd = require_var(blk);
strcpy(vd->var_name, body);
ph1_ir->src0 = vd;

basic_block_t *body_ = bb_create(parent);
basic_block_t *body_ = bb_create(blk);
bb_connect(cond_, body_, THEN);
body_ = read_body_statement(parent, body_);
body_ = read_body_statement(blk, body_);

if (body_) {
bb_connect(body_, inc_, NEXT);
Expand All @@ -2420,7 +2470,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)

/* jump to increment */
ph1_ir = add_ph1_ir(OP_jump);
vd = require_var(parent);
vd = require_var(blk);
strcpy(vd->var_name, inc);
ph1_ir->dest = vd;

Expand All @@ -2431,6 +2481,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)

continue_pos_idx--;
break_exit_idx--;
add_ph1_ir(OP_block_end);
return for_end;
}

Expand Down Expand Up @@ -2504,6 +2555,7 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb)

continue_pos_idx--;
break_exit_idx--;
add_ph1_ir(OP_block_end);
return do_while_end;
}

Expand Down
12 changes: 12 additions & 0 deletions tests/driver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -580,4 +580,16 @@ int main()
}
EOF

# Variables can be declared within a for-loop iteration
try_ 120 << EOF
int main()
{
int fac = 1;
for (int i = 1; i <= 5; i++) {
fac = fac * i;
}
return fac;
}
EOF

echo OK
2 changes: 1 addition & 1 deletion tests/snapshots/fib.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/hello.json

Large diffs are not rendered by default.