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 "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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,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
@@ -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;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user