diff options
author | Preston Pan <preston@nullring.xyz> | 2023-01-05 18:41:13 -0800 |
---|---|---|
committer | Preston Pan <preston@nullring.xyz> | 2023-01-05 18:41:13 -0800 |
commit | 75bffac83e8e8a30ae7643a5d830e580d1ffee65 (patch) | |
tree | 56e6ea17c8110f9383f12ef1fa03ad60ddec3962 | |
parent | 346507f767d71c69e55b9f663449eb39e1bc7e54 (diff) |
add more primitives
-rw-r--r-- | README.md | 11 | ||||
-rw-r--r-- | src/ast.c | 10 | ||||
-rw-r--r-- | src/include/ast.h | 2 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/visitor.c | 120 |
5 files changed, 132 insertions, 15 deletions
@@ -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 @@ -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 @@ -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); |