Builtin functions defined in jq.

This commit is contained in:
Stephen Dolan committed 2012-09-18 10:17:38 +01:00
1 parent 5b9bb64a88
commit 940f8c4270
5 files changed
+79 -20

No files matched your search

+22 -3
View File
@@ -1,5 +1,9 @@
#include <string.h>
#include "builtin.h" #include "builtin.h"
#include "compile.h" #include "compile.h"
#include "parser.h"
#include "locfile.h"
static void f_plus(jv input[], jv output[]) { static void f_plus(jv input[], jv output[]) {
jv_free(input[0]); jv_free(input[0]);
@@ -183,7 +187,7 @@ static struct cfunction function_list[] = {
{f_type, "type", CALL_BUILTIN_1_1}, {f_type, "type", CALL_BUILTIN_1_1},
}; };
static struct symbol_table builtins = {function_list, sizeof(function_list)/sizeof(function_list[0])}; static struct symbol_table cbuiltins = {function_list, sizeof(function_list)/sizeof(function_list[0])};
typedef block (*bytecoded_builtin)(); typedef block (*bytecoded_builtin)();
static bytecoded_builtin bytecoded_builtins[] = { static bytecoded_builtin bytecoded_builtins[] = {
@@ -194,10 +198,25 @@ static bytecoded_builtin bytecoded_builtins[] = {
j_not, j_not,
}; };
static const char* jq_builtins[] = {
"def map(f): [.[] | f];"
};
block builtins_bind(block b) { block builtins_bind(block b) {
block builtins = gen_noop();
for (unsigned i=0; i<sizeof(bytecoded_builtins)/sizeof(bytecoded_builtins[0]); i++) { for (unsigned i=0; i<sizeof(bytecoded_builtins)/sizeof(bytecoded_builtins[0]); i++) {
b = block_bind(bytecoded_builtins[i](), b, OP_IS_CALL_PSEUDO); block_append(&builtins, bytecoded_builtins[i]());
} }
return gen_cbinding(&builtins, b); for (unsigned i=0; i<sizeof(jq_builtins)/sizeof(jq_builtins[0]); i++) {
struct locfile src;
locfile_init(&src, jq_builtins[i], strlen(jq_builtins[i]));
block funcs;
int nerrors = jq_parse_library(&src, &funcs);
assert(!nerrors);
block_append(&builtins, funcs);
locfile_free(&src);
}
b = block_bind(builtins, b, OP_IS_CALL_PSEUDO);
return gen_cbinding(&cbuiltins, b);
} }
+14 -1
View File
@@ -237,6 +237,16 @@ block block_join(block a, block b) {
return c; return c;
} }
int block_has_only_binders(block binders, int bindflags) {
bindflags |= OP_HAS_BINDING;
for (inst* curr = binders.first; curr; curr = curr->next) {
if ((opcode_describe(curr->op)->flags & bindflags) != bindflags) {
return 0;
}
}
return 1;
}
static void block_bind_subblock(block binder, block body, int bindflags) { static void block_bind_subblock(block binder, block body, int bindflags) {
assert(block_is_single(binder)); assert(block_is_single(binder));
assert((opcode_describe(binder.first->op)->flags & bindflags) == bindflags); assert((opcode_describe(binder.first->op)->flags & bindflags) == bindflags);
@@ -260,8 +270,11 @@ static void block_bind_subblock(block binder, block body, int bindflags) {
} }
block block_bind(block binder, block body, int bindflags) { block block_bind(block binder, block body, int bindflags) {
assert(block_has_only_binders(binder, bindflags));
bindflags |= OP_HAS_BINDING; bindflags |= OP_HAS_BINDING;
block_bind_subblock(binder, body, bindflags); for (inst* curr = binder.first; curr; curr = curr->next) {
block_bind_subblock(inst_block(curr), body, bindflags);
}
return block_join(binder, body); return block_join(binder, body);
} }
+1
View File
@@ -43,6 +43,7 @@ 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);
int block_has_only_binders(block, int bindflags);
block block_bind(block binder, block body, int bindflags); block block_bind(block binder, block body, int bindflags);
int block_compile(block, struct locfile*, struct bytecode**); int block_compile(block, struct locfile*, struct bytecode**);
+1 -2
View File
@@ -1,13 +1,12 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "compile.h" #include "compile.h"
#include "parser.tab.h"
#include "builtin.h" #include "builtin.h"
#include "jv.h" #include "jv.h"
#include "jv_parse.h" #include "jv_parse.h"
#include "locfile.h" #include "locfile.h"
#include "parser.h"
int jq_parse(struct locfile* source, block* answer);
void jq_init(struct bytecode* bc, jv value); void jq_init(struct bytecode* bc, jv value);
jv jq_next(); jv jq_next();
+41 -14
View File
@@ -79,7 +79,7 @@
%left '*' '/' %left '*' '/'
%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody QQString %type <blk> Exp Term MkDict MkDictPair ExpD ElseBody QQString FuncDef FuncDefs
%{ %{
#include "lexer.yy.h" #include "lexer.yy.h"
#define FAIL(loc, msg) \ #define FAIL(loc, msg) \
@@ -160,21 +160,25 @@ static block gen_update(block a, block op, int optype) {
%} %}
%% %%
program: Exp { *answer = $1; } TopLevel:
Exp {
*answer = $1;
} |
FuncDefs {
*answer = $1;
}
FuncDefs:
/* empty */ {
$$ = gen_noop();
} |
FuncDef FuncDefs {
$$ = block_join($1, $2);
}
Exp: Exp:
"def" IDENT ':' Exp ';' Exp { FuncDef Exp %prec ';' {
block body = block_join($4, gen_op_simple(RET)); $$ = block_bind($1, $2, OP_IS_CALL_PSEUDO);
$$ = block_bind(gen_op_block_defn_rec(CLOSURE_CREATE, jv_string_value($2), body),
$6, OP_IS_CALL_PSEUDO);
jv_free($2);
} |
"def" IDENT '(' IDENT ')' ':' Exp ';' Exp {
block body = block_bind(gen_op_block_unbound(CLOSURE_PARAM, jv_string_value($4)), block_join($7, gen_op_simple(RET)), OP_IS_CALL_PSEUDO);
$$ = block_bind(gen_op_block_defn_rec(CLOSURE_CREATE, jv_string_value($2), body), $9, OP_IS_CALL_PSEUDO);
jv_free($2);
jv_free($4);
} | } |
Term "as" '$' IDENT '|' Exp { Term "as" '$' IDENT '|' Exp {
@@ -273,6 +277,19 @@ Term {
$$ = $1; $$ = $1;
} }
FuncDef:
"def" IDENT ':' Exp ';' {
block body = block_join($4, gen_op_simple(RET));
$$ = gen_op_block_defn_rec(CLOSURE_CREATE, jv_string_value($2), body);
jv_free($2);
} |
"def" IDENT '(' IDENT ')' ':' Exp ';' {
block body = block_bind(gen_op_block_unbound(CLOSURE_PARAM, jv_string_value($4)), block_join($7, gen_op_simple(RET)), OP_IS_CALL_PSEUDO);
$$ = gen_op_block_defn_rec(CLOSURE_CREATE, jv_string_value($2), body);
jv_free($2);
jv_free($4);
}
QQString: QQString:
/* empty */ { /* empty */ {
@@ -405,3 +422,13 @@ int jq_parse(struct locfile* locations, block* answer) {
} }
return errors; return errors;
} }
int jq_parse_library(struct locfile* locations, block* answer) {
int errs = jq_parse(locations, answer);
if (errs) return errs;
if (!block_has_only_binders(*answer, OP_IS_CALL_PSEUDO)) {
locfile_locate(locations, UNKNOWN_LOCATION, "error: library should only have function definitions, not a main expression");
return 1;
}
return 0;
}