diff options
author | Bad Diode <bd@badd10de.dev> | 2021-10-09 13:46:54 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-10-09 13:46:54 +0200 |
commit | 376b83e6a44271599ed563e3510b2411beab5921 (patch) | |
tree | 7d8b47146046fb055df2504461762093e6dcfc2a /src | |
parent | 24b76ba094b7638280bc9e1f7da5136a8d1f9772 (diff) | |
download | bdl-376b83e6a44271599ed563e3510b2411beab5921.tar.gz bdl-376b83e6a44271599ed563e3510b2411beab5921.zip |
Enable eval expressions from stdin and small cleanup
Diffstat (limited to 'src')
-rwxr-xr-x | src/bootstrap/main.c | 108 |
1 files changed, 45 insertions, 63 deletions
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index e0012eb..f5653d6 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c | |||
@@ -36,8 +36,10 @@ sv_equal(StringView a, StringView b) { | |||
36 | return false; | 36 | return false; |
37 | } | 37 | } |
38 | 38 | ||
39 | #define READLINE_VALID_CHAR(C) (((u8)(C) >= 0x20 && (u8)(C) < 0x7F) || (C) == '\n') | ||
40 | |||
39 | StringView | 41 | StringView |
40 | read_line(void) { | 42 | read_line(FILE *fd, char delimiter) { |
41 | #define RL_BUF_SIZE 1024 | 43 | #define RL_BUF_SIZE 1024 |
42 | static char readline_buf[RL_BUF_SIZE]; | 44 | static char readline_buf[RL_BUF_SIZE]; |
43 | 45 | ||
@@ -49,11 +51,11 @@ read_line(void) { | |||
49 | // Barebones readline implementation. | 51 | // Barebones readline implementation. |
50 | size_t n = 0; | 52 | size_t n = 0; |
51 | char c; | 53 | char c; |
52 | while ((c = getchar()) != '\n') { | 54 | while ((c = getc(fd)) != delimiter) { |
53 | if (c == '\b') { | 55 | if (c == '\b') { |
54 | readline_buf[n] = '\0'; | 56 | readline_buf[n] = '\0'; |
55 | n--; | 57 | n--; |
56 | } else if (((u8)c >= 0x20 && (u8)c <= 0x7F) && n < RL_BUF_SIZE) { | 58 | } else if (READLINE_VALID_CHAR(c) && n < RL_BUF_SIZE) { |
57 | readline_buf[n] = c; | 59 | readline_buf[n] = c; |
58 | n++; | 60 | n++; |
59 | } | 61 | } |
@@ -697,30 +699,20 @@ eval(Object *root) { | |||
697 | } | 699 | } |
698 | 700 | ||
699 | void | 701 | void |
700 | print_usage(void) { | 702 | eval_line(FILE *fd, char delimiter) { |
701 | printf("Usage: %s [options] <filename>\n", BIN_NAME); | 703 | StringView line = read_line(fd, delimiter); |
702 | printf("\n"); | 704 | Tokens tokens = tokenize(line); |
703 | printf("\t-i\tInteractive mode (REPL).\n"); | ||
704 | printf("\n"); | ||
705 | } | ||
706 | |||
707 | void | ||
708 | run_repl(void) { | ||
709 | printf("BDL REPL (Press Ctrl-C to exit)\n"); | ||
710 | while (true) { | ||
711 | printf(REPL_PROMPT); | ||
712 | StringView line = read_line(); | ||
713 | Tokens tokens = tokenize(line); | ||
714 | #if DEBUG | 705 | #if DEBUG |
715 | printf("N_TOKENS: %ld\n", tokens.n); | 706 | printf("N_TOKENS: %ld\n", tokens.n); |
716 | for (size_t i = 0; i < tokens.n; i++) { | 707 | for (size_t i = 0; i < tokens.n; i++) { |
717 | printf("\tTYPE: %3d ", tokens.start[i].type); | 708 | printf("\tTYPE: %3d ", tokens.start[i].type); |
718 | printf("N: %3ld ", tokens.start[i].value.n); | 709 | printf("N: %3ld ", tokens.start[i].value.n); |
719 | printf("VALUE: "); | 710 | printf("VALUE: "); |
720 | sv_write(tokens.start[i].value); | 711 | sv_write(tokens.start[i].value); |
721 | printf("\n"); | 712 | printf("\n"); |
722 | } | 713 | } |
723 | #endif | 714 | #endif |
715 | while (tokens.n > 0) { | ||
724 | Object *ast = parse(&tokens); | 716 | Object *ast = parse(&tokens); |
725 | if (ast) { | 717 | if (ast) { |
726 | #if DEBUG | 718 | #if DEBUG |
@@ -736,52 +728,35 @@ run_repl(void) { | |||
736 | } | 728 | } |
737 | 729 | ||
738 | void | 730 | void |
731 | run_repl(void) { | ||
732 | printf("BDL REPL (Press Ctrl-C to exit)\n"); | ||
733 | while (true) { | ||
734 | printf(REPL_PROMPT); | ||
735 | eval_line(stdin, '\n'); | ||
736 | } | ||
737 | } | ||
738 | |||
739 | void | ||
739 | run_file(char *file_name) { | 740 | run_file(char *file_name) { |
740 | #if DEBUG | 741 | #if DEBUG |
741 | printf("Executing file: %s\n", file_name); | 742 | printf("Executing file: %s\n", file_name); |
742 | #endif | 743 | #endif |
743 | |||
744 | // Load entire file into memory. | ||
745 | char * src = NULL; | ||
746 | FILE *fd = fopen(file_name, "r"); | 744 | FILE *fd = fopen(file_name, "r"); |
747 | if (!fd) { | 745 | if (!fd) { |
748 | fprintf(stderr, "couldn't open file: %s\n", file_name); | 746 | fprintf(stderr, "couldn't open file: %s\n", file_name); |
749 | exit(-1); | 747 | exit(EXIT_FAILURE); |
750 | } | ||
751 | fseek(fd, 0, SEEK_END); | ||
752 | size_t file_size = ftell(fd); | ||
753 | fseek(fd, 0, SEEK_SET); | ||
754 | src = malloc(file_size + 1); | ||
755 | fread(src, 1, file_size, fd); | ||
756 | src[file_size] = '\0'; | ||
757 | fclose(fd); | ||
758 | |||
759 | Tokens tokens = tokenize((StringView){.start = src, .n = file_size}); | ||
760 | #if DEBUG | ||
761 | printf("N_TOKENS: %ld\n", tokens.n); | ||
762 | for (size_t i = 0; i < tokens.n; i++) { | ||
763 | printf("\tTYPE: %3d ", tokens.start[i].type); | ||
764 | printf("N: %3ld ", tokens.start[i].value.n); | ||
765 | printf("VALUE: "); | ||
766 | sv_write(tokens.start[i].value); | ||
767 | printf("\n"); | ||
768 | } | ||
769 | #endif | ||
770 | while (tokens.n) { | ||
771 | Object *ast = parse(&tokens); | ||
772 | if (ast) { | ||
773 | #if DEBUG | ||
774 | printf("AST: "); | ||
775 | display(ast); | ||
776 | printf("\n"); | ||
777 | printf("EVAL: "); | ||
778 | #endif | ||
779 | display(eval(ast)); | ||
780 | printf("\n"); | ||
781 | } | ||
782 | } | 748 | } |
749 | eval_line(fd, EOF); | ||
750 | fclose(fd); | ||
751 | } | ||
783 | 752 | ||
784 | free(src); | 753 | void |
754 | print_usage(void) { | ||
755 | printf("Usage: %s [options] <filename>\n", BIN_NAME); | ||
756 | printf("\n"); | ||
757 | printf("\t-i\tInteractive mode (REPL).\n"); | ||
758 | printf("\t-x\tExecute expression from stdin.\n"); | ||
759 | printf("\n"); | ||
785 | } | 760 | } |
786 | 761 | ||
787 | int | 762 | int |
@@ -789,12 +764,18 @@ main(int argc, char *argv[]) { | |||
789 | init(); | 764 | init(); |
790 | 765 | ||
791 | int option; | 766 | int option; |
792 | while ((option = getopt(argc, argv, "i")) != -1) { | 767 | while ((option = getopt(argc, argv, "ix")) != -1) { |
793 | switch (option) { | 768 | switch (option) { |
794 | case 'i': { | 769 | case 'i': { |
770 | // Interactive mode. | ||
795 | run_repl(); | 771 | run_repl(); |
796 | return EXIT_SUCCESS; | 772 | return EXIT_SUCCESS; |
797 | } break; | 773 | } break; |
774 | case 'x': { | ||
775 | // Execute expression from stdin. | ||
776 | eval_line(stdin, EOF); | ||
777 | return EXIT_SUCCESS; | ||
778 | } break; | ||
798 | default: { | 779 | default: { |
799 | print_usage(); | 780 | print_usage(); |
800 | return EXIT_FAILURE; | 781 | return EXIT_FAILURE; |
@@ -802,6 +783,7 @@ main(int argc, char *argv[]) { | |||
802 | } | 783 | } |
803 | } | 784 | } |
804 | 785 | ||
786 | // Run from file. | ||
805 | if (optind != argc - 1) { | 787 | if (optind != argc - 1) { |
806 | fprintf(stderr, "%s: No input file given.\n", BIN_NAME); | 788 | fprintf(stderr, "%s: No input file given.\n", BIN_NAME); |
807 | print_usage(); | 789 | print_usage(); |