master expl.c
  1#include <ctype.h>
  2#include <stdio.h>
  3#include <stdlib.h>
  4#include <string.h>
  5
  6#include "expl.h"
  7
  8#define current(p)    ((p)->src[(p)->pos])
  9#define peek(p)       ((p)->src[(p)->pos + 1])
 10#define is(p, c)      (current(p) == (c))
 11#define end(p)        (is(p, '\0'))
 12#define advance(p)    ((p)->pos++)
 13#define length(p, s)  ((p)->pos - (s))
 14
 15typedef enum {
 16	EXPRESSION_TYPE_ATOM,
 17	EXPRESSION_TYPE_STRING,
 18	EXPRESSION_TYPE_LIST,
 19
 20	EXPRESSION_TYPE_COUNT
 21} expression_type;
 22
 23typedef struct environment environment;
 24typedef struct function function;
 25typedef struct parser parser;
 26
 27struct expl {
 28	environment* env;
 29	expression*  programs;
 30};
 31
 32struct environment {
 33	char*        name;
 34	expl_value   value;
 35	environment* next;
 36};
 37
 38struct function {
 39	expl_native native;
 40	expression*  args;
 41	expression*  body;
 42	void*       data;
 43};
 44
 45struct expression {
 46	char*      value;
 47	expression_type  type;
 48	expression* child;
 49	expression* next;
 50};
 51
 52struct parser {
 53	const char* src;
 54	size_t      pos;
 55	expl_error  err;
 56};
 57
 58static int define(environment** env, const char* name, expl_value value);
 59static expression* parse_expression(parser* p);
 60static expression* list(parser* p);
 61static expl_value* lookup(environment* env, const char* name);
 62expression* parse(const char* source);
 63static expression* value(parser* p, expression_type type);
 64
 65static expl_value eval(expression* n, environment** env);
 66static expl_value eval_call(expression* args, environment** env);
 67static expl_value eval_fn(expression* args, environment** env);
 68static expl_value eval_user(function* f, int argc, expl_value* argv, environment** env);
 69
 70static void skip_space(parser* p);
 71static char* _strndup(const char* src, size_t len);
 72static void unescape(char* src);
 73
 74static expression* new_node(expression_type type);
 75static void free_node(expression* node);
 76static void free_environment(environment* env);
 77
 78static int
 79define(environment** env, const char* name, expl_value value)
 80{
 81	environment* b = malloc(sizeof(*b));
 82	if (!b)
 83		return 0;
 84
 85	b->name = _strndup(name, strlen(name));
 86	if (!b->name) {
 87		free(b);
 88		return 0;
 89	}
 90
 91	b->value = value;
 92	b->next = *env;
 93	*env = b;
 94
 95	return 1;
 96}
 97
 98static expression*
 99parse_expression(parser* p)
100{
101	skip_space(p);
102	switch (current(p)) {
103	case '"':
104		return value(p, EXPRESSION_TYPE_STRING);
105	case '(':
106		return list(p);
107	case ')':
108	case '\0':
109		p->err = EXPL_ERR_UNEXPECTED_TOKEN;
110		return NULL;
111	default:
112		return value(p, EXPRESSION_TYPE_ATOM);
113	}
114}
115
116static expression*
117list(parser* p)
118{
119	expression* node = NULL;
120	expression** next = NULL;
121
122	advance(p);
123
124	node = new_node(EXPRESSION_TYPE_LIST);
125	if (!node) {
126		p->err = EXPL_ERR_OUT_OF_MEMORY;
127		return NULL;
128	}
129
130	next = &node->child;
131
132	skip_space(p);
133	while (!is(p, ')') && !end(p)) {
134		*next = parse_expression(p);
135		if (!*next) {
136			free_node(node);
137			return NULL;
138		}
139
140		next = &(*next)->next;
141		skip_space(p);
142	}
143
144	if (end(p)) {
145		p->err = EXPL_ERR_EXPECTED_LIST;
146		free_node(node);
147		return NULL;
148	}
149
150	advance(p);
151	return node;
152}
153
154static expl_value*
155lookup(environment* env, const char* name)
156{
157	while (env) {
158		if (strcmp(env->name, name) == 0)
159			return &env->value;
160		env = env->next;
161	}
162
163	return NULL;
164}
165
166expression*
167parse(const char* source)
168{
169	parser p = { 0 };
170	expression* head = NULL;
171	expression** next = &head;
172
173	if (!source)
174		return NULL;
175	p.src = source;
176
177	skip_space(&p);
178	while (!end(&p)) {
179		*next = parse_expression(&p);
180		if (!*next) {
181			free_node(head);
182			return NULL;
183		}
184
185		next = &(*next)->next;
186		skip_space(&p);
187	}
188
189	return head;
190}
191
192static expression*
193value(parser* p, expression_type type)
194{
195	expression* node = NULL;
196	size_t start = 0;
197
198	if (type == EXPRESSION_TYPE_STRING)
199		advance(p);
200
201	start = p->pos;
202
203	if (type == EXPRESSION_TYPE_STRING) {
204		while (!is(p, '"') && !end(p)) {
205			if (is(p, '\\') && peek(p))
206				advance(p);
207			advance(p);
208		}
209
210		if (end(p)) {
211			p->err = EXPL_ERR_EXPECTED_STRING;
212			return NULL;
213		}
214	}
215	else {
216		while (!end(p) &&
217		       !strchr("();\"", current(p)) &&
218		       !isspace((unsigned char)current(p)))
219			advance(p);
220	}
221
222	if (start == p->pos && type == EXPRESSION_TYPE_ATOM) {
223		p->err = EXPL_ERR_EXPECTED_ATOM;
224		return NULL;
225	}
226
227	node = new_node(type);
228	if (!node) {
229		p->err = EXPL_ERR_OUT_OF_MEMORY;
230		return NULL;
231	}
232
233	node->value = _strndup(p->src + start, length(p, start));
234	if (!node->value) {
235		free_node(node);
236		p->err = EXPL_ERR_OUT_OF_MEMORY;
237		return NULL;
238	}
239
240	if (type == EXPRESSION_TYPE_STRING) {
241		unescape(node->value);
242		advance(p);
243	}
244
245	return node;
246}
247
248static expl_value
249eval(expression* n, environment** env)
250{
251	expl_value result = { 0 };
252	expl_value* v;
253	char* end;
254
255	if (!n)
256		return result;
257
258	switch (n->type) {
259	case EXPRESSION_TYPE_STRING:
260		result.type = EXPL_VALUE_STRING;
261		result.as.string = n->value;
262		return result;
263
264	case EXPRESSION_TYPE_ATOM:
265		result.as.number = strtod(n->value, &end);
266		if (end != n->value && !*end) {
267			result.type = EXPL_VALUE_NUMBER;
268			return result;
269		}
270
271		v = lookup(*env, n->value);
272		if (v)
273			return *v;
274		return result;
275
276	case EXPRESSION_TYPE_LIST:
277		return eval_call(n, env);
278
279	default:
280		return result;
281	}
282}
283
284static expl_value
285eval_call(expression* n, environment** env)
286{
287	expl_value result = { 0 };
288	expl_value* fn = NULL;
289	expl_value* argv = NULL;
290	expression* arg = NULL;
291	function* f = NULL;
292	int argc = 0;
293	int i = 0;
294
295	if (!n->child || n->child->type != EXPRESSION_TYPE_ATOM)
296		return result;
297	
298	/* defined function */
299	if (!strcmp(n->child->value, "fn"))
300		return eval_fn(n->child->next, env);	
301
302	fn = lookup(*env, n->child->value);
303	if (!fn || fn->type != EXPL_VALUE_FUNCTION)
304		return result;
305
306	for (arg = n->child->next; arg; arg = arg->next)
307		argc++;
308
309	/* allocate argv */
310	if (argc) {
311		argv = malloc(argc * sizeof(*argv));
312		if (!argv)
313			return result;
314	}
315
316	/* evaluate arguments */
317	for (arg = n->child->next; arg; arg = arg->next)
318		argv[i++] = eval(arg, env);
319
320	/* call */
321	f = fn->as.function;
322	if (f->native)
323		result = f->native(argc, argv, f->data);
324	else
325		result = eval_user(f, argc, argv, env);
326
327	free(argv);
328	return result;
329}
330
331static expl_value
332eval_fn(expression* args, environment** env)
333{
334	expl_value result = { 0 };
335	expression* name = NULL;
336	function* f = NULL;
337
338	name = args;
339	if (!name || name->type != EXPRESSION_TYPE_ATOM ||
340	    !name->next || !name->next->next ||
341	    name->next->type != EXPRESSION_TYPE_LIST)
342		return result;
343
344	f = malloc(sizeof(*f));
345	if (!f)
346		return result;
347
348	f->native = NULL;
349	f->args = name->next->child;
350	f->body = name->next->next;
351
352	result.type = EXPL_VALUE_FUNCTION;
353	result.as.function = f;
354
355	if (!define(env, name->value, result)) {
356		free(f);
357		result.type = EXPL_VALUE_NIL;
358	}
359
360	return result;
361}
362
363static expl_value
364eval_user(function* f, int argc, expl_value* argv, environment** env)
365{
366	environment* local = *env;
367	expression* param = f->args;
368	environment* next = NULL;
369	expression* body = NULL;
370	expl_value result = { 0 };
371	int i;
372
373	for (i = 0; i < argc && param; i++) {
374		if (!define(&local, param->value, argv[i]))
375			break;
376		param = param->next;
377	}
378
379	if (i == argc && !param) {
380		for (body = f->body; body; body = body->next)
381			result = eval(body, &local);
382	}
383
384	while (local != *env) {
385		next = local->next;
386		free(local->name);
387		free(local);
388		local = next;
389	}
390
391	return result;
392}
393
394static void
395skip_space(parser* p)
396{
397	for (;;) {
398		if (is(p, ';')) {
399			while (!is(p, '\n') && !end(p))
400				advance(p);
401		}
402		else if (isspace((unsigned char)current(p)))
403			advance(p);
404		else
405			break;
406	}
407}
408
409static char*
410_strndup(const char* src, size_t len)
411{
412	char* str = malloc(len + 1);
413	if (!str)
414		return NULL;
415
416	memcpy(str, src, len);
417	str[len] = '\0';
418
419	return str;
420}
421
422static void
423unescape(char* src)
424{
425	char* dst = src;
426
427	while (*src) {
428		if (*src == '\\' && src[1]) {
429			src++;
430			switch (*src) {
431			case 'n':  *dst++ = '\n'; break;
432			case 't':  *dst++ = '\t'; break;
433			case 'r':  *dst++ = '\r'; break;
434			case '\\': *dst++ = '\\'; break;
435			case '"':  *dst++ = '"';  break;
436			default:
437				*dst++ = '\\';
438				*dst++ = *src;
439			}
440		}
441		else {
442			*dst++ = *src;
443		}
444
445		src++;
446	}
447
448	*dst = '\0';
449}
450
451static expression*
452new_node(expression_type type)
453{
454	expression* node = calloc(1, sizeof(*node));
455	if (!node)
456		return NULL;
457	node->type = type;
458	return node;
459}
460
461static void
462free_node(expression* node)
463{
464	if (!node)
465		return;
466
467	free(node->value);
468	free_node(node->child);
469	free_node(node->next);
470	free(node);
471}
472
473static void
474free_environment(environment* env)
475{
476	while (env) {
477		environment* next = env->next;
478
479		if (env->value.type == EXPL_VALUE_FUNCTION)
480			free(env->value.as.function);
481
482		free(env->name);
483		free(env);
484		env = next;
485	}
486}
487
488expl* expl_init(void)
489{
490	return calloc(1, sizeof(expl));
491}
492
493void expl_close(expl* ctx)
494{
495	if (!ctx)
496		return;
497
498	free_environment(ctx->env);
499	free_node(ctx->programs);
500	free(ctx);
501}
502
503int
504expl_register(expl* ctx, const char* name, expl_native fn, void* data)
505{
506	function* f = NULL;
507	expl_value value = { 0 };
508
509	if (!f || !ctx || !name || !fn)
510		return 0;
511
512	f = calloc(1, sizeof(*f));
513	f->native = fn;
514	f->data = data;
515
516	value.type = EXPL_VALUE_FUNCTION;
517	value.as.function = f;
518
519	if (!define(&ctx->env, name, value)) {
520		free(f);
521		return 0;
522	}
523
524	return 1;
525}
526
527expl_value
528expl_run(expl* ctx, const char* source)
529{
530	expl_value result = { 0 };
531	expression* program = NULL;
532	expression* n = NULL;
533
534	if (!ctx || !source)
535		return result;
536
537	program = parse(source);
538	if (!program)
539		return result;
540
541	for (n = program; n; n = n->next)
542		result = eval(n, &ctx->env);
543
544	if (ctx->programs) {
545		n = ctx->programs;
546		while (n->next)
547			n = n->next;
548		n->next = program;
549	}
550	else
551		ctx->programs = program;
552
553	return result;
554}
555