}
-block gen_op_const(opcode op, jv constant) {
- assert(opcode_describe(op)->flags & OP_HAS_CONSTANT);
- inst* i = inst_new(op);
+block gen_const(jv constant) {
+ assert(opcode_describe(LOADK)->flags & OP_HAS_CONSTANT);
+ inst* i = inst_new(LOADK);
i->imm.constant = constant;
return inst_block(i);
}
return b;
}
-block gen_op_symbol(opcode op, const char* sym) {
- assert(opcode_describe(op)->flags & OP_HAS_SYMBOL);
- inst* i = inst_new(op);
- i->symbol = strdup(sym);
- return inst_block(i);
-}
-
block gen_op_block_unbound(opcode op, const char* name) {
assert(opcode_describe(op)->flags & OP_IS_CALL_PSEUDO);
inst* i = inst_new(op);
b->prev = a;
}
-static void block_insert_after(inst* i, block b) {
- if (b.first) {
- assert(b.last);
- if (i->next) {
- inst* j = i->next;
- i->next = 0;
- j->prev = 0;
- inst_join(b.last, j);
- }
- inst_join(i, b.first);
- }
-}
-
-static void block_insert_before(inst* i, block b) {
- if (b.first) {
- assert(b.last);
- if (i->prev) {
- inst* j = i->prev;
- i->prev = 0;
- j->next = 0;
- inst_join(j, b.first);
- }
- inst_join(b.last, i);
- }
-}
-
void block_append(block* b, block b2) {
if (b2.first) {
if (b->last) {
// bind this instruction
i->bound_by = binder.first;
}
- if (flags & OP_HAS_BLOCK) {
- // binding recurses into closures
- block_bind_subblock(binder, i->subfn, bindflags);
- }
- if (flags & OP_HAS_VARIABLE_LENGTH_ARGLIST) {
- // binding recurses into argument list
- block_bind_subblock(binder, i->arglist, bindflags);
- }
+ // binding recurses into closures
+ block_bind_subblock(binder, i->subfn, bindflags);
+ // binding recurses into argument list
+ block_bind_subblock(binder, i->arglist, bindflags);
}
}
block gen_collect(block expr) {
block array_var = block_bind(gen_op_var_unbound(STOREV, "collect"),
gen_noop(), OP_HAS_VARIABLE);
- block c = BLOCK(gen_op_simple(DUP), gen_op_const(LOADK, jv_array()), array_var);
+ block c = BLOCK(gen_op_simple(DUP), gen_const(jv_array()), array_var);
block tail = BLOCK(gen_op_simple(DUP),
gen_op_var_bound(LOADV, array_var),
// var found := false
block found_var = block_bind(gen_op_var_unbound(STOREV, "found"),
gen_noop(), OP_HAS_VARIABLE);
- block init = BLOCK(gen_op_simple(DUP), gen_op_const(LOADK, jv_false()), found_var);
+ block init = BLOCK(gen_op_simple(DUP), gen_const(jv_false()), found_var);
// if found, backtrack. Otherwise execute b
block backtrack = gen_op_simple(BACKTRACK);
// found := true, produce result
block if_found = BLOCK(gen_op_simple(DUP),
- gen_op_const(LOADK, jv_true()),
+ gen_const(jv_true()),
gen_op_var_bound(STOREV, found_var),
gen_op_target(JUMP, tail));
return BLOCK(gen_op_simple(DUP), a,
gen_condbranch(BLOCK(gen_op_simple(POP),
b,
- gen_condbranch(gen_op_const(LOADK, jv_true()),
- gen_op_const(LOADK, jv_false()))),
- BLOCK(gen_op_simple(POP), gen_op_const(LOADK, jv_false()))));
+ gen_condbranch(gen_const(jv_true()),
+ gen_const(jv_false()))),
+ BLOCK(gen_op_simple(POP), gen_const(jv_false()))));
}
block gen_or(block a, block b) {
// a or b = if a then true else (if b then true else false)
return BLOCK(gen_op_simple(DUP), a,
- gen_condbranch(BLOCK(gen_op_simple(POP), gen_op_const(LOADK, jv_true())),
+ gen_condbranch(BLOCK(gen_op_simple(POP), gen_const(jv_true())),
BLOCK(gen_op_simple(POP),
b,
- gen_condbranch(gen_op_const(LOADK, jv_true()),
- gen_op_const(LOADK, jv_false())))));
+ gen_condbranch(gen_const(jv_true()),
+ gen_const(jv_false())))));
}
block gen_cond(block cond, block iftrue, block iffalse) {
int n = 0;
for (inst* i = b.first; i; i = i->next) {
if (i->op == CLOSURE_CREATE_C) n++;
- if (opcode_describe(i->op)->flags & OP_HAS_BLOCK)
- n += count_cfunctions(i->subfn);
+ n += count_cfunctions(i->subfn);
}
return n;
}
static block expand_call_arglist(block b) {
block ret = gen_noop();
for (inst* curr; (curr = block_take(&b));) {
- if (opcode_describe(curr->op)->flags & OP_HAS_VARIABLE_LENGTH_ARGLIST) {
- assert(curr->op == CALL_JQ);
+ if (curr->op == CALL_JQ) {
inst* seq_end = block_take(&b);
assert(seq_end && seq_end->op == CALLSEQ_END);
// We expand the argument list as a series of instructions
curr->bound_by == curr) {
curr->imm.intval = var_frame_idx++;
}
- if (opflags & OP_HAS_BLOCK) {
+
+ if (curr->op == CLOSURE_CREATE) {
assert(curr->bound_by == curr);
curr->imm.intval = bc->nsubfunctions++;
}
-
if (curr->op == CLOSURE_PARAM) {
assert(curr->bound_by == curr);
curr->imm.intval = bc->nclosures++;
if (bc->nsubfunctions) {
bc->subfunctions = malloc(sizeof(struct bytecode*) * bc->nsubfunctions);
for (inst* curr = b.first; curr; curr = curr->next) {
- if (!(opcode_describe(curr->op)->flags & OP_HAS_BLOCK))
- continue;
- struct bytecode* subfn = malloc(sizeof(struct bytecode));
- bc->subfunctions[curr->imm.intval] = subfn;
- subfn->globals = bc->globals;
- subfn->parent = bc;
- errors += compile(locations, subfn, curr->subfn);
- curr->subfn = gen_noop();
+ if (curr->op == CLOSURE_CREATE) {
+ struct bytecode* subfn = malloc(sizeof(struct bytecode));
+ bc->subfunctions[curr->imm.intval] = subfn;
+ subfn->globals = bc->globals;
+ subfn->parent = bc;
+ errors += compile(locations, subfn, curr->subfn);
+ curr->subfn = gen_noop();
+ }
}
} else {
bc->subfunctions = 0;
if (op->length == 0)
continue;
code[pos++] = curr->op;
- int opflags = op->flags;
assert(!(op->flags & OP_IS_CALL_PSEUDO));
if (curr->op == CALL_BUILTIN) {
int nargs = curr->imm.intval;
assert(block_is_single(curr->arglist));
inst* cfunc = curr->arglist.first;
assert(cfunc && cfunc->bound_by->op == CLOSURE_CREATE_C);
- //*opcode_rewrite = bc->globals->cfunctions[cfunc->bound_by->imm.intval].callop;
code[pos++] = cfunc->bound_by->imm.intval;
// FIXME arg errors
assert(nargs == bc->globals->cfunctions[cfunc->bound_by->imm.intval].nargs);
- } else if (opflags & OP_HAS_VARIABLE_LENGTH_ARGLIST) {
- assert(curr->op == CALL_JQ);
+ } else if (curr->op == CALL_JQ) {
int nargs = curr->imm.intval;
assert(nargs >= 0 && nargs < 100); //FIXME
code[pos++] = (uint16_t)nargs;
assert(curr->bound_by->op == CLOSURE_CREATE);
code[pos++] = curr->bound_by->imm.intval | ARG_NEWCLOSURE;
}
- } else if (opflags & OP_HAS_CONSTANT) {
+ } else if (op->flags & OP_HAS_CONSTANT) {
code[pos++] = jv_array_length(jv_copy(constant_pool));
constant_pool = jv_array_append(constant_pool, jv_copy(curr->imm.constant));
- } else if (opflags & OP_HAS_VARIABLE) {
+ } else if (op->flags & OP_HAS_VARIABLE) {
code[pos++] = nesting_level(bc, curr->bound_by);
uint16_t var = (uint16_t)curr->bound_by->imm.intval;
code[pos++] = var;
if (var > maxvar) maxvar = var;
- } else if (opflags & OP_HAS_BRANCH) {
+ } else if (op->flags & OP_HAS_BRANCH) {
assert(curr->imm.target->bytecode_pos != -1);
assert(curr->imm.target->bytecode_pos > pos); // only forward branches
code[pos] = curr->imm.target->bytecode_pos - (pos + 1);
$$ = $1;
}
-String:
-QQSTRING_START QQString QQSTRING_END {
- $$ = $2;
-}
-
FuncDef:
"def" IDENT ':' Exp ';' {
$$ = gen_function(jv_string_value($2), $4);
jv_free($4);
}
+
+String:
+QQSTRING_START QQString QQSTRING_END {
+ $$ = $2;
+}
+
QQString:
/* empty */ {
- $$ = gen_op_const(LOADK, jv_string(""));
+ $$ = gen_const(jv_string(""));
} |
QQString QQSTRING_TEXT {
- $$ = gen_binop($1, gen_op_const(LOADK, $2), '+');
+ $$ = gen_binop($1, gen_const($2), '+');
} |
QQString QQSTRING_INTERP_START Exp QQSTRING_INTERP_END {
$$ = gen_binop($1, gen_format($3), '+');
$$ = gen_noop();
} |
Term '.' IDENT {
- $$ = gen_index($1, gen_op_const(LOADK, $3));
+ $$ = gen_index($1, gen_const($3));
} |
'.' IDENT {
- $$ = gen_index(gen_noop(), gen_op_const(LOADK, $2));
+ $$ = gen_index(gen_noop(), gen_const($2));
} |
/* FIXME: string literals */
Term '[' Exp ']' {
$$ = block_join($1, gen_op_simple(EACH));
} |
LITERAL {
- $$ = gen_op_const(LOADK, $1);
+ $$ = gen_const($1);
} |
String {
$$ = $1;
$$ = gen_collect($2);
} |
'[' ']' {
- $$ = gen_op_const(LOADK, jv_array());
+ $$ = gen_const(jv_array());
} |
'{' MkDict '}' {
- $$ = BLOCK(gen_subexp(gen_op_const(LOADK, jv_object())), $2, gen_op_simple(POP));
+ $$ = BLOCK(gen_subexp(gen_const(jv_object())), $2, gen_op_simple(POP));
} |
'$' IDENT {
$$ = gen_location(@$, gen_op_var_unbound(LOADV, jv_string_value($2)));
MkDictPair
: IDENT ':' ExpD {
- $$ = gen_dictpair(gen_op_const(LOADK, $1), $3);
+ $$ = gen_dictpair(gen_const($1), $3);
}
| String ':' ExpD {
$$ = gen_dictpair($1, $3);
}
| IDENT {
- $$ = gen_dictpair(gen_op_const(LOADK, jv_copy($1)),
- gen_index(gen_noop(), gen_op_const(LOADK, $1)));
+ $$ = gen_dictpair(gen_const(jv_copy($1)),
+ gen_index(gen_noop(), gen_const($1)));
}
| '(' Exp ')' ':' ExpD {
$$ = gen_dictpair($2, $5);