// File: /workspace/github_c_makefile_star2_O2/Gaurang18[P]Compiler-Project-BITS-Pilani/./TypeChecker.c
// Function: TypeChecker
int TypeChecker(FILE *fp, parsetree head, char *scope){
	int type1, type2;
	int i,error=0;

	switch(head->value){

		case 100:
		{	
			
				type1 = TypeChecker(fp, head->parent->parent->parent->child, scope);
				type2 = TypeChecker(fp, head->right, scope);


				if(type2==-2 || type1==-2) return -2;
				else
					if(type2!=type1) 
					{
						fprintf(fp,"\nERROR 15: Type of left variable %s not equal to type of right expression, line number %d\n", head->parent->parent->parent->child->Lex->tk->value, head->Lex->tk->line);
						//printf("Left type %d Right Type %d\n", type1, type2);
						return -2;
					}
				else return type2;
				
		} break;

		case 106:{ 	
					// if(head->value==4){
     //     				strcpy(scope, "driver");
     //     				break;
     //    			}
					// if(head->parent->value==7)
     //   				 {
     //        			strcpy(scope, head->Lex->tk->value);
     //        			break;
     //    			 }

				if(!checksymbolpresent(head->Lex->tk->value, scope))
					return -2;
				else{

					char type[25] = {'\0'};
					strcpy(type, gettype(head->Lex->tk->value, scope));
					char *token = NULL;
            		token = strtok(gettype(head->Lex->tk->value, scope), "(");
            		if(token!=NULL){
                		token = strtok(NULL, ",");
                		if(token!=NULL)
                		strcpy(type, token);
            			}
            		// printf("%s %s\n", head->Lex->tk->value, type);



            		if(strcmp(type, "INTEGER")==0)
            			return 0;
            		if(strcmp(type, "REAL")==0)
            			return 1;
            		if(strcmp(type, "BOOLEAN")==0)
            			return -1;
            	}
            } break;


            case 107: return 0;

            case 108: return 1;

            case 68:
            case 69: return -1;

            case 82:
            case 83:
            		if(head->value==83 && head->parent->value==30)
            		{
            			return TypeChecker(fp, head->right, scope);
            		}

            		if(head->parent->parent->parent->value==38){
            			//printf("%s %s \n", terms[head->parent->parent->parent->child->right->value], terms[head->parent->right->value]);

            		if((type1 = TypeChecker(fp, head->parent->parent->parent->child->right,scope))==-2)
						return -2;
					if((type2 = TypeChecker(fp, head->parent->right, scope))==-2)
						return -2;
					}

					if(head->parent->parent->parent->value==35){

						//printf("%s %s \n", terms[head->parent->parent->parent->child->value], terms[head->parent->right->value]);
						if((type1 = TypeChecker(fp, head->parent->parent->parent->child,scope))==-2)
						return -2;
						if((type2 = TypeChecker(fp, head->parent->right, scope))==-2)
						return -2;
					}
					
					// printf("%d, %d", type1, type2);

					if(type1!=type2)
					{
						fprintf(fp,"ERROR 16: Types don't match, line number %d\n",head->Lex->tk->line);
						return -2;
					}		
					if(type1==-1)
					{
						fprintf(fp,"ERROR 17: Boolean expressions cannot be added or subtracted, line number %d\n", head->Lex->tk->line);
						return -2;
					}	
					return type1;
					break;

            case 84:
            case 85:
            		// printf("MUL value %d\n",head->parent->parent->parent->value );
            		if(head->parent->parent->parent->value==41){
            			// printf("41 %s %s \n", terms[head->parent->parent->parent->child->right->value], terms[head->parent->right->value]);

            		if((type1 = TypeChecker(fp, head->parent->parent->parent->child->right,scope))==-2)
						return -2;
					if((type2 = TypeChecker(fp, head->parent->right, scope))==-2)
						return -2;
					}

					if(head->parent->parent->parent->value==37){

						//printf("37 %s %s \n", terms[head->parent->parent->parent->child->value], terms[head->parent->right->value]);
						if((type1 = TypeChecker(fp, head->parent->parent->parent->child,scope))==-2)
						return -2;
						if((type2 = TypeChecker(fp, head->parent->right, scope))==-2)
						return -2;
					}
					
					//printf("%d, %d", type1, type2);

					if(type1!=type2)
					{
						fprintf(fp,"ERROR 18: Types don't match, line number %d\n",head->Lex->tk->line);
						return -2;
					}		
					if(type1==-1)
					{
						fprintf(fp,"ERROR 19: Boolean expressions cannot be added or subtracted, line number %d\n", head->Lex->tk->line);
						return -2;
					}	
					return type1;
					break;

			case 86:
			case 87:
			case 88:
			case 89:
			case 90:
			case 91:
					if(head->parent->parent->parent->value==43){
					if((type1 = TypeChecker(fp, head->parent->parent->parent->child,scope))==-2)
						return -2;
					if((type2 = TypeChecker(fp, head->parent->right, scope))==-2)
						return -2;
					}

					if(head->parent->parent->parent->value==49){
					if((type1 = TypeChecker(fp, head->parent->parent->parent->child->right,scope))==-2)
						return -2;
					if((type2 = TypeChecker(fp, head->parent->right, scope))==-2)
						return -2;
					}

					if((type1!=0&&type1!=1)||(type2!=0&&type2!=1))
					{
						fprintf(fp,"ERROR 20: Invalid expression. Relational operations possible only on int and real, line number %d\n", head->Lex->tk->line);
						return -2;
					}
					if(type1!=type2)
					{
						fprintf(fp,"ERROR 21: Types of expressions should be same while comparing, line number %d\n", head->Lex->tk->line);
						return -2;
					}
				return -1;

				break;

			case 73:
			case 74:

					if(head->parent->parent->parent->value==42){
						if((type1 = TypeChecker(fp, head->parent->parent->parent->child,scope))!=-1)
					{
						fprintf(fp,"ERROR 22: Logical operators can only be applied to boolean type, line number %d\n",  head->Lex->tk->line);
						return -2;
					}
					if((type2 = TypeChecker(fp, head->parent->right, scope))!=-1)
					{
						fprintf(fp,"ERROR 23: Logical operators can only be applied to boolean type, line number %d\n",  head->Lex->tk->line);
						return -2;
					}
					}


					if(head->parent->parent->parent->value==48){
					if((type1 = TypeChecker(fp, head->parent->parent->parent->child->right,scope))!=-1)
					{
						fprintf(fp,"ERROR 24: Logical operators can only be applied to boolean type, line number %d\n",  head->Lex->tk->line);
						return -2;
					}
					if((type2 = TypeChecker(fp, head->parent->right, scope))!=-1)
					{
						fprintf(fp,"ERROR 25: Logical operators can only be applied to boolean type, line number %d\n",  head->Lex->tk->line);
						return -2;
					}
				}
				return -1;
				break;

			default: 
			{
				parsetree child = head->child;

				while(child!=NULL && child->value!=109 )
				{	
					if(child->value==24){

					}
					/*else if(child->left->value == 49 ){
						return type1;
					}*/
					//child = child->right;

					else if((type1 = TypeChecker(fp, child,scope))==-2)
						error=1;
					if(type1 == -1 && child->value == 45){
						return -1;
					}
					
					child = child->right;
				}

				if(error==1)
					return -2;

				return type1;
			}

			
				
		 		
	}

	return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rdx, %r15
movq %rsi, %r14
movq %rdi, %rbx
leaq 0x32c9(%rip), %rax      # 0x80ac
movl 0x8(%r14), %ecx
addl $-0x44, %ecx
cmpl $0x28, %ecx
ja 0x51d1
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x30(%r14), %rcx
cmpl $0x1e, 0x8(%rcx)
jne 0x50e6
movq 0x28(%r14), %r14
jmp 0x4de3
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rcx
movl 0x8(%rcx), %edx
cmpl $0x2b, %edx
jne 0x4e70
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
pushq $-0x2
popq %r12
cmpl $-0x2, %eax
je 0x5382
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x2, %eax
je 0x5382
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
movl 0x8(%rcx), %edx
jmp 0x4e70
cmpl $0x31, %edx
jne 0x4eb4
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
pushq $-0x2
popq %r12
cmpl $-0x2, %eax
je 0x5382
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x2, %eax
je 0x5382
movl %eax, %ecx
orl %r13d, %ecx
cmpl $0x2, %ecx
jae 0x4f82
cmpl %eax, %r13d
jne 0x52a1
pushq $-0x1
jmp 0x5380
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rcx
movl 0x8(%rcx), %edx
cmpl $0x29, %edx
jne 0x4f97
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
pushq $-0x2
popq %r12
cmpl $-0x2, %eax
je 0x5382
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x2, %eax
je 0x5382
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
movl 0x8(%rcx), %edx
movl %r13d, %r12d
jmp 0x4f97
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
movl 0x8(%rax), %ecx
cmpl $0x2a, %ecx
jne 0x5319
movq 0x18(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x1, %eax
je 0x52e0
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x39f9(%rip), %rsi      # 0x8976
jmp 0x5374
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3932(%rip), %rsi      # 0x88c4
jmp 0x5374
cmpl $0x25, %edx
jne 0x4fda
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
pushq $-0x2
popq %r12
cmpl $-0x2, %eax
je 0x5382
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x2, %eax
je 0x5382
movl %r13d, %r12d
cmpl %eax, %r12d
jne 0x52b6
cmpl $-0x1, %r12d
jne 0x5382
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x387a(%rip), %rsi      # 0x8877
jmp 0x5374
movq (%r14), %rax
movq (%rax), %rbx
addq $0x1e, %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x4b65
testl %eax, %eax
je 0x537e
xorps %xmm0, %xmm0
leaq -0x50(%rbp), %r14
movups %xmm0, 0x9(%r14)
movaps %xmm0, (%r14)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x4c3e
movq %r14, %rdi
movq %rax, %rsi
callq 0x2060
movq %rbx, %rdi
movq %r15, %rsi
callq 0x4c3e
leaq 0x3376(%rip), %rsi      # 0x83cd
movq %rax, %rdi
callq 0x2190
testq %rax, %rax
je 0x5083
leaq 0x3356(%rip), %rsi      # 0x83c1
xorl %edi, %edi
callq 0x2190
testq %rax, %rax
je 0x5083
leaq -0x50(%rbp), %rdi
movq %rax, %rsi
callq 0x2060
movq -0x50(%rbp), %rbx
xorl %r12d, %r12d
movabsq $0x52454745544e49, %rax # imm = 0x52454745544E49
cmpq %rax, %rbx
je 0x5382
leaq 0x3a22(%rip), %rsi      # 0x8ac6
leaq -0x50(%rbp), %rdi
pushq $0x5
popq %rdx
callq 0x2160
testl %eax, %eax
je 0x50d3
movabsq $0x4e41454c4f4f42, %rax # imm = 0x4E41454C4F4F42
xorl %ecx, %ecx
cmpq %rax, %rbx
setne %cl
leal -0x1(,%rcx,2), %r12d
jmp 0x5382
pushq $0x1
jmp 0x5380
xorl %r12d, %r12d
jmp 0x5382
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rax
movq 0x30(%rax), %rcx
movl 0x8(%rcx), %edx
cmpl $0x26, %edx
jne 0x5228
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
pushq $-0x2
popq %r12
cmpl $-0x2, %eax
je 0x5382
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x2, %eax
je 0x5382
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
movl 0x8(%rcx), %edx
movl %r13d, %r12d
jmp 0x5228
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
movq 0x18(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
movl %eax, %r12d
movq 0x28(%r14), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
pushq $-0x2
popq %r15
cmpl $-0x2, %eax
je 0x51c9
cmpl $-0x2, %r12d
je 0x51c9
cmpl %r12d, %eax
je 0x5382
movq (%r14), %rax
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
movq 0x18(%rcx), %rcx
movq (%rcx), %rcx
movq (%rcx), %rdx
addq $0x1e, %rdx
movq (%rax), %rax
movl 0x3c(%rax), %ecx
leaq 0x35b6(%rip), %rsi      # 0x8775
movq %rbx, %rdi
xorl %eax, %eax
callq 0x2130
movl %r15d, %r12d
jmp 0x5382
addq $0x18, %r14
xorl %r13d, %r13d
pushq $-0x1
popq %r12
movq (%r14), %r14
testq %r14, %r14
je 0x528f
movl 0x8(%r14), %ecx
cmpl $0x18, %ecx
je 0x5212
cmpl $0x6d, %ecx
je 0x528f
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x2, %eax
pushq $0x1
popq %rcx
cmovel %ecx, %r13d
cmpl $-0x1, %eax
jne 0x5222
cmpl $0x2d, 0x8(%r14)
je 0x5382
addq $0x28, %r14
jmp 0x51dc
cmpl $0x23, %edx
jne 0x526b
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
pushq $-0x2
popq %r12
cmpl $-0x2, %eax
je 0x5382
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x2, %eax
je 0x5382
movl %r13d, %r12d
cmpl %eax, %r12d
jne 0x52cb
cmpl $-0x1, %r12d
jne 0x5382
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3573(%rip), %rsi      # 0x87fd
jmp 0x5374
cmpl $0x1, %r13d
pushq $-0x2
popq %rcx
cmovel %ecx, %eax
movl %eax, %r12d
jmp 0x5382
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3676(%rip), %rsi      # 0x8927
jmp 0x5374
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3584(%rip), %rsi      # 0x884a
jmp 0x5374
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x34f5(%rip), %rsi      # 0x87d0
jmp 0x5374
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x1, %eax
je 0x530a
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x36bf(%rip), %rsi      # 0x89c7
jmp 0x5374
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
movl 0x8(%rax), %ecx
pushq $-0x1
popq %r12
cmpl $0x30, %ecx
jne 0x5382
movq 0x18(%rax), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x1, %eax
je 0x534c
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x36ce(%rip), %rsi      # 0x8a18
jmp 0x5374
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x4dc2
cmpl $-0x1, %eax
je 0x5382
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x36f5(%rip), %rsi      # 0x8a69
movq %rbx, %rdi
xorl %eax, %eax
callq 0x2130
pushq $-0x2
popq %r12
movl %r12d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq