Example #1
0
//Actually creates the quads by recursing;
//We will return the quad that was the last result or -1 if we have no result
int CG(ast_node n)
{
	//printf("Called CG\n");
	
	//temporaries we're going to use throughout the CG function, just for
	//convenience
	Address ar1, ar2, ar3, ar4, ar5, tqa, ta, topatch, e, nq;
	int lrp, rrp;
	int tq, t, testq, gq;
	int typer;
	SymNode *sn;
	value v;
	
	ast_node next;
	
	ast_node x;
	
	if (n == NULL)
	{
		//printf("Error CG called on NULL node\n");
		
		return -1;
	}
	
	switch (n->node_type) {
			
		case CONTINUE_ST:
			
			e.kind = Empty;

			GenQuad(con, e, e, e);
			
			break;
			
		case BREAK_ST:
			
			e.kind = Empty;
			
			GenQuad(brk, e, e, e);
			
			break;
		
		//just has id which we set its attr to constant
		case CONSTANT:
			//first we get the id
			lrp = CG(n->left_child);
			//id
			ar1 = quads[lrp]->addr1;
			
			sn = LookupInSymbolTable(symtab, ar1.contents.name);
			
			SetFlagsAttr(sn, 1);
			
			break;
			
		case OP_SIZEOF:
			//first we get the id
			lrp = CG(n->left_child);
			//id
			ar1 = quads[lrp]->addr1;
			sn = LookupInSymbolTable(symtab, ar1.contents.name);
			
			t = GetTypeAttr(sn);
			
			switch (t) {
				case IntT:
					tq = 4;
					break;
				case DouT:
					tq = 8;
					break;
				case IArT:
					gq = GetSizeAttr(sn);
					tq = 4*gq;
					break;
				case DArT:
					gq = GetSizeAttr(sn);
					tq = 8*gq;
					break;
				default:
					tq = 4;
					break;
			}
			
			//Address ar1, ar2, ar3;
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			//we are assigning this literal value to ar1
			ar2.kind = IntConst;
			ar2.contents.val = tq;
			
			//we don't need ar3
			ar3.kind = Empty;
			
			return GenQuad(asn, ar1, ar2, ar3);
			
			
			break;
			
		case ARRAY_PULL:
			//printf("ARRAY_PULL Case in CG\n");
			
			e.kind = Empty;
			
			//first we get the id, the name
			lrp = CG(n->left_child);
			
			//then we get the left child, right sibling, which is the index of the array
			rrp = CG(n->left_child->right_sibling);
			
			//id
			ar1 = quads[lrp]->addr1;
			
			//index
			ar2 = quads[rrp]->addr1;
			
			ar3.kind = String;
			
			
			sn = LookupInSymbolTable(symtab, ar1.contents.name);
			
			//if int array
			if (GetTypeAttr(sn) == IArT) {
				typer = 4;
			}
			//if double array
			else {
				typer = 8;
			}

			
			t = GetOffsetAttr(sn);
			
			//we have a constant
			if (ar2.kind != String) {
				tq = ar2.contents.val;
			}
			//temporary must be changed
			else {
				tq = 4;
			}

			
			
			if (typer == 4) {
				ar3.contents.name = NewTemp(4);
			}
			else {
				ar3.contents.name = NewTemp(8);
			}

			
			sn = LookupInSymbolTable(symtab, ar3.contents.name);
			
			if (typer == 4) {
				SetTypeAttr(sn, IntT);
				SetOffsetAttr(sn, t-(tq*typer));
			}
			else {
				SetTypeAttr(sn, DouT);
				SetOffsetAttr(sn, t-(tq*typer));
			}
			
			return GenQuad(sym, ar3, e, e);
			
			
			break;
			
		case INT_ARRAY_DEC:
			//printf("INT_ARRAY_DEC Case in CG\n");
			
			//first we get the id, the name
			lrp = CG(n->left_child);
			
			//then we get the left child, right sibling, which is the size of the array
			rrp = CG(n->left_child->right_sibling);
			
			//id
			ar1 = quads[lrp]->addr1;
			
			//size
			ar2 = quads[rrp]->addr1;
			
			if (ar2.kind == IntConst) 
			{
				t = ar2.contents.val;
			}
			//otherwise we have a string
			else 
			{
				sn = LookupInSymbolTable(symtab, ar2.contents.name);
				v = GetValueAttr(sn);
				t = v.ival;
			}

			
			e.kind = Empty;
			
			//going to insert into symbol table
			//printf("inserting int int array id into sym table \n");
			//printf("%s is the symbol going in\n", ar1.contents.name);
			sn = InsertIntoSymbolTable(symtab, ar1.contents.name);
			//printf("Setting type attribute for that\n");
			SetTypeAttr(sn, IArT);
			//printf("Set type successfully\n");
			SetSizeAttr(sn, t);
			//printf("Set size successfully\n");
			
			if (sn->level == 1) 
			{
				SetOffsetAttr(sn, goffset);
				goffset -= 4*t;
			}
			else {
				SetOffsetAttr(sn, foffset);
				foffset -= 4*t;
			}
			//PLACEHOLDER - Need to set the TYPE ATTRIBUTE in the symbol table to int
			
			break;
			
		case DOU_ARRAY_DEC:
			//printf("DOU_ARRAY_DEC Case in CG\n");
			
			//first we get the id, the name
			lrp = CG(n->left_child);
			
			//then we get the left child, right sibling, which is the size of the array
			rrp = CG(n->left_child->right_sibling);
			
			//id
			ar1 = quads[lrp]->addr1;
			
			//size
			ar2 = quads[rrp]->addr1;
			
			if (ar2.kind == IntConst) 
			{
				t = ar2.contents.val;
			}
			//otherwise we have a string
			else 
			{
				sn = LookupInSymbolTable(symtab, ar2.contents.name);
				v = GetValueAttr(sn);
				t = v.ival;
			}
			
			
			e.kind = Empty;
			
			//going to insert into symbol table
			//printf("inserting int int array id into sym table \n");
			//printf("%s is the symbol going in\n", ar1.contents.name);
			sn = InsertIntoSymbolTable(symtab, ar1.contents.name);
			//printf("Setting type attribute for that\n");
			SetTypeAttr(sn, DArT);
			//printf("Set type successfully\n");
			SetSizeAttr(sn, t);
			//printf("Set size successfully\n");
			
			if (sn->level == 1) {
				SetOffsetAttr(sn, goffset);
				goffset -= 8*t;
			}
			else {
				SetOffsetAttr(sn, foffset);
				foffset -= 8*t;
			}
			//PLACEHOLDER - Need to set the TYPE ATTRIBUTE in the symbol table to int
			
			break;

			
		case SWITCH_ST:
			//this is the id or int we compare against
			lrp = CG(n->left_child);
			ar1 = quads[lrp]->addr1;
			
			e.kind = Empty;
			
			//traverse the cases
			next = n->left_child->right_sibling;
			while (next->node_type == SWITCH_CASE) 
			{
				//get the case
				rrp = CG(next->left_child);
				ar2 = quads[rrp]->addr1;
				
				//if the values are not equal, skip this case
				gq = GenQuad(jne, e, ar2, ar1);
				
				//process the sequence
				CG(next->left_child->right_sibling);
				
				nq.kind = IntConst;
				nq.contents.val = NextQuad();
				PatchQuad(gq, 1, nq);
				
				next=next->right_sibling;
			}
							
			//last node should be the default
			
			CG(next);
			
			break;
			
		case SWITCH_CASE:
			
			break;
			
			//we have a function with parameters
		//Based on Louden p 442
		case FUNC_DEF:
			//printf("In FUNC_DEF Case\n");
			//add the function name to the symbol table
			//
			
			e.kind = Empty;
			
			//we must reset f-offset for memory management purposes
			foffset = -4;
			
			//this will generate a sym quad which is the start of the function
			//it's also a dummy quad for integer defintions
			//we're using it like ENT in this case in Louden
			lrp = CG(n->left_child);
			//we expect an ID, so add it to the symbol table
			sn = InsertIntoSymbolTable(symtab, quads[lrp]->addr1.contents.name);
			//this is the quad where we'll need to jump if this function is called
			v.ival = lrp;
			SetValueAttr(sn, v);
			//we're going to ignore the parameters as per louden p 441
			next = n->left_child->right_sibling;
			while (next->node_type == FUNC_PARAM) 
			{
				next=next->right_sibling;
			}
			//now we're done so we should be at the SEQ of actual instructions
			CG(next);
			//finish it off with a ret
			GenQuad(ret, e, e, e);
			
			break;
		
		//has id and parameters - we jump to the quad of the id
		//Based on Louden p 442
		case FUNC_CALL:
			//printf("FUNC_CALL in Switch of CG\n");
			e.kind = Empty;
			
			//load all the params
			next = n->left_child;
			while (next->node_type == FUNC_PARAM) 
			{
				//we're telling the assembler we want it to load parameters for a function call
				lrp = CG(next);
				GenQuad(loadpar, quads[lrp]->addr1, e, e);
				next=next->right_sibling;
			}
			
			//the id has in the symbol table a value associated with it
			//which represents the quad we want to jump to
			lrp = CG(next);
			
			//get the name of the ID and look up its place
			sn = LookupInSymbolTable(symtab, quads[lrp]->addr1.contents.name);
			v = GetValueAttr(sn);
			
			t = v.ival;
			
			ar1.kind = IntConst;
			ar1.contents.val = t; 
			
			GenQuad(gotoq, ar1, e, e);
			//jump to the location of the id
			
			break;
			
		case FUNC_PARAM:
			return CG(n->left_child);
			break;
		
		case RETURN_S:
			//printf("In RETURN Case\n");
			gq = GenQuad(ret, e, e, e);
			
			//if we have a return after the statement
			if(n->left_child != NULL)
			{
				lrp = CG(n->left_child);
				PatchQuad(gq, 1, quads[lrp]->addr1);
			}
			
			break;
			
			// "==" (IS EQUAL TO) operation
		case OP_EQUALS:
			//printf("In OP_EQUALS Case\n");
			//Address ar1, ar2, ar3;
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			//left result needs to be put in
			if (n->left_child == NULL) {
				printf("Error child is null\n");
			}
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//printf("%s the value\n", ar2.contents.name);
			
			//right child's result needs to be the other operand
			if (n->left_child->right_sibling == NULL) {
				printf("Error left_child->right sibling is null\n");
			}
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			//printf("%s the value\n", ar3.contents.name);
			
			return GenQuad(eq, ar1, ar2, ar3);
			break;
			
			
			//ROOT is nothing in itself, so we just start recursing down the tree
		case ROOT:
			//printf("In ROOT case\n");
			CG(n->left_child);
			break;
			
			
			// "!=" (IS NOT EQUAL TO) operation
		case OP_NOT_EQUALS:
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			return GenQuad(neq, ar1, ar2, ar3);
			break;
			
			// ">" (GREATER THAN) operation
		case OP_GREATER_THAN:
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			return GenQuad(gt, ar1, ar2, ar3);
			break;
			
			// "<" (LESS THAN) operation
		case OP_LESS_THAN:
			//printf("LESS THAN Case in CG\n");
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			return GenQuad(lt, ar1, ar2, ar3);
			break;
			
			// ">=" (GREATER THAN OR EQUAL TO) operation
		case OP_GREATER_EQUALS:
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			return GenQuad(gteq, ar1, ar2, ar3);
			break;
			
			// "<=" (LESS THAN OR EQUAL TO) operation
		case OP_LESS_EQUALS:
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			return GenQuad(lteq, ar1, ar2, ar3);
			break;
			
			
			// "||" (OR) operation
		case OP_OR:
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			ar2.kind = IntConst;
			ar2.contents.val = 1;
			
			ar3.kind = IntConst;
			ar3.contents.val = 0;
			
			ar4.kind = String;
			ar4.contents.name = NewTemp(4);
			
			e.kind = Empty;
			
			lrp = CG(n->left_child);
			ta = quads[lrp]->addr1;
			
			gq = GenQuad(if_f, ta, e, e);
			
			GenQuad(asn, ar4, ar2, e);
			typer = GenQuad(gotoq, e, e, e);
			
			t = CG(n->left_child->right_sibling);
			ar5.kind = IntConst;
			ar5.contents.val = t;
			
			ta = quads[t]->addr1;
			
			testq = GenQuad(if_f, ta, e, e);
			
			GenQuad(asn, ar4, ar2, e);
			
			tq = GenQuad(gotoq, e, e, e);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			
			PatchQuad(testq, 2, nq);
			
			
			GenQuad(asn, ar4, ar3, e);
			PatchQuad(typer, 1, nq);
			PatchQuad(gq, 2, ar5);
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(tq, 1, nq);
			
			rrp = GenQuad(asn, ar1, ar4, e);
			
			
			return rrp;
			
			break;
			
			// "&&" (AND) operation - based on THC code
		case OP_AND:
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			ar2.kind = IntConst;
			ar2.contents.val = 1;
			
			ar3.kind = IntConst;
			ar3.contents.val = 0;
			
			ar4.kind = String;
			ar4.contents.name = NewTemp(4);
			
			e.kind = Empty;
			
			lrp = CG(n->left_child);
			ta = quads[lrp]->addr1;
			
			gq = GenQuad(if_f, ta, e, e);
			
			t = CG(n->left_child->right_sibling);
			
			ta = quads[t]->addr1;
			
			testq = GenQuad(if_f, ta, e, e);
			
			GenQuad(asn, ar4, ar2, e);
			
			tq = GenQuad(gotoq, e, e, e);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(gq, 2, nq);
			PatchQuad(testq, 2, nq);
			
			GenQuad(asn, ar4, ar3, e);
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(tq, 1, nq);
			rrp = GenQuad(asn, ar1, ar4, e);
			
			
			
			return rrp;
			break;		 
			
		case OP_NOT:
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			ar2.kind = IntConst;
			ar2.contents.val = 1;
			
			ar3.kind = IntConst;
			ar3.contents.val = 0;
			
			ar4.kind = String;
			ar4.contents.name = NewTemp(4);
			
			e.kind = Empty;
			
			t = CG(n->left_child);
			
			ta = quads[t]->addr1;
			
			//if false go to the end and give it a 0
			gq = GenQuad(if_f, ta, e, e);
			GenQuad(asn, ar4, ar2, e);
			
			tq = GenQuad(gotoq, e, e, e);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(gq, 2, nq);
			GenQuad(asn, ar4, ar3, e);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			
			PatchQuad(tq, 1, nq);
			rrp = GenQuad(asn, ar1, ar4, e);
			
			return rrp;
			break;		 
			
			
			
			
			
			//if it's a SEQ, we want to just recursively produce code for all the children
		case SEQ:
			//adapted from THC if code
			e.kind = Empty;
			//EnterScope(symtab);
			//we must tell the assembly generator we've entered a new scope
			GenQuad(ens, e, e, e);
			x = n->left_child;
			while (x != NULL) {
				CG(x);
				x = x->right_sibling;
			}
			GenQuad(exs, e, e, e);
			//we must tell the assembly generator we've exited a scope
			//LeaveScope(symtab);
			break;
			
			
			//Here we do the addition and then we return the position so higher up nodes can find the result
		case OP_PLUS:
			//printf("OP_PLUS Case in CG\n");
			ar1.kind = String;
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			ar1.contents.name = NewTemp(MaxType(ar2, ar3));
			
			return GenQuad(add, ar1, ar2, ar3);
			break;
			
		case OP_MINUS:
			ar1.kind = String;
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			ar1.contents.name = NewTemp(MaxType(ar2, ar3));
			
			return GenQuad(sub, ar1, ar2, ar3);
			break;
			
		case OP_TIMES:
			//printf("OP_TIMES Case in CG\n");
			ar1.kind = String;
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			ar1.contents.name = NewTemp(MaxType(ar2, ar3));
			
			return GenQuad(mul, ar1, ar2, ar3);
			break;
			
		case OP_DIVIDE:
			ar1.kind = String;
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar3 = quads[rrp]->addr1;
			
			ar1.contents.name = NewTemp(MaxType(ar2, ar3));
			
			return GenQuad(divi, ar1, ar2, ar3);
			break;
			
			//negate a number
		case OP_NEGATIVE:
			//printf("OP_NEGATIVE Case in CG\n");
			ar1.kind = String;
			
			//this should only have one child
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//we need to subtract from 0
			ar3.kind = IntConst;
			ar3.contents.val = 0;
			
			ar1.contents.name = NewTemp(MaxType(ar2, ar3));
			
			return GenQuad(sub, ar1, ar3, ar2);
			break;
			
		case INT_LITERAL:
			//printf("INT_LITERAL Case in CG\n");
			//Address ar1, ar2, ar3;
			ar1.kind = String;
			ar1.contents.name = NewTemp(4);
			
			//we are assigning this literal value to ar1
			ar2.kind = IntConst;
			//printf("n->value.int_value %d \n", n->value.int_value);
			ar2.contents.val = n->value.int_value;
			
			//we don't need ar3
			ar3.kind = Empty;
			
			return GenQuad(asn, ar1, ar2, ar3);
			break;
			
			
		case DOUBLE_LITERAL:
			//printf("DOUBLE_LITERAL Case in CG\n");
			ar1.kind = String;
			ar1.contents.name = NewTemp(8);
			
			//we are assigning this literal value to ar1
			ar2.kind = DouConst;
			ar2.contents.dval = n->value.double_value;
			
			//we don't need ar3
			ar3.kind = Empty;
			
			return GenQuad(asn, ar1, ar2, ar3);
			break;
			
		case STRING_LITERAL:
			ar1.kind = String;
			ar1.contents.name = NewTemp(240);
			
			//we are assigning this literal value to ar1
			ar2.kind = String;
			ar2.contents.name = n->value.string;
			
			//we don't need ar3
			ar3.kind = Empty;
			
			return GenQuad(asn, ar1, ar2, ar3);
			break;
			
			
			
			//we must insert in the symbol table the child's name
		case INT_DEC:
			//printf("INT_DEC Case in CG\n");
			lrp = CG(n->left_child);
			ar1 = quads[lrp]->addr1;
			
			ar2.kind = Empty;
			
			ar3.kind = Empty;
			
			//going to insert into symbol table
			//printf("inserting int dec id into sym table \n");
			//printf("%s is the symbol going in\n", ar1.contents.name);
			sn = InsertIntoSymbolTable(symtab, ar1.contents.name);
			//printf("Setting type attribute for that\n");
			SetTypeAttr(sn, IntT);
			//printf("Set type successfully\n");
			
			if (sn->level == 1) {
				SetOffsetAttr(sn, goffset);
				goffset -= 4;
			}
			else {
				SetOffsetAttr(sn, foffset);
				foffset -= 4;
			}
			//PLACEHOLDER - Need to set the TYPE ATTRIBUTE in the symbol table to int
			
			break;
			
			//we must insert the child in the symbol table
		case DOU_DEC:
			//printf("DOU_DEC Case in CG\n");
			lrp = CG(n->left_child);
			ar1 = quads[lrp]->addr1;
			
			ar2.kind = Empty;
			
			ar3.kind = Empty;
			
			sn = InsertIntoSymbolTable(symtab, ar1.contents.name);
			SetTypeAttr(sn, DouT);
			
			if (sn->level == 1) {
				SetOffsetAttr(sn, goffset);
				goffset -= 8;
			}
			else {
				SetOffsetAttr(sn, foffset);
				foffset -= 8;
			}
			//PLACEHOLDER - Need to set the TYPE ATTRIBUTE in the symbol table to double
			break;
			
		case FOR_LOOP:
			//printf("FORLOOP Case in CG\n");
			
			//the first statement is always executed
			CG(n->left_child);
			
			//the inequality is statement two
			t = CG(n->left_child->right_sibling);
			ta = quads[t]->addr1;
			testq = GenQuad(if_f, ta, topatch, e);
			
			//we do the sequence before the final statement
			CG(n->left_child->right_sibling->right_sibling->right_sibling);
			
			//now we do the third statement in the for-loop header
			CG(n->left_child->right_sibling->right_sibling);
			
			//then we loop around
			e.kind = Empty;
			
			nq.kind = IntConst;
			nq.contents.val = t;
			GenQuad(gotoq, nq, e, e);
			
			//finally we must patch the inequality		
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(testq, 2, nq);
			
			break;
			
		case OP_PRE_INCR:
			//printf("PRE++ Case in CG\n");
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			ar3.kind = IntConst;
			ar3.contents.val = 1;
			
			return GenQuad(add, ar2, ar2, ar3);
			break;
			
		case OP_POST_INCR:
			//printf("POST++ Case in CG\n");
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			ar3.kind = IntConst;
			ar3.contents.val = 1;
			
			return GenQuad(add, ar2, ar2, ar3);
			break;
			
		case OP_PRE_DECR:
			//printf("PRE-- Case in CG\n");
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			ar3.kind = IntConst;
			ar3.contents.val = 1;
			
			return GenQuad(sub, ar2, ar2, ar3);
			break;
			
		case OP_POST_DECR:
			//printf("POST-- Case in CG\n");
			
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar2 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			ar3.kind = IntConst;
			ar3.contents.val = 1;
			
			return GenQuad(sub, ar2, ar2, ar3);
			break;
			
		case IF_ELSE:
			//printf("IF_ELSE Case in CG\n");
			t = CG(n->left_child);
			
			ta = quads[t]->addr1;
			
			topatch.kind = Empty;
			
			e.kind = Empty;
			
			testq = GenQuad(if_f, ta, topatch, e);
			
			CG(n->left_child->right_sibling);
			gq = GenQuad(gotoq, e, e, e);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(testq, 2, nq);
			
			CG(n->left_child->right_sibling->right_sibling);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(gq, 1, nq);
			
			break;
			
		case IF:
			//printf("IF Case in CG\n");
			t = CG(n->left_child);
			ta = quads[t]->addr1;
			
			topatch.kind = Empty;
			e.kind = Empty;
			
			//this is where we would switch the order for the dowhile
			testq = GenQuad(if_f, ta, topatch, e);
			
			CG(n->left_child->right_sibling);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			
			PatchQuad(testq, 2, nq);
			
			break;
			
			
			//adapted from THC's code in class
			//MUST TYPE CHECK THAT t RETURNS AN INT FOR COMPARISON
		case WHILE_LOOP:
			//printf("WHILE Case in CG\n");
			tq = NextQuad();
			t = CG(n->left_child);
			
			tqa.kind = IntConst;
			tqa.contents.val = tq;
			
			ta = quads[t]->addr1;
			
			topatch.kind = Empty;
			
			e.kind = Empty;
			
			//this is where we would switch the order for the dowhile
			testq = GenQuad(if_f, ta, topatch, e);
			
			CG(n->left_child->right_sibling);
			
			GenQuad(gotoq, tqa, e, e);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(testq, 2, nq);
			break;
			
			//we're still assuming the comparison is the left child
			//not the left child->right sibling
		case DO_WHILE_LOOP:
			tq = NextQuad();
			t = CG(n->left_child);
			
			//just do the other stuff first and then we potentially loop or leave
			CG(n->left_child->right_sibling);
			
			tqa.kind = IntConst;
			tqa.contents.val = tq;
			
			ta = quads[t]->addr1;
			
			topatch.kind = Empty;
			
			e.kind = Empty;
			
			//this is where we would switch the order for the dowhile
			testq = GenQuad(if_f, ta, topatch, e);
			
			GenQuad(gotoq, tqa, e, e);
			
			nq.kind = IntConst;
			nq.contents.val = NextQuad();
			PatchQuad(testq, 2, nq);
			break;
			
			//the assembler has a built in read facility, so this is very simple
			//NEED TO DEAL WITH DOUBLES HERE TOO BASED ON TYPE CHECK of CHILD's ATTRIBUTE
		case READ:
			//printf("READ Case in CG\n");
			lrp = CG(n->left_child);
			//printf("read back in for real\n");
			ar1 = quads[lrp]->addr1;
			
			//printf("read back in\n");
			
			ar2.kind = Empty;
			
			ar3.kind = Empty;
			
			gq = GenQuad(rd, ar1, ar2, ar3);
			
			//PUT VALUE IN SYMBOL TABLE UNDER READ's CHILD
			
			return gq;
			
			break;
			
			//the assembler has a built in write facility, so this is very simple
			//NEED TO HANDLE DOUBLES HERE TOO BASED ON TYPE CHECK of CHILD's TYPE ATTRIBUTE
		case WRITE:
			//printf("WRITE Case in CG\n");
			lrp = CG(n->left_child);
			ar1 = quads[lrp]->addr1;
			
			ar2.kind = Empty;
			
			ar3.kind = Empty;
			
			GenQuad(wri, ar1, ar2, ar3);
			
			break;
			
			//we put in a dummy just so that higher ups can use it, also put in symbol table
		case ID:
			//printf("ID Case in CG\n");
			
			ar1.contents.name = strdup(n->value.string);
			
			//printf("%s is the id\n", ar1.contents.name);
			
			//printf("tried strdup\n");
			//if (ar1.contents.name == NULL) {
			//		printf("NULL STRING?!\n");
			//	}
			
			//printf("%s is the id\n", ar1.contents.name);
			
			ar1.kind = String;
			//ar1.contents.name = n->value.string;
			//printf("%s is the id", n->value.string);
			
			ar2.kind = Empty;
			
			ar3.kind = Empty;
			
			
			
			return GenQuad(sym, ar1, ar2, ar3);
			break;
			
			//we put in a dummy just so that higher ups can use it, also put in symbol table
		case OP_ASSIGN:
			//left result needs to be put in
			lrp = CG(n->left_child);
			ar1 = quads[lrp]->addr1;
			
			//right child's result needs to be the other operand
			rrp = CG(n->left_child->right_sibling);
			ar2 = quads[rrp]->addr1;
			
			ar3.kind = Empty;
			
			return GenQuad(asn, ar1, ar2, ar3);
			break;
			
			//MISSING CONST, RETURN, SWITCH, BREAK, CONTINUE
			//RETURN NEEDS TO GO TOGETHER WITH FUNCTIONS I THINK...  MAYBE WE NEED TO TYPE CHECK WITH ANOTHER
			//SWITCH WITHIN THE CASE OF A FUNCTION CALL
			
		default:
			break;
	}
	
	//default, we return -1 which means no result from the previous call...
	return -1;
}
Example #2
0
Error
_dxf_quadsToQmesh (xfieldT *xf, void *globals)
{
  DEFGLOBALDATA(globals) ;
  Quadruple *neighbors ;       /* neighbors array gives a quad's neighbors  */
  Qstrip *stripArray = 0 ;     /* temp array of strips                      */
  int point[MaxQstripSize] ;   /* array into which to build point list      */
  char *usedArray = 0 ;        /* marks quads already used                  */
  int nStrips = 0 ;            /* number of strips generated                */
  int nStrippedPts = 0 ;       /* number of points stripped                 */
  int nPtsInStrip ;            /* number of points in current strip         */
  int start_quad ;             /* first quad of the strip                   */
  int quad ;                   /* the current quad                          */
  int dir, i0, i1, i2, i3 ;    /* the 4 indexes into quads[quad].p[?]       */
  int prev_quad, prev_i0,      /* used to determine the same current info   */
      prev_i1,prev_i2,prev_i3 ;
  Quadruple *quads ;           /* array of original quad connections        */
  int nquads ;                 /* number of original quad connections       */
  int i, j, k ;                /* misc. indices                             */
  QMesh qmesh = NULL;
  dxObject qmesho = NULL;

  ENTRY(("_dxf_quadsToQmesh(0x%x)", xf));

  qmesho = _dxf_QueryObject(MESHHASH, (dxObject)xf->field);
  if (qmesho)
  {
      xf->meshObject = DXReference(qmesho);
      qmesh = (QMesh)DXGetPrivateData((Private)qmesho);
      _installQMeshInfo(xf, qmesh);

      return OK;
  }

  if (xf->connectionType != ct_quads)
    {
      EXIT(("xf->connectionType not ct_quads"));
      return OK ;
    }

  PRINT(("invalid connections: %d",
	   xf->invCntns? DXGetInvalidCount(xf->invCntns): 0)) ;

  neighbors = getNeighbors(xf);

  /* get quad connection info; quad connections are replaced by strips */
  quads = DXGetArrayData(xf->connections_array) ;
  nquads = xf->nconnections ;
  /*npoints = xf->npositions ;*/

  xf->origNConnections = nquads;
  xf->origConnections_array = xf->connections_array;
  xf->connections_array = NULL;

  /* allocate temporary array to hold maximum possible number of strips */
  if (!(stripArray = (Qstrip *) tdmAllocate(sizeof(Qstrip) * nquads)))
    {
      PRINT(("out of memory"));
      DXErrorGoto (ERROR_NO_MEMORY, "#13000") ;
    }

  if (neighbors)
    {
      /* quad connections expressed explicitly, we need usedArray */
      if (!(usedArray = tdmAllocateZero(sizeof(char) * Bytes(nquads))))
	{
	  PRINT(("out of memory"));
	  DXErrorGoto (ERROR_NO_MEMORY, "#13000") ;
	}

      /* strip the field, placing strip info into temporary arrays */
      for (start_quad = 0; start_quad < nquads; start_quad++)
	{
	  if (GoodQuad(start_quad))
	    {
	      nPtsInStrip = 0 ;
	      quad = start_quad ;
	      InitFirstQuad(i0,i1,i2,i3) ; /* pick 1st quad initial vertices */
	      AddPoint(quad,i1) ;          /* add the 1st two...             */
	      AddPoint(quad,i0) ;          /* ...points to the mesh          */
	      while (quad >= 0)            /* while there's a valid quad...  */
		{
		  AddPoint(quad,i3) ;      /*  add another quad to the strip */
		  AddPoint(quad,i2) ;
		  MarkQuad(quad) ;         /*  mark it as used               */
		  NextQuad(quad) ;         /*  move on to next quad          */
		}

	      /* save strip points */
	      AllocateAndCopyQstripPointArray() ;
	    }
	}
      tdmFree((Pointer)usedArray) ;
      usedArray = NULL;
    }
  else
    {
      /* quad connections expressed in compact mesh array form */
      int n, counts[100] ;

      if (!DXQueryGridConnections (xf->origConnections_array, &n, counts) || n != 2)
	  DXErrorGoto (ERROR_INTERNAL, "#13140") ;

      PRINT(("counts[0] = %d", counts[0]));
      PRINT(("counts[1] = %d", counts[1]));

      for (n = 0, i = 0 ; i < counts[0]-1 ; i++)
	{
	  j = 0 ;
	  while (j < counts[1]-1)
	    {
	      for ( ; j < counts[1]-1 && !ValidQuad(xf->invCntns, n) ; j++, n++)
		  /* skip invalid quads up to end of row/column */ ;

	      if (j == counts[1]-1)
		  break ;

	      /* start triangle strip */
	      nPtsInStrip = 0 ;
	      point[nPtsInStrip++] = n + i ;
	      point[nPtsInStrip++] = n + i + counts[1] ;

	      while (j < counts[1]-1 &&
		     nPtsInStrip < MaxQstripSize &&
		     ValidQuad(xf->invCntns, n))
		{
		  /* add valid quads up to end of row/column or strip limit  */
		  point[nPtsInStrip++] = n + i + 1 ;
		  point[nPtsInStrip++] = n + i + 1 + counts[1] ;
		  j++ ; n++ ;
		}

	      /* save strip points */
	      AllocateAndCopyQstripPointArray() ;
	    }
	}
    }

  PRINT(("stripped %d quadrangles", (nStrippedPts - 2*nStrips)/2));
  PRINT(("generated %d triangle strips", nStrips));
  PRINT(("average number of triangles per strip: %f",
	   nStrips? (nStrippedPts - 2*nStrips)/(float)nStrips: 0));

  if (! _newQMesh(nStrips, nStrippedPts, &qmesh, &qmesho))
      goto error;

  for (i=j=k=0 ; i<nStrips ; i++)
    {
      qmesh->meshes[j++] = k;
      qmesh->meshes[j++] = stripArray[i].points;
      memcpy(qmesh->connections+k, stripArray[i].point, stripArray[i].points*sizeof(int));
      k += stripArray[i].points;
    }

  _dxf_InsertObject(MESHHASH, (dxObject)(xf->field), (dxObject)qmesho);
  xf->meshObject = DXReference(qmesho);
  _installQMeshInfo(xf, qmesh);

  /* free temporary array of strips */
  if (usedArray)
      tdmFree((Pointer)usedArray);
  if (stripArray)
      FreeTempStrips() ;

  EXIT(("OK"));
  return OK ;

 error:
  if (usedArray)
      tdmFree((Pointer)usedArray);
  if (stripArray)
      FreeTempStrips() ;

  EXIT(("ERROR"));
  return 0 ;
}