aboutsummaryrefslogtreecommitdiffstats
path: root/src/backend/backend.c
blob: b6b78bdf5fe6420c1c0dc23348467b5c455e0f4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#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