diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 115 |
1 files changed, 69 insertions, 46 deletions
@@ -1,6 +1,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <getopt.h> #include "lexer.h" #include "value.h" @@ -9,7 +10,6 @@ #ifdef ENABLE_MEMDEBUG #define MEMDEBUG_OUT_OF_BOUNDS #define MEMDEBUG_IMPLEMENTATION -#define MEMDEBUG_MAIN_VOID #define MEMDEBUG_OUTPUT_DIR "files" #endif @@ -22,7 +22,7 @@ // - Think about memory leakage and on non fatal errors // like failed list creation and faild s-exp parsing // - Check for functions not wrapped in ERR_* macro -// - Add more error messages +// - Add more and better error messages #define TOKEN(tctx) (tctx)->token @@ -120,10 +120,6 @@ static struct token *next_token(struct tctx *tctx) break; } - #ifdef DEBUG - // print_token(tctx->token); - #endif - return tctx->token; fail: tctx->token = NULL; @@ -147,6 +143,7 @@ value_t quote_sexp(env_t env, struct tctx *tctx); size_t toklist_expr(struct tctx *tctx, struct token **toklist); static env_t global_env = ENV_EMPTY; +static value_t global_nil = VALUE_EMPTY; static void destroy_env(char *key, value_t value) { @@ -160,22 +157,40 @@ static void destroy_global_env(char *key, value_t value) value_destroy(value); } -int main(void) +int main(int argc, char **argv) { + int opt, repl_flag = 0; +#ifdef DEBUG char *filename = "files/test-lambda.l"; +#else + char *filename = NULL; +#endif - FILE *fp = fopen(filename, "r"); - if(!fp) { - die("fopen: %s", strerror(errno)); + while((opt = getopt(argc, argv, "rhf:")) != -1) { + switch(opt) { + case 'h': + printf("help????"); + return 0; + case 'r': repl_flag = 1; break; + case 'f': filename = optarg; break; + default: + err("No such option %c", opt); + return 1; + } } - lexer_t lexer = lexer_create(fp); + if(optind < argc) { + filename = argv[optind]; + } + + if(!filename) repl_flag = 1; + env_t builtin_env = env_create(ENV_EMPTY, destroy_env); global_env = env_create(builtin_env, destroy_global_env); + global_nil = value_create(VALUE_NIL, NULL); - // add builtins for(size_t i = 0; i < BUILTIN_PROCEDURES; i++) { value_t proc_value = value_create( VALUE_PROC_BUILTIN, @@ -185,28 +200,51 @@ int main(void) (void *)proc_value, NULL, NULL); } + FILE *fp = stdin; + if(!repl_flag) { + fp = fopen(filename, "r"); + if(!fp) { + die("fopen: %s", strerror(errno)); + } + } + + lexer_t lexer = lexer_create(fp); + struct tctx tctx = {0}; tctx_init_lexer(&tctx, lexer); + if(repl_flag) printf("> "); while(next_token(&tctx)) { value_t val = evaluate_expr(ENV_EMPTY, &tctx); - #ifdef DEBUG - info("Line %zu evaluates to:", lexer->line); - print_value(val); - #else - char buf[256] = {0}; - value_string(val, LEN(buf), buf); - printf("%s:%zu: %s\n", filename, lexer->line, buf); - #endif + if(val == VALUE_EMPTY) { + if(!repl_flag) { + printf("%s:%zu: FAILED\n", filename, lexer->line); + break; + } else { + printf("=> FAILED\n"); + lexer_clear_line(lexer); + } + } else { + char buf[256] = {0}; + value_string(val, sizeof(buf), buf); + + if(!repl_flag) { + printf("%s:%zu: %s\n", filename, lexer->line, buf); + } else { + printf("=> %s\n", buf); + } + } + if(repl_flag) printf("> "); value_destroy(val); } lexer_destroy(lexer); fclose(fp); + value_destroy(global_nil); env_destroy(global_env); return 0; } @@ -243,8 +281,7 @@ exit: value_t apply(value_t proc, size_t argc, value_t *argv) { - // TODO: make a global nil and copy it - if(proc == VALUE_EMPTY) return value_create(VALUE_NIL, NULL); + if(proc == VALUE_EMPTY) return value_copy(global_nil); switch(proc->type) { case VALUE_PROC: @@ -338,23 +375,8 @@ value_t evaluate_sexp(env_t env, struct tctx *tctx) TOKEN_NEXT(tctx); } -#ifdef DEBUG - // info("------------------"); - // info("Applying procedure"); - // print_value(body[0]); - // info("With Arguemnts"); - // if(argc > 0) - // for(size_t i = 0; i < argc-1; i++) print_value(body[i+1]); -#endif - ret = apply(body[0], argc-1, &body[1]); -#ifdef DEBUG - // info("Returns"); - // print_value(ret); - // info("-----------------"); -#endif - exit: for(size_t i = 0; i < argc; i++) value_destroy(body[i]); @@ -488,7 +510,7 @@ value_t evaluate_define(env_t env, struct tctx *tctx) if(prevkey) free(prevkey); value_destroy(prevval); - return VALUE_EMPTY; + return value_copy(global_nil); fail: if(key) free(key); @@ -504,6 +526,13 @@ value_t evaluate_if(env_t env, struct tctx *tctx) ERR_Z(cond = evaluate_expr(env, tctx), goto exit); + // if(cond->type == VALUE_NIL) { + // toklist_expr(tctx, NULL); // skip one expression + // TOKEN_NEXT(tctx); + // TOKEN_MATCH(tctx, TOKEN_RP, goto exit); + // goto exit; + // } + ERR_Z(cond->type == VALUE_INT, err("expected condition to evaluate to VALUE_INT"); goto exit); @@ -567,16 +596,11 @@ value_t quote_sexp(env_t env, struct tctx *tctx) value_t ret = VALUE_EMPTY; value_t left = VALUE_EMPTY; value_t right = VALUE_EMPTY; - value_t nil = VALUE_EMPTY; - - // TODO: make global nil and copy it - ERR_Z(nil = value_create(VALUE_NIL, NULL), goto exit); TOKEN_SKIP(tctx, TOKEN_LP, goto exit); - // Parse NIL if(TOKEN(tctx)->type == TOKEN_RP) { - ret = value_copy(nil); + ret = value_copy(global_nil); goto exit; } @@ -596,7 +620,7 @@ value_t quote_sexp(env_t env, struct tctx *tctx) } // Parse list - right = value_copy(nil); + right = value_copy(global_nil); value_t *rightmost = &right; // the final nil while(TOKEN(tctx)->type != TOKEN_RP) { @@ -636,7 +660,6 @@ value_t quote_sexp(env_t env, struct tctx *tctx) exit: value_destroy(left); value_destroy(right); - value_destroy(nil); return ret; } |