Remove syntax distinction between builtin and user calls
This commit is contained in:
1 parent
6c8b55793a
commit
dc6cf2fb58
8 files changed
+68
-19
No files matched your search
+43
-2
@@ -14,6 +14,7 @@ struct inst {
|
|||||||
uint16_t intval;
|
uint16_t intval;
|
||||||
struct inst* target;
|
struct inst* target;
|
||||||
json_t* constant;
|
json_t* constant;
|
||||||
|
struct cfunction* cfunc;
|
||||||
} imm;
|
} imm;
|
||||||
|
|
||||||
// Binding
|
// Binding
|
||||||
@@ -311,6 +312,16 @@ block gen_else(block a, block b) {
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
block gen_cbinding(struct symbol_table* t, block code) {
|
||||||
|
for (int cfunc=0; cfunc<t->ncfunctions; cfunc++) {
|
||||||
|
inst* i = inst_new(CLOSURE_CREATE_C);
|
||||||
|
i->imm.cfunc = &t->cfunctions[cfunc];
|
||||||
|
i->symbol = strdup(i->imm.cfunc->name);
|
||||||
|
code = block_bind(inst_block(i), code, OP_IS_CALL_PSEUDO);
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
static uint16_t nesting_level(struct bytecode* bc, inst* target) {
|
static uint16_t nesting_level(struct bytecode* bc, inst* target) {
|
||||||
uint16_t level = 0;
|
uint16_t level = 0;
|
||||||
assert(bc && target->compiled);
|
assert(bc && target->compiled);
|
||||||
@@ -322,6 +333,16 @@ static uint16_t nesting_level(struct bytecode* bc, inst* target) {
|
|||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int count_cfunctions(block b) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static void compile(struct bytecode* bc, block b) {
|
static void compile(struct bytecode* bc, block b) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int var_frame_idx = 0;
|
int var_frame_idx = 0;
|
||||||
@@ -349,6 +370,12 @@ static void compile(struct bytecode* bc, block b) {
|
|||||||
assert(curr->bound_by == curr);
|
assert(curr->bound_by == curr);
|
||||||
curr->imm.intval = bc->nclosures++;
|
curr->imm.intval = bc->nclosures++;
|
||||||
}
|
}
|
||||||
|
if (curr->op == CLOSURE_CREATE_C) {
|
||||||
|
assert(curr->bound_by == curr);
|
||||||
|
int idx = bc->globals->ncfunctions++;
|
||||||
|
bc->globals->cfunctions[idx] = *curr->imm.cfunc;
|
||||||
|
curr->imm.intval = idx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (bc->nsubfunctions) {
|
if (bc->nsubfunctions) {
|
||||||
bc->subfunctions = malloc(sizeof(struct bytecode*) * bc->nsubfunctions);
|
bc->subfunctions = malloc(sizeof(struct bytecode*) * bc->nsubfunctions);
|
||||||
@@ -374,6 +401,7 @@ static void compile(struct bytecode* bc, block b) {
|
|||||||
const struct opcode_description* op = opcode_describe(curr->op);
|
const struct opcode_description* op = opcode_describe(curr->op);
|
||||||
if (op->length == 0)
|
if (op->length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
uint16_t* opcode_rewrite = &code[pos];
|
||||||
code[pos++] = curr->op;
|
code[pos++] = curr->op;
|
||||||
int opflags = op->flags;
|
int opflags = op->flags;
|
||||||
assert(!(op->flags & OP_IS_CALL_PSEUDO));
|
assert(!(op->flags & OP_IS_CALL_PSEUDO));
|
||||||
@@ -381,6 +409,7 @@ static void compile(struct bytecode* bc, block b) {
|
|||||||
int nargs = curr->imm.intval;
|
int nargs = curr->imm.intval;
|
||||||
assert(nargs > 0);
|
assert(nargs > 0);
|
||||||
code[pos++] = (uint16_t)nargs;
|
code[pos++] = (uint16_t)nargs;
|
||||||
|
int desired_params;
|
||||||
for (int i=0; i<nargs; i++) {
|
for (int i=0; i<nargs; i++) {
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
assert(curr && opcode_describe(curr->op)->flags & OP_IS_CALL_PSEUDO);
|
assert(curr && opcode_describe(curr->op)->flags & OP_IS_CALL_PSEUDO);
|
||||||
@@ -389,12 +418,20 @@ static void compile(struct bytecode* bc, block b) {
|
|||||||
default: assert(0 && "Unknown type of argument");
|
default: assert(0 && "Unknown type of argument");
|
||||||
case CLOSURE_CREATE:
|
case CLOSURE_CREATE:
|
||||||
code[pos++] = curr->bound_by->imm.intval | ARG_NEWCLOSURE;
|
code[pos++] = curr->bound_by->imm.intval | ARG_NEWCLOSURE;
|
||||||
|
if (i == 0) desired_params = bc->subfunctions[curr->bound_by->imm.intval]->nclosures;
|
||||||
break;
|
break;
|
||||||
case CLOSURE_PARAM:
|
case CLOSURE_PARAM:
|
||||||
code[pos++] = curr->bound_by->imm.intval;
|
code[pos++] = curr->bound_by->imm.intval;
|
||||||
|
if (i == 0) desired_params = 0;
|
||||||
|
break;
|
||||||
|
case CLOSURE_CREATE_C:
|
||||||
|
code[pos++] = curr->bound_by->imm.intval;
|
||||||
|
*opcode_rewrite = bc->globals->cfunctions[curr->bound_by->imm.intval].callop;
|
||||||
|
if (i == 0) desired_params = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(nargs - 1 == desired_params);
|
||||||
} else if (opflags & OP_HAS_CONSTANT) {
|
} else if (opflags & OP_HAS_CONSTANT) {
|
||||||
code[pos++] = json_array_size(constant_pool);
|
code[pos++] = json_array_size(constant_pool);
|
||||||
json_array_append(constant_pool, curr->imm.constant);
|
json_array_append(constant_pool, curr->imm.constant);
|
||||||
@@ -427,11 +464,15 @@ static void compile(struct bytecode* bc, block b) {
|
|||||||
bc->nlocals = maxvar + 2; // FIXME: frames of size zero?
|
bc->nlocals = maxvar + 2; // FIXME: frames of size zero?
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bytecode* block_compile(struct symbol_table* syms, block b) {
|
struct bytecode* block_compile(block b) {
|
||||||
struct bytecode* bc = malloc(sizeof(struct bytecode));
|
struct bytecode* bc = malloc(sizeof(struct bytecode));
|
||||||
bc->parent = 0;
|
bc->parent = 0;
|
||||||
bc->globals = syms;
|
bc->globals = malloc(sizeof(struct symbol_table));
|
||||||
|
int ncfunc = count_cfunctions(b);
|
||||||
|
bc->globals->ncfunctions = 0;
|
||||||
|
bc->globals->cfunctions = malloc(sizeof(struct cfunction) * ncfunc);
|
||||||
compile(bc, b);
|
compile(bc, b);
|
||||||
|
assert(bc->globals->ncfunctions == ncfunc);
|
||||||
return bc;
|
return bc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -28,11 +28,14 @@ block gen_collect(block expr);
|
|||||||
block gen_assign(block expr);
|
block gen_assign(block expr);
|
||||||
block gen_else(block a, block b);
|
block gen_else(block a, block b);
|
||||||
|
|
||||||
|
block gen_cbinding(struct symbol_table* functions, block b);
|
||||||
|
|
||||||
void block_append(block* b, block b2);
|
void block_append(block* b, block b2);
|
||||||
block block_join(block a, block b);
|
block block_join(block a, block b);
|
||||||
block block_bind(block binder, block body, int bindflags);
|
block block_bind(block binder, block body, int bindflags);
|
||||||
|
|
||||||
struct bytecode* block_compile(struct symbol_table*, block);
|
struct bytecode* block_compile(block);
|
||||||
|
|
||||||
void block_free(block);
|
void block_free(block);
|
||||||
|
|
||||||
|
|
||||||
@@ -349,6 +349,9 @@ json_t* jq_next() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case CALL_BUILTIN_1_1: {
|
case CALL_BUILTIN_1_1: {
|
||||||
|
assert(*pc == 1); // no closure args allowed
|
||||||
|
pc++; // skip nclosures
|
||||||
|
pc++; // skip level
|
||||||
stackval top = stack_pop();
|
stackval top = stack_pop();
|
||||||
cfunc_input[0] = top.value;
|
cfunc_input[0] = top.value;
|
||||||
struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
|
struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
|
||||||
@@ -359,6 +362,9 @@ json_t* jq_next() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case CALL_BUILTIN_3_1: {
|
case CALL_BUILTIN_3_1: {
|
||||||
|
assert(*pc == 1); // no closure args allowed
|
||||||
|
pc++; // skip nclosures
|
||||||
|
pc++; // skip level
|
||||||
stackval top = stack_pop();
|
stackval top = stack_pop();
|
||||||
json_t* a = stack_pop().value;
|
json_t* a = stack_pop().value;
|
||||||
json_t* b = stack_pop().value;
|
json_t* b = stack_pop().value;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ void run_tests() {
|
|||||||
block program = compile(buf);
|
block program = compile(buf);
|
||||||
block_append(&program, gen_op_simple(YIELD));
|
block_append(&program, gen_op_simple(YIELD));
|
||||||
block_append(&program, gen_op_simple(BACKTRACK));
|
block_append(&program, gen_op_simple(BACKTRACK));
|
||||||
struct bytecode* bc = block_compile(&builtins, program);
|
struct bytecode* bc = block_compile(gen_cbinding(&builtins, program));
|
||||||
block_free(program);
|
block_free(program);
|
||||||
printf("Disassembly:\n");
|
printf("Disassembly:\n");
|
||||||
dump_disassembly(2, bc);
|
dump_disassembly(2, bc);
|
||||||
@@ -76,7 +76,7 @@ int main(int argc, char* argv[]) {
|
|||||||
if (argc == 1) { run_tests(); return 0; }
|
if (argc == 1) { run_tests(); return 0; }
|
||||||
block blk = compile(argv[1]);
|
block blk = compile(argv[1]);
|
||||||
block_append(&blk, block_join(gen_op_simple(YIELD), gen_op_simple(BACKTRACK)));
|
block_append(&blk, block_join(gen_op_simple(YIELD), gen_op_simple(BACKTRACK)));
|
||||||
struct bytecode* bc = block_compile(&builtins, blk);
|
struct bytecode* bc = block_compile(gen_cbinding(&builtins, blk));
|
||||||
block_free(blk);
|
block_free(blk);
|
||||||
dump_disassembly(0, bc);
|
dump_disassembly(0, bc);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|||||||
+2
-1
@@ -5,10 +5,11 @@
|
|||||||
#define CONSTANT OP_HAS_CONSTANT, 2
|
#define CONSTANT OP_HAS_CONSTANT, 2
|
||||||
#define VARIABLE (OP_HAS_VARIABLE | OP_HAS_BINDING), 3
|
#define VARIABLE (OP_HAS_VARIABLE | OP_HAS_BINDING), 3
|
||||||
#define BRANCH OP_HAS_BRANCH, 2
|
#define BRANCH OP_HAS_BRANCH, 2
|
||||||
#define CFUNC (OP_HAS_SYMBOL | OP_HAS_CFUNC), 2
|
#define CFUNC (OP_HAS_SYMBOL | OP_HAS_CFUNC | OP_HAS_VARIABLE_LENGTH_ARGLIST), 2
|
||||||
#define UFUNC (OP_HAS_UFUNC | OP_HAS_VARIABLE_LENGTH_ARGLIST), 2
|
#define UFUNC (OP_HAS_UFUNC | OP_HAS_VARIABLE_LENGTH_ARGLIST), 2
|
||||||
#define CLOSURE_PARAM_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0
|
#define CLOSURE_PARAM_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0
|
||||||
#define CLOSURE_CREATE_IMM (OP_HAS_BLOCK | OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0
|
#define CLOSURE_CREATE_IMM (OP_HAS_BLOCK | OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0
|
||||||
|
#define CLOSURE_CREATE_C_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0
|
||||||
#define CLOSURE_REF_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 2
|
#define CLOSURE_REF_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 2
|
||||||
|
|
||||||
#define OP(name, imm, in, out) \
|
#define OP(name, imm, in, out) \
|
||||||
|
|||||||
@@ -26,3 +26,4 @@ OP(RET, NONE, 1, 1)
|
|||||||
OP(CLOSURE_PARAM, CLOSURE_PARAM_IMM, 0, 0)
|
OP(CLOSURE_PARAM, CLOSURE_PARAM_IMM, 0, 0)
|
||||||
OP(CLOSURE_REF, CLOSURE_REF_IMM, 0, 0)
|
OP(CLOSURE_REF, CLOSURE_REF_IMM, 0, 0)
|
||||||
OP(CLOSURE_CREATE, CLOSURE_CREATE_IMM, 0, 0)
|
OP(CLOSURE_CREATE, CLOSURE_CREATE_IMM, 0, 0)
|
||||||
|
OP(CLOSURE_CREATE_C, CLOSURE_CREATE_C_IMM, 0, 0)
|
||||||
+6
-9
@@ -106,7 +106,7 @@ Exp '+' Exp {
|
|||||||
$$ = gen_noop();
|
$$ = gen_noop();
|
||||||
block_append(&$$, gen_subexp($1));
|
block_append(&$$, gen_subexp($1));
|
||||||
block_append(&$$, gen_subexp($3));
|
block_append(&$$, gen_subexp($3));
|
||||||
block_append(&$$, gen_op_symbol(CALL_BUILTIN_3_1, "_plus"));
|
block_append(&$$, gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, "_plus")));
|
||||||
} |
|
} |
|
||||||
|
|
||||||
Term {
|
Term {
|
||||||
@@ -158,21 +158,18 @@ NUMBER {
|
|||||||
block_append(&$$, $2);
|
block_append(&$$, $2);
|
||||||
block_append(&$$, gen_op_simple(POP));
|
block_append(&$$, gen_op_simple(POP));
|
||||||
} |
|
} |
|
||||||
IDENT {
|
|
||||||
$$ = gen_op_symbol(CALL_BUILTIN_1_1, $1);
|
|
||||||
} |
|
|
||||||
'$' IDENT {
|
'$' IDENT {
|
||||||
$$ = gen_op_var_unbound(LOADV, $2);
|
$$ = gen_op_var_unbound(LOADV, $2);
|
||||||
} |
|
} |
|
||||||
'$' '$' IDENT {
|
IDENT {
|
||||||
$$ = gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, $3));
|
$$ = gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, $1));
|
||||||
} |
|
} |
|
||||||
'$' '$' IDENT '(' Exp ')' {
|
IDENT '(' Exp ')' {
|
||||||
$$ = gen_op_call(CALL_1_1,
|
$$ = gen_op_call(CALL_1_1,
|
||||||
block_join(gen_op_block_unbound(CLOSURE_REF, $3),
|
block_join(gen_op_block_unbound(CLOSURE_REF, $1),
|
||||||
block_bind(gen_op_block_defn(CLOSURE_CREATE,
|
block_bind(gen_op_block_defn(CLOSURE_CREATE,
|
||||||
"lambda",
|
"lambda",
|
||||||
block_join($5, gen_op_simple(RET))),
|
block_join($3, gen_op_simple(RET))),
|
||||||
gen_noop(), OP_IS_CALL_PSEUDO)));
|
gen_noop(), OP_IS_CALL_PSEUDO)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -133,21 +133,21 @@ null
|
|||||||
# Oh god.
|
# Oh god.
|
||||||
#
|
#
|
||||||
|
|
||||||
def f: . + 1; def g: def g: . + 100; $$f | $$g | $$f; ($$f | $$g), $$g
|
def f: . + 1; def g: def g: . + 100; f | g | f; (f | g), g
|
||||||
3.0
|
3.0
|
||||||
106.0
|
106.0
|
||||||
105.0
|
105.0
|
||||||
|
|
||||||
def f: (1000,2000); $$f
|
def f: (1000,2000); f
|
||||||
123412345
|
123412345
|
||||||
1000
|
1000
|
||||||
2000
|
2000
|
||||||
|
|
||||||
[[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | $$g; $$f[0] | [$$f][0][1] | $$f]
|
[[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f]
|
||||||
"woo, testing!"
|
"woo, testing!"
|
||||||
[[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]]
|
[[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]]
|
||||||
|
|
||||||
def f(x): $$x | $$x; $$f([.], . + [42])
|
def f(x): x | x; f([.], . + [42])
|
||||||
[1,2,3]
|
[1,2,3]
|
||||||
[[[1,2,3]]]
|
[[[1,2,3]]]
|
||||||
[[1,2,3],42]
|
[[1,2,3],42]
|
||||||
|
|||||||
Reference in new issue
Block a user