// File: /workspace/github_c_makefile_star2_O3/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 $0x38, %rsp
movq %rsi, %r12
movq %rdi, %r15
movabsq $-0x800000000000, %rcx  # imm = 0xFFFF800000000000
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
movabsq $-0x7800000000000, %rdx # imm = 0xFFF8800000000000
movq (%rdi), %rdi
movq 0x28(%r15), %rax
movq %rax, -0x48(%rbp)
movq %r12, 0x28(%r15)
movq %rdi, -0x38(%rbp)
movq %r12, %r14
andq %rcx, %r14
cmpq %rsi, %r14
movq %r15, -0x30(%rbp)
movq %rdi, -0x50(%rbp)
jne 0x3cca3
movl $0x400, %ebx            # imm = 0x400
leaq -0x38(%rbp), %r15
leaq 0x1(%rdx), %rax
movq %rax, -0x58(%rbp)
movq %r12, %rsi
movq %r15, %rdx
callq 0x47574
movq -0x38(%rbp), %rdi
testq %rdi, %rdi
je 0x3cc1a
movq %rax, %r13
movq %rax, %r14
movabsq $-0x800000000000, %rax  # imm = 0xFFFF800000000000
andq %rax, %r14
movabsq $-0x7800000000000, %rax # imm = 0xFFF8800000000000
cmpq %rax, %r14
jne 0x3cc64
movq -0x30(%rbp), %rax
movq 0x8(%rax), %rdi
testq %rdi, %rdi
je 0x3cc31
movq %r12, %rsi
callq 0x474e0
jmp 0x3cc3a
movq -0x58(%rbp), %rdi
callq 0x4ece6
movq %rax, %r13
movq %rax, %r14
movabsq $-0x800000000000, %rax  # imm = 0xFFFF800000000000
andq %rax, %r14
movabsq $-0x7800000000000, %rax # imm = 0xFFF8800000000000
cmpq %rax, %r14
je 0x3d094
movq -0x38(%rbp), %rdi
movq -0x30(%rbp), %rax
movq %r13, 0x28(%rax)
movq %rdi, (%rax)
leal -0x1(%rbx), %eax
cmpl $0x1, %ebx
je 0x3cc8f
movq %r13, %r12
movl %eax, %ebx
movabsq $-0x5000000000000, %rcx # imm = 0xFFFB000000000000
cmpq %rcx, %r14
je 0x3cbe4
testl %eax, %eax
movq -0x30(%rbp), %r15
jne 0x3cca6
leaq 0x2b268(%rip), %rsi     # 0x67f06
jmp 0x3d0ab
movq %r12, %r13
movabsq $-0x4000000000000, %rbx # imm = 0xFFFC000000000000
movq %r13, %rsi
cmpq %rbx, %r14
jne 0x3ccbf
callq 0x4760f
jmp 0x3ccc4
callq 0x474e0
movq %rax, %rcx
movabsq $-0x800000000000, %rdx  # imm = 0xFFFF800000000000
andq %rdx, %rcx
movabsq $-0x7800000000000, %rdx # imm = 0xFFF8800000000000
cmpq %rdx, %rcx
jne 0x3ccfd
subl $0x1, 0x30(%r15)
jb 0x3d0a4
movq 0x20(%r15), %rax
testq %rax, %rax
je 0x3cd1b
movl -0x4(%rax), %r15d
jmp 0x3cd1e
movq -0x48(%rbp), %rcx
movq %rcx, 0x28(%r15)
movq -0x50(%rbp), %rcx
movq %rcx, (%r15)
movq %rax, %xmm0
cvttsd2si %xmm0, %r15
jmp 0x3d082
xorl %r15d, %r15d
movabsq $-0x3000000000000, %rax # imm = 0xFFFD000000000000
cmpq %rax, %r14
je 0x3cd62
movq -0x38(%rbp), %rax
cmpq %rbx, %r14
jne 0x3cd3b
movq %rax, %r12
jmp 0x3cd47
movq %rax, %r12
movq 0x28(%rax), %rax
testq %rax, %rax
jne 0x3cd3b
movl %r15d, %eax
cvtsi2sd %rax, %xmm0
callq 0x4ee44
movq %r12, %rdi
movq %r13, %rsi
movq %rax, %rdx
callq 0x476f0
movq %r13, %xmm0
movq %r13, %rcx
shrq $0x2f, %rcx
andl $0xf, %ecx
xorl %eax, %eax
ucomisd %xmm0, %xmm0
cmovpl %ecx, %eax
cmpl $0xb, %eax
ja 0x3d0b3
leaq 0x2ab32(%rip), %rcx     # 0x678bc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x30(%rbp), %rbx
movq %rbx, %rdi
movq %r13, %rsi
callq 0x3d1db
movl %eax, %r14d
movq %rbx, %rdi
movl $0x2, %esi
callq 0x3d15c
movq %rax, %rdi
movq %rdx, %rsi
testl %r14d, %r14d
js 0x3cfea
leaq -0x3c(%rbp), %r8
movl %r14d, (%r8)
movl $0x1, %edx
jmp 0x3cff9
movq %r13, %rdi
callq 0x4ebc4
movq %rax, %rdi
callq 0x478f5
movq %rax, %r14
movq -0x38(%rbp), %rax
movq %rax, 0x28(%r14)
movq %r14, -0x38(%rbp)
movq -0x30(%rbp), %rbx
movq %r14, (%rbx)
leaq 0x2b156(%rip), %rdi     # 0x67f55
callq 0x47261
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4ed39
movq %r14, %rdi
movq %rax, %rsi
callq 0x4760f
movabsq $-0x800000000000, %rcx  # imm = 0xFFFF800000000000
andq %rax, %rcx
movabsq $-0x7800000000000, %rdx # imm = 0xFFF8800000000000
cmpq %rdx, %rcx
je 0x3cf5c
movq %rbx, %rdi
movq %rax, %rsi
callq 0x3cb74
movl %eax, %r15d
jmp 0x3d070
movl $0x2, %r12d
movq -0x30(%rbp), %rbx
movq %rbx, %rdi
movl $0x2, %esi
callq 0x3d15c
andl $0x1, %r13d
subl %r13d, %r12d
leaq -0x3c(%rbp), %r8
movl $0x0, (%r8)
movq %rax, %rdi
movq %rdx, %rsi
movl %r12d, %edx
movl $0x1, %ecx
callq 0x3d395
jmp 0x3d070
movq %r13, %rdi
callq 0x4ebc4
movq %rax, %r14
movl -0x10(%rax), %edi
addl %edi, %edi
callq 0x47425
movq %rax, %r15
movl -0x10(%r14), %eax
testl %eax, %eax
movabsq $-0x7800000000000, %r13 # imm = 0xFFF8800000000000
jle 0x3cf0a
movq %r14, %rbx
addq $0x8, %rbx
xorl %r12d, %r12d
movq -0x8(%rbx), %rsi
movq %rsi, %rcx
movabsq $-0x800000000000, %rdx  # imm = 0xFFFF800000000000
andq %rdx, %rcx
movabsq $-0x5000000000000, %rdx # imm = 0xFFFB000000000000
cmpq %rdx, %rcx
jne 0x3cefb
movq (%rbx), %rdx
movq %r15, %rdi
callq 0x476f0
movl -0x10(%r14), %eax
incq %r12
movslq %eax, %rcx
addq $0x10, %rbx
cmpq %rcx, %r12
jl 0x3cec9
movq -0x38(%rbp), %rax
movq %rax, 0x28(%r15)
movq %r15, -0x38(%rbp)
movq -0x30(%rbp), %rbx
movq %r15, (%rbx)
leaq 0x2b031(%rip), %rdi     # 0x67f55
callq 0x47261
movq %rax, %rdi
movabsq $-0x5000000000000, %rsi # imm = 0xFFFB000000000000
callq 0x4ed39
movq %r15, %rdi
movq %rax, %rsi
callq 0x4760f
movabsq $-0x800000000000, %rcx  # imm = 0xFFFF800000000000
andq %rax, %rcx
cmpq %r13, %rcx
jne 0x3ce41
leaq 0x2aff7(%rip), %rsi     # 0x67f5a
movq %rbx, %rdi
callq 0x3d135
movq %r13, %rdi
callq 0x4ebc4
movl -0x8(%rax), %esi
movq -0x30(%rbp), %rbx
movq %rbx, %rdi
movq %rax, %rdx
jmp 0x3cfe0
movq %r13, %rdi
callq 0x4ebc4
movl -0x10(%rax), %r12d
testl %r12d, %r12d
je 0x3d0bc
movq %rax, %r14
movq (%rax), %rdi
callq 0x49912
testl %eax, %eax
je 0x3d009
cvttsd2si (%r14), %esi
testl %esi, %esi
js 0x3d0c5
movq -0x30(%rbp), %rbx
movq %rbx, %rdi
movl %r12d, %esi
movq %r14, %rdx
callq 0x3d314
jmp 0x3d070
movq %r13, %rdi
callq 0x4ebc4
movl 0x10(%rax), %esi
movq 0x18(%rax), %rdx
movq -0x30(%rbp), %rbx
movq %rbx, %rdi
callq 0x3d21e
jmp 0x3d070
negl %r14d
leaq -0x3c(%rbp), %r8
movl %r14d, (%r8)
movl $0x2, %edx
movl $0x1, %ecx
callq 0x3d395
movq -0x30(%rbp), %rbx
jmp 0x3d070
movq (%r14), %rsi
movabsq $-0x800000000000, %rcx  # imm = 0xFFFF800000000000
andq %rsi, %rcx
movabsq $-0x5800000000000, %rax # imm = 0xFFFA800000000000
cmpq %rax, %rcx
jne 0x3d0d5
movq %rsi, %rdi
callq 0x4ebc4
movq %rax, %r13
leaq 0x46792(%rip), %rdi     # 0x837d0
movl $0x36, %esi
movl $0x10, %edx
movq %rax, %rcx
callq 0x48773
testq %rax, %rax
je 0x3d0de
decl %r12d
addq $0x8, %r14
movq -0x30(%rbp), %rbx
movq %rbx, %rdi
movl %r12d, %esi
movq %r14, %rdx
callq *0x8(%rax)
incl 0x30(%rbx)
movq -0x48(%rbp), %rax
movq %rax, 0x28(%rbx)
movq -0x50(%rbp), %rax
movq %rax, (%rbx)
movl %r15d, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2ae5e(%rip), %rsi     # 0x67ef9
movq -0x30(%rbp), %rdi
callq 0x3d135
leaq 0x2ae74(%rip), %rsi     # 0x67f1f
movq %r15, %rdi
callq 0x3d135
leaq 0x2ae85(%rip), %rsi     # 0x67f3f
jmp 0x3d09b
leaq 0x2aeb3(%rip), %rsi     # 0x67f76
jmp 0x3d09b
leaq 0x2aed5(%rip), %rdi     # 0x67fa1
xorl %eax, %eax
callq 0x3f652
jmp 0x3d0ef
leaq 0x2aeeb(%rip), %rdi     # 0x67fc7
jmp 0x3d0e8
leaq 0x2af05(%rip), %rdi     # 0x67fea
movq %r13, %rsi
xorl %eax, %eax
callq 0x3f652
movq -0x30(%rbp), %rdi
movq %rax, %rsi
callq 0x3d135