summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPreston Pan <preston@nullring.xyz>2023-01-05 18:41:13 -0800
committerPreston Pan <preston@nullring.xyz>2023-01-05 18:41:13 -0800
commit75bffac83e8e8a30ae7643a5d830e580d1ffee65 (patch)
tree56e6ea17c8110f9383f12ef1fa03ad60ddec3962
parent346507f767d71c69e55b9f663449eb39e1bc7e54 (diff)
add more primitives
-rw-r--r--README.md11
-rw-r--r--src/ast.c10
-rw-r--r--src/include/ast.h2
-rw-r--r--src/main.c4
-rw-r--r--src/visitor.c120
5 files changed, 132 insertions, 15 deletions
diff --git a/README.md b/README.md
index 675a87f..a05b2c1 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,15 @@
# NoExcess
This is basically a scheme-like language that is aimed to
-be scheme with no additional fluff.
+be scheme with no additional fluff. The programming language
+is "done" now in the sense that it is turing complete and
+there are some features like strings, ints, floats, booleans, and
+some built-in functions to make he language usable, though
+I plan to add support for macros and other stuff. This
+is a functional programming language so functions are first-class.
## TODO
- [X] Write the lexer
- [X] Write the parser
-- [ ] Write hash table
-- [ ] Write the visitor
+- [X] Write hash table
+- [X] Write the visitor
- [ ] Write the print functions
diff --git a/src/ast.c b/src/ast.c
index faffacd..eefbc45 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -84,3 +84,13 @@ void ast_type_print(ast_t *e) {
printf("Root Node\n");
}
}
+
+bool is_proper_list(ast_t *e) {
+ ast_t *cur = e;
+ while (cur->cdr != NULL) {
+ cur = cur->cdr;
+ }
+ if (cur->type == AST_PAIR && cur->car == NULL)
+ return true;
+ return false;
+}
diff --git a/src/include/ast.h b/src/include/ast.h
index c99564d..8b60490 100644
--- a/src/include/ast.h
+++ b/src/include/ast.h
@@ -52,4 +52,6 @@ ast_t *init_ast_function(ast_t *car, ast_t *cdr);
ast_t *init_ast_root(ast_t **subnodes, int size);
void ast_type_print(ast_t *e);
+
+bool is_proper_list(ast_t *e);
#endif
diff --git a/src/main.c b/src/main.c
index 9eec089..3dbbf86 100644
--- a/src/main.c
+++ b/src/main.c
@@ -98,9 +98,9 @@ int main(int argc, char **argv) {
/* ast_t *root = eval(visitor); */
/* ast_t *res = root->subnodes[0]; */
/* print(res); */
- /* TODO: TEST NON-BUILTIN FUNCTIONS (stack frame) */
- lexer_t *lexer = init_lexer("((lambda (x y) (+ x y)) (+ 3.0 4.0) 4)");
+ /* DONE: TEST NON-BUILTIN FUNCTIONS (stack frame) */
+ lexer_t *lexer = init_lexer("((lambda (x y) (+ x y)) (+ 3 4) 4)");
parser_t *parser = init_parser(lexer);
visitor_t *visitor = init_visitor(parser);
diff --git a/src/visitor.c b/src/visitor.c
index cbe72d8..f6008dd 100644
--- a/src/visitor.c
+++ b/src/visitor.c
@@ -67,13 +67,10 @@ bool is_built_in(ast_t *e) {
* =, equal (for strings), input */
ast_t *eval_symbol(visitor_t *v, ast_t *e) {
/* hash_table_t *lmao = stack_peek(v->stack_frame); */
- printf("%s\n", e->string_value);
if (is_built_in(e))
return e;
/* first, it looks in the stack frame for a variable */
- if (stack_peek(v->stack_frame) == NULL) {
- printf("Does not work\n");
- } else if (hash_table_exists(stack_peek(v->stack_frame), e->string_value))
+ else if (hash_table_exists(stack_peek(v->stack_frame), e->string_value))
return hash_table_get(stack_peek(v->stack_frame), e->string_value);
/* Then the variables that have already been evaluated */
else if (hash_table_exists(v->eval_table, e->string_value))
@@ -87,7 +84,6 @@ ast_t *eval_symbol(visitor_t *v, ast_t *e) {
hash_table_add(v->eval_table, e->string_value, eval);
return eval;
} else {
- printf("eval symbol error\n");
eval_error(v, e);
}
}
@@ -127,7 +123,6 @@ ast_t *eval_list(visitor_t *v, ast_t *e) {
} else if ((arg1->type == AST_FLOAT) && (arg2->type == AST_INT)) {
return init_ast_float(arg1->float_value + arg2->int_value);
} else if ((arg1->type == AST_FLOAT) && (arg2->type) == AST_FLOAT) {
- printf("plus evaled\n");
return init_ast_float(arg1->float_value + arg2->float_value);
} else
eval_error(v, e);
@@ -289,8 +284,116 @@ ast_t *eval_list(visitor_t *v, ast_t *e) {
return init_ast_int(a);
} else
eval_error(v, e);
+ } else if (strcmp(function->string_value, "if") == 0) {
+ if (cmp != 3)
+ eval_error(v, e);
+
+ ast_t *arg1 = eval_expr(v, args->car);
+ ast_t *arg2 = eval_expr(v, args->cdr->car);
+ ast_t *arg3 = eval_expr(v, args->cdr->cdr->car);
+ if (arg1->type == AST_BOOL) {
+ if (arg1->bool_value)
+ return arg2;
+ else
+ return arg3;
+ } else
+ eval_error(v, e);
+ } else if (strcmp(function->string_value, "<") == 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_INT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->int_value < arg2->int_value);
+ } else if ((arg1->type == AST_INT) && (arg2->type == AST_FLOAT)) {
+ return init_ast_bool(arg1->int_value < arg2->float_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->float_value < arg2->int_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type) == AST_FLOAT) {
+ return init_ast_bool(arg1->float_value < arg2->float_value);
+ } else
+ eval_error(v, e);
+ } else if (strcmp(function->string_value, "=") == 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_INT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->int_value == arg2->int_value);
+ } else if ((arg1->type == AST_INT) && (arg2->type == AST_FLOAT)) {
+ return init_ast_bool(arg1->int_value == arg2->float_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->float_value == arg2->int_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type) == AST_FLOAT) {
+ return init_ast_bool(arg1->float_value == arg2->float_value);
+ } else
+ eval_error(v, e);
+ } else if (strcmp(function->string_value, ">") == 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_INT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->int_value > arg2->int_value);
+ } else if ((arg1->type == AST_INT) && (arg2->type == AST_FLOAT)) {
+ return init_ast_bool(arg1->int_value > arg2->float_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->float_value > arg2->int_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type) == AST_FLOAT) {
+ return init_ast_bool(arg1->float_value > arg2->float_value);
+ } else
+ eval_error(v, e);
+ } else if (strcmp(function->string_value, ">=") == 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_INT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->int_value >= arg2->int_value);
+ } else if ((arg1->type == AST_INT) && (arg2->type == AST_FLOAT)) {
+ return init_ast_bool(arg1->int_value >= arg2->float_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->float_value >= arg2->int_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type) == AST_FLOAT) {
+ return init_ast_bool(arg1->float_value >= arg2->float_value);
+ } else
+ eval_error(v, e);
+ } else if (strcmp(function->string_value, "<=") == 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_INT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->int_value <= arg2->int_value);
+ } else if ((arg1->type == AST_INT) && (arg2->type == AST_FLOAT)) {
+ return init_ast_bool(arg1->int_value <= arg2->float_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type == AST_INT)) {
+ return init_ast_bool(arg1->float_value <= arg2->int_value);
+ } else if ((arg1->type == AST_FLOAT) && (arg2->type) == AST_FLOAT) {
+ return init_ast_bool(arg1->float_value <= arg2->float_value);
+ } else
+ eval_error(v, e);
+ } else if (strcmp(function->string_value, "cons") == 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);
+ ast_t *ret = init_ast_pair(arg1, arg2);
+ return ret;
}
}
+
/* printf("debug 2\n"); */
/* NON BUILT-INS */
/* Checking that the parameters are actually valid */
@@ -309,13 +412,10 @@ ast_t *eval_list(visitor_t *v, ast_t *e) {
char *name;
ast_t *evaled_arg;
while (cur_arg->cdr != NULL && cur_arg_name->cdr != NULL) {
- ast_type_print(cur_arg->car);
name = cur_arg_name->car->string_value;
- printf("name: %s\n", name);
evaled_arg = eval_expr(v, cur_arg->car);
/* printf("%f\n", evaled_arg->float_value); */
hash_table_add(stack_frame, name, evaled_arg);
- printf("after hash_add\n");
cur_arg_name = cur_arg_name->cdr;
cur_arg = cur_arg->cdr;
}
@@ -330,7 +430,7 @@ ast_t *eval_expr(visitor_t *v, ast_t *e) {
/* ast_type_print(e); */
if (is_self_evaluating(e))
return e;
- else if (e->type == AST_PAIR)
+ else if (e->type == AST_PAIR && is_proper_list(e))
return eval_list(v, e);
else if (e->type == AST_SYMBOL)
return eval_symbol(v, e);