From 49aa5542a8e13d2d808f7dee6bd7418add6d74ea Mon Sep 17 00:00:00 2001 From: jdlugosz963 Date: Sun, 5 Mar 2023 23:10:15 +0100 Subject: Add primitive evaluation system --- eval.c | 61 +++++++++++++++++ eval.h | 20 ++++++ parser.c | 11 ---- repl.c | 109 +++++++++++++++++++++++++++++++ repl.h | 6 ++ types.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ types.h | 27 +++++++- 7 files changed, 446 insertions(+), 12 deletions(-) create mode 100644 eval.c create mode 100644 eval.h create mode 100644 repl.c create mode 100644 repl.h diff --git a/eval.c b/eval.c new file mode 100644 index 0000000..4e593d9 --- /dev/null +++ b/eval.c @@ -0,0 +1,61 @@ +#include "eval.h" +#include "types.h" + + +LISP_OBJECT *eval_apply(LISP_OBJECT *lisp_list, HashMap *env) +{ + if(lisp_list == NULL || lisp_list->type != LISP_TYPE_LIST) + return lisp_list; + + LISP_OBJECT *symbol = lisp_list->value.list->ptr; + List *args = lisp_list->value.list->next; + + LISP_OBJECT *func = hash_map_find(env, symbol->value.symbol)->value; + + if(func->type != LISP_TYPE_FUNC) + return lisp_list; + + List *tmp = lisp_list->value.list; + lisp_list->value.list = args; + LISP_OBJECT *ret = func->value.func(lisp_list); + lisp_list->value.list = tmp; + return ret; +} + +LISP_OBJECT *eval_prepere_args(LISP_OBJECT *lisp_list, HashMap *env) +{ + if(lisp_list == NULL || lisp_list->type != LISP_TYPE_LIST) + return lisp_list; + + LISP_OBJECT *args = lisp_object_make_list(); + List **args_list = &args->value.list; + + List *list = lisp_list->value.list; + LISP_OBJECT *obj = NULL; + + while(list) + { + obj = list->ptr; + if(obj->type==LISP_TYPE_LIST) + obj = eval(obj, env); + + *args_list = list_push(*args_list, obj); + list = list->next; + } + + *args_list = list_reverse(*args_list); + + return eval_apply(args, env); +} + + +LISP_OBJECT *eval(LISP_OBJECT *lisp_obj, HashMap *env) +{ + if(lisp_obj == NULL) + return NULL; + + if(lisp_obj->type == LISP_TYPE_LIST) + return eval_prepere_args(lisp_obj, env); + + return lisp_obj; +} diff --git a/eval.h b/eval.h new file mode 100644 index 0000000..0af0c87 --- /dev/null +++ b/eval.h @@ -0,0 +1,20 @@ +#ifndef _EVAL +#define _EVAL + +#include +#include +#include +#include +#include + +#include "types.h" +#include "memory.h" + + +// HashMap *repl_env = NULL; + +LISP_OBJECT *eval_apply(LISP_OBJECT *lisp_list, HashMap *env); +LISP_OBJECT *eval_prepere_args(LISP_OBJECT *lisp_list, HashMap *env); +LISP_OBJECT *eval(LISP_OBJECT *lisp_obj, HashMap *env); + +#endif diff --git a/parser.c b/parser.c index 574d2ac..4b408ab 100644 --- a/parser.c +++ b/parser.c @@ -161,14 +161,3 @@ LISP_OBJECT *parser_make_nil(Token **token) return lisp_obj; } -int main() -{ - char *test = "(display (string-append \"4*3+2=\" (number->string (+ (* 4 3) 1))))"; - - - LISP_OBJECT *obj = NULL; - - obj = parser_parse_str(test); - lisp_object_print(obj, 0); - lisp_object_free(obj); -} diff --git a/repl.c b/repl.c new file mode 100644 index 0000000..53be144 --- /dev/null +++ b/repl.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +#include "types.h" +#include "parser.h" +#include "eval.h" + + +LISP_OBJECT *Fadd(LISP_OBJECT *l) +{ + long long natural=0; + + List *list = l->value.list; + LISP_OBJECT *a = NULL; + while(list) + { + a = list->ptr; + natural += *a->value.number_natural; + list = list->next; + } + LISP_OBJECT *c = lisp_object_make_number_natural(natural); + return c; +} + +LISP_OBJECT *Fminus(LISP_OBJECT *l) +{ + LISP_OBJECT *a = l->value.list->ptr; + LISP_OBJECT *b = l->value.list->next->ptr; + LISP_OBJECT *c = lisp_object_make_number_natural( + *a->value.number_natural - *b->value.number_natural); + return c; +} + +LISP_OBJECT *Fmul(LISP_OBJECT *l) +{ + LISP_OBJECT *a = l->value.list->ptr; + LISP_OBJECT *b = l->value.list->next->ptr; + LISP_OBJECT *c = lisp_object_make_number_natural( + *a->value.number_natural * *b->value.number_natural); + return c; +} + +LISP_OBJECT *Fdiv(LISP_OBJECT *l) +{ + LISP_OBJECT *a = l->value.list->ptr; + LISP_OBJECT *b = l->value.list->next->ptr; + LISP_OBJECT *c = lisp_object_make_number_natural( + *a->value.number_natural / *b->value.number_natural); + return c; +} + +LISP_OBJECT *Fplusone(LISP_OBJECT *l) +{ + LISP_OBJECT *a = l->value.list->ptr; + LISP_OBJECT *c = lisp_object_make_number_natural( + *a->value.number_natural+1); + return c; +} + + +LISP_OBJECT *READ(char *input) +{ + return parser_parse_str(input); +} + +LISP_OBJECT *EVAL(LISP_OBJECT *input, HashMap *env) +{ + return eval(input, env); +} + +void PRINT(LISP_OBJECT *input) +{ + lisp_object_print(input, 0); + lisp_object_free(input); +} + +void rep(char *input, HashMap *env) +{ + PRINT(EVAL(READ(input), env)); +} + + +int main() +{ + HashMap *env = NULL; + env = hash_map_push(env, "+", lisp_object_make_func(&Fadd)); + env = hash_map_push(env, "-", lisp_object_make_func(&Fminus)); + env = hash_map_push(env, "*", lisp_object_make_func(&Fmul)); + env = hash_map_push(env, "/", lisp_object_make_func(&Fdiv)); + env = hash_map_push(env, "++", lisp_object_make_func(&Fplusone)); + + char *input1 = NULL; + char *input = NULL; + + while(1) + { + input = readline("JADL> "); + input1 = malloc(sizeof(char) * strlen(input) + 1); + strcpy(input1, input); + input1[strlen(input)] = '\0'; + + free(input); + + rep(input1, env); + free(input1); + } +} diff --git a/repl.h b/repl.h new file mode 100644 index 0000000..faf70b4 --- /dev/null +++ b/repl.h @@ -0,0 +1,6 @@ +#include "types.h" + +LISP_OBJECT PRINT(char *input); +LISP_OBJECT EVAL(char *input); +LISP_OBJECT READ(char *input); +LISP_OBJECT rep(char *input); diff --git a/types.c b/types.c index 42359bb..4fd00d2 100644 --- a/types.c +++ b/types.c @@ -1,6 +1,7 @@ #include "types.h" #include "memory.h" #include +#include List *list_make(void *ptr) @@ -174,6 +175,14 @@ LISP_OBJECT *lisp_object_make_false() return lisp_obj; } +LISP_OBJECT *lisp_object_make_func(LISP_OBJECT *(*func)(LISP_OBJECT*)) +{ + LISP_OBJECT *lisp_obj = lisp_object_make(); + lisp_obj->type = LISP_TYPE_FUNC; + lisp_obj->value.func = func; + return lisp_obj; +} + int lisp_object_print(LISP_OBJECT *obj, int indent) { int count = 0; @@ -230,3 +239,218 @@ int lisp_object_print(LISP_OBJECT *obj, int indent) } return count; } + +int lisp_object_cmp_types(LISP_OBJECT *a, LISP_OBJECT *b) +{ + if(a==NULL && b==NULL) + return 1; + else if(a==NULL || b==NULL) + return 0; + else if(a->type != b->type) + return 0; + else if(a->type == b->type) + return 1; + return 0; +} + +int lisp_object_cmp(LISP_OBJECT *a, LISP_OBJECT *b) +{ + int is_same_type = lisp_object_cmp_types(a, b); + if(!is_same_type) + return 0; + + switch(a->type) + { + case LISP_TYPE_LIST: + break; + case LISP_TYPE_NUMBER: + return lisp_object_cmp_numbers(a, b); + break; + case LISP_TYPE_STRING: + lisp_object_cmp_string(a, b); + break; + case LISP_TYPE_SYMBOL: + lisp_object_cmp_symbol(a, b); + break; + case LISP_TYPE_NIL: + case LISP_TYPE_TRUE: + case LISP_TYPE_FALSE: + case LISP_TYPE_ERROR: + return 1; + break; + } +} + +int lisp_object_cmp_numbers(LISP_OBJECT *a, LISP_OBJECT *b) // TODO: make it works +{ + int is_same_type= lisp_object_cmp_types(a, b); + if(!is_same_type && a->type == LISP_TYPE_NUMBER) + return 0; + + if(a->is_decimal_point && b->is_decimal_point) + return *a->value.number_float == *b->value.number_float; + else if(a->is_decimal_point && !b->is_decimal_point) + return *a->value.number_float == *(double *)b->value.number_natural; + else if(!a->is_decimal_point && b->is_decimal_point) + return *(double *)a->value.number_natural == *b->value.number_float; + else + return *a->value.number_natural == *b->value.number_natural; +} + +int lisp_object_cmp_symbol(LISP_OBJECT *a, LISP_OBJECT *b) +{ + int is_same_type= lisp_object_cmp_types(a, b); + if(!is_same_type && a->type == LISP_TYPE_SYMBOL) + return 0; + + return strcmp(a->value.symbol, b->value.symbol) == 0; +} + +int lisp_object_cmp_string(LISP_OBJECT *a, LISP_OBJECT *b) +{ + int is_same_type= lisp_object_cmp_types(a, b); + if(!is_same_type && a->type == LISP_TYPE_STRING) + return 0; + + return strcmp(a->value.string, b->value.string) == 0; +} + +HashMap *hash_map_make(char *key, LISP_OBJECT *value) +{ + return hash_map_push(NULL, key, value); +} + +HashMap *hash_map_push(HashMap *hash_map, char *key, LISP_OBJECT *value) +{ + HashMap *is_exist = hash_map_find(hash_map, key); + + if(is_exist != NULL) + return NULL; + + HashMap *new_hash_map = jadl_malloc(sizeof(HashMap)); + + new_hash_map->key = jadl_malloc(sizeof(char) * strlen(key));; + strcpy(new_hash_map->key, key); + + new_hash_map->value = value; + new_hash_map->prev = NULL; + + if(hash_map != NULL) + hash_map->prev = new_hash_map; + new_hash_map->next = hash_map; + + return new_hash_map; +} + +HashMap *hash_map_reverse(HashMap *hash_map) +{ + HashMap *current = hash_map; + HashMap *next = NULL; + HashMap *new_hash_map = NULL; + while (current) { + next = current->next; + + current->next = new_hash_map; + new_hash_map = current; + + current = next; + } + + return new_hash_map; +} + + +void hash_map_free(HashMap *hash_map) +{ + HashMap *next = NULL; + + while (hash_map) + { + next = hash_map->next; + + jadl_free(hash_map->key); + lisp_object_free(hash_map->value); + jadl_free(hash_map); + + hash_map = next; + } +} + +HashMap *hash_map_find(HashMap *hash_map, char* key) +{ + if (hash_map == NULL) + return NULL; + + while (hash_map) + { + if(strcmp(hash_map->key, key) == 0) + return hash_map; + + hash_map = hash_map->next; + } + + return NULL; +} + +HashMap *hash_map_delete(HashMap *hash_map, char* key) +{ + HashMap *hash_map_to_free = hash_map_find(hash_map, key); + + if(hash_map_to_free == NULL) + return hash_map; + + HashMap *new_hash_map = NULL; + + if(hash_map_to_free->prev == NULL) + { + new_hash_map = hash_map_to_free->next; + new_hash_map->prev = NULL; + } else + { + new_hash_map = hash_map_to_free->prev; + new_hash_map->next=hash_map_to_free->next; + if(new_hash_map->next) + new_hash_map->next->prev = new_hash_map; + } + + HashMap *prev = new_hash_map->prev; + while(prev) + { + new_hash_map = prev; + prev = prev->prev; + } + + hash_map_to_free->next = NULL; + hash_map_free(hash_map_to_free); + + return new_hash_map; +} + + +void hash_map_print(HashMap *hash_map) +{ + while (hash_map) + { + printf("-------------\n"); + printf("HashMap->key = %s\n", hash_map->key); + printf("HashMap->value: \n"); + lisp_object_print(hash_map->value, 0); + + hash_map = hash_map->next; + } + + printf("-------------\n"); +} + +HashMap *hash_last(HashMap *hash_map) +{ + HashMap *next = NULL; + while (hash_map) + { + next = hash_map->next; + if(!next) + return hash_map; + hash_map = next; + } + return NULL; +} diff --git a/types.h b/types.h index 632e283..f6e3fcf 100644 --- a/types.h +++ b/types.h @@ -16,6 +16,7 @@ typedef enum _LispType { LISP_TYPE_NIL, LISP_TYPE_TRUE, LISP_TYPE_FALSE, + LISP_TYPE_FUNC, LISP_TYPE_ERROR } LispType; @@ -39,7 +40,7 @@ typedef struct _LispObject { char *error; long long *number_natural; double *number_float; - struct _LispObject (*function)(struct _LispObject*); + struct _LispObject *(*func)(struct _LispObject*); List *list; void *ptr; } value; @@ -59,7 +60,31 @@ LISP_OBJECT *lisp_object_make_error(char *str); LISP_OBJECT *lisp_object_make_nil(); LISP_OBJECT *lisp_object_make_true(); LISP_OBJECT *lisp_object_make_false(); +LISP_OBJECT *lisp_object_make_func(LISP_OBJECT *(*func)(LISP_OBJECT*)); int lisp_object_print(LISP_OBJECT *obj, int indent); +int lisp_object_cmp_types(LISP_OBJECT *a, LISP_OBJECT *b); +int lisp_object_cmp(LISP_OBJECT *a, LISP_OBJECT *b); +int lisp_object_cmp_symbol(LISP_OBJECT *a, LISP_OBJECT *b); +int lisp_object_cmp_numbers(LISP_OBJECT *a, LISP_OBJECT *b); +int lisp_object_cmp_string(LISP_OBJECT *a, LISP_OBJECT *b); + +typedef struct _HashMap +{ + char *key; + LISP_OBJECT *value; + struct _HashMap *prev; + struct _HashMap *next; + +} HashMap; + +HashMap *hash_map_make(char *key, LISP_OBJECT *value); +HashMap *hash_map_push(HashMap *hash_map, char *key, LISP_OBJECT *value); +HashMap *hash_map_reverse(HashMap *hash_map); +HashMap *hash_map_find(HashMap *hash_map, char* key); +HashMap *hash_map_delete(HashMap *hash_map, char* key); +void hash_map_free(HashMap *hash_map); +void hash_map_print(HashMap *hash_map); + #endif -- cgit v1.2.3