// File: /workspace/github_c_makefile_star2_O1/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 %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
testq %rsi, %rsi
je 0x69e8
movq %rsi, %r14
movq %rdi, %rbx
movq %rsi, %rdi
callq 0x673d
movq %r14, %rdi
callq 0x1240
movl %eax, %r15d
movl %eax, %edi
movq %r14, %rsi
callq 0x1090
cmpl $0x23, %r15d
je 0x67f7
cmpl $-0x1, %r15d
jne 0x6824
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x7410
movq %r14, %rdi
callq 0x1240
movq %r14, %rdi
callq 0x1240
cmpl $0x5c, %eax
je 0x6870
cmpl $0x66, %eax
je 0x685c
cmpl $0x74, %eax
jne 0x6a07
movq %rbx, %rdi
movl $0x1, %esi
jmp 0x6861
leal -0x30(%r15), %eax
cmpb $0x9, %al
ja 0x6841
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x63ea
cmpl $0x22, %r15d
jne 0x6885
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x6495
movq %rbx, %rdi
xorl %esi, %esi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x7096
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x62a4
movl %r15d, %eax
andb $-0x21, %al
addb $-0x41, %al
cmpb $0x1a, %al
jb 0x68c4
movsbl %r15b, %esi
leaq 0x2396(%rip), %rdi      # 0x8c31
movl $0xf, %edx
callq 0x1170
testq %rax, %rax
jne 0x68c4
cmpb $0x2e, %r15b
ja 0x68d9
movzbl %r15b, %eax
movabsq $0x680000000000, %rcx   # imm = 0x680000000000
btq %rax, %rcx
jae 0x68d9
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x650f
cmpl $0x2b, %r15d
jg 0x690c
cmpl $0x27, %r15d
je 0x693b
cmpl $0x28, %r15d
jne 0x6a0c
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x664f
cmpl $0x2c, %r15d
je 0x695a
cmpl $0x60, %r15d
jne 0x6a0c
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x67a6
movq %rax, %r14
leaq 0x227e(%rip), %rsi      # 0x8bb7
jmp 0x69af
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x67a6
movq %rax, %r14
leaq 0x2264(%rip), %rsi      # 0x8bbc
jmp 0x69af
movq %r14, %rdi
callq 0x1240
movq %r14, %rdi
callq 0x1240
movl %eax, %ebp
movl %eax, %edi
movq %r14, %rsi
callq 0x1090
cmpl $0x40, %ebp
jne 0x699a
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x67a6
movq %rax, %r14
leaq 0x222a(%rip), %rsi      # 0x8bc2
jmp 0x69af
movq %rbx, %rdi
movq %r14, %rsi
callq 0x67a6
movq %rax, %r14
leaq 0x2224(%rip), %rsi      # 0x8bd3
movq %rbx, %rdi
callq 0x71a1
movq %rax, %r15
movq %rbx, %rdi
callq 0x7044
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x7205
movq %rbx, %rdi
movq %r15, %rsi
movq %rax, %rdx
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x7205
leaq 0x215f(%rip), %rdi      # 0x8b4e
leaq 0x2163(%rip), %rsi      # 0x8b59
leaq 0x2169(%rip), %rcx      # 0x8b66
movl $0x14b, %edx            # imm = 0x14B
callq 0x10f0
callq 0x2fca
callq 0x2fef
nopl (%rax)