// File: /workspace/github_c_makefile_star2_O0/ejunjsh[P]mycc/expr.c
// Function: binexpr
struct ASTnode *binexpr(int ptp) {
  struct ASTnode *left, *right;
  struct ASTnode *ltemp, *rtemp;
  int ASTop;
  int tokentype;

  // 获取树放在left
  // 同时获得下个token
  left = prefix(ptp);

  // 如果遇到下面终结token之一，直接返回这个left节点
  tokentype = Token.token;
  if (tokentype == T_SEMI || tokentype == T_RPAREN ||
      tokentype == T_RBRACKET || tokentype == T_COMMA ||
      tokentype == T_COLON || tokentype == T_RBRACE) {
    left->rvalue = 1;
    return (left);
  }

  // 当前token的优先级大于之前token的优先级(ptp)
  // 或者是右关联同时跟之前token的优先级(ptp)相等
  while ((op_precedence(tokentype) > ptp) ||
	 (rightassoc(tokentype) && op_precedence(tokentype) == ptp)) {
    // 获取下一个token
    scan(&Token);

    // 递归调用binexpr()，其参数就是当前的优先级
    // 创建子树放到right
    right = binexpr(OpPrec[tokentype]);

    // 判断操作符，执行相应操作
    ASTop = binastop(tokentype);

    switch (ASTop) {
    // 三元操作符 aaa?bbb:ccc
    case A_TERNARY:
      // 确认后面跟着的是':'
      match(T_COLON, ":");
      ltemp = binexpr(0);

      // 创建一个语法树节点，然后返回
      // 中间表达式（right）的类型作为该节点类型
      // TODO: 为什么不考虑下第三个表达式（left）的类型呢
      return (mkastnode
	      (A_TERNARY, right->type, right->ctype, left, right, ltemp,
	       NULL, 0));

    case A_ASSIGN:
      // 赋值
      // 令right树为右值
      right->rvalue = 1;

      // 保证right的类型匹配left的
      right = modify_type(right, left->type, left->ctype, 0);
      if (right == NULL)
	      fatal("Incompatible expression in assignment");

      // 交换right和left
      // 这样right表达式生成的汇编会在left表达式前面
      // 例如a=b+1,是不是b+1要先执行呢 
      ltemp = left;
      left = right;
      right = ltemp;
      break;

    default:
      // 如果没有三元或者赋值，那就把left和right树都变成右值
      left->rvalue = 1;
      right->rvalue = 1;

      // TODO: 对于A_ASPLUS等类型加上解引用是有问题等，mark之
      // if(ASTop==A_ASPLUS){
      //   left->rvalue = 0;
      // }

      // 保证这两个类型要兼容，
      // 如果兼容的话，修改其中一个树去匹配另外一个树
      ltemp = modify_type(left, right->type, right->ctype, ASTop);
      rtemp = modify_type(right, left->type, left->ctype, ASTop);
      if (ltemp == NULL && rtemp == NULL)
	      fatal("Incompatible types in binary expression");
      if (ltemp != NULL)
	      left = ltemp;
      if (rtemp != NULL)
	      right = rtemp;
    }

    // left和right合成一个新节点又放回left
    // 新节点的操作是从token类型转换过来的
    left =
      mkastnode(binastop(tokentype), left->type, left->ctype, left, NULL,
		right, NULL, 0);

    // 下面的操作符，都使节点类型变成整型，不管操作数是什么类型
    switch (binastop(tokentype)) {
    case A_LOGOR:
    case A_LOGAND:
    case A_EQ:
    case A_NE:
    case A_LT:
    case A_GT:
    case A_LE:
    case A_GE:
      left->type = P_INT;
    }

    // 获取最新的token类型
    // 如果到了结束token，返回left节点
    tokentype = Token.token;
    if (tokentype == T_SEMI || tokentype == T_RPAREN ||
        tokentype == T_RBRACKET || tokentype == T_COMMA ||
        tokentype == T_COLON || tokentype == T_RBRACE) {
      left->rvalue = 1;
      return (left);
    }
  }

