diff options
author | Preston Pan <preston@nullring.xyz> | 2023-01-08 14:44:25 -0800 |
---|---|---|
committer | Preston Pan <preston@nullring.xyz> | 2023-01-08 14:44:25 -0800 |
commit | 87d82ead963c24d84a4f6e417b96b9bf73d132bb (patch) | |
tree | 096e60118f6e62508db653d5102d85e77b8d73e9 | |
parent | aa1dd020edb82f26dd5bc29378177cfcaa4c53ed (diff) |
fix memory problem
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | doc/main.nxs | 7 | ||||
-rw-r--r-- | src/hash_table.c | 11 | ||||
-rw-r--r-- | src/include/macros.h | 2 | ||||
-rw-r--r-- | src/lexer.c | 8 | ||||
-rw-r--r-- | src/macros.c | 7 | ||||
-rw-r--r-- | src/main.c | 11 | ||||
-rw-r--r-- | src/parser.c | 4 | ||||
-rw-r--r-- | src/visitor.c | 54 | ||||
-rw-r--r-- | stdlib/math.nxs | 20 |
10 files changed, 109 insertions, 18 deletions
@@ -7,6 +7,9 @@ some built-in functions to make the language usable, though I plan to add support for macros and other stuff. This is a functional programming language so functions are first-class. +I wrote this programming language within just six days, and I wrote +the bulk of it (~1400 LoC) within the first two days. + ## TODO Each todo here represents one task that I have not done. Note that all the tasks that I finished are bigger than diff --git a/doc/main.nxs b/doc/main.nxs index d3aa986..cb6985d 100644 --- a/doc/main.nxs +++ b/doc/main.nxs @@ -1,8 +1,9 @@ (include "fib.nxs") (bind factorial (lambda (n) - (if (= n 0) 1 (* n (factorial (print(- n 1))))))) -(print(fib 7)) + (if (= n 0) 1 (* n (factorial (- n 1)))))) + +(print (fib 7)) (print (+ (factorial 5) 10)) -(print(car (quote (+ (3 2) 4)))) +(print (quote (+ (3 2) 4))) diff --git a/src/hash_table.c b/src/hash_table.c index 6648bd1..29946b1 100644 --- a/src/hash_table.c +++ b/src/hash_table.c @@ -78,6 +78,15 @@ void sl_list_add(sl_list_t *l, char *key, ast_t *value) { } } +void sl_list_modify(sl_list_t *l, char *key, ast_t *value) { + sl_node_t *cur = l->head; + while (cur != NULL) { + if (strcmp(cur->value->key, key) == 0) + cur->value->value = value; + cur = cur->next; + } +} + ast_t *sl_list_get(sl_list_t *l, char *key) { sl_node_t *cur = l->head; for (int i = 0; i < l->size; i++) { @@ -123,6 +132,8 @@ hash_table_t *init_hash_table(int size) { void hash_table_add(hash_table_t *h, char *key, ast_t *value) { sl_list_t *l = h->buckets[hash(key, h->size)]; + if (sl_list_exists(l, key)) + sl_list_modify(l, key, value); sl_list_add(l, key, value); } diff --git a/src/include/macros.h b/src/include/macros.h index ee89597..bbf541e 100644 --- a/src/include/macros.h +++ b/src/include/macros.h @@ -82,4 +82,6 @@ #define COLOR_RESET "\e[0m" void die(char *message); + +char *char_to_string(char c); #endif diff --git a/src/lexer.c b/src/lexer.c index e58197a..4e03a02 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -57,13 +57,6 @@ static bool is_valid_id_char(char c) { return true; } -static char *char_to_string(char c) { - char *s = (char *)malloc(2 * sizeof(char)); - s[0] = c; - s[1] = '\0'; - return s; -} - token_t *lexer_collect_bool(lexer_t *lexer) { lexer_move(lexer); if (lexer->c == 't') { @@ -158,7 +151,6 @@ start: return lexer_move_with( lexer, init_token(TOKEN_PERIOD, ".", lexer->row, lexer->col)); else { - printf("returns null\n"); return NULL; } } diff --git a/src/macros.c b/src/macros.c index 1effefe..1643168 100644 --- a/src/macros.c +++ b/src/macros.c @@ -8,3 +8,10 @@ void die(char *message) { fprintf(stderr, "%sFATAL ERROR: %s%s\n", RED, message, reset); exit(EXIT_FAILURE); } + +char *char_to_string(char c) { + char *s = malloc(2); + s[0] = c; + s[1] = '\0'; + return s; +} @@ -12,9 +12,6 @@ #include <stdlib.h> #include <string.h> -// Read the file into allocated memory. -// Return NULL on error. - int main(int argc, char **argv) { /* DONE: TEST LEXER */ /* lexer_t *lexer = init_lexer("'(fasd asdf)"); */ @@ -134,6 +131,8 @@ int main(int argc, char **argv) { if (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version") == 0) { printf("nxs, version 1.2 alpha\n"); exit(0); + } else if (strcmp(argv[1], "-r") == 0 || strcmp(argv[1], "--repl") == 0) { + /* Start a REPL */ } char *filename = argv[1]; @@ -145,13 +144,13 @@ int main(int argc, char **argv) { fseek(f, 0, SEEK_END); length = ftell(f); fseek(f, 0, SEEK_SET); - buffer = malloc(length); + buffer = malloc(length + 1); if (buffer) { fread(buffer, 1, length, f); } fclose(f); } - + buffer[length] = '\0'; if (buffer) { /* lexer_t *lexer = init_lexer(buffer); */ /* token_t *t = lexer_collect_next(lexer); */ @@ -163,7 +162,7 @@ int main(int argc, char **argv) { lexer_t *lexer = init_lexer(buffer); parser_t *parser = init_parser(lexer); visitor_t *visitor = init_visitor(parser); - ast_t *root = eval(visitor); + eval(visitor); /* print_root(root); */ } diff --git a/src/parser.c b/src/parser.c index 157bc4d..0f1ba69 100644 --- a/src/parser.c +++ b/src/parser.c @@ -30,6 +30,7 @@ parser_t *init_parser_copy_hash(lexer_t *lexer, hash_table_t *h) { p->tokens[size - 1] = t; if (t == NULL) break; + /* printf("%d: %s\n", t->type, t->value); */ } p->size = size; return p; @@ -185,7 +186,7 @@ ast_t *parse_include(parser_t *parser) { fseek(f, 0, SEEK_END); length = ftell(f); fseek(f, 0, SEEK_SET); - buffer = malloc(length); + buffer = malloc(length + 1); if (buffer) { fread(buffer, 1, length, f); } @@ -194,6 +195,7 @@ ast_t *parse_include(parser_t *parser) { parser_error(parser); } if (buffer) { + buffer[length] = '\0'; lexer_t *lexer = init_lexer(buffer); parser_t *p = init_parser_copy_hash(lexer, parser->symbol_table); ast_t *root = parse_all(p); diff --git a/src/visitor.c b/src/visitor.c index 6fd487a..65af934 100644 --- a/src/visitor.c +++ b/src/visitor.c @@ -449,6 +449,60 @@ ast_t *eval_list(visitor_t *v, ast_t *e) { print(arg1); printf("\n"); return arg1; + } else if (strcmp(function->string_value, "read") == 0) { + if (cmp != 1) + eval_error(v, e); + + ast_t *arg1 = eval_expr(v, args->car); + if (arg1->type == AST_STRING) { + char *buffer = 0; + long length; + FILE *f = fopen(arg1->string_value, "rb"); + + if (f) { + fseek(f, 0, SEEK_END); + length = ftell(f); + fseek(f, 0, SEEK_SET); + buffer = malloc(length); + if (buffer) { + fread(buffer, 1, length, f); + } + fclose(f); + } else { + eval_error(v, e); + } + + if (buffer) { + return init_ast_string(buffer); + } else { + eval_error(v, e); + } + } + } else if (strcmp(function->string_value, "bound?") == 0) { + if (cmp != 1) + eval_error(v, e); + + ast_t *arg1 = eval_expr(v, args->car); + + if (arg1->type == AST_SYMBOL) { + if (hash_table_exists(v->p->symbol_table, arg1->string_value)) { + return init_ast_bool(true); + } + return init_ast_bool(false); + } else + eval_error(v, e); + } else if (strcmp(function->string_value, "at") == 0) { + if (cmp != 2) + eval_error(v, e); + + ast_t *arg1 = eval_expr(v, args->car); + ast_t *arg2 = eval_expr(v, args->cdr->car); + if (arg1->type == AST_STRING && arg2->type == AST_INT && + arg2->int_value < strlen(arg1->string_value)) { + return init_ast_string( + char_to_string(arg1->string_value[arg2->int_value])); + } else + eval_error(v, e); } return NULL; diff --git a/stdlib/math.nxs b/stdlib/math.nxs new file mode 100644 index 0000000..f913d82 --- /dev/null +++ b/stdlib/math.nxs @@ -0,0 +1,20 @@ +;; some bootstrapping needed in order to obtain more complicated functions; +;; the power series requires a factorial and integer power function +(bind powi (lambda (x y) + (if (= y 1) + x + (* x (pow x (- y 1))) +))) +(bind factorial (lambda (n) + (if (= n 0) 1 (* n (factorial (print(- n 1))))))) + +;; complicated functions +(bind exp (lambda (x) x)) + +(bind ln (lambda (x) x)) + +(bind sin (lambda (x) x)) + +(bind cos (lambda (x) x)) + +(bind tan (lambda (x) (/ (sin x) (cos x)))) |