summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPreston Pan <preston@nullring.xyz>2023-01-08 14:44:25 -0800
committerPreston Pan <preston@nullring.xyz>2023-01-08 14:44:25 -0800
commit87d82ead963c24d84a4f6e417b96b9bf73d132bb (patch)
tree096e60118f6e62508db653d5102d85e77b8d73e9
parentaa1dd020edb82f26dd5bc29378177cfcaa4c53ed (diff)
fix memory problem
-rw-r--r--README.md3
-rw-r--r--doc/main.nxs7
-rw-r--r--src/hash_table.c11
-rw-r--r--src/include/macros.h2
-rw-r--r--src/lexer.c8
-rw-r--r--src/macros.c7
-rw-r--r--src/main.c11
-rw-r--r--src/parser.c4
-rw-r--r--src/visitor.c54
-rw-r--r--stdlib/math.nxs20
10 files changed, 109 insertions, 18 deletions
diff --git a/README.md b/README.md
index 15a5257..f84dd0a 100644
--- a/README.md
+++ b/README.md
@@ -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;
+}
diff --git a/src/main.c b/src/main.c
index c75ef85..ba710bf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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))))