mirror of
https://github.com/janet-lang/janet
synced 2025-06-07 09:04:11 +00:00
Simplify peg caching further.
Remove the multiple caching tables we were using and use the grammar table for caching. This works well because we can use raw_get for checking the local cache, and normal get fro checking the global cache.
This commit is contained in:
parent
54a04b5894
commit
98eaadf2d1
@ -445,8 +445,6 @@ tail:
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
JanetTable *grammar;
|
JanetTable *grammar;
|
||||||
JanetTable *memoized;
|
|
||||||
JanetTable *memoized_scopes;
|
|
||||||
JanetTable *tags;
|
JanetTable *tags;
|
||||||
Janet *constants;
|
Janet *constants;
|
||||||
uint32_t *bytecode;
|
uint32_t *bytecode;
|
||||||
@ -881,16 +879,54 @@ static uint32_t peg_compile1(Builder *b, Janet peg) {
|
|||||||
|
|
||||||
/* Keep track of the form being compiled for error purposes */
|
/* Keep track of the form being compiled for error purposes */
|
||||||
Janet old_form = b->form;
|
Janet old_form = b->form;
|
||||||
|
JanetTable *old_grammar = b->grammar;
|
||||||
b->form = peg;
|
b->form = peg;
|
||||||
|
|
||||||
/* Check depth */
|
/* Resolve keyword references */
|
||||||
if (b->depth-- == 0) {
|
int i = JANET_RECURSION_GUARD;
|
||||||
peg_panic(b, "peg grammar recursed too deeply");
|
JanetTable *grammar = old_grammar;
|
||||||
|
for (; i > 0 && janet_checktype(peg, JANET_KEYWORD); --i) {
|
||||||
|
peg = janet_table_get_ex(grammar, peg, &grammar);
|
||||||
|
if (!grammar)
|
||||||
|
peg_panic(b, "unknown rule");
|
||||||
|
b->form = peg;
|
||||||
|
b->grammar = grammar;
|
||||||
}
|
}
|
||||||
|
if (i == 0)
|
||||||
|
peg_panic(b, "reference chain too deep");
|
||||||
|
|
||||||
|
/* Check cache - for tuples we check only the local cache, as
|
||||||
|
* in a different grammar, the same tuple can compile to a different
|
||||||
|
* rule - for example, (+ :a :b) depends on whatever :a and :b are bound to. */
|
||||||
|
Janet check = janet_checktype(peg, JANET_TUPLE)
|
||||||
|
? janet_table_rawget(grammar, peg)
|
||||||
|
: janet_table_get(grammar, peg);
|
||||||
|
if (!janet_checktype(check, JANET_NIL)) {
|
||||||
|
b->form = old_form;
|
||||||
|
b->grammar = old_grammar;
|
||||||
|
return (uint32_t) janet_unwrap_number(check);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check depth */
|
||||||
|
if (b->depth-- == 0)
|
||||||
|
peg_panic(b, "peg grammar recursed too deeply");
|
||||||
|
|
||||||
/* The final rule to return */
|
/* The final rule to return */
|
||||||
uint32_t rule = janet_v_count(b->bytecode);
|
uint32_t rule = janet_v_count(b->bytecode);
|
||||||
|
|
||||||
|
/* Add to cache. Do not cache structs, as we don't yet know
|
||||||
|
* what rule they will return! We can just as effectively cache
|
||||||
|
* the structs main rule. */
|
||||||
|
if (!janet_checktype(peg, JANET_STRUCT)) {
|
||||||
|
JanetTable *which_grammar = grammar;
|
||||||
|
/* If we are a primitive pattern, add to the global cache (root grammar table) */
|
||||||
|
if (!janet_checktype(peg, JANET_TUPLE)) {
|
||||||
|
while (which_grammar->proto)
|
||||||
|
which_grammar = which_grammar->proto;
|
||||||
|
}
|
||||||
|
janet_table_put(which_grammar, peg, janet_wrap_number(rule));
|
||||||
|
}
|
||||||
|
|
||||||
switch (janet_type(peg)) {
|
switch (janet_type(peg)) {
|
||||||
default:
|
default:
|
||||||
peg_panic(b, "unexpected peg source");
|
peg_panic(b, "unexpected peg source");
|
||||||
@ -911,37 +947,22 @@ static uint32_t peg_compile1(Builder *b, Janet peg) {
|
|||||||
emit_bytes(b, RULE_LITERAL, len, str);
|
emit_bytes(b, RULE_LITERAL, len, str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JANET_KEYWORD: {
|
|
||||||
/* Find rule in grammar */
|
|
||||||
JanetTable *scope = NULL;
|
|
||||||
Janet check = janet_table_get_ex(b->grammar, peg, &scope);
|
|
||||||
if (scope == NULL)
|
|
||||||
peg_panic(b, "unknown rule");
|
|
||||||
|
|
||||||
/* Check if we should compile as a recursion */
|
|
||||||
Janet memo_rule = janet_table_get(b->memoized, peg);
|
|
||||||
Janet memo_scope = janet_table_get(b->memoized_scopes, peg);
|
|
||||||
if (!janet_checktype(memo_rule, JANET_NIL) &&
|
|
||||||
scope == janet_unwrap_table(memo_scope)) {
|
|
||||||
rule = (uint32_t) janet_unwrap_number(memo_rule);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compile with rule and current scope memoized. This will
|
|
||||||
* let child rules refer to this rule for recursion */
|
|
||||||
janet_table_put(b->memoized, peg, janet_wrap_number(rule));
|
|
||||||
janet_table_put(b->memoized_scopes, peg, janet_wrap_table(scope));
|
|
||||||
rule = peg_compile1(b, check);
|
|
||||||
janet_table_put(b->memoized, peg, memo_rule);
|
|
||||||
janet_table_put(b->memoized_scopes, peg, memo_scope);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case JANET_STRUCT: {
|
case JANET_STRUCT: {
|
||||||
JanetTable *grammar = janet_struct_to_table(janet_unwrap_struct(peg));
|
/* Build grammar table */
|
||||||
grammar->proto = b->grammar;
|
const JanetKV *st = janet_unwrap_struct(peg);
|
||||||
b->grammar = grammar;
|
JanetTable *new_grammar = janet_table(2 * janet_struct_capacity(st));
|
||||||
rule = peg_compile1(b, janet_ckeywordv("main"));
|
for (int32_t i = 0; i < janet_struct_capacity(st); i++) {
|
||||||
b->grammar = grammar->proto;
|
if (janet_checktype(st[i].key, JANET_KEYWORD)) {
|
||||||
|
janet_table_put(new_grammar, st[i].key, st[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_grammar->proto = grammar;
|
||||||
|
b->grammar = grammar = new_grammar;
|
||||||
|
/* Run the main rule */
|
||||||
|
Janet main_rule = janet_table_rawget(grammar, janet_ckeywordv("main"));
|
||||||
|
if (janet_checktype(main_rule, JANET_NIL))
|
||||||
|
peg_panic(b, "grammar requires :main rule");
|
||||||
|
rule = peg_compile1(b, main_rule);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JANET_TUPLE: {
|
case JANET_TUPLE: {
|
||||||
@ -968,6 +989,7 @@ static uint32_t peg_compile1(Builder *b, Janet peg) {
|
|||||||
/* Increase depth again */
|
/* Increase depth again */
|
||||||
b->depth++;
|
b->depth++;
|
||||||
b->form = old_form;
|
b->form = old_form;
|
||||||
|
b->grammar = old_grammar;
|
||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1194,8 +1216,6 @@ static Peg *make_peg(Builder *b) {
|
|||||||
static Peg *compile_peg(Janet x) {
|
static Peg *compile_peg(Janet x) {
|
||||||
Builder builder;
|
Builder builder;
|
||||||
builder.grammar = janet_table(0);
|
builder.grammar = janet_table(0);
|
||||||
builder.memoized = janet_table(0);
|
|
||||||
builder.memoized_scopes = janet_table(0);
|
|
||||||
builder.tags = janet_table(0);
|
builder.tags = janet_table(0);
|
||||||
builder.constants = NULL;
|
builder.constants = NULL;
|
||||||
builder.bytecode = NULL;
|
builder.bytecode = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user