Add licence
[ilari-esolangs.git] / message.c
blobae9ee36cdb8e2ecf1866d36e1dca5bf899595948
1 #include "object.h"
2 #include "message.h"
3 #include <stdio.h>
4 #include <stdlib.h>
6 /* Message. */
7 struct message
9 /* Target object. */
10 struct object* m_target;
11 /* Number of parameters in message. */
12 size_t m_parameter_count;
13 /* Parameters contained. */
14 struct object* m_parameters[];
17 /* Message queue node. */
18 struct message_queue_node
20 /* Message. */
21 struct message* mqn_message;
22 /* Next in list. */
23 struct message_queue_node* mqn_next;
26 /* Message queue. */
27 struct message_queue
29 /* First message in queue. */
30 struct message_queue_node* mq_first;
31 /* Last message in queue. */
32 struct message_queue_node* mq_last;
35 /*****************************************************************************/
36 struct message_queue* message_queue_create()
38 struct message_queue* queue;
40 queue = malloc(sizeof(struct message_queue));
41 if(!queue) {
42 fprintf(stderr, "Out of memory!\n");
43 exit(1);
45 queue->mq_first = NULL;
46 queue->mq_last = NULL;
47 return queue;
50 /*****************************************************************************/
51 void message_queue_destroy(struct message_queue* queue)
53 struct message_queue_node* tmp;
54 while(queue->mq_first) {
55 tmp = queue->mq_first;
56 queue->mq_first = queue->mq_first->mqn_next;
57 free(tmp->mqn_message);
58 free(tmp);
60 free(queue);
63 /*****************************************************************************/
64 void message_queue_queue(struct message_queue* queue, struct message* msg)
66 struct message_queue_node* node;
68 node = malloc(sizeof(struct message_queue_node));
69 if(!node) {
70 fprintf(stderr, "Out of memory!\n");
71 exit(1);
74 node->mqn_message = msg;
75 node->mqn_next = NULL;
76 if(queue->mq_last)
77 queue->mq_last = queue->mq_last->mqn_next = node;
78 else
79 queue->mq_last = queue->mq_first = node;
82 /*****************************************************************************/
83 struct message* message_queue_deque(struct message_queue* queue)
85 if(!queue->mq_first)
86 return NULL;
88 /* Is the first message returnable? */
89 if(!object_is_executing(queue->mq_first->mqn_message->m_target)) {
90 struct message_queue_node* node = queue->mq_first;
91 struct message* msg = node->mqn_message;
92 queue->mq_first = node->mqn_next;
93 free(node);
94 if(!queue->mq_first)
95 queue->mq_last = NULL;
96 return msg;
99 /* Scan the rest of list. */
100 struct message_queue_node* itr = queue->mq_first;
101 while(itr->mqn_next)
102 if(object_is_executing(itr->mqn_next->mqn_message->m_target))
103 itr = itr->mqn_next;
104 if(!itr->mqn_next)
105 return NULL;
108 struct message_queue_node* node = itr->mqn_next;
109 struct message* msg = node->mqn_message;
110 itr->mqn_next = node->mqn_next;
111 free(node);
112 if(queue->mq_last == node)
113 queue->mq_last = itr;
114 return msg;
118 /*****************************************************************************/
119 void message_queue_forall(struct message_queue* queue,
120 void (*callback)(struct message* msg))
122 struct message_queue_node* itr = queue->mq_first;
123 while(itr) {
124 callback(itr->mqn_message);
125 itr = itr->mqn_next;
129 /*****************************************************************************/
130 struct object* message_target(struct message* msg)
132 return msg->m_target;
135 /*****************************************************************************/
136 size_t message_parameters(struct message* msg)
138 return msg->m_parameter_count;
141 /*****************************************************************************/
142 struct object* message_read_slot(struct message* msg, size_t slot)
144 if(slot < msg->m_parameter_count)
145 return msg->m_parameters[slot];
146 else
147 return NULL;
150 /*****************************************************************************/
151 void message_write_slot(struct message* msg, size_t slot, struct object* obj)
153 if(slot < msg->m_parameter_count)
154 msg->m_parameters[slot] = obj;
157 /*****************************************************************************/
158 struct message* message_create(struct object* target, size_t parameters)
160 struct message* msg;
161 msg = malloc(sizeof(struct message) + parameters *
162 sizeof(struct object*));
163 if(!msg) {
164 fprintf(stderr, "Out of memory!\n");
165 exit(1);
167 msg->m_target = target;
168 msg->m_parameter_count = parameters;
169 for(size_t i = 0; i < parameters; i++)
170 msg->m_parameters[i] = NULL;
172 return msg;