aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-09 13:46:54 +0200
committerBad Diode <bd@badd10de.dev>2021-10-09 13:46:54 +0200
commit376b83e6a44271599ed563e3510b2411beab5921 (patch)
tree7d8b47146046fb055df2504461762093e6dcfc2a
parent24b76ba094b7638280bc9e1f7da5136a8d1f9772 (diff)
downloadbdl-376b83e6a44271599ed563e3510b2411beab5921.tar.gz
bdl-376b83e6a44271599ed563e3510b2411beab5921.zip
Enable eval expressions from stdin and small cleanup
-rwxr-xr-xsrc/bootstrap/main.c108
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
39StringView 41StringView
40read_line(void) { 42read_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
699void 701void
700print_usage(void) { 702eval_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
707void
708run_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
738void 730void
731run_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
739void
739run_file(char *file_name) { 740run_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); 753void
754print_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
787int 762int
@@ -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();