// File: /workspace/github_c_makefile_star2_O2/janet-lang[P]janet/src/core/peg.c
// Function: peg_compile1
static uint32_t peg_compile1(Builder *b, Janet peg) {

    /* Keep track of the form being compiled for error purposes */
    Janet old_form = b->form;
    JanetTable *old_grammar = b->grammar;
    b->form = peg;

    /* Resolve keyword references */
    int i = JANET_RECURSION_GUARD;
    JanetTable *grammar = old_grammar;
    for (; i > 0 && janet_checktype(peg, JANET_KEYWORD); --i) {
        Janet nextPeg = janet_table_get_ex(grammar, peg, &grammar);
        if (!grammar || janet_checktype(nextPeg, JANET_NIL)) {
            nextPeg = (b->default_grammar == NULL)
                      ? janet_wrap_nil()
                      : janet_table_get(b->default_grammar, peg);
            if (janet_checktype(nextPeg, JANET_NIL)) {
                peg_panic(b, "unknown rule");
            }
        }
        peg = nextPeg;
        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 */
    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)) {
        default:
            peg_panic(b, "unexpected peg source");
            return 0;

        case JANET_BOOLEAN: {
            int n = janet_unwrap_boolean(peg);
            Reserve r = reserve(b, 2);
            emit_1(r, n ? RULE_NCHAR : RULE_NOTNCHAR, 0);
            break;
        }
        case JANET_NUMBER: {
            int32_t n = peg_getinteger(b, peg);
            Reserve r = reserve(b, 2);
            if (n < 0) {
                emit_1(r, RULE_NOTNCHAR, -n);
            } else {
                emit_1(r, RULE_NCHAR, n);
            }
            break;
        }
        case JANET_STRING: {
            const uint8_t *str = janet_unwrap_string(peg);
            int32_t len = janet_string_length(str);
            emit_bytes(b, RULE_LITERAL, len, str);
            break;
        }
        case JANET_BUFFER: {
            const JanetBuffer *buf = janet_unwrap_buffer(peg);
            emit_bytes(b, RULE_LITERAL, buf->count, buf->data);
            break;
        }
        case JANET_TABLE: {
            /* Build grammar table */
            JanetTable *new_grammar = janet_table_clone(janet_unwrap_table(peg));
            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;
        }
        case JANET_STRUCT: {
            /* Build grammar table */
            const JanetKV *st = janet_unwrap_struct(peg);
            JanetTable *new_grammar = janet_table(2 * janet_struct_capacity(st));
            for (int32_t i = 0; i < janet_struct_capacity(st); i++) {
                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;
        }
        case JANET_TUPLE: {
            const Janet *tup = janet_unwrap_tuple(peg);
            int32_t len = janet_tuple_length(tup);
            if (len == 0) peg_panic(b, "tuple in grammar must have non-zero length");
            if (janet_checkint(tup[0])) {
                int32_t n = janet_unwrap_integer(tup[0]);
                if (n < 0) {
                    peg_panicf(b, "expected non-negative integer, got %d", n);
                }
                spec_repeat(b, len, tup);
                break;
            }
            if (!janet_checktype(tup[0], JANET_SYMBOL))
                peg_panicf(b, "expected grammar command, found %v", tup[0]);
            const uint8_t *sym = janet_unwrap_symbol(tup[0]);
            const SpecialPair *sp = janet_strbinsearch(
                                        &peg_specials,
                                        sizeof(peg_specials) / sizeof(SpecialPair),
                                        sizeof(SpecialPair),
                                        sym);
            if (sp) {
                sp->special(b, len - 1, tup + 1);
            } else {
                peg_panicf(b, "unknown special %S", sym);
            }
            break;
        }
    }

    /* Increase depth again */
    b->depth++;
    b->form = old_form;
    b->grammar = old_grammar;
    return rule;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rsi, %rbx
movabsq $-0x800000000000, %r14  # imm = 0xFFFF800000000000
movabsq $-0x7800000000000, %rdx # imm = 0xFFF8800000000000
movq (%rdi), %rax
movq 0x28(%rdi), %rcx
movq %rcx, -0x38(%rbp)
movq %rdi, -0x30(%rbp)
movq %rsi, 0x28(%rdi)
leaq -0x48(%rbp), %r15
movq %rax, (%r15)
movl $0xfffffc00, %r13d      # imm = 0xFFFFFC00
leaq 0x1(%rdx), %rcx
movq %rcx, -0x50(%rbp)
movq %rax, -0x40(%rbp)
movq %rax, %rdi
movq %rbx, %r12
andq %r14, %r12
testl %r13d, %r13d
je 0x39962
movabsq $-0x5000000000000, %rax # imm = 0xFFFB000000000000
cmpq %rax, %r12
jne 0x39962
movq %rbx, %rsi
movq %r15, %rdx
callq 0x43cbd
movq -0x48(%rbp), %rdi
testq %rdi, %rdi
movq -0x30(%rbp), %r12
je 0x39914
movq %rax, %rcx
andq %r14, %rcx
movabsq $-0x7800000000000, %rdx # imm = 0xFFF8800000000000
cmpq %rdx, %rcx
jne 0x3994e
movq 0x8(%r12), %rdi
testq %rdi, %rdi
je 0x39928
movq %rbx, %rsi
callq 0x43c35
jmp 0x39931
movq -0x50(%rbp), %rdi
callq 0x4b313
movq %rax, %rcx
andq %r14, %rcx
movabsq $-0x7800000000000, %rdx # imm = 0xFFF8800000000000
cmpq %rdx, %rcx
je 0x39c91
movq -0x48(%rbp), %rdi
movq %rax, 0x28(%r12)
movq %rdi, (%r12)
incl %r13d
movq %rax, %rbx
jmp 0x398c9
testl %r13d, %r13d
je 0x39ca0
movabsq $-0x4000000000000, %r13 # imm = 0xFFFC000000000000
movq %rbx, %rsi
cmpq %r13, %r12
jne 0x39984
callq 0x43d50
jmp 0x39989
callq 0x43c35
movq %rax, %rcx
andq %r14, %rcx
movabsq $-0x7800000000000, %rdx # imm = 0xFFF8800000000000
cmpq %rdx, %rcx
jne 0x399bb
movq -0x30(%rbp), %rdi
subl $0x1, 0x30(%rdi)
jb 0x39cb0
movq 0x20(%rdi), %rax
testq %rax, %rax
je 0x399dd
movl -0x4(%rax), %r15d
jmp 0x399e0
movq -0x30(%rbp), %rcx
movq -0x38(%rbp), %rdx
movq %rdx, 0x28(%rcx)
movq -0x40(%rbp), %rdx
movq %rdx, (%rcx)
movq %rax, %xmm0
cvttsd2si %xmm0, %r15
jmp 0x39c27
xorl %r15d, %r15d
movabsq $-0x3000000000000, %rax # imm = 0xFFFD000000000000
cmpq %rax, %r12
je 0x39a24
movq -0x48(%rbp), %rax
cmpq %r13, %r12
jne 0x399fd
movq %rax, %r13
jmp 0x39a09
movq %rax, %r13
movq 0x28(%rax), %rax
testq %rax, %rax
jne 0x399fd
movl %r15d, %eax
cvtsi2sd %rax, %xmm0
callq 0x4b471
movq %r13, %rdi
movq %rbx, %rsi
movq %rax, %rdx
callq 0x43e19
movq %rbx, %xmm0
movq %rbx, %rcx
shrq $0x2f, %rcx
andl $0xf, %ecx
xorl %eax, %eax
ucomisd %xmm0, %xmm0
cmovpl %ecx, %eax
cmpl $0xb, %eax
ja 0x39cc5
leaq 0x29e90(%rip), %rcx     # 0x638dc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x30(%rbp), %r12
movq %r12, %rdi
movq %rbx, %rsi
callq 0x39e22
movl %eax, %r14d
pushq $0x2
popq %rsi
movq %r12, %rdi
callq 0x39d6e
testl %r14d, %r14d
js 0x39bfb
pushq $0x1
jmp 0x39c00
movq %rbx, %rdi
callq 0x4b1f1
movq %rax, %rdi
callq 0x44033
movq %rax, %r15
movq -0x48(%rbp), %rax
movq %rax, 0x28(%r15)
movq %r15, -0x48(%rbp)
movq -0x30(%rbp), %r12
movq %r15, (%r12)
leaq 0x2a4c5(%rip), %rdi     # 0x63f75
callq 0x439c6
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4b366
movq %r15, %rdi
movq %rax, %rsi
callq 0x43d50
andq %rax, %r14
movabsq $-0x7800000000000, %rcx # imm = 0xFFF8800000000000
cmpq %rcx, %r14
je 0x39cbc
movq %r12, %rdi
movq %rax, %rsi
callq 0x39872
movl %eax, %r15d
jmp 0x39c11
pushq $0x2
popq %r14
movq -0x30(%rbp), %r12
movq %r12, %rdi
movl %r14d, %esi
callq 0x39d6e
andl $0x1, %ebx
subl %ebx, %r14d
movq %rax, %rdi
movq %rdx, %rsi
movl %r14d, %edx
xorl %ecx, %ecx
jmp 0x39c0c
movq %rbx, %rdi
callq 0x4b1f1
movq %rax, %r12
movl -0x10(%rax), %edi
addl %edi, %edi
callq 0x43b8a
movq %rax, %r15
movq %r12, %rbx
addq $0x8, %rbx
xorl %r13d, %r13d
movslq -0x10(%r12), %rax
cmpq %rax, %r13
jge 0x39a95
movq -0x8(%rbx), %rsi
movq %rsi, %rax
andq %r14, %rax
movabsq $-0x5000000000000, %rcx # imm = 0xFFFB000000000000
cmpq %rcx, %rax
jne 0x39b78
movq (%rbx), %rdx
movq %r15, %rdi
callq 0x43e19
incq %r13
addq $0x10, %rbx
jmp 0x39b46
movq %rbx, %rdi
callq 0x4b1f1
movl -0x8(%rax), %esi
movq -0x30(%rbp), %r12
movq %r12, %rdi
movq %rax, %rdx
jmp 0x39bf4
movq %rbx, %rdi
callq 0x4b1f1
movl -0x10(%rax), %r12d
testl %r12d, %r12d
je 0x39cce
movq %rax, %r13
movq (%rax), %rdi
callq 0x45e2b
testl %eax, %eax
je 0x39c39
cvttsd2si (%r13), %esi
testl %esi, %esi
js 0x39cd7
movq -0x30(%rbp), %rdi
movl %r12d, %esi
movq %rdi, %r12
movq %r13, %rdx
callq 0x39f5f
jmp 0x39c11
movq %rbx, %rdi
callq 0x4b1f1
movl 0x10(%rax), %esi
movq 0x18(%rax), %rdx
movq -0x30(%rbp), %r12
movq %r12, %rdi
callq 0x39e65
jmp 0x39c11
negl %r14d
pushq $0x2
popq %rcx
movq %rax, %rdi
movq %rdx, %rsi
movl %ecx, %edx
movl %r14d, %ecx
callq 0x39e05
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rcx
incl 0x30(%r12)
movq %rcx, 0x28(%r12)
movq %rax, (%r12)
movl %r15d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%r13), %rsi
andq %rsi, %r14
movabsq $-0x5800000000000, %rax # imm = 0xFFFA800000000000
cmpq %rax, %r14
jne 0x39ce7
movq %rsi, %rdi
callq 0x4b1f1
movq %rax, %r14
leaq 0x44b6b(%rip), %rdi     # 0x7e7d0
pushq $0x36
popq %rsi
pushq $0x10
popq %rdx
movq %rax, %rcx
callq 0x44cee
testq %rax, %rax
je 0x39cf0
decl %r12d
addq $0x8, %r13
movq -0x30(%rbp), %rdi
movl %r12d, %esi
movq %rdi, %r12
movq %r13, %rdx
callq *0x8(%rax)
jmp 0x39c11
leaq 0x2a281(%rip), %rsi     # 0x63f19
movq %r12, %rdi
callq 0x39d47
leaq 0x2a27f(%rip), %rsi     # 0x63f26
movq -0x30(%rbp), %rdi
callq 0x39d47
leaq 0x2a288(%rip), %rsi     # 0x63f3f
callq 0x39d47
leaq 0x2a2b7(%rip), %rsi     # 0x63f7a
jmp 0x39c98
leaq 0x2a293(%rip), %rsi     # 0x63f5f
jmp 0x39ca7
leaq 0x2a2c1(%rip), %rsi     # 0x63f96
jmp 0x39ca7
leaq 0x2a2e3(%rip), %rdi     # 0x63fc1
xorl %eax, %eax
callq 0x3c0ed
jmp 0x39d01
leaq 0x2a2f9(%rip), %rdi     # 0x63fe7
jmp 0x39cfa
leaq 0x2a313(%rip), %rdi     # 0x6400a
movq %r14, %rsi
xorl %eax, %eax
callq 0x3c0ed
movq -0x30(%rbp), %rdi
movq %rax, %rsi
callq 0x39d47