// File: /workspace/github_c_makefile_star2_O3/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 0x69a1
movq %rsi, %r14
movq %rdi, %rbx
movq %rsi, %rdi
callq 0x66f6
movq %r14, %rdi
callq 0x1240
movl %eax, %r15d
movl %eax, %edi
movq %r14, %rsi
callq 0x1090
cmpl $0x23, %r15d
je 0x67b0
cmpl $-0x1, %r15d
jne 0x67dd
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x743d
movq %r14, %rdi
callq 0x1240
movq %r14, %rdi
callq 0x1240
cmpl $0x5c, %eax
je 0x6829
cmpl $0x66, %eax
je 0x6815
cmpl $0x74, %eax
jne 0x69c0
movq %rbx, %rdi
movl $0x1, %esi
jmp 0x681a
leal -0x30(%r15), %eax
cmpb $0x9, %al
ja 0x67fa
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x6398
cmpl $0x22, %r15d
jne 0x683e
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x6448
movq %rbx, %rdi
xorl %esi, %esi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x70c3
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x6250
movl %r15d, %eax
andb $-0x21, %al
addb $-0x41, %al
cmpb $0x1a, %al
jb 0x687d
movsbl %r15b, %esi
leaq 0x23dd(%rip), %rdi      # 0x8c31
movl $0xf, %edx
callq 0x1170
testq %rax, %rax
jne 0x687d
cmpb $0x2e, %r15b
ja 0x6892
movzbl %r15b, %eax
movabsq $0x680000000000, %rcx   # imm = 0x680000000000
btq %rax, %rcx
jae 0x6892
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x64c2
cmpl $0x2b, %r15d
jg 0x68c5
cmpl $0x27, %r15d
je 0x68f4
cmpl $0x28, %r15d
jne 0x69c5
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x6608
cmpl $0x2c, %r15d
je 0x6913
cmpl $0x60, %r15d
jne 0x69c5
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x675f
movq %rax, %r14
leaq 0x22c5(%rip), %rsi      # 0x8bb7
jmp 0x6968
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x675f
movq %rax, %r14
leaq 0x22ab(%rip), %rsi      # 0x8bbc
jmp 0x6968
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 0x6953
movq %r14, %rdi
callq 0x1240
movq %rbx, %rdi
movq %r14, %rsi
callq 0x675f
movq %rax, %r14
leaq 0x2271(%rip), %rsi      # 0x8bc2
jmp 0x6968
movq %rbx, %rdi
movq %r14, %rsi
callq 0x675f
movq %rax, %r14
leaq 0x226b(%rip), %rsi      # 0x8bd3
movq %rbx, %rdi
callq 0x71ce
movq %rax, %r15
movq %rbx, %rdi
callq 0x7071
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x7232
movq %rbx, %rdi
movq %r15, %rsi
movq %rax, %rdx
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x7232
leaq 0x21a6(%rip), %rdi      # 0x8b4e
leaq 0x21aa(%rip), %rsi      # 0x8b59
leaq 0x21b0(%rip), %rcx      # 0x8b66
movl $0x14b, %edx            # imm = 0x14B
callq 0x10f0
callq 0x2fca
callq 0x2fef
nop