// File: /workspace/github_c_makefile_star2_O3/oridb[P]mc/parse/infer.c
// Function: inferpat
static void
inferpat(Node **np, Node *val, Node ***bind, size_t *nbind)
{
	size_t i;
	Node **args;
	Node *s, *n;
	Stab *ns;
	Type *t;

	n = *np;
	n = checkns(n, np);
	n->expr.ispat = 1;
	args = n->expr.args;
	for (i = 0; i < n->expr.nargs; i++)
		if (args[i]->type == Nexpr) {
			inferpat(&args[i], val, bind, nbind);
		}
	switch (exprop(n)) {
	case Otup:
	case Ostruct:
	case Oarr:
	case Olit:
	case Omemb:
	case Olor:
		infernode(np, NULL, NULL);
		break;
		/* arithmetic expressions just need to be constant */
	case Oneg:
	case Oadd:
	case Osub:
	case Omul:
	case Odiv:
	case Obsl:
	case Obsr:
	case Oband:
	case Obor:
	case Obxor:
	case Obnot:
		infernode(np, NULL, NULL);
		if (!n->expr.isconst)
			fatal(n, "matching against non-constant expression near %s", ctxstr(n));
		break;
	case Oucon:
		inferucon(n, &n->expr.isconst);
		break;
	case Ovar:
		ns = curstab();
		if (args[0]->name.ns)
			ns = getns(args[0]->name.ns);
		s = getdcl(ns, args[0]);
		if (s && !s->decl.ishidden) {
			if (s->decl.isgeneric)
				t = tysubst(s->decl.type, s->decl.type);
			else if (s->decl.isconst)
				t = s->decl.type;
			else
				fatal(n, "pattern shadows variable declared on %s:%d near %s",
						fname(s->loc), lnum(s->loc), ctxstr(s));
		} else {
			/* Scan the already collected bound variables in the pattern of this match case.
			 * If a bound variable with the same name is found, assign the variable the existing decl.
			 * Otherwise, create a new decl for the variable */
			s = NULL;
			for (i = 0; !s && i < *nbind; i++)
				if (nameeq(args[0], (*bind)[i]->decl.name))
					s = (*bind)[i];

			if (s) {
				t = s->decl.type;
			} else {
				t = mktyvar(n->loc);
				s = mkdecl(n->loc, n->expr.args[0], t);
				s->decl.init = val;
				settype(n, t);
				lappend(bind, nbind, s);
			}
		}
		settype(n, t);
		n->expr.did = s->decl.did;
		n->expr.isconst = s->decl.isconst;
		break;
	case Oaddr:
		infernode(np, NULL, NULL);
		break;
	case Ogap:
		infernode(np, NULL, NULL);	break;
	default: fatal(n, "invalid pattern"); break;
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %r12
movq (%rdi), %rdi
movq %r12, %rsi
callq 0x1c6e4
movq %rax, %rbx
movl $0x1, 0x34(%rax)
movq 0x40(%rax), %rax
movq 0x50(%rbx), %rcx
movq %rcx, (%rsp)
testq %rax, %rax
je 0x1babb
xorl %ebp, %ebp
movq (%rsp), %r13
movq (%r13), %rcx
cmpl $0x8, 0x8(%rcx)
jne 0x1baaf
movq %r13, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x1ba53
movq 0x40(%rbx), %rax
incq %rbp
addq $0x8, %r13
cmpq %rax, %rbp
jb 0x1ba93
movq %rbx, %rdi
callq 0x1d422
cmpl $0x11, %eax
jg 0x1bafd
leal -0x7(%rax), %ecx
cmpl $0x7, %ecx
jb 0x1bad8
addl $-0x2, %eax
cmpl $0x4, %eax
jae 0x1bb39
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x187ee
cmpl $0x0, 0x30(%rbx)
je 0x1bc98
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leal -0x2a(%rax), %ecx
cmpl $0xf, %ecx
ja 0x1bb2f
leaq 0x1a03c(%rip), %rax     # 0x35b48
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x187ee
cmpl $0x12, %eax
je 0x1bb15
cmpl $0x14, %eax
je 0x1bb15
leaq 0x1a958(%rip), %rsi     # 0x36498
movq %rbx, %rdi
xorl %eax, %eax
callq 0x138e7
movq %rbx, %rsi
addq $0x30, %rsi
movq %rbx, %rdi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1c7f2
callq 0x1fdf7
movq (%rsp), %rbp
movq (%rbp), %rsi
movq 0x18(%rsi), %rdi
testq %rdi, %rdi
je 0x1bb86
callq 0x1ffef
movq (%rbp), %rsi
movq %rax, %rdi
callq 0x20250
testq %rax, %rax
je 0x1bb9c
movq %rax, %r12
cmpb $0x0, 0x76(%rax)
je 0x1bc1a
xorl %r13d, %r13d
cmpq (%r14), %r13
jae 0x1bbd7
movq (%rbp), %rdi
movq (%r15), %rax
movq (%rax,%r13,8), %rax
movq 0x20(%rax), %rsi
callq 0x1e523
testl %eax, %eax
je 0x1bbc5
movq (%r15), %rax
movq (%rax,%r13,8), %r12
jmp 0x1bbc8
xorl %r12d, %r12d
incq %r13
testq %r12, %r12
je 0x1bb9f
movq 0x28(%r12), %r13
jmp 0x1bc32
movq (%rbx), %rdi
callq 0x22b29
movq %rax, %r13
movq (%rbx), %rdi
movq 0x50(%rbx), %rax
movq (%rax), %rsi
movq %r13, %rdx
callq 0x1e04f
movq %rax, %r12
movq $0x0, 0x30(%rax)
movq %rbx, %rdi
movq %r13, %rsi
callq 0x1c686
movq %r15, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x2ceff
jmp 0x1bc32
cmpb $0x0, 0x73(%r12)
je 0x1bc54
movq 0x28(%r12), %rdi
movq %rdi, %rsi
callq 0x1b658
movq %rax, %r13
movq %rbx, %rdi
movq %r13, %rsi
callq 0x1c686
movq 0x18(%r12), %rax
movq %rax, 0x38(%rbx)
movsbl 0x72(%r12), %eax
movl %eax, 0x30(%rbx)
jmp 0x1baee
cmpb $0x0, 0x72(%r12)
jne 0x1bbd0
movq (%r12), %rdi
callq 0x1d31c
movq %rax, %r14
movq (%r12), %rdi
callq 0x1d330
movl %eax, %ebp
movq %r12, %rdi
callq 0x19858
leaq 0x1a7df(%rip), %rsi     # 0x36465
movq %rbx, %rdi
movq %r14, %rdx
movl %ebp, %ecx
movq %rax, %r8
xorl %eax, %eax
callq 0x138e7
movq %rbx, %rdi
callq 0x19858
leaq 0x1a78d(%rip), %rsi     # 0x36434
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x138e7