#include #include #include #include #include #include #include #include "darray.h" #include "hashtable.h" #include "singletons.c" #include "environment.c" #include "errors.c" #include "gc.c" #include "lexer.c" #include "objects.c" #include "parser.c" #include "primitives.c" #include "read_line.c" #include "string_view.c" int main(void) { // Initialize GC. gc_init(); // Initialize key-value objects. Object *k1 = MAKE_SYM("Alice"); Object *k2 = MAKE_SYM("Bob"); Object *k3 = MAKE_SYM("Dog"); Object *v1 = make_fixnum(10); Object *v2 = make_fixnum(49); Object *v3 = make_fixnum(333); // Initialize hash table. HashTable *table = ht_init(); // Add some key-value pairs. ht_insert(table, k1, v1); ht_insert(table, k2, v2); ht_insert(table, k3, v3); // Test lookups. Object *alice_val = ht_lookup(table, k1); Object *bob_val = ht_lookup(table, MAKE_SYM("Bob")); Object *dog_val = ht_lookup(table, k3); if (v1 == alice_val) { printf("Alice match!\n"); } if (v2 == bob_val) { printf("Bob match!\n"); } if (v3 == dog_val) { printf("Dog match!\n"); } ht_debug(table); return 0; } // void // init(void) { // // Initialize garbage collector. // gc_init(); // // Initialize singletons. // obj_nil = alloc_object(OBJ_TYPE_NIL); // obj_true = alloc_object(OBJ_TYPE_BOOL); // obj_false = alloc_object(OBJ_TYPE_BOOL); // obj_err = alloc_object(OBJ_TYPE_ERR); // obj_quote = make_symbol((StringView){"quote", 5}); // proc_if = alloc_object(OBJ_TYPE_ERR); // push_root(obj_nil); // push_root(obj_true); // push_root(obj_false); // push_root(obj_err); // push_root(obj_quote); // push_root(proc_if); // // Global environment. // global_env = env_create(NULL); // // TODO: make sure we create symbols and strings only once (interning // // strings?) // push_active_env(global_env); // // Primitive symbols. // MAKE_ENV_VAR(global_env, "else", obj_true); // MAKE_ENV_VAR(global_env, "nil", obj_nil); // MAKE_ENV_VAR(global_env, "if", proc_if); // // Primitive procedures. // MAKE_ENV_PROC(global_env, "eval", proc_eval); // MAKE_ENV_PROC(global_env, "quote", proc_quote); // MAKE_ENV_PROC(global_env, "car", proc_car); // MAKE_ENV_PROC(global_env, "cdr", proc_cdr); // MAKE_ENV_PROC(global_env, "cons", proc_cons); // MAKE_ENV_PROC(global_env, "list", proc_list); // MAKE_ENV_PROC(global_env, "+", proc_sum); // MAKE_ENV_PROC(global_env, "-", proc_sub); // MAKE_ENV_PROC(global_env, "*", proc_mul); // MAKE_ENV_PROC(global_env, "/", proc_div); // MAKE_ENV_PROC(global_env, "%", proc_mod); // MAKE_ENV_PROC(global_env, "print", proc_print); // MAKE_ENV_PROC(global_env, "display", proc_display); // MAKE_ENV_PROC(global_env, "newline", proc_newline); // MAKE_ENV_PROC(global_env, "boolean?", proc_is_boolean); // MAKE_ENV_PROC(global_env, "nil?", proc_is_nil); // MAKE_ENV_PROC(global_env, "symbol?", proc_is_symbol); // MAKE_ENV_PROC(global_env, "string?", proc_is_string); // MAKE_ENV_PROC(global_env, "fixnum?", proc_is_fixnum); // MAKE_ENV_PROC(global_env, "pair?", proc_is_pair); // MAKE_ENV_PROC(global_env, "procedure?", proc_is_procedure); // MAKE_ENV_PROC(global_env, "error?", proc_is_error); // MAKE_ENV_PROC(global_env, "not", proc_not); // MAKE_ENV_PROC(global_env, "and", proc_and); // MAKE_ENV_PROC(global_env, "or", proc_or); // MAKE_ENV_PROC(global_env, "cond", proc_cond); // MAKE_ENV_PROC(global_env, "<", proc_num_less_than); // MAKE_ENV_PROC(global_env, "<=", proc_num_lesseq_than); // MAKE_ENV_PROC(global_env, ">", proc_num_greater_than); // MAKE_ENV_PROC(global_env, ">=", proc_num_greatereq_than); // MAKE_ENV_PROC(global_env, "=", proc_num_equal); // MAKE_ENV_PROC(global_env, "eq?", proc_equal); // MAKE_ENV_PROC(global_env, "def", proc_define); // MAKE_ENV_PROC(global_env, "set!", proc_set); // MAKE_ENV_PROC(global_env, "lambda", proc_lambda); // MAKE_ENV_PROC(global_env, "fun", proc_fun); // // Runtime procedures. // MAKE_ENV_PROC(global_env, "supress-errors", proc_supress_errors); // } // void // process_source(const StringView *source) { // Token *tokens = tokenize(source); // if (errors_n != 0) { // if (tokens != NULL) { // array_free(tokens); // } // return; // } // Visitor visitor = (Visitor){ // .tokens = tokens, // .current = 0, // }; // while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) { // // Check the root node stack size before parsing // size_t root_stack_size = array_size(gc.roots); // Object *root = parse_tree(&visitor); // array_head(gc.roots)->size = root_stack_size; // if (root == obj_err || errors_n != 0) { // break; // } // push_root(root); // Object *result = eval(global_env, root); // if (result != obj_nil) { // display(result); // printf("\n"); // } // pop_root(); // } // if (tokens != NULL) { // array_free(tokens); // } // } // #define REPL_PROMPT "bdl> " // void // run_repl(void) { // printf("BDL REPL (Press Ctrl-D or Ctrl-C to exit)\n"); // while (true) { // printf(REPL_PROMPT); // StringView sv = read_line(); // if (sv.start == NULL) { // return; // } // process_source(&sv); // // Check if there were any errors. // if (errors_n != 0 && !supress_errors) { // for (size_t i = 0; i < errors_n; i++) { // Error err = errors[i]; // for (size_t j = 0; j < err.col + sizeof(REPL_PROMPT) - 2; j++) { // putchar(' '); // } // printf("|\n"); // for (size_t j = 0; j < err.col + sizeof(REPL_PROMPT) - 2; j++) { // putchar(' '); // } // printf("%s\n", error_msgs[err.value]); // } // errors_n = 0; // continue; // } // } // } // void // run_file(char *file_name) { // FILE *file = fopen(file_name, "r"); // if (!file) { // fprintf(stderr, "error: couldn't open input file: %s\n", file_name); // exit(EXIT_FAILURE); // } // // Read entire file into memory. // fseek(file, 0, SEEK_END); // size_t file_size = ftell(file); // fseek(file, 0, SEEK_SET); // char *source = malloc(file_size + 1); // fread(source, 1, file_size, file); // source[file_size] = 0; // StringView sv = (StringView){ // .start = source, // .n = file_size, // }; // process_source(&sv); // // Check if there were any errors. // if (errors_n != 0 && !supress_errors) { // for (size_t i = 0; i < errors_n; i++) { // Error err = errors[i]; // fprintf(stderr, "%s", file_name); // if (err.line != 0) { // fprintf(stderr, ":%ld:%ld", err.line, err.col); // } // fprintf(stderr, ": %s\n", error_msgs[err.value]); // } // errors_n = 0; // } // free(source); // fclose(file); // } // #define STDIN_BUF_CAP 16 // void // run_stdin(void) { // size_t buf_size = 0; // char *source = NULL; // array_init(source, STDIN_BUF_CAP); // char c; // while ((c = getchar()) != EOF) { // array_push(source, c); // buf_size++; // } // StringView sv = (StringView){ // .start = source, // .n = buf_size, // }; // process_source(&sv); // // Check if there were any errors. // if (errors_n != 0 && !supress_errors) { // for (size_t i = 0; i < errors_n; i++) { // Error err = errors[i]; // fprintf(stderr, "stdin"); // if (err.line != 0) { // fprintf(stderr, ":%ld:%ld", err.line, err.col); // } // fprintf(stderr, ": %s\n", error_msgs[err.value]); // } // errors_n = 0; // } // array_free(source); // } // #ifndef BIN_NAME // #define BIN_NAME "bdl" // #endif // void // print_usage(void) { // printf("Usage: %s [options] \n", BIN_NAME); // printf("\n"); // printf("\t-i\tInteractive mode (REPL).\n"); // printf("\n"); // } // int // main(int argc, char *argv[]) { // init(); // int option; // while ((option = getopt(argc, argv, "i")) != -1) { // switch (option) { // case 'i': { // // Interactive mode. // run_repl(); // return EXIT_SUCCESS; // } break; // default: { // print_usage(); // return EXIT_FAILURE; // } break; // } // } // // Run from stdin. // if (optind == argc) { // run_stdin(); // return EXIT_SUCCESS; // } // // Run from file. // while (optind < argc) { // char *file_name = argv[optind]; // run_file(file_name); // optind++; // } // return EXIT_SUCCESS; // }