// File: /workspace/github_c_makefile_star2_O2/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 0x1af03
movq %rax, %rbx
movl $0x1, 0x34(%rax)
movq 0x50(%rax), %r13
xorl %ebp, %ebp
movq %r13, (%rsp)
cmpq 0x40(%rbx), %rbp
jae 0x1a041
movq (%r13), %rax
cmpl $0x8, 0x8(%rax)
jne 0x1a038
movq %r13, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x19fe7
incq %rbp
addq $0x8, %r13
jmp 0x1a01a
movq %rbx, %rdi
callq 0x1b5e6
leal -0x2a(%rax), %ecx
cmpl $0xf, %ecx
jbe 0x1a086
leal -0x7(%rax), %ecx
cmpl $0x7, %ecx
jb 0x1a061
leal -0x2(%rax), %ecx
cmpl $0x4, %ecx
jae 0x1a0b0
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x16e0d
cmpl $0x0, 0x30(%rbx)
je 0x1a1e3
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x17a8b(%rip), %rax     # 0x31b18
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 0x16e0d
cmpl $0x12, %eax
je 0x1a096
cmpl $0x14, %eax
je 0x1a096
leaq 0x183a7(%rip), %rsi     # 0x32468
movq %rbx, %rdi
xorl %eax, %eax
callq 0x120fd
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 0x1b00f
callq 0x1d859
movq (%rsp), %rbp
movq (%rbp), %rsi
movq 0x18(%rsi), %rdi
testq %rdi, %rdi
je 0x1a107
callq 0x1da38
movq (%rbp), %rsi
movq %rax, %rdi
callq 0x1dc67
testq %rax, %rax
je 0x1a11d
movq %rax, %r12
cmpb $0x0, 0x76(%rax)
je 0x1a19a
xorl %r13d, %r13d
xorl %r12d, %r12d
testq %r12, %r12
jne 0x1a1bc
cmpq (%r14), %r13
jae 0x1a15a
movq (%rbp), %rdi
movq (%r15), %rax
movq (%rax,%r13,8), %rax
movq 0x20(%rax), %rsi
callq 0x1c100
testl %eax, %eax
je 0x1a152
movq (%r15), %rax
movq (%rax,%r13,8), %r12
jmp 0x1a155
xorl %r12d, %r12d
incq %r13
jmp 0x1a123
movq (%rbx), %rdi
callq 0x2003f
movq %rax, %r13
movq (%rbx), %rdi
movq 0x50(%rbx), %rax
movq (%rax), %rsi
movq %r13, %rdx
callq 0x1bd5f
movq %rax, %r12
andq $0x0, 0x30(%rax)
movq %rbx, %rdi
movq %r13, %rsi
callq 0x1aea7
movq %r15, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0x29b2d
jmp 0x1a1c1
cmpb $0x0, 0x73(%r12)
je 0x1a1b4
movq 0x28(%r12), %rdi
movq %rdi, %rsi
callq 0x19c17
movq %rax, %r13
jmp 0x1a1c1
cmpb $0x0, 0x72(%r12)
je 0x1a1ff
movq 0x28(%r12), %r13
movq %rbx, %rdi
movq %r13, %rsi
callq 0x1aea7
movq 0x18(%r12), %rax
movq %rax, 0x38(%rbx)
movsbl 0x72(%r12), %eax
movl %eax, 0x30(%rbx)
jmp 0x1a077
movq %rbx, %rdi
callq 0x17f9e
leaq 0x18212(%rip), %rsi     # 0x32404
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x120fd
movq (%r12), %rdi
callq 0x1b4f4
movq %rax, %r14
movq (%r12), %rdi
callq 0x1b508
movl %eax, %ebp
movq %r12, %rdi
callq 0x17f9e
leaq 0x18210(%rip), %rsi     # 0x32435
movq %rbx, %rdi
movq %r14, %rdx
movl %ebp, %ecx
movq %rax, %r8
xorl %eax, %eax
callq 0x120fd