From 405739c217793838b3ddd4ac4d426a69ef825bc3 Mon Sep 17 00:00:00 2001 From: kappa Date: Tue, 22 Jan 2019 00:08:27 +0100 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=BC=D0=BF=D0=BB=D0=B5=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B8=D1=80=D0=B0=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=86=D0=B5=D0=B4=D1=83=D1=80=D0=B0=20=D0=B7=D0=B0=20=D0=B4?= =?UTF-8?q?=D0=B5=D1=84=D0=B8=D0=BD=D0=B8=D1=86=D0=B0=D1=9A=D0=B5=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=BC=D0=B5=D0=BD=D1=99=D0=B8=D0=B2=D0=B8=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 4 +-- eval.c | 11 ++++++-- init.c | 1 + internals.c | 20 ++++++++++++++ internals.h | 2 ++ symtable.c | 80 +++++++++++++++++++++++++++++++++++++---------------- symtable.h | 11 +++++++- util.c | 21 ++++++++++++++ util.h | 1 + 9 files changed, 122 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index efbe299..f39c6e5 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,8 @@ VERSION = 0.5 PREFIX = /usr/local # флегови за C компајлер и линкер -# CFLAGS = -g -std=c99 -pedantic -Wall -O0 -CFLAGS = -std=c99 -pedantic -Wall -O1 +CFLAGS = -g -std=c99 -pedantic -Wall -O0 +# CFLAGS = -std=c99 -pedantic -Wall -O1 LDFLAGS = -lm -lc CC = cc diff --git a/eval.c b/eval.c index 861448d..bf25dc3 100644 --- a/eval.c +++ b/eval.c @@ -20,7 +20,14 @@ object eval(object input) { if (symbolExists(SYM(input))) { - result = copyObject(input); + if (typeOf(SYM(input)) == variableSymbol) + { + result = referVariable(SYM(input)); + } + else + { + result = copyObject(input); + } } else { @@ -42,7 +49,7 @@ object eval(object input) while (TYPE(*currentCell) != nilObject) { if (TYPE(CAR(input)) != symbolObject || - strcmp(SYM(CAR(input)), "навод") != 0) + !isSpecialForm(SYM(CAR(input)))) { CAR(*currentCell) = eval(CAR(*currentCell)); diff --git a/init.c b/init.c index 1ed3054..6f91274 100644 --- a/init.c +++ b/init.c @@ -21,6 +21,7 @@ void init() addSymbolInternal("*", &multiply); addSymbolInternal("/", ÷); addSymbolInternal("навод", "e); + addSymbolInternal("дефиниши", &define); addSymbolInternal("тачно->нетачно", &exactToInexact); addSymbolInternal("нетачно->тачно", &inexactToExact); } diff --git a/internals.c b/internals.c index 69ac06b..e9d2422 100644 --- a/internals.c +++ b/internals.c @@ -1,4 +1,6 @@ +#include "symtable.h" #include "util.h" +#include "eval.h" int allNumbers(object list) { @@ -189,3 +191,21 @@ object quote(object parameters) } return result; } + +object define(object parameters) +{ + object result; + if (listLength(parameters) != 2) + { + TYPE(result) = errorObject; + ERR(result) = argumentNumberError; + } + else if (TYPE(CAR(parameters)) == symbolObject) + { + result = copyObject(CAR(parameters)); + addSymbolVariable(SYM(result), + eval(copyObject(CAR(CDR(parameters))))); + } + + return result; +} diff --git a/internals.h b/internals.h index 0a0f1ba..b986afc 100644 --- a/internals.h +++ b/internals.h @@ -1,4 +1,5 @@ #pragma once +#include "util.h" object add(object parameters); object subtract(object parameters); @@ -7,3 +8,4 @@ object divide(object parameters); object exactToInexact(object parameters); object inexactToExact(object parameters); object quote(object parameters); +object define(object parameters); diff --git a/symtable.c b/symtable.c index f7f3cbc..7feee56 100644 --- a/symtable.c +++ b/symtable.c @@ -5,12 +5,6 @@ #include "util.h" #include "symtable.h" -typedef enum -{ - internalSymbol, - objectSymbol -} symbolType; - typedef struct entry { symbolType type; @@ -18,7 +12,7 @@ typedef struct entry union { object (*function)(); - object definition; + object variable; } value; struct entry *left; struct entry *right; @@ -54,47 +48,67 @@ entry **findEntry(entry **current, char *symbol) * одвојене ради читљивости */ } +void freeEntry(entry **current) +{ + free((*current)->name); + if ((*current)->type == variableSymbol) + { + deleteObject((*current)->value.variable); + } +} + +symbolType typeOf(char *symbol) +{ + entry **e = findEntry(&root, symbol); + + return (*e)->type; +} + int addSymbolInternal(char *symbol, object (*function)()) { int status = 1; entry **e = findEntry(&root, symbol); - if (*e == NULL) + if (*e != NULL) { - *e = malloc(sizeof(entry)); - (*e)->type = internalSymbol; - (*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1)); - strcpy((*e)->name, symbol); - (*e)->value.function = function; - (*e)->left = (*e)->right = NULL; + status = 0; + freeEntry(e); } else { - status = 0; + *e = malloc(sizeof(entry)); } + (*e)->type = internalSymbol; + (*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1)); + strcpy((*e)->name, symbol); + (*e)->value.function = function; + (*e)->left = (*e)->right = NULL; + return status; } -int addSymbolDefinition(char *symbol, object definition) +int addSymbolVariable(char *symbol, object variable) { int status = 1; entry **e = findEntry(&root, symbol); - if (*e == NULL) + if (*e != NULL) { - *e = malloc(sizeof(entry)); - (*e)->type = objectSymbol; - (*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1)); - strcpy((*e)->name, symbol); - (*e)->value.definition = copyObject(definition); - (*e)->left = (*e)->right = NULL; + status = 0; + freeEntry(e); } else { - status = 0; + *e = malloc(sizeof(entry)); } + (*e)->type = variableSymbol; + (*e)->name = malloc(sizeof(char) * (strlen(symbol) + 1)); + strcpy((*e)->name, symbol); + (*e)->value.variable = copyObject(variable); + (*e)->left = (*e)->right = NULL; + return status; } @@ -128,3 +142,21 @@ object (*internalFunction(char *symbol)) (object) return ((*e)->value.function); } } + +object referVariable(char *symbol) +{ + object result; + entry **e = findEntry(&root, symbol); + + if (*e == NULL || (*e)->type != variableSymbol) + { + TYPE(result) = errorObject; + ERR(result) = unrecognizedSymbolError; + } + else + { + result = (*e)->value.variable; + } + + return result; +} diff --git a/symtable.h b/symtable.h index 5736008..7279eb9 100644 --- a/symtable.h +++ b/symtable.h @@ -2,16 +2,25 @@ #include "util.h" +typedef enum +{ + internalSymbol, + variableSymbol +} symbolType; + int addSymbolInternal(char *symbol, object (*function)()); -int addSymbolDefinition(char *symbol, object definition); +int addSymbolVariable(char *symbol, object variable); /* служе за различите методе дефинисања нових симбола у језику * враћају 1 уколико је нови симбол успешно додат, а 0 уколико није * (постоји симбол са истим именом) */ int symbolExists(char *symbol); /* враћа 1 уколико симбол постоји и 0 у супротном */ +symbolType typeOf(char *symbol); object (*internalFunction(char *symbol)) (object parameters); /* враћа показивач на функцију уколико је симбол дефинисан као интерна * функција, NULL уколико симбол није функција или уколико не постоји * */ +object referVariable(char *symbol); +/* враћа вредност на коју се односи име симбола у табели */ diff --git a/util.c b/util.c index 3dc0993..ee1f280 100644 --- a/util.c +++ b/util.c @@ -5,6 +5,27 @@ #include "util.h" +#define SPECIALFORMSNUM 2 +int isSpecialForm(char *symbol) +{ + int result = 0; + char *specialForms[] = + { + "навод", + "дефиниши" + }; + + for (int i = 0; i < SPECIALFORMSNUM; ++i) + { + if (!strcmp(symbol, specialForms[i])) + { + result = 1; + } + } + + return result; +} + int properList(object list) { object *current = &list; diff --git a/util.h b/util.h index 9c00060..37bd0b1 100644 --- a/util.h +++ b/util.h @@ -75,6 +75,7 @@ struct cons object cdr; }; +int isSpecialForm(char *symbol); int properList(object list); int listLength(object list); void deleteObject(object input);