MEGATRON



LOG | FILES | OVERVIEW


#ifndef BACKEND_C
#define BACKEND_C BACKEND_C
#include <backend.h>

/*returns an array of pointers to state_and_transition structs*/
struct State_And_Transitions** extract_transition_table(struct AST_States *states,struct AST_Transitions *transitions)
{
	struct State_And_Transitions **ret;
	struct AST_State *hold_state;
	struct Queue *qs;
	size_t i;

	ret=malloc(sizeof(struct State_And_Transitions)*states->number_of_states);

	/*calloc also initialises the queues
	 *i-th queue is for transitions starting from the i-th state
	 * */
	qs=calloc(sizeof(struct Queue),states->number_of_states);

	/*traverse transitions and push them into the queue of their coresponding state*/
	for(i=0;i<transitions->size;++i)
	{
		hold_state=transitions->transitions[i]->from;
		Queue_Push(qs+hold_state->number,transitions->transitions[i]);
	}

	/*condense the queues into the arrays*/
	for(i=0;i<states->number_of_states;++i)
	{
		ret[i]=malloc(sizeof(struct State_And_Transitions)+sizeof(struct AST_Transitions *[qs[i].size]));
		ret[i]->state=states->states[i];
		ret[i]->number_of_transitions=qs[i].size;
		pointer_array_fill((void**)ret[i]->transitions,qs+i);
	}

	free(qs);

	return ret;
}

_Bool expression_is_binary(struct AST* expression)
{
	return (expression->type==AST_TYPE_OP_OR || expression->type==AST_TYPE_OP_AND || expression->type==AST_TYPE_OP_SELECTOR);
}
_Bool expression_is_unary(struct AST* expression)
{
	return (expression->type==AST_TYPE_OP_NOT);
}
_Bool state_is_in_states(struct AST_State *state,struct AST_States *states)
{
	return state==Map_Check(states->states_map,state->name->data,state->name->size);
}

struct AST_State* extract_state(struct AST *expression,struct AST_States *states)
{
	struct AST_State *hold_state;

	assert(expression->type==AST_TYPE_OP_NOT || expression->type==AST_TYPE_OP_AND || expression->type==AST_TYPE_OP_OR
			|| expression->type==AST_TYPE_STATE );
	
	if(expression->type==AST_TYPE_STATE)
	{
		if(state_is_in_states((struct AST_State*)expression,states))
			return (struct AST_State*)expression;
		else
			return NULL;
	}else if(expression_is_binary(expression))
	{
		hold_state=extract_state(((struct AST_Binary_Expression*)expression)->left,states);
		if(hold_state)
			return hold_state;
		else
			return extract_state(((struct AST_Binary_Expression*)expression)->right,states);
	}else 
	{
		return extract_state(((struct AST_Unary_Expression*)expression)->operand,states);
	}
}

_Bool check_expression(struct AST *state,struct AST_Translation_Unit *unit)
{

}
_Bool check_transition(struct AST *state,struct AST_Translation_Unit *unit)
{

}
void anotate_unchecked_states(struct AST_Translation_Unit *unit,struct Translation_Data *translation_data)
{
	size_t i;
	for(i=0;i<unit->number_of_machines;++i)
	{
		anotate_machine(unit->machines[i],unit,translation_data);
	}
}
void anotate_machine(struct AST_Machine *machine,struct AST_Translation_Unit *unit,struct Translation_Data *translation_data)
{
	size_t i;
	for(i=0;i<machine->transitions->size;++i)
	{
		machine->transitions->transitions[i]->statement=anotate_statement(machine->transitions->transitions[i]->statement,unit,machine,translation_data);
		if(machine->transitions->transitions[i]->granted)
			machine->transitions->transitions[i]->granted=anotate_expression(machine->transitions->transitions[i]->granted,unit,machine,translation_data);
	}
	if(has_new_errors(translation_data))
	{
		push_error_with_token("in machine",machine->id,translation_data);
	}
}
struct AST* anotate_statement(struct AST *statement,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data)
{
	if(statement==NULL)return NULL;
	if(statement->type==AST_TYPE_IF)
	{
		((struct AST_If_Statement*)statement)->condition=anotate_expression(((struct AST_If_Statement*)statement)->condition,unit,current_machine,translation_data);
	}else
	{
		return statement;
	}
}
struct AST* anotate_expression(struct AST *expression,struct AST_Translation_Unit *unit,struct AST_Machine *current_machine,struct Translation_Data *translation_data)
{
	struct AST_Machine *hold_machine;
	struct AST *hold_left;
	struct AST *hold_right;

	if(expression_is_binary(expression))
	{
		hold_left=((struct AST_Binary_Expression*)expression)->left;
		hold_right=((struct AST_Binary_Expression*)expression)->right;

		if(expression->type==AST_TYPE_OP_SELECTOR)
		{
			hold_machine=Map_Check(unit->machines_map,((struct AST_Unchecked_State*)hold_left)->name->data,((struct AST_Unchecked_State*)hold_left)->name->size);
			if(hold_machine==NULL)
			{
				push_error_with_token("machine id is undefined",((struct AST_Unchecked_State*)hold_left)->name,translation_data);
				return NULL;
			}else if(hold_machine==current_machine)
			{
				push_error_with_token("using a state from the current machine is disallowed",((struct AST_Unchecked_State*)hold_left)->name,translation_data);
				return NULL;
			}else
			{
				hold_left=(struct AST*)ast_check_state((struct AST_Unchecked_State*)hold_right,hold_machine->states,translation_data);
				if(hold_left)
				{
					((struct AST_State*)hold_left)->parent=hold_machine;
					return hold_left;
				}else
				{
					push_error_with_token("state id from foreign machine is undefined",((struct AST_Unchecked_State*)hold_right)->name,translation_data);
					return NULL;
				} 
			}
		}else
		{
			AS_BIN_EXPR_PTR(expression)->right=anotate_expression(AS_BIN_EXPR_PTR(expression)->right,unit,current_machine,translation_data);
			AS_BIN_EXPR_PTR(expression)->left=anotate_expression(AS_BIN_EXPR_PTR(expression)->left,unit,current_machine,translation_data);
			return expression;
		}
	}else if(expression_is_unary(expression))
	{
		AS_UN_EXPR_PTR(expression)->operand=anotate_expression(AS_UN_EXPR_PTR(expression)->operand,unit,current_machine,translation_data);
	}else if(expression->type==AST_TYPE_UNFINISHED_STATE)
	{
		hold_left=(struct AST*)ast_check_state((struct AST_Unchecked_State*)expression,current_machine->states,translation_data);
		((struct AST_State*)hold_left)->parent=current_machine;
		return hold_left;
	}
}
#endif