// File: /workspace/github_c_makefile_star2_O1/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 0x3c64(%rip), %rax      # 0x90ac
movl 0x8(%r14), %ecx
addl $-0x44, %ecx
cmpl $0x28, %ecx
ja 0x58ac
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x30(%r14), %rcx
cmpl $0x1e, 0x8(%rcx)
jne 0x565c
movq 0x28(%r14), %r14
jmp 0x5448
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rcx
cmpl $0x2b, 0x8(%rcx)
jne 0x54c4
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x59e8
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x2, %eax
je 0x59e8
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
cmpl $0x31, 0x8(%rcx)
jne 0x5517
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x59e8
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x2, %eax
je 0x59e8
movl %eax, %ecx
orl %r13d, %ecx
cmpl $0x2, %ecx
jae 0x572c
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
cmpl %eax, %r13d
je 0x59e8
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x43e3(%rip), %rsi      # 0x9927
jmp 0x59d8
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rcx
cmpl $0x29, 0x8(%rcx)
jne 0x559f
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x59e8
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x2, %eax
je 0x59e8
movl %r13d, %r12d
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
cmpl $0x25, 0x8(%rcx)
jne 0x55f1
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x59e8
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x2, %eax
je 0x59e8
movl %r13d, %r12d
cmpl %eax, %r12d
jne 0x5918
cmpl $-0x1, %r12d
jne 0x59e8
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x4263(%rip), %rsi      # 0x9877
jmp 0x59d8
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
cmpl $0x2a, 0x8(%rax)
jne 0x596c
movq 0x18(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x1, %eax
je 0x5942
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x431f(%rip), %rsi      # 0x9976
jmp 0x59d8
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rcx
cmpl $0x26, 0x8(%rcx)
jne 0x56b2
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x59e8
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x2, %eax
je 0x59e8
movl %r13d, %r12d
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
cmpl $0x23, 0x8(%rcx)
jne 0x5704
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x59e8
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x2, %eax
je 0x59e8
movl %r13d, %r12d
cmpl %eax, %r12d
jne 0x592d
cmpl $-0x1, %r12d
jne 0x59e8
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x40d6(%rip), %rsi      # 0x97fd
jmp 0x59d8
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x4188(%rip), %rsi      # 0x98c4
jmp 0x59d8
movq (%r14), %r14
movq (%r14), %rdi
addq $0x1e, %rdi
movq %r15, %rsi
callq 0x50a0
testl %eax, %eax
je 0x59e2
xorps %xmm0, %xmm0
leaq -0x50(%rbp), %rbx
movups %xmm0, 0x9(%rbx)
movaps %xmm0, (%rbx)
movq (%r14), %rdi
addq $0x1e, %rdi
movq %r15, %rsi
callq 0x520d
movq %rbx, %rdi
movq %rax, %rsi
callq 0x2060
movq (%r14), %rdi
addq $0x1e, %rdi
movq %r15, %rsi
callq 0x520d
leaq 0x3c34(%rip), %rsi      # 0x93cd
movq %rax, %rdi
callq 0x2180
testq %rax, %rax
je 0x57c5
leaq 0x3c14(%rip), %rsi      # 0x93c1
xorl %edi, %edi
callq 0x2180
testq %rax, %rax
je 0x57c5
leaq -0x50(%rbp), %rdi
movq %rax, %rsi
callq 0x2060
movq -0x50(%rbp), %rax
xorl %r12d, %r12d
movabsq $0x52454745544e49, %rcx # imm = 0x52454745544E49
cmpq %rcx, %rax
je 0x59e8
movl $0x4c414552, %ecx       # imm = 0x4C414552
xorl -0x50(%rbp), %ecx
movzbl -0x4c(%rbp), %edx
orl %ecx, %edx
je 0x580e
movabsq $0x4e41454c4f4f42, %rcx # imm = 0x4E41454C4F4F42
xorl %edx, %edx
cmpq %rcx, %rax
setne %dl
leal -0x1(,%rdx,2), %r12d
jmp 0x59e8
movl $0x1, %r12d
jmp 0x59e8
xorl %r12d, %r12d
jmp 0x59e8
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
movq 0x18(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
movl %eax, %r13d
movq 0x28(%r14), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x59e8
cmpl $-0x2, %r13d
je 0x59e8
movl %eax, %r12d
cmpl %r13d, %eax
je 0x59e8
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 0x3ed8(%rip), %rsi      # 0x9775
movq %rbx, %rdi
xorl %eax, %eax
callq 0x2130
jmp 0x59e2
movq 0x18(%r14), %r14
testq %r14, %r14
je 0x59ae
xorl %r12d, %r12d
movl $0x1, %r13d
movl 0x8(%r14), %ecx
cmpl $0x18, %ecx
je 0x58e5
cmpl $0x6d, %ecx
je 0x58fa
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x5427
cmpl $-0x2, %eax
cmovel %r13d, %r12d
cmpl $-0x1, %eax
jne 0x58f1
cmpl $0x2d, 0x8(%r14)
je 0x590d
movq 0x28(%r14), %r14
testq %r14, %r14
jne 0x58c2
cmpl $0x1, %r12d
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmovnel %eax, %r12d
jmp 0x59e8
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
jmp 0x59e8
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3f22(%rip), %rsi      # 0x984a
jmp 0x59d8
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3e93(%rip), %rsi      # 0x97d0
jmp 0x59d8
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x1, %eax
je 0x596c
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x405d(%rip), %rsi      # 0x99c7
jmp 0x59d8
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
cmpl $0x30, 0x8(%rax)
jne 0x59e8
movq 0x18(%rax), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x1, %eax
je 0x59b0
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x406c(%rip), %rsi      # 0x9a18
jmp 0x59d8
jmp 0x59e8
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5427
cmpl $-0x1, %eax
je 0x59e8
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x4091(%rip), %rsi      # 0x9a69
movq %rbx, %rdi
xorl %eax, %eax
callq 0x2130
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
movl %r12d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq