aboutsummaryrefslogtreecommitdiff
path: root/interpreter
diff options
context:
space:
mode:
authorCamil Staps2016-08-26 00:46:55 +0200
committerCamil Staps2016-08-26 00:46:55 +0200
commit00e2c70b01f28c9b00ec3d5096895a387676774d (patch)
tree8ee65ec944e5cdd79d517c723e6b506fa7ee43a1 /interpreter
parentAdded tup example (diff)
Linking C functions
Diffstat (limited to 'interpreter')
-rw-r--r--interpreter/Makefile6
-rw-r--r--interpreter/code.c54
-rw-r--r--interpreter/code.h12
-rw-r--r--interpreter/eval.c77
-rw-r--r--interpreter/fuspelc.c4
-rw-r--r--interpreter/lex.c13
-rw-r--r--interpreter/parse.c14
-rw-r--r--interpreter/print.c7
-rw-r--r--interpreter/syntax.c9
-rw-r--r--interpreter/syntax.h2
10 files changed, 190 insertions, 8 deletions
diff --git a/interpreter/Makefile b/interpreter/Makefile
index 5288c88..25c28ee 100644
--- a/interpreter/Makefile
+++ b/interpreter/Makefile
@@ -1,7 +1,7 @@
-CFLAGS=-Wall -Wextra -Werror -Wpedantic -s
+CFLAGS=-Wall -Wextra -Werror -s
-DEPS=lex.h syntax.h print.h parse.h log.h eval.h mem.h
-OBJ=fuspelc.o lex.o syntax.o print.o parse.o log.o eval.o mem.o
+DEPS=lex.h syntax.h print.h parse.h log.h eval.h mem.h code.h
+OBJ=fuspelc.o lex.o syntax.o print.o parse.o log.o eval.o mem.o code.o
EXE=fuspelc
.PHONY: all clean
diff --git a/interpreter/code.c b/interpreter/code.c
new file mode 100644
index 0000000..8845227
--- /dev/null
+++ b/interpreter/code.c
@@ -0,0 +1,54 @@
+#include "code.h"
+
+#include <string.h>
+#include <time.h>
+
+#include "mem.h"
+
+expression* make_int_expression(int i) {
+ expression* result = my_calloc(1, sizeof(expression));
+ result->kind = EXPR_INT;
+ result->var1 = my_calloc(1, sizeof(int));
+ *((int*) result->var1) = i;
+ return result;
+}
+
+expression* make_name_expression(char* s) {
+ expression* result = my_calloc(1, sizeof(expression));
+ result->kind = EXPR_NAME;
+ result->var1 = my_calloc(1, strlen(s) + 1);
+ strcpy(result->var1, s);
+ return result;
+}
+
+expression* code_time(void) {
+ return make_int_expression((int) time(NULL));
+}
+
+expression* code_mul(expression* a, expression* b) {
+ return (a->kind != EXPR_INT || b->kind != EXPR_INT)
+ ? make_name_expression("mul on non-ints")
+ : make_int_expression(*((int*) a->var1) * *((int*) b->var1));
+}
+
+expression* code_sub(expression* a, expression* b) {
+ return (a->kind != EXPR_INT || b->kind != EXPR_INT)
+ ? make_name_expression("sub on non-ints")
+ : make_int_expression(*((int*) b->var1) - *((int*) a->var1));
+}
+
+unsigned char code_find(char* name, void** function) {
+ if (!strcmp(name, "mul")) {
+ *function = (void(*)(void)) code_mul;
+ return 2;
+ } else if (!strcmp(name, "sub")) {
+ *function = (void(*)(void)) code_sub;
+ return 2;
+ } else if (!strcmp(name, "time")) {
+ *function = (void(*)(void)) code_time;
+ return 0;
+ }
+
+ *function = NULL;
+ return 0;
+}
diff --git a/interpreter/code.h b/interpreter/code.h
new file mode 100644
index 0000000..4c850a2
--- /dev/null
+++ b/interpreter/code.h
@@ -0,0 +1,12 @@
+#ifndef _H_CODE
+#define _H_CODE
+
+#include "syntax.h"
+
+typedef expression* (Code_0) ();
+typedef expression* (Code_1) (expression*);
+typedef expression* (Code_2) (expression*, expression*);
+
+unsigned char code_find(char* name, void** function);
+
+#endif
diff --git a/interpreter/eval.c b/interpreter/eval.c
index 6468bb8..7349c28 100644
--- a/interpreter/eval.c
+++ b/interpreter/eval.c
@@ -2,6 +2,7 @@
#include <string.h>
+#include "code.h"
#include "mem.h"
void free_rules_until(fuspel* new, fuspel* old) {
@@ -30,6 +31,7 @@ void replace(char* name, expression* new, expression* expr) {
break;
}
case EXPR_INT:
+ case EXPR_CODE:
break;
case EXPR_TUPLE:
case EXPR_LIST:
@@ -193,7 +195,56 @@ expression* append_to_app(expression* app, expression* from, unsigned char n) {
return app;
}
+expression* eval_code(fuspel* rules, expression* expr) {
+ expression *root, *result, **args;
+ Code_1* f1; Code_2* f2;
+ expression *a1, *a2;
+ unsigned char args_len;
+
+ for (root = expr; root->kind == EXPR_APP; root = root->var1);
+ if (root->kind != EXPR_CODE) {
+ return NULL;
+ }
+
+ args = flatten_app_args(expr);
+
+ switch (*((unsigned char*) root->var2)) {
+ case 1:
+ f1 = (Code_1*) root->var1;
+ a1 = eval(rules, args[1]);
+ if (!a1) {
+ my_free(a1);
+ my_free(args);
+ return NULL;
+ }
+ result = f1(a1);
+ break;
+ case 2:
+ f2 = (Code_2*) root->var1;
+ a1 = eval(rules, args[1]);
+ a2 = eval(rules, args[2]);
+ if (!a1 || !a2) {
+ my_free(a1);
+ my_free(a2);
+ my_free(args);
+ return NULL;
+ }
+ result = f2(a1, a2);
+ break;
+ }
+
+ for (args_len = 0; args[args_len]; args_len++);
+ append_to_app(result, expr, args_len - *((unsigned char*) root->var2));
+
+ my_free(args);
+ my_free(a1);
+ my_free(a2);
+
+ return result;
+}
+
expression* eval_rnf(fuspel* rules, expression* expr) {
+ expression* code_result;
expression* result = my_calloc(1, sizeof(expression));
fuspel* _rules = rules;
@@ -204,11 +255,19 @@ expression* eval_rnf(fuspel* rules, expression* expr) {
case EXPR_INT:
case EXPR_TUPLE:
case EXPR_LIST:
+ case EXPR_CODE:
cpy_expression(result, expr);
break;
case EXPR_NAME:
case EXPR_APP:
+ code_result = eval_code(rules, expr);
+ if (code_result) {
+ my_free(result);
+ result = code_result;
+ break;
+ }
+
while (_rules) {
char skip_args;
if ((skip_args = match_rule(
@@ -244,6 +303,7 @@ expression* eval(fuspel* rules, expression* expr) {
expression *e1, *e2;
fuspel* _rules = rules;
expression* result = my_calloc(1, sizeof(expression));
+ expression* code_result;
replacements** repls = my_calloc(1, sizeof(replacements*));
switch (expr->kind) {
@@ -251,8 +311,25 @@ expression* eval(fuspel* rules, expression* expr) {
cpy_expression(result, expr);
break;
+ case EXPR_CODE:
+ if (*((unsigned char*) expr->var2) == 0) {
+ Code_0* code_fun = (Code_0*) expr->var1;
+ my_free(result);
+ result = code_fun();
+ } else {
+ cpy_expression(result, expr);
+ }
+ break;
+
case EXPR_NAME:
case EXPR_APP:
+ code_result = eval_code(rules, expr);
+ if (code_result) {
+ my_free(result);
+ result = code_result;
+ break;
+ }
+
while (_rules) {
char skip_args;
if ((skip_args = match_rule(
diff --git a/interpreter/fuspelc.c b/interpreter/fuspelc.c
index 5edb48c..4450486 100644
--- a/interpreter/fuspelc.c
+++ b/interpreter/fuspelc.c
@@ -39,9 +39,9 @@ int main(void) {
exit(EXIT_FAILURE);
}
- printf("\nParsed program:\n");
+ printf("\n");
print_fuspel(pgm);
- printf("\n\n\n");
+ printf("\n\n");
to_eval.kind = EXPR_NAME;
to_eval.var1 = my_calloc(1, 5);
diff --git a/interpreter/lex.c b/interpreter/lex.c
index b238b5e..bd64349 100644
--- a/interpreter/lex.c
+++ b/interpreter/lex.c
@@ -49,7 +49,7 @@ token_list* lex(token_list* list, char* input) {
}
while (*input) {
- unsigned proceed_to_next_token = 1;
+ unsigned create_new_token = 1;
list->elem.var = NULL;
@@ -62,6 +62,13 @@ token_list* lex(token_list* list, char* input) {
case ']': list->elem.kind = TOKEN_CLOSE_SQ; break;
case '=': list->elem.kind = TOKEN_EQUALS; break;
case ',': list->elem.kind = TOKEN_COMMA; break;
+ case 'c':
+ if (input[1] == 'o' && input[2] == 'd' && input[3] == 'e' &&
+ is_space_char(input[4])) {
+ list->elem.kind = TOKEN_CODE;
+ input += 4;
+ }
+ break;
default:
if (is_int_char(*input)) {
@@ -81,7 +88,7 @@ token_list* lex(token_list* list, char* input) {
strncpy(list->elem.var, input, len);
input += len - 1;
} else if (is_space_char(*input)) {
- proceed_to_next_token = 0;
+ create_new_token = 0;
} else {
free_token_list(first_list);
my_free(first_list);
@@ -91,7 +98,7 @@ token_list* lex(token_list* list, char* input) {
input++;
- if (*input && proceed_to_next_token) {
+ if (*input && create_new_token) {
list->rest = my_calloc(1, sizeof(token_list));
list = list->rest;
}
diff --git a/interpreter/parse.c b/interpreter/parse.c
index a9fc345..4c5ba99 100644
--- a/interpreter/parse.c
+++ b/interpreter/parse.c
@@ -2,6 +2,7 @@
#include <string.h>
+#include "code.h"
#include "log.h"
#include "mem.h"
@@ -30,6 +31,19 @@ token_list* parse_simple_expression(expression* expr, token_list* list) {
list = parse_name((char**) &expr->var1, list);
return list;
+ case TOKEN_CODE:
+ if (list->rest && list->rest->elem.kind == TOKEN_NAME) {
+ char* name;
+ expr->kind = EXPR_CODE;
+ list = parse_name(&name, list->rest);
+ expr->var2 = my_calloc(1, sizeof(unsigned char));
+ *((unsigned char*) expr->var2) = code_find(name, &expr->var1);
+ my_free(name);
+ return list;
+ } else {
+ return NULL;
+ }
+
case TOKEN_OPEN_P:
list = parse_simple_expression(expr, list->rest);
if (!list)
diff --git a/interpreter/print.c b/interpreter/print.c
index a71e71f..c60c190 100644
--- a/interpreter/print.c
+++ b/interpreter/print.c
@@ -15,6 +15,9 @@ void print_token(token* tk) {
case TOKEN_CLOSE_SQ: c = ']'; break;
case TOKEN_EQUALS: c = '='; break;
case TOKEN_COMMA: c = ','; break;
+ case TOKEN_CODE:
+ printf("code ");
+ return;
case TOKEN_NAME:
printf("%s", (char*) tk->var);
return;
@@ -41,6 +44,10 @@ void print_expression(expression* expr) {
case EXPR_NAME:
printf("%s", (char*) expr->var1);
break;
+ case EXPR_CODE:
+ printf("code [%p, %d args]",
+ (void*) expr->var1, *((unsigned char*) expr->var2));
+ break;
case EXPR_LIST:
if (!expr->var1) {
printf("[]");
diff --git a/interpreter/syntax.c b/interpreter/syntax.c
index 7a0dd39..1722761 100644
--- a/interpreter/syntax.c
+++ b/interpreter/syntax.c
@@ -41,6 +41,11 @@ void cpy_expression(expression* dst, expression* src) {
dst->var1 = my_calloc(1, strlen((char*) src->var1) + 1);
strcpy(dst->var1, src->var1);
break;
+ case EXPR_CODE:
+ dst->var1 = src->var1;
+ dst->var2 = my_calloc(1, sizeof(unsigned char));
+ *((unsigned char*) dst->var2) = *((unsigned char*) src->var2);
+ break;
case EXPR_LIST:
if (!src->var1)
break;
@@ -61,6 +66,7 @@ unsigned eq_expression(expression* a, expression* b) {
switch (a->kind) {
case EXPR_INT: return *((int*) a->var1) == *((int*) b->var1);
case EXPR_NAME: return !strcmp(a->var1, b->var1);
+ case EXPR_CODE: return a->var1 == b->var1;
case EXPR_TUPLE:
case EXPR_LIST:
case EXPR_APP:
@@ -139,6 +145,9 @@ void free_expression(expression* expr) {
case EXPR_NAME:
my_free(expr->var1);
break;
+ case EXPR_CODE:
+ my_free(expr->var2);
+ break;
case EXPR_LIST:
case EXPR_TUPLE:
case EXPR_APP:
diff --git a/interpreter/syntax.h b/interpreter/syntax.h
index bed4fcd..89242ac 100644
--- a/interpreter/syntax.h
+++ b/interpreter/syntax.h
@@ -12,6 +12,7 @@ typedef enum {
TOKEN_CLOSE_P, /* ) */
TOKEN_COMMA, /* , */
TOKEN_COLON, /* : */
+ TOKEN_CODE, /* code */
TOKEN_NAME,
TOKEN_INT
} token_kind;
@@ -34,6 +35,7 @@ void free_token_list(token_list*);
typedef enum {
EXPR_INT,
EXPR_NAME,
+ EXPR_CODE,
EXPR_LIST,
EXPR_TUPLE,
EXPR_APP