aboutsummaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c115
1 files changed, 69 insertions, 46 deletions
diff --git a/src/main.c b/src/main.c
index a63a392..0ddb7f9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}