// File: /workspace/github_c_makefile_star2_O2/theandrew168[P]squeaky/src/reader.c
// Function: reader_read
struct value*
reader_read(struct vm* vm, FILE* fp)
{
    assert(fp != NULL);

    eat_whitespace(fp);
    int c = peek(fp);

    if (c == EOF) {
        return vm_make_eof(vm);
    }

    // sharp expr: boolean, character, vector, etc
    if (c == '#') {
        advance(fp);  // skip sharp
        c = advance(fp);
        if (c == 't') {
            return vm_make_boolean(vm, true);
        } else if (c == 'f') {
            return vm_make_boolean(vm, false);
        } else if (c == '\\') {
            return read_character(vm, fp);
        // TODO: read vectors
//        } else if (c == '(') {
//            return read_vector(fp);
        } else {
            fprintf(stderr, "reader: invalid sharp expression\n");
            exit(EXIT_FAILURE);
        }
    }

    // numeric literal
    if (is_digit(c)) {
        return read_number(vm, fp);
    }

    // string literal
    if (c == '"') {
        return read_string(vm, fp);
    }

    // symbol
    if (is_initial(c) || is_peculiar_identifier(c)) {
        return read_symbol(vm, fp);
    }

    // quoted expr
    if (c == '\'') {
        advance(fp);  // skip quote
        struct value* exp = reader_read(vm, fp);
        return vm_make_pair(vm, vm_make_symbol(vm, "quote"),
                                vm_make_pair(vm, exp,
                                                 vm_make_empty_list(vm)));
    }

    // quasiquoted expr
    if (c == '`') {
        advance(fp);  // skip quasiquote
        struct value* exp = reader_read(vm, fp);
        return vm_make_pair(vm, vm_make_symbol(vm, "quasiquote"),
                                vm_make_pair(vm, exp,
                                                 vm_make_empty_list(vm)));
    }

    // unquote / unquote-splicing expr
    if (c == ',') {
        advance(fp);  // skip unquote
        if (peek(fp) == '@') {
            advance(fp);  // skip splicing
            struct value* exp = reader_read(vm, fp);
            return vm_make_pair(vm, vm_make_symbol(vm, "unquote-splicing"),
                                    vm_make_pair(vm, exp,
                                                     vm_make_empty_list(vm)));
        }

        struct value* exp = reader_read(vm, fp);
        return vm_make_pair(vm, vm_make_symbol(vm, "unquote"),
                                vm_make_pair(vm, exp,
                                                 vm_make_empty_list(vm)));
    }

    // pair / list / s-expression
    if (c == '(') {
        advance(fp);  // skip opening paren
        return read_pair(vm, fp);
    }

    fprintf(stderr, "reader: invalid expression\n");
    exit(EXIT_FAILURE);
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
testq %rsi, %rsi
je 0x60b5
movq %rsi, %r14
movq %rdi, %rbx
movq %rsi, %rdi
callq 0x5e80
movq %r14, %rdi
callq 0x59ec
cmpl $0x23, %eax
je 0x5f10
movl %eax, %r15d
cmpl $-0x1, %eax
jne 0x5f3b
movq %rbx, %rdi
popq %rbx
popq %r14
popq %r15
jmp 0x6b19
movq %r14, %rdi
callq 0x1240
movq %r14, %rdi
callq 0x1240
cmpl $0x5c, %eax
je 0x5f78
cmpl $0x66, %eax
je 0x5f69
cmpl $0x74, %eax
jne 0x60d4
pushq $0x1
popq %rsi
movq %rbx, %rdi
jmp 0x5f6e
leal -0x30(%r15), %eax
cmpb $0x9, %al
ja 0x5f53
movq %rbx, %rdi
movq %r14, %rsi
popq %rbx
popq %r14
popq %r15
jmp 0x5aba
cmpl $0x22, %r15d
jne 0x5f88
movq %rbx, %rdi
movq %r14, %rsi
popq %rbx
popq %r14
popq %r15
jmp 0x5b78
movq %rbx, %rdi
xorl %esi, %esi
popq %rbx
popq %r14
popq %r15
jmp 0x676a
movq %rbx, %rdi
movq %r14, %rsi
popq %rbx
popq %r14
popq %r15
jmp 0x5938
movsbl %r15b, %edi
callq 0x610d
testb %al, %al
jne 0x5faf
cmpb $0x2e, %r15b
ja 0x5fbf
movzbl %r15b, %eax
movabsq $0x680000000000, %rcx   # imm = 0x680000000000
btq %rax, %rcx
jae 0x5fbf
movq %rbx, %rdi
movq %r14, %rsi
popq %rbx
popq %r14
popq %r15
jmp 0x5c2b
cmpl $0x60, %r15d
je 0x6035
cmpl $0x28, %r15d
je 0x6054
cmpl $0x2c, %r15d
je 0x6001
cmpl $0x27, %r15d
jne 0x60f8
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5ed2
movq %rax, %r14
leaq 0x1bc0(%rip), %rsi      # 0x7bbc
jmp 0x6081
movq %r14, %rdi
callq 0x1240
movq %r14, %rdi
callq 0x59ec
cmpl $0x40, %eax
jne 0x606c
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5ed2
movq %rax, %r14
leaq 0x1b8f(%rip), %rsi      # 0x7bc2
jmp 0x6081
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5ed2
movq %rax, %r14
leaq 0x1b65(%rip), %rsi      # 0x7bb7
jmp 0x6081
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
popq %rbx
popq %r14
popq %r15
jmp 0x5d91
movq %rbx, %rdi
movq %r14, %rsi
callq 0x5ed2
movq %rax, %r14
leaq 0x1b52(%rip), %rsi      # 0x7bd3
movq %rbx, %rdi
callq 0x6875
movq %rax, %r15
movq %rbx, %rdi
callq 0x66fc
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x68d9
movq %rbx, %rdi
movq %r15, %rsi
movq %rax, %rdx
popq %rbx
popq %r14
popq %r15
jmp 0x68d9
leaq 0x1a92(%rip), %rdi      # 0x7b4e
leaq 0x1a96(%rip), %rsi      # 0x7b59
leaq 0x1a9c(%rip), %rcx      # 0x7b66
movl $0x14b, %edx            # imm = 0x14B
callq 0x10f0
movq 0x5f05(%rip), %rax      # 0xbfe0
movq (%rax), %rcx
leaq 0x1ab0(%rip), %rdi      # 0x7b95
pushq $0x21
popq %rsi
pushq $0x1
popq %rdx
callq 0x1260
pushq $0x1
popq %rdi
callq 0x11b0
movq 0x5ee1(%rip), %rax      # 0xbfe0
movq (%rax), %rcx
leaq 0x1ad2(%rip), %rdi      # 0x7bdb
pushq $0x1b
jmp 0x60e7