// File: /workspace/github_c_makefile_star2_O3/mattn[P]orelang/ore.c
// Function: ore_call
static ore_value
ore_call(ore_context* ore, mpc_ast_t *t) {
  ore_value fn;
  const char* pfn = NULL;
  if (is_a(t->children[0], "ident")) {
    pfn = t->children[0]->contents;
    fn = ore_get(ore, pfn);
  } else if (is_a(t->children[0], "prop")) {
    pfn = t->children[0]->children[2]->contents;
    fn = ore_eval(ore, t->children[0]);
    if (fn.t == ORE_TYPE_NIL) {
      // FIXME
      ore_context* tmp = ore;
      ore_value inst = ore_eval(tmp, t->children[0]->children[0]);
      while (1) {
        inst = ore_prop(inst.v.o->e, "super");
        if (inst.t == ORE_TYPE_NIL)
          break;
        fn = ore_prop(inst.v.o->e, pfn);
        if (fn.t == ORE_TYPE_FUNC || fn.t == ORE_TYPE_CFUNC) {
          break;
        }
      }
    }
  } else {
    pfn = "<anonymous>";
    fn = ore_eval(ore, t->children[0]);
  }
  if (ore->err != ORE_ERROR_NONE)
    return ore_value_nil();
  if (fn.t != ORE_TYPE_FUNC && fn.t != ORE_TYPE_CFUNC) {
    fprintf(stderr, "unknown function '%s'\n", pfn);
    ore->err = ORE_ERROR_EXCEPTION;
    return ore_value_nil();
  }
  ore_value v = ore_value_nil();
  switch (fn.t) {
    case ORE_TYPE_CFUNC:
      {
        int num_in = t->children_num / 2 - 1, n = 0, i;
        if (num_in < fn.v.f.num_in || (fn.v.f.max_in != -1 && num_in > fn.v.f.max_in)) {
          fprintf(stderr, "number of arguments mismatch: %d for %d\n",
            num_in, fn.v.f.num_in);
          ore->err = ORE_ERROR_EXCEPTION;
          return ore_value_nil();
        }
        ore_value* args = (ore_value*) malloc(sizeof(ore_value) * num_in);
        if (!args) {
          fprintf(stderr, "failed to allocate memory\n");
          ore->err = ORE_ERROR_EXCEPTION;
          return ore_value_nil();
        }
        for (i = 2; i < t->children_num - 1; i += 2) {
          args[n++] = ore_eval(ore, t->children[i]);
        }
        v = ((ore_cfunc_t)fn.v.f.x.c) ((ore_context*) ore, num_in, args, fn.v.f.u);
        free(args);
      }
      break;
    case ORE_TYPE_FUNC:
      {
        ore_context* env = ore_new((ore_context*) fn.v.f.ore);
        mpc_ast_t* stmts = ore_find_statements(fn.v.f.x.o);
        if (stmts) {
          ore_value* args = ore_bind_args(ore, fn.v.f.x.o, env, t);
          v = ore_eval(env, stmts);
          if (env->err == ORE_ERROR_EXCEPTION)
            ore->err = env->err;
          char buf[64];
          sprintf(buf, "0x%p", env->env);
          ore_define(ore, buf, ore_value_env_from_context(env));
          free(args);
        }
      }
      break;
    default:
      fprintf(stderr, "invalid function call\n");
      ore->err = ORE_ERROR_EXCEPTION;
      return ore_value_nil();
  }
  return v;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movq %rdx, %r15
movq %rsi, %r14
movq %rdi, %r13
movq 0x30(%rdx), %rax
movq (%rax), %rbx
movq (%rbx), %r12
leaq 0x2f5c(%rip), %rsi      # 0x14b36
movq %r12, %rdi
callq 0x2290
testq %rax, %rax
movq %r13, 0x30(%rsp)
je 0x11c48
movq 0x8(%rbx), %rdx
leaq 0x80(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
movq %rdx, 0x28(%rsp)
callq 0xce0e
movl (%r13), %ebp
movq 0x8(%r13), %rbx
movq 0x10(%r13), %xmm1
movq 0x18(%r13), %r12
movq 0x20(%r13), %r13
cmpl $0x0, 0x20(%r14)
je 0x11dac
pxor %xmm0, %xmm0
movq 0x30(%rsp), %rax
movdqu %xmm0, 0x10(%rax)
movdqu %xmm0, (%rax)
movq $0x0, 0x20(%rax)
jmp 0x11fa9
leaq 0x2f27(%rip), %rsi      # 0x14b76
movq %r12, %rdi
callq 0x2290
testq %rax, %rax
je 0x11fbb
movq 0x30(%rbx), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, 0x28(%rsp)
leaq 0x80(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0xdc73
movl (%r13), %ebp
movq 0x8(%r13), %rbx
movq 0x10(%r13), %xmm1
movq 0x18(%r13), %r12
movq 0x20(%r13), %r13
testl %ebp, %ebp
jne 0x11c1e
movdqa %xmm1, 0x70(%rsp)
movq 0x30(%r15), %rax
movq (%rax), %rax
movq 0x30(%rax), %rax
movq (%rax), %rdx
leaq 0x80(%rsp), %rbp
movq %rbp, %rdi
movq %r14, 0x38(%rsp)
movq %r14, %rsi
callq 0xdc73
movq 0x8(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0x4435(%rip), %rdx      # 0x16115
leaq 0x40(%rsp), %r14
movq %r14, %rdi
callq 0xccb4
movq 0x20(%r14), %rax
movq %rax, 0x20(%rbp)
movdqu (%r14), %xmm0
movups 0x10(%r14), %xmm1
movaps %xmm1, 0x10(%rbp)
movdqa %xmm0, (%rbp)
cmpl $0x0, (%rbp)
je 0x11ff8
movq 0x88(%rsp), %r12
movq 0x10(%r12), %rsi
leaq 0x40(%rsp), %rdi
movq 0x28(%rsp), %rdx
callq 0xccb4
movl 0x40(%rsp), %ebp
movq 0x48(%rsp), %rbx
movsd 0x50(%rsp), %xmm0
movaps %xmm0, 0x70(%rsp)
movq 0x58(%rsp), %r14
movq 0x60(%rsp), %r13
movl %ebp, %eax
andl $-0x2, %eax
cmpl $0x8, %eax
je 0x11ffd
movq 0x10(%r12), %rsi
leaq 0x40(%rsp), %rdi
leaq 0x43aa(%rip), %rdx      # 0x16115
callq 0xccb4
movq 0x60(%rsp), %rax
movq %rax, 0xa0(%rsp)
movdqu 0x40(%rsp), %xmm0
movups 0x50(%rsp), %xmm1
movaps %xmm1, 0x90(%rsp)
movdqa %xmm0, 0x80(%rsp)
cmpl $0x0, 0x80(%rsp)
jne 0x11d12
jmp 0x11ffd
leaq 0x20(%r14), %rcx
leal -0xa(%rbp), %eax
cmpl $-0x3, %eax
jbe 0x12010
pxor %xmm0, %xmm0
movdqa %xmm0, 0x50(%rsp)
movdqa %xmm0, 0x40(%rsp)
movq $0x0, 0x60(%rsp)
cmpl $0x9, %ebp
jne 0x11ed1
movq %rcx, %rbp
movl 0x28(%r15), %ebx
movl %ebx, %eax
shrl $0x1f, %eax
addl %ebx, %eax
sarl %eax
leal -0x1(%rax), %edx
movd %xmm1, %ecx
cmpl %ecx, %eax
jle 0x12038
pshufd $0x55, %xmm1, %xmm0     # xmm0 = xmm1[1,1,1,1]
movd %xmm0, %eax
cmpl $-0x1, %eax
setne %sil
cmpl %eax, %edx
setg %al
andb %sil, %al
cmpb $0x1, %al
je 0x12038
movl %edx, 0x70(%rsp)
movslq %edx, %rax
shlq $0x3, %rax
leaq (%rax,%rax,4), %rdi
callq 0x21a0
movq %rax, 0x28(%rsp)
testq %rax, %rax
je 0x1206e
movq %r12, 0x38(%rsp)
cmpl $0x4, %ebx
jl 0x11eae
movl $0x2, %ebp
leaq 0x80(%rsp), %rbx
movq 0x28(%rsp), %r12
movq 0x30(%r15), %rax
movq (%rax,%rbp,8), %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0xdc73
movq 0xa0(%rsp), %rax
movq %rax, 0x20(%r12)
movdqu 0x80(%rsp), %xmm0
movdqu 0x90(%rsp), %xmm1
movdqu %xmm1, 0x10(%r12)
movdqu %xmm0, (%r12)
addq $0x2, %rbp
movslq 0x28(%r15), %rax
decq %rax
addq $0x28, %r12
cmpq %rax, %rbp
jl 0x11e5b
leaq 0x40(%rsp), %rdi
movq %r14, %rsi
movl 0x70(%rsp), %edx
movq 0x28(%rsp), %rbx
movq %rbx, %rcx
movq %r13, %r8
callq *0x38(%rsp)
movq %rbx, %rdi
jmp 0x11f81
movq %rcx, %rbp
movq %rbx, %rdi
callq 0xd661
movq %rax, %rbx
movq %r12, %rdi
callq 0x12282
testq %rax, %rax
je 0x11f86
movq %rax, %r13
movq %r14, %rdi
movq %r12, %rsi
movq %rbx, %rdx
movq %r15, %rcx
callq 0x128ac
movq %rax, %r15
leaq 0x40(%rsp), %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0xdc73
cmpl $0x1, 0x20(%rbx)
jne 0x11f24
movl $0x1, (%rbp)
movq (%rbx), %rdx
leaq 0x2c0e(%rip), %rsi      # 0x14b3c
leaq 0x80(%rsp), %r12
movq %r12, %rdi
xorl %eax, %eax
callq 0x2240
leaq 0xc0(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
callq 0xcc04
movq 0x20(%r13), %rax
movq %rax, 0x20(%rsp)
movdqu (%r13), %xmm0
movdqu 0x10(%r13), %xmm1
movdqu %xmm1, 0x10(%rsp)
movdqu %xmm0, (%rsp)
movq %r14, %rdi
movq %r12, %rsi
callq 0xd3c9
movq %r15, %rdi
callq 0x22c0
movq 0x60(%rsp), %rax
movq 0x30(%rsp), %rcx
movq %rax, 0x20(%rcx)
movdqa 0x40(%rsp), %xmm0
movdqa 0x50(%rsp), %xmm1
movdqu %xmm1, 0x10(%rcx)
movdqu %xmm0, (%rcx)
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x80(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0xdc73
movl (%r13), %ebp
movq 0x8(%r13), %rbx
movq 0x10(%r13), %xmm1
movq 0x18(%r13), %r12
movq 0x20(%r13), %r13
leaq 0x4132(%rip), %rax      # 0x16120
movq %rax, 0x28(%rsp)
jmp 0x11c1e
movq %r12, %r14
xorl %ebp, %ebp
movq %r14, %r12
movq 0x38(%rsp), %r14
movdqa 0x70(%rsp), %xmm1
jmp 0x11c1e
movq 0x9fe1(%rip), %rax      # 0x1bff8
movq %rcx, %rbx
movq (%rax), %rdi
leaq 0x4108(%rip), %rsi      # 0x1612c
movq 0x28(%rsp), %rdx
xorl %eax, %eax
callq 0x2160
movl $0x1, (%rbx)
jmp 0x12057
movq 0x9fb9(%rip), %rax      # 0x1bff8
movq (%rax), %rdi
leaq 0x2abd(%rip), %rsi      # 0x14b06
xorl %eax, %eax
callq 0x2160
movl $0x1, (%rbp)
pxor %xmm0, %xmm0
movq 0x30(%rsp), %rax
movdqu %xmm0, (%rax)
movdqu %xmm0, 0x10(%rax)
jmp 0x11c3b
movq %rbp, %rdi
movq 0x30(%rsp), %rsi
callq 0x28de
jmp 0x11fa9