Builtin functions defined in jq.
This commit is contained in:
1 parent
5b9bb64a88
commit
940f8c4270
5 files changed
+79
-20
No files matched your search
+22
-3
@@ -1,5 +1,9 @@
|
||||
#include <string.h>
|
||||
#include "builtin.h"
|
||||
#include "compile.h"
|
||||
#include "parser.h"
|
||||
#include "locfile.h"
|
||||
|
||||
|
||||
static void f_plus(jv input[], jv output[]) {
|
||||
jv_free(input[0]);
|
||||
@@ -183,7 +187,7 @@ static struct cfunction function_list[] = {
|
||||
{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)();
|
||||
static bytecoded_builtin bytecoded_builtins[] = {
|
||||
@@ -194,10 +198,25 @@ static bytecoded_builtin bytecoded_builtins[] = {
|
||||
j_not,
|
||||
};
|
||||
|
||||
static const char* jq_builtins[] = {
|
||||
"def map(f): [.[] | f];"
|
||||
};
|
||||
|
||||
|
||||
block builtins_bind(block b) {
|
||||
block builtins = gen_noop();
|
||||
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
@@ -237,6 +237,16 @@ block block_join(block a, block b) {
|
||||
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) {
|
||||
assert(block_is_single(binder));
|
||||
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) {
|
||||
assert(block_has_only_binders(binder, bindflags));
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ block gen_cbinding(struct symbol_table* functions, block b);
|
||||
|
||||
void block_append(block* b, block b2);
|
||||
block block_join(block a, block b);
|
||||
int block_has_only_binders(block, int bindflags);
|
||||
block block_bind(block binder, block body, int bindflags);
|
||||
|
||||
int block_compile(block, struct locfile*, struct bytecode**);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "compile.h"
|
||||
#include "parser.tab.h"
|
||||
#include "builtin.h"
|
||||
#include "jv.h"
|
||||
#include "jv_parse.h"
|
||||
#include "locfile.h"
|
||||
#include "parser.h"
|
||||
|
||||
int jq_parse(struct locfile* source, block* answer);
|
||||
|
||||
void jq_init(struct bytecode* bc, jv value);
|
||||
jv jq_next();
|
||||
|
||||
+41
-14
@@ -79,7 +79,7 @@
|
||||
%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"
|
||||
#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:
|
||||
"def" IDENT ':' Exp ';' Exp {
|
||||
block body = block_join($4, gen_op_simple(RET));
|
||||
$$ = 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);
|
||||
FuncDef Exp %prec ';' {
|
||||
$$ = block_bind($1, $2, OP_IS_CALL_PSEUDO);
|
||||
} |
|
||||
|
||||
Term "as" '$' IDENT '|' Exp {
|
||||
@@ -273,6 +277,19 @@ Term {
|
||||
$$ = $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:
|
||||
/* empty */ {
|
||||
@@ -405,3 +422,13 @@ int jq_parse(struct locfile* locations, block* answer) {
|
||||
}
|
||||
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;
|
||||
}
|
||||
Reference in new issue
Block a user