  // 如果优先级一样或者更加低，直接返回
  left->rvalue = 1;
  return (left);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movl %edi, -0xc(%rbp)
movl -0xc(%rbp), %edi
callq 0x5bd0
movq %rax, -0x18(%rbp)
leaq 0xcc52(%rip), %rax      # 0x12530
movl (%rax), %eax
movl %eax, -0x38(%rbp)
cmpl $0x35, -0x38(%rbp)
je 0x5907
cmpl $0x3a, -0x38(%rbp)
je 0x5907
cmpl $0x3c, -0x38(%rbp)
je 0x5907
cmpl $0x3d, -0x38(%rbp)
je 0x5907
cmpl $0x40, -0x38(%rbp)
je 0x5907
cmpl $0x38, -0x38(%rbp)
jne 0x591f
movq -0x18(%rbp), %rax
movl $0x1, 0x18(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5bc0
jmp 0x5921
movl -0x38(%rbp), %edi
callq 0x5ec0
movl %eax, %ecx
movb $0x1, %al
cmpl -0xc(%rbp), %ecx
movb %al, -0x39(%rbp)
jg 0x5960
movl -0x38(%rbp), %edi
callq 0x5f30
movl %eax, %ecx
xorl %eax, %eax
cmpl $0x0, %ecx
movb %al, -0x3a(%rbp)
je 0x595a
movl -0x38(%rbp), %edi
callq 0x5ec0
cmpl -0xc(%rbp), %eax
sete %al
movb %al, -0x3a(%rbp)
movb -0x3a(%rbp), %al
movb %al, -0x39(%rbp)
movb -0x39(%rbp), %al
testb $0x1, %al
jne 0x596c
jmp 0x5bad
leaq 0xcbbd(%rip), %rdi      # 0x12530
callq 0x84c0
movslq -0x38(%rbp), %rcx
leaq 0xc89d(%rip), %rax      # 0x12220
movl (%rax,%rcx,4), %edi
callq 0x58c0
movq %rax, -0x20(%rbp)
movl -0x38(%rbp), %edi
callq 0x5f60
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
movl %eax, -0x40(%rbp)
subl $0x1, %eax
je 0x5a13
jmp 0x59a7
movl -0x40(%rbp), %eax
subl $0x7, %eax
jne 0x5a6c
jmp 0x59b5
movl $0x40, %edi
leaq 0x6bc4(%rip), %rsi      # 0xc585
callq 0x7f70
xorl %edi, %edi
callq 0x58c0
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rdx
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %r8
movq -0x28(%rbp), %r9
movl $0x7, %edi
xorl %eax, %eax
xorl %eax, %eax
movq $0x0, (%rsp)
movl $0x0, 0x8(%rsp)
callq 0xac90
movq %rax, -0x8(%rbp)
jmp 0x5bc0
movq -0x20(%rbp), %rax
movl $0x1, 0x18(%rax)
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdx
xorl %ecx, %ecx
callq 0xb800
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0x5a4f
leaq 0x7320(%rip), %rdi      # 0xcd6a
callq 0x8110
movq -0x18(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x5afa
movq -0x18(%rbp), %rax
movl $0x1, 0x18(%rax)
movq -0x20(%rbp), %rax
movl $0x1, 0x18(%rax)
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rdx
movl -0x34(%rbp), %ecx
callq 0xb800
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rdi
movq -0x18(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rdx
movl -0x34(%rbp), %ecx
callq 0xb800
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x5ada
cmpq $0x0, -0x30(%rbp)
jne 0x5ada
leaq 0x73d9(%rip), %rdi      # 0xceae
callq 0x8110
cmpq $0x0, -0x28(%rbp)
je 0x5ae9
movq -0x28(%rbp), %rax
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x5af8
movq -0x30(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x5afa
movl -0x38(%rbp), %edi
callq 0x5f60
movl %eax, %edi
movq -0x18(%rbp), %rcx
movl 0x8(%rcx), %esi
movq 0x10(%rcx), %rdx
movq -0x20(%rbp), %r9
movq %rsp, %rax
movl $0x0, 0x8(%rax)
movq $0x0, (%rax)
xorl %eax, %eax
movl %eax, %r8d
callq 0xac90
movq %rax, -0x18(%rbp)
movl -0x38(%rbp), %edi
callq 0x5f60
movl %eax, %ecx
movl %ecx, %eax
addl $-0x8, %eax
movl %ecx, -0x44(%rbp)
subl $0x2, %eax
jb 0x5b58
jmp 0x5b4b
movl -0x44(%rbp), %eax
addl $-0xd, %eax
subl $0x5, %eax
ja 0x5b63
jmp 0x5b58
movq -0x18(%rbp), %rax
movl $0x30, 0x8(%rax)
leaq 0xc9c6(%rip), %rax      # 0x12530
movl (%rax), %eax
movl %eax, -0x38(%rbp)
cmpl $0x35, -0x38(%rbp)
je 0x5b93
cmpl $0x3a, -0x38(%rbp)
je 0x5b93
cmpl $0x3c, -0x38(%rbp)
je 0x5b93
cmpl $0x3d, -0x38(%rbp)
je 0x5b93
cmpl $0x40, -0x38(%rbp)
je 0x5b93
cmpl $0x38, -0x38(%rbp)
jne 0x5ba8
movq -0x18(%rbp), %rax
movl $0x1, 0x18(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5bc0
jmp 0x5921
movq -0x18(%rbp), %rax
movl $0x1, 0x18(%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x60, %rsp
popq %rbp
retq
nopw (%rax,%rax)