diff options
author | Camil Staps | 2016-08-26 00:46:55 +0200 |
---|---|---|
committer | Camil Staps | 2016-08-26 00:46:55 +0200 |
commit | 00e2c70b01f28c9b00ec3d5096895a387676774d (patch) | |
tree | 8ee65ec944e5cdd79d517c723e6b506fa7ee43a1 | |
parent | Added tup example (diff) |
Linking C functions
-rw-r--r-- | examples/fac.fusp | 7 | ||||
-rw-r--r-- | interpreter/Makefile | 6 | ||||
-rw-r--r-- | interpreter/code.c | 54 | ||||
-rw-r--r-- | interpreter/code.h | 12 | ||||
-rw-r--r-- | interpreter/eval.c | 77 | ||||
-rw-r--r-- | interpreter/fuspelc.c | 4 | ||||
-rw-r--r-- | interpreter/lex.c | 13 | ||||
-rw-r--r-- | interpreter/parse.c | 14 | ||||
-rw-r--r-- | interpreter/print.c | 7 | ||||
-rw-r--r-- | interpreter/syntax.c | 9 | ||||
-rw-r--r-- | interpreter/syntax.h | 2 |
11 files changed, 197 insertions, 8 deletions
diff --git a/examples/fac.fusp b/examples/fac.fusp new file mode 100644 index 0000000..38643d5 --- /dev/null +++ b/examples/fac.fusp @@ -0,0 +1,7 @@ +mul a b = code mul a b; +sub a b = code sub a b; + +fac 0 = 1; +fac n = mul n (fac (sub 1 n)); + +main = fac 5; 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 |