// File: /workspace/github_c_makefile_star2_O3/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 0x3d58(%rip), %rax      # 0x90ac
movl 0x8(%r14), %ecx
addl $-0x44, %ecx
cmpl $0x28, %ecx
ja 0x5767
movslq (%rax,%rcx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x30(%r14), %rcx
cmpl $0x1e, 0x8(%rcx)
jne 0x5670
movq 0x28(%r14), %r14
jmp 0x5354
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rcx
movl 0x8(%rcx), %edx
cmpl $0x2b, %edx
jne 0x53e3
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x590e
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x2, %eax
je 0x590e
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
movl 0x8(%rcx), %edx
jmp 0x53e3
cmpl $0x31, %edx
jne 0x5429
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x590e
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x2, %eax
je 0x590e
movl %eax, %ecx
orl %r13d, %ecx
cmpl $0x2, %ecx
jae 0x550d
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
cmpl %eax, %r13d
je 0x590e
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x44d1(%rip), %rsi      # 0x9927
jmp 0x58fe
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rcx
movl 0x8(%rcx), %edx
cmpl $0x29, %edx
jne 0x5522
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x590e
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x2, %eax
je 0x590e
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
movl 0x8(%rcx), %edx
movl %r13d, %r12d
jmp 0x5522
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
movl 0x8(%rax), %ecx
cmpl $0x2a, %ecx
jne 0x58a1
movq 0x18(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x1, %eax
je 0x5866
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x446e(%rip), %rsi      # 0x9976
jmp 0x58fe
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x43a7(%rip), %rsi      # 0x98c4
jmp 0x58fe
cmpl $0x25, %edx
jne 0x5567
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x590e
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x2, %eax
je 0x590e
movl %r13d, %r12d
cmpl %eax, %r12d
jne 0x583c
cmpl $-0x1, %r12d
jne 0x590e
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x42ed(%rip), %rsi      # 0x9877
jmp 0x58fe
movq (%r14), %rax
movq (%rax), %rbx
addq $0x1e, %rbx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x4fae
testl %eax, %eax
je 0x5908
xorps %xmm0, %xmm0
leaq -0x50(%rbp), %r14
movups %xmm0, 0x9(%r14)
movaps %xmm0, (%r14)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x5119
movq %r14, %rdi
movq %rax, %rsi
callq 0x2060
movq %rbx, %rdi
movq %r15, %rsi
callq 0x5119
leaq 0x3de9(%rip), %rsi      # 0x93cd
movq %rax, %rdi
callq 0x2180
testq %rax, %rax
je 0x5610
leaq 0x3dc9(%rip), %rsi      # 0x93c1
xorl %edi, %edi
callq 0x2180
testq %rax, %rax
je 0x5610
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 0x590e
movl $0x4c414552, %ecx       # imm = 0x4C414552
xorl -0x50(%rbp), %ecx
movzbl -0x4c(%rbp), %edx
orl %ecx, %edx
je 0x5659
movabsq $0x4e41454c4f4f42, %rcx # imm = 0x4E41454C4F4F42
xorl %edx, %edx
cmpq %rcx, %rax
setne %dl
leal -0x1(,%rdx,2), %r12d
jmp 0x590e
movl $0x1, %r12d
jmp 0x590e
xorl %r12d, %r12d
jmp 0x590e
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rax
movq 0x30(%rax), %rcx
movl 0x8(%rcx), %edx
cmpl $0x26, %edx
jne 0x57d3
movq 0x18(%rcx), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x590e
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x2, %eax
je 0x590e
movq 0x30(%r14), %rcx
movq 0x30(%rcx), %rcx
movq 0x30(%rcx), %rcx
movl 0x8(%rcx), %edx
movl %r13d, %r12d
jmp 0x57d3
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
movq 0x18(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
movl %eax, %r13d
movq 0x28(%r14), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x590e
cmpl $-0x2, %r13d
je 0x590e
movl %r13d, %r12d
cmpl %r13d, %eax
je 0x590e
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 0x401d(%rip), %rsi      # 0x9775
movq %rbx, %rdi
xorl %eax, %eax
callq 0x2130
jmp 0x5908
movq 0x18(%r14), %r14
testq %r14, %r14
je 0x5890
xorl %r12d, %r12d
movl $0x1, %r13d
movl 0x8(%r14), %ecx
cmpl $0x18, %ecx
je 0x57a0
cmpl $0x6d, %ecx
je 0x57b5
movq %rbx, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x5333
cmpl $-0x2, %eax
cmovel %r13d, %r12d
cmpl $-0x1, %eax
jne 0x57ac
cmpl $0x2d, 0x8(%r14)
je 0x57c8
movq 0x28(%r14), %r14
testq %r14, %r14
jne 0x577d
cmpl $0x1, %r12d
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmovnel %eax, %r12d
jmp 0x590e
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
jmp 0x590e
cmpl $0x23, %edx
jne 0x5818
movq 0x18(%rcx), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
cmpl $-0x2, %eax
je 0x590e
movl %eax, %r13d
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x2, %eax
je 0x590e
movl %r13d, %r12d
cmpl %eax, %r12d
jne 0x5851
cmpl $-0x1, %r12d
jne 0x590e
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3fc6(%rip), %rsi      # 0x97fd
jmp 0x58fe
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3ffe(%rip), %rsi      # 0x984a
jmp 0x58fe
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x3f6f(%rip), %rsi      # 0x97d0
jmp 0x58fe
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x1, %eax
je 0x5892
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x4139(%rip), %rsi      # 0x99c7
jmp 0x58fe
jmp 0x590e
movq 0x30(%r14), %rax
movq 0x30(%rax), %rax
movq 0x30(%rax), %rax
movl 0x8(%rax), %ecx
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
cmpl $0x30, %ecx
jne 0x590e
movq 0x18(%rax), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x1, %eax
je 0x58d6
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x4144(%rip), %rsi      # 0x9a18
jmp 0x58fe
movq 0x30(%r14), %rax
movq 0x28(%rax), %rsi
movq %rbx, %rdi
movq %r15, %rdx
callq 0x5333
cmpl $-0x1, %eax
je 0x590e
movq (%r14), %rax
movq (%rax), %rax
movl 0x3c(%rax), %edx
leaq 0x416b(%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