From bc3165d7e6c5b4a24598c344783ae3d393a4416d Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 18 Apr 2024 11:45:32 -0700 Subject: [PATCH 01/81] Added documentation for flags --- README.md | 3 +++ examples/tests.modal | 4 ++-- makefile | 8 ++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 90d65a4..033992c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ cc src/modal.c -o bin/modal ``` bin/modal examples/hello.modal + -v Print version + -q Quiet mode, no step printing + -n Infinite mode, no rewrites limit ``` ## Credits diff --git a/examples/tests.modal b/examples/tests.modal index f8e329e..7a1698f 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -67,8 +67,8 @@ implode (12 (34 (56 ()))) 123456 test ?(?-) (Test Primitives) <> (?: print) (?:) -<> (?x = ?x test) (#ok) -<> (?x = ?y test) (#fail) +<> (?x = ?x test) (#ok\n print) +<> (?x = ?y test) (#fail\n print) ?(?-) (List reversal) diff --git a/makefile b/makefile index ab918b7..cf49fed 100644 --- a/makefile +++ b/makefile @@ -8,12 +8,12 @@ all: dest dest: @ mkdir -p bin run: all bin/modal - @ bin/modal examples/hello.modal 2> /dev/null -debug: bin/modal-debug + @ bin/modal -q examples/hello.modal +debug: all bin/modal-debug @ bin/modal-debug examples/hello.modal -test: bin/modal-debug bin/modal +test: all bin/modal-debug bin/modal @ bin/modal -v - @ bin/modal-debug examples/tests.modal + @ bin/modal-debug -q examples/tests.modal install: bin/modal cp bin/modal ~/bin/ uninstall: From 6f89fb02bc58a6ddcf6da59cc6f051e8fa34de76 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Fri, 19 Apr 2024 11:10:37 -0700 Subject: [PATCH 02/81] Added postcard example --- examples/shirt.modal | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 examples/shirt.modal diff --git a/examples/shirt.modal b/examples/shirt.modal new file mode 100644 index 0000000..478b784 --- /dev/null +++ b/examples/shirt.modal @@ -0,0 +1,9 @@ + +<> (what is ?x) (is ?x a (programming language)) +<> (is ?x a ?y) (or, is ?x (a virtual machine)) +<> (or, is ?x ?y) (?x is ?y <> ?y (a meta-language)) +<> ((a meta-language)) modal +<> (?x is ?x) (?(?: ?:) ?x) + +what is modal + From 0e6e963425a8e22af385ea47889cfd0425f8f9eb Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Fri, 19 Apr 2024 14:08:18 -0700 Subject: [PATCH 03/81] Fixed issue with matching tokens of different length --- src/modal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modal.c b/src/modal.c index 5f3206b..b9f4c90 100644 --- a/src/modal.c +++ b/src/modal.c @@ -35,7 +35,7 @@ set_reg(int r, char *b) { if(regs[r]) { char *a = regs[r], *aa = walk(a), *bb = walk(b); - while(a < aa && b < bb) + while(a < aa || b < bb) if(*a++ != *b++) return 0; } else { regs[r] = b; @@ -222,7 +222,7 @@ main(int argc, char **argv) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { - case 'v': /* version */ return !printf("Modal Interpreter, 18 Apr 2024.\n"); + case 'v': /* version */ return !printf("Modal Interpreter, 19 Apr 2024.\n"); case 'q': /* quiet */ fclose(stderr); break; case 'n': /* infinite */ cycles = 0xffffffff; break; } From 6a61088a70f4f84d5d75344010eb212088c63dc1 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 11:01:20 -0700 Subject: [PATCH 04/81] Use cached data in register --- src/modal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modal.c b/src/modal.c index b9f4c90..3b654cd 100644 --- a/src/modal.c +++ b/src/modal.c @@ -158,9 +158,9 @@ parse_frag(char *s) { char c, *ss; while((c = *s) && c <= ' ') s++; - if(*s != ')' && !(*s == '<' && s[1] == '>')) { + if(c != ')' && !(c == '<' && s[1] == '>')) { ss = walk(s); - if(*s == '(') { + if(c == '(') { s++; while(s < ss - 1) *dict_++ = *s++; s++; @@ -188,13 +188,13 @@ rewrite(void) while((c = *s)) { if(spacer(last)) { Rule *r; - if(*s == '<' && s[1] == '>') { + if(c == '<' && s[1] == '>') { r = rules_++; s = create_rule(r, rules_ - rules - 1, s); while((c = *s) && c <= ' ') s++; return commit_rule(r, s, 1); } - if(*s == '?' && s[1] == '(') { + if(c == '?' && s[1] == '(') { r = &lambda, cap = walk(s + 1); create_rule(&lambda, -1, s), s = cap; while((c = *s) && c <= ' ') s++; From f139f3218e0f8a74abd2c42908b38c79b01d4cee Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 11:09:43 -0700 Subject: [PATCH 05/81] Do not injest register on empty put_reg --- src/modal.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/modal.c b/src/modal.c index 3b654cd..fd5e6e5 100644 --- a/src/modal.c +++ b/src/modal.c @@ -48,12 +48,7 @@ set_reg(int r, char *b) static void put_reg(char r) { - char c, *s = regs[(int)r], *ss; - if(!s) { - *dst_++ = '?', *dst_++ = r; - return; - } - ss = walk(s); + char c, *s = regs[(int)r], *ss = walk(s); if(r == '*') { int i, depth = 0; if(*s == '(') { /* special explode tuple */ @@ -142,7 +137,7 @@ write_rule(Rule *r, char last, char *res) { char c, *b = r->b, *origin = dst_; while((c = *b++)) - if(spacer(last) && c == '?') + if(spacer(last) && c == '?' && regs[(int)*b]) put_reg(*b++); else *dst_++ = c, last = c; @@ -222,7 +217,7 @@ main(int argc, char **argv) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { - case 'v': /* version */ return !printf("Modal Interpreter, 19 Apr 2024.\n"); + case 'v': /* version */ return !printf("Modal Interpreter, 20 Apr 2024.\n"); case 'q': /* quiet */ fclose(stderr); break; case 'n': /* infinite */ cycles = 0xffffffff; break; } From b725a608da8ab1ca2b7bd3e8e4424dfd632d94fc Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 11:26:57 -0700 Subject: [PATCH 06/81] Escape question marks --- src/modal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modal.c b/src/modal.c index fd5e6e5..70f07bc 100644 --- a/src/modal.c +++ b/src/modal.c @@ -84,6 +84,7 @@ put_reg(char r) case 't': putc(0x09, stdout); break; case 'n': putc(0x0a, stdout); break; case 's': putc(0x20, stdout); break; + case '?': putc(0x3f, stdout); break; } } else putc(c, stdout); @@ -103,7 +104,7 @@ match_rule(Rule *r, char *p) rmin = 0xff, rmax = 0x00; } while((c = *a)) { - if(spacer(last) && c == '?') { + if(c == '?' && last != '\\') { if(!set_reg(*(++a), b)) return NULL; a++, b = walk(b); continue; @@ -137,7 +138,7 @@ write_rule(Rule *r, char last, char *res) { char c, *b = r->b, *origin = dst_; while((c = *b++)) - if(spacer(last) && c == '?' && regs[(int)*b]) + if(c == '?' && last != '\\' && regs[(int)*b]) put_reg(*b++); else *dst_++ = c, last = c; From 9029c64c77685d396b94b911c95af398a7e96d0d Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 12:00:25 -0700 Subject: [PATCH 07/81] A register is surrounded by spacers --- src/modal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modal.c b/src/modal.c index 70f07bc..81ed6ff 100644 --- a/src/modal.c +++ b/src/modal.c @@ -138,7 +138,7 @@ write_rule(Rule *r, char last, char *res) { char c, *b = r->b, *origin = dst_; while((c = *b++)) - if(c == '?' && last != '\\' && regs[(int)*b]) + if(c == '?' && regs[(int)*b] && spacer(last) && spacer(b[1])) put_reg(*b++); else *dst_++ = c, last = c; From 529777fcb4f24b32eecbdcf2db124bc808101fd2 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 12:06:32 -0700 Subject: [PATCH 08/81] Can merge token during reg writing --- src/modal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modal.c b/src/modal.c index 81ed6ff..77f8666 100644 --- a/src/modal.c +++ b/src/modal.c @@ -104,7 +104,7 @@ match_rule(Rule *r, char *p) rmin = 0xff, rmax = 0x00; } while((c = *a)) { - if(c == '?' && last != '\\') { + if(c == '?' && spacer(last) && spacer(a[2])) { if(!set_reg(*(++a), b)) return NULL; a++, b = walk(b); continue; @@ -138,7 +138,7 @@ write_rule(Rule *r, char last, char *res) { char c, *b = r->b, *origin = dst_; while((c = *b++)) - if(c == '?' && regs[(int)*b] && spacer(last) && spacer(b[1])) + if(c == '?' && last != '\\' && regs[(int)*b]) put_reg(*b++); else *dst_++ = c, last = c; From 9295a4d2b4d905d3654cec2f8fd84893aaef8b97 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 12:38:05 -0700 Subject: [PATCH 09/81] Added tests --- examples/tests.modal | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/examples/tests.modal b/examples/tests.modal index 7a1698f..d2a891d 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -39,6 +39,18 @@ compare (abc abc abc) (#t) test replace-empty abc = ?y test +?(?-) (Connecting register output) + +<> (connect ?x ?y ?z) (?x-?y?z) + +connect foo bar baz = foo-barbaz test + +?(?-) (Inline register) + +<> inline?register ERROR + +(inline egister) = (inline egister) test + ?(?-) (Guards setups) <> (join (String ?x) (String ?y)) ((?x ?y) =) From 4322d96ee236c20be5414a8583b21c24a4c97058 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 18:56:04 -0700 Subject: [PATCH 10/81] Improved native substring capabilities --- examples/tests.modal | 4 +++- src/modal.c | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/tests.modal b/examples/tests.modal index d2a891d..e4f1f28 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -39,11 +39,13 @@ compare (abc abc abc) (#t) test replace-empty abc = ?y test -?(?-) (Connecting register output) +?(?-) (Substring registers) <> (connect ?x ?y ?z) (?x-?y?z) +<> (prefix-?x) (?x-suffix) connect foo bar baz = foo-barbaz test +prefix-anything = anything-suffix test ?(?-) (Inline register) diff --git a/src/modal.c b/src/modal.c index 77f8666..28b70a5 100644 --- a/src/modal.c +++ b/src/modal.c @@ -97,20 +97,22 @@ static char * match_rule(Rule *r, char *p) { int i; - char c, last = 0, *a = r->a, *b = p; + char c, *a = r->a, *b = p; if(rmax) { for(i = rmin; i <= rmax; i++) regs[i] = 0; rmin = 0xff, rmax = 0x00; } while((c = *a)) { - if(c == '?' && spacer(last) && spacer(a[2])) { + if(c == '?') { if(!set_reg(*(++a), b)) return NULL; a++, b = walk(b); + if(!spacer(*a)) + while((c = *a) && !spacer(c)) a++; continue; } if(c != *b) return NULL; - a++, b++, last = c; + a++, b++; } c = *b; return spacer(c) ? b : NULL; From 222c7f6f4c6d90ba5668f300517533e691b3edbf Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 21:50:56 -0700 Subject: [PATCH 11/81] Blacklist ?) register --- src/modal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modal.c b/src/modal.c index 28b70a5..ba9a1c5 100644 --- a/src/modal.c +++ b/src/modal.c @@ -104,7 +104,7 @@ match_rule(Rule *r, char *p) rmin = 0xff, rmax = 0x00; } while((c = *a)) { - if(c == '?') { + if(c == '?' && !spacer(c)) { if(!set_reg(*(++a), b)) return NULL; a++, b = walk(b); if(!spacer(*a)) From 7a124eb70f0731cb5d77e29dbf953ff2c3b767df Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 22:31:58 -0700 Subject: [PATCH 12/81] Do not pass last to write_rule --- src/modal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modal.c b/src/modal.c index ba9a1c5..ff780b3 100644 --- a/src/modal.c +++ b/src/modal.c @@ -136,9 +136,9 @@ commit_rule(Rule *r, char *s, int create) } static int -write_rule(Rule *r, char last, char *res) +write_rule(Rule *r, char *res) { - char c, *b = r->b, *origin = dst_; + char c, last = 0, *b = r->b, *origin = dst_; while((c = *b++)) if(c == '?' && last != '\\' && regs[(int)*b]) put_reg(*b++); @@ -197,11 +197,11 @@ rewrite(void) create_rule(&lambda, -1, s), s = cap; while((c = *s) && c <= ' ') s++; if((res = match_rule(&lambda, s)) != NULL) - return write_rule(&lambda, last, res); + return write_rule(&lambda, res); } for(r = rules; r < rules_; r++) if((res = match_rule(r, s)) != NULL) - return write_rule(r, last, res); + return write_rule(r, res); } *dst_++ = last = c; s++; From a2f60e12fff4b956b69fceacdf2fc66b9062ca62 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 20 Apr 2024 22:34:28 -0700 Subject: [PATCH 13/81] Removed old test --- examples/tests.modal | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/tests.modal b/examples/tests.modal index e4f1f28..2d52858 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -47,12 +47,6 @@ replace-empty abc = ?y test connect foo bar baz = foo-barbaz test prefix-anything = anything-suffix test -?(?-) (Inline register) - -<> inline?register ERROR - -(inline egister) = (inline egister) test - ?(?-) (Guards setups) <> (join (String ?x) (String ?y)) ((?x ?y) =) From 73e9ebcfdd91b6e70b21147e3ce99583a635bf25 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sun, 21 Apr 2024 09:13:30 -0700 Subject: [PATCH 14/81] Only check for register value once --- examples/tests.modal | 1 - src/modal.c | 69 ++++++++++++++++++++++---------------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/examples/tests.modal b/examples/tests.modal index 2d52858..121d991 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -85,4 +85,3 @@ implode (12 (34 (56 ()))) 123456 test <> (reverse List (?x ?y) ?z) (reverse List ?y (?x ?z)) reverse (modal) = ladom test - diff --git a/src/modal.c b/src/modal.c index ff780b3..7f22e9d 100644 --- a/src/modal.c +++ b/src/modal.c @@ -46,51 +46,50 @@ set_reg(int r, char *b) } static void -put_reg(char r) +put_reg(char r, char *reg) { - char c, *s = regs[(int)r], *ss = walk(s); + char c, *cap = walk(reg); if(r == '*') { int i, depth = 0; - if(*s == '(') { /* special explode tuple */ - s++; - while(s < ss) { - while((c = *s) && !spacer(c)) - *dst_++ = c, s++; + if(*reg == '(') { /* special explode tuple */ + reg++; + while(reg < cap) { + while((c = *reg) && !spacer(c)) + *dst_++ = c, reg++; *dst_++ = ' '; - *dst_++ = '(', s++, depth++; + *dst_++ = '(', reg++, depth++; } } else { /* special explode token */ - while((c = *s++) && !spacer(c)) + while((c = *reg++) && !spacer(c)) *dst_++ = c, *dst_++ = ' ', *dst_++ = '(', depth++; } for(i = 0; i < depth; i++) *dst_++ = ')'; } else if(r == '.') { /* special unpack */ - if(*s == '(') s++, --ss; - while(s < ss) *dst_++ = *s++; + if(*reg == '(') reg++, --cap; + while(reg < cap) *dst_++ = *reg++; } else if(r == '^') { /* special join */ - if(*s == '(') s++, --ss; - while(s < ss && (c = *s++)) + if(*reg == '(') reg++, --cap; + while(reg < cap && (c = *reg++)) if(!spacer(c)) *dst_++ = c; } else if(r == '~') { /* special stdin */ while(fread(&c, 1, 1, stdin) && c >= ' ') *dst_++ = c; } else if(r == ':') { /* special stdout */ - if(*s == '(') s++, --ss; - while(s < ss) { - c = *s++; + if(*reg == '(') reg++, --cap; + while(reg < cap) { + c = *reg++; if(c == '\\') { - switch(*s++) { + switch(*reg++) { case 't': putc(0x09, stdout); break; case 'n': putc(0x0a, stdout); break; case 's': putc(0x20, stdout); break; - case '?': putc(0x3f, stdout); break; } } else putc(c, stdout); } } else - while(s < ss) *dst_++ = *s++; + while(reg < cap) *dst_++ = *reg++; } static char * @@ -136,34 +135,34 @@ commit_rule(Rule *r, char *s, int create) } static int -write_rule(Rule *r, char *res) +write_rule(Rule *r, char *s) { - char c, last = 0, *b = r->b, *origin = dst_; + char c, *b = r->b, *reg, *origin = dst_; while((c = *b++)) - if(c == '?' && last != '\\' && regs[(int)*b]) - put_reg(*b++); + if(c == '?' && (reg = regs[(int)*b])) + put_reg(*b++, reg); else - *dst_++ = c, last = c; + *dst_++ = c; if(dst_ == origin) { - while(*res == ' ') res++; - if(*res == ')' && *(dst_ - 1) == ' ') dst_--; + while(*s == ' ') s++; + if(*s == ')' && *(dst_ - 1) == ' ') dst_--; } - return commit_rule(r, res, 0); + return commit_rule(r, s, 0); } static char * parse_frag(char *s) { - char c, *ss; - while((c = *s) && c <= ' ') s++; + char c, *cap; + while((c = *s) && c == ' ') s++; if(c != ')' && !(c == '<' && s[1] == '>')) { - ss = walk(s); + cap = walk(s); if(c == '(') { s++; - while(s < ss - 1) *dict_++ = *s++; + while(s < cap - 1) *dict_++ = *s++; s++; } else - while(s < ss) *dict_++ = *s++; + while(s < cap) *dict_++ = *s++; } *dict_++ = 0; return s; @@ -182,20 +181,20 @@ static int rewrite(void) { char c, last = 0, *cap, *s = src_, *res; - while((c = *s) && c <= ' ') s++; + while(*s == ' ') s++; while((c = *s)) { if(spacer(last)) { Rule *r; if(c == '<' && s[1] == '>') { r = rules_++; s = create_rule(r, rules_ - rules - 1, s); - while((c = *s) && c <= ' ') s++; + while(*s == ' ') s++; return commit_rule(r, s, 1); } if(c == '?' && s[1] == '(') { r = &lambda, cap = walk(s + 1); create_rule(&lambda, -1, s), s = cap; - while((c = *s) && c <= ' ') s++; + while(*s == ' ') s++; if((res = match_rule(&lambda, s)) != NULL) return write_rule(&lambda, res); } From 05e620bac5850f134bf2bbf8ca78267529bd1314 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sun, 21 Apr 2024 09:24:05 -0700 Subject: [PATCH 15/81] Inlined create_rule --- src/modal.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/modal.c b/src/modal.c index 7f22e9d..adaa97d 100644 --- a/src/modal.c +++ b/src/modal.c @@ -168,15 +168,6 @@ parse_frag(char *s) return s; } -static char * -create_rule(Rule *r, int id, char *s) -{ - r->id = id, s += 2; - r->a = dict_, s = parse_frag(s); - r->b = dict_, s = parse_frag(s); - return s; -} - static int rewrite(void) { @@ -186,14 +177,17 @@ rewrite(void) if(spacer(last)) { Rule *r; if(c == '<' && s[1] == '>') { - r = rules_++; - s = create_rule(r, rules_ - rules - 1, s); + r = rules_++, r->id = rules_ - rules - 1; + r->a = dict_, s = parse_frag(s + 2); + r->b = dict_, s = parse_frag(s); while(*s == ' ') s++; return commit_rule(r, s, 1); } if(c == '?' && s[1] == '(') { - r = &lambda, cap = walk(s + 1); - create_rule(&lambda, -1, s), s = cap; + cap = walk(s + 1); + r = &lambda, r->id = -1; + r->a = dict_, s = parse_frag(s + 2); + r->b = dict_, parse_frag(s), s = cap; while(*s == ' ') s++; if((res = match_rule(&lambda, s)) != NULL) return write_rule(&lambda, res); @@ -219,7 +213,7 @@ main(int argc, char **argv) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { - case 'v': /* version */ return !printf("Modal Interpreter, 20 Apr 2024.\n"); + case 'v': /* version */ return !printf("Modal Interpreter, 21 Apr 2024.\n"); case 'q': /* quiet */ fclose(stderr); break; case 'n': /* infinite */ cycles = 0xffffffff; break; } From 111e143d2f10b91d5d40fc40ba68f7988163b4c3 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sun, 21 Apr 2024 09:43:00 -0700 Subject: [PATCH 16/81] Added tests --- examples/tests.modal | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/examples/tests.modal b/examples/tests.modal index 121d991..77866f2 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -9,12 +9,16 @@ nap tap test ?(?-) (Empty replacements) -<> (?x pop-plain) +<> (?x rightless/pop) <> (?x pop) () <> (ghost) () +<> (prefix/pop ?x) (ok) +<> (?x suffix/pop) (ok) -abc def pop-plain = abc test -abc def pop = abc test +(abc rightless/pop) = () test +(prefix/pop foo) = (ok) test +(foo suffix/pop) = (ok) test +(abc def pop) = (abc) test (ghost) = () test ?(?-) (Basic replacements) @@ -25,13 +29,15 @@ replace-name (foo) (bar) test ?(?-) (Basic register setups) -<> (dup (?x)) ((?x ?x) =) -<> (swap (?x ?y)) ((?y ?x) =) -<> (compare (?x ?x ?x)) ((#t) =) +<> (dup (?x)) (?x ?x) +<> (swap (?x ?y)) (?y ?x) +<> (compare (?x ?x ?x)) (#t) +<> (rotate (?x (?y (?z)))) (?y (?z (?x))) -dup (abc) (abc abc) test -swap (abc def) (def abc) test -compare (abc abc abc) (#t) test +(dup (abc)) = (abc abc) test +(swap (abc def)) = (def abc) test +compare (abc abc abc) = #t test +(rotate (abc (def (ghi)))) = (def (ghi (abc))) test ?(?-) (Empty register replacement) From ed5c0763e220ca4bef1a0f3dcf99a5708d57d350 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sun, 21 Apr 2024 09:46:53 -0700 Subject: [PATCH 17/81] Warn on imbalance --- src/modal.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modal.c b/src/modal.c index adaa97d..38d9cae 100644 --- a/src/modal.c +++ b/src/modal.c @@ -207,7 +207,7 @@ int main(int argc, char **argv) { FILE *f; - int i; + int i, pl = 0, pr = 0; char c, *w = bank_a; if(argc < 2) return !printf("usage: modal [-vqn] source.modal\n"); @@ -219,18 +219,22 @@ main(int argc, char **argv) } } if(!(f = fopen(argv[i], "r"))) - return !fprintf(stdout, "Invalid Modal file: %s.\n", argv[i]); + return !fprintf(stdout, "Modal file invalid: %s.\n", argv[i]); while(fread(&c, 1, 1, f)) { c = c <= 0x20 ? 0x20 : c; if(w > bank_a) { if(c == ' ' && *(w - 1) == '(') continue; if(c == ')' && *(w - 1) == ' ') w--; if(c == ' ' && *(w - 1) == ' ') w--; + if(c == '(') pl++; + if(c == ')') pr++; } *w++ = c; } while(*(--w) <= ' ') *w = 0; fclose(f); + if(pr != pl) + return !fprintf(stdout, "Modal program imbalanced.\n"); while(rewrite()) if(!cycles--) return !fprintf(stdout, "Modal rewrites exceeded.\n"); return 0; From 0be295a237ff0b7941b56c4f863d20fec052b8d4 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sun, 21 Apr 2024 16:47:27 -0700 Subject: [PATCH 18/81] Added sierpinski to examples/ --- examples/sierpinski.modal | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 examples/sierpinski.modal diff --git a/examples/sierpinski.modal b/examples/sierpinski.modal new file mode 100644 index 0000000..a5781e6 --- /dev/null +++ b/examples/sierpinski.modal @@ -0,0 +1,21 @@ +?(?-) (Rules) + +<> (* (. > (. ?x))) (* (. (. > ?x))) +<> (. (. > (* ?x))) (* (. (* > ?x))) + +?(?-) (Physics) + +<> (Tri > (?x ?y)) (Tri (?x > ?y)) +<> (Tri (?x > (?y ?z))) (Tri (?x (?y > ?z))) +<> (?x (?y > (?z ?n))) (. (?y (?z > ?n))) +<> ((?x > ())) (< ()) +<> (Tri < (* ?^)) (?(?: ?:) (*?^)) +<> ((?x < ?y)) (< (?x ?y)) + +?(?-) (Print) + +<> (Tri.join ?x ?:) (Tri > ?x ?:) +<> (Tri.dup ?x ?^) (Tri.join ?x ?^) +<> (Tri < ?x) (Tri.dup (. ?x) (?x \n)) + +Tri < (. (. (. (. (. (. (. (. (. (. (. (. (. (. (. (* (. (. (. (. (. (. (. (. (. (. (. (. (. (. (. ()))))))))))))))))))))))))))))))) \ No newline at end of file From 150d0ff032918c56ad4704e9fb42387e88053b79 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sun, 21 Apr 2024 18:06:08 -0700 Subject: [PATCH 19/81] Improved init for sierpinski --- examples/sierpinski.modal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/sierpinski.modal b/examples/sierpinski.modal index a5781e6..9c2a50a 100644 --- a/examples/sierpinski.modal +++ b/examples/sierpinski.modal @@ -9,7 +9,7 @@ <> (Tri (?x > (?y ?z))) (Tri (?x (?y > ?z))) <> (?x (?y > (?z ?n))) (. (?y (?z > ?n))) <> ((?x > ())) (< ()) -<> (Tri < (* ?^)) (?(?: ?:) (*?^)) +<> (Tri < (* ?^)) (?(?: ?:) (*?^ \n)) <> ((?x < ?y)) (< (?x ?y)) ?(?-) (Print) @@ -18,4 +18,4 @@ <> (Tri.dup ?x ?^) (Tri.join ?x ?^) <> (Tri < ?x) (Tri.dup (. ?x) (?x \n)) -Tri < (. (. (. (. (. (. (. (. (. (. (. (. (. (. (. (* (. (. (. (. (. (. (. (. (. (. (. (. (. (. (. ()))))))))))))))))))))))))))))))) \ No newline at end of file +?(?* (Tri < (?*))) ...............*............... \ No newline at end of file From 94d9ecfa7249ae9b402a18d9177dd15363fef7e0 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sun, 21 Apr 2024 19:34:43 -0700 Subject: [PATCH 20/81] Renamed shirt.modal to postcard.modal --- examples/{shirt.modal => postcard.modal} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{shirt.modal => postcard.modal} (100%) diff --git a/examples/shirt.modal b/examples/postcard.modal similarity index 100% rename from examples/shirt.modal rename to examples/postcard.modal From aa0cc804555d000ecad654745712b17daa73b4e5 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 09:54:41 -0700 Subject: [PATCH 21/81] Inlined set_reg --- src/modal.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/modal.c b/src/modal.c index 38d9cae..9c27fad 100644 --- a/src/modal.c +++ b/src/modal.c @@ -30,21 +30,6 @@ walk(char *s) return s; } -static int -set_reg(int r, char *b) -{ - if(regs[r]) { - char *a = regs[r], *aa = walk(a), *bb = walk(b); - while(a < aa || b < bb) - if(*a++ != *b++) return 0; - } else { - regs[r] = b; - if(r < rmin) rmin = r; - if(r > rmax) rmax = r; - } - return 1; -} - static void put_reg(char r, char *reg) { @@ -96,7 +81,7 @@ static char * match_rule(Rule *r, char *p) { int i; - char c, *a = r->a, *b = p; + char c, *a = r->a; if(rmax) { for(i = rmin; i <= rmax; i++) regs[i] = 0; @@ -104,17 +89,27 @@ match_rule(Rule *r, char *p) } while((c = *a)) { if(c == '?' && !spacer(c)) { - if(!set_reg(*(++a), b)) return NULL; - a++, b = walk(b); + int regid = (int)*(++a); + char *pcap = walk(p), *reg = regs[regid]; + if(reg) { /* reg cmp */ + char *rcap = walk(reg), *pp = p; + while(reg < rcap || pp < pcap) + if(*reg++ != *pp++) return NULL; + } else { /* reg set */ + regs[regid] = p; + if(regid < rmin) rmin = regid; + if(regid > rmax) rmax = regid; + } + a++, p = pcap; if(!spacer(*a)) while((c = *a) && !spacer(c)) a++; continue; } - if(c != *b) return NULL; - a++, b++; + if(c != *p) return NULL; + a++, p++; } - c = *b; - return spacer(c) ? b : NULL; + c = *p; + return spacer(c) ? p : NULL; } static int @@ -213,7 +208,7 @@ main(int argc, char **argv) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { - case 'v': /* version */ return !printf("Modal Interpreter, 21 Apr 2024.\n"); + case 'v': /* version */ return !printf("Modal Interpreter, 22 Apr 2024.\n"); case 'q': /* quiet */ fclose(stderr); break; case 'n': /* infinite */ cycles = 0xffffffff; break; } From 6fb9f96b0cefcbe73e9ea79c5aab6481196ef41d Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 10:10:55 -0700 Subject: [PATCH 22/81] Oups --- src/modal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modal.c b/src/modal.c index 9c27fad..6bbd6d9 100644 --- a/src/modal.c +++ b/src/modal.c @@ -88,7 +88,7 @@ match_rule(Rule *r, char *p) rmin = 0xff, rmax = 0x00; } while((c = *a)) { - if(c == '?' && !spacer(c)) { + if(c == '?') { int regid = (int)*(++a); char *pcap = walk(p), *reg = regs[regid]; if(reg) { /* reg cmp */ From e153eb797bca148158c017b6198712eafb632196 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 15:29:54 -0700 Subject: [PATCH 23/81] Print unused rules --- src/modal.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/modal.c b/src/modal.c index 6bbd6d9..78b4e2b 100644 --- a/src/modal.c +++ b/src/modal.c @@ -1,11 +1,11 @@ #include typedef struct { - int id; + int id, refs; char *a, *b; } Rule; -static int flip, rmin = 0xff, rmax = 0x00, cycles = 0x10000; +static int flip, quiet, rmin = 0xff, rmax = 0x00, cycles = 0x10000; static Rule rules[0x1000], lambda, *rules_ = rules; static char dict[0x8000], *dict_ = dict; static char bank_a[0x4000], *src_ = bank_a; @@ -122,10 +122,12 @@ commit_rule(Rule *r, char *s, int create) src_ = bank_b, dst_ = bank_a; else src_ = bank_a, dst_ = bank_b; - if(create) - fprintf(stderr, "<> (%s) (%s)\n", r->a, r->b); - else - fprintf(stderr, "%02d %s\n", r->id, src_); + if(!quiet) { + if(create) + fprintf(stderr, "<> (%s) (%s)\n", r->a, r->b); + else + fprintf(stderr, "%02d %s\n", r->id, src_), ++r->refs; + } return 1; } @@ -209,7 +211,7 @@ main(int argc, char **argv) for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { case 'v': /* version */ return !printf("Modal Interpreter, 22 Apr 2024.\n"); - case 'q': /* quiet */ fclose(stderr); break; + case 'q': /* quiet */ quiet = 1; break; case 'n': /* infinite */ cycles = 0xffffffff; break; } } @@ -232,5 +234,7 @@ main(int argc, char **argv) return !fprintf(stdout, "Modal program imbalanced.\n"); while(rewrite()) if(!cycles--) return !fprintf(stdout, "Modal rewrites exceeded.\n"); + while(rules_-- > rules && !quiet) + if(!rules_->refs) printf("-- Unused rule: %d <> (%s) (%s)\n", rules_->refs, rules_->a, rules_->b); return 0; } \ No newline at end of file From 8e7bbb51d7c3f2de0e6c42ab37fc9541c38747fa Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 17:27:34 -0700 Subject: [PATCH 24/81] Store lambda in rules[0] --- src/modal.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modal.c b/src/modal.c index 78b4e2b..c9e677c 100644 --- a/src/modal.c +++ b/src/modal.c @@ -6,7 +6,7 @@ typedef struct { } Rule; static int flip, quiet, rmin = 0xff, rmax = 0x00, cycles = 0x10000; -static Rule rules[0x1000], lambda, *rules_ = rules; +static Rule rules[0x1000], *rules_ = rules + 1; static char dict[0x8000], *dict_ = dict; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; @@ -173,23 +173,23 @@ rewrite(void) while((c = *s)) { if(spacer(last)) { Rule *r; - if(c == '<' && s[1] == '>') { + if(c == '<' && s[1] == '>') { /* rule */ r = rules_++, r->id = rules_ - rules - 1; r->a = dict_, s = parse_frag(s + 2); r->b = dict_, s = parse_frag(s); while(*s == ' ') s++; return commit_rule(r, s, 1); } - if(c == '?' && s[1] == '(') { + if(c == '?' && s[1] == '(') { /* lambda */ cap = walk(s + 1); - r = &lambda, r->id = -1; + r = &rules[0], r->id = -1; r->a = dict_, s = parse_frag(s + 2); r->b = dict_, parse_frag(s), s = cap; while(*s == ' ') s++; - if((res = match_rule(&lambda, s)) != NULL) - return write_rule(&lambda, res); - } - for(r = rules; r < rules_; r++) + r = rules; + } else + r = rules + 1; + for(; r < rules_; r++) if((res = match_rule(r, s)) != NULL) return write_rule(r, res); } From 4fce0e83e54e329a731b1d1dea17d2688b002542 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 17:39:39 -0700 Subject: [PATCH 25/81] Abstracted match/write rule --- src/modal.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/modal.c b/src/modal.c index c9e677c..86a888d 100644 --- a/src/modal.c +++ b/src/modal.c @@ -165,10 +165,19 @@ parse_frag(char *s) return s; } +static int +run_rule(Rule *r, char *s) +{ + char *res; + if((res = match_rule(r, s)) != NULL) + return write_rule(r, res); + return 0; +} + static int rewrite(void) { - char c, last = 0, *cap, *s = src_, *res; + char c, last = 0, *cap, *s = src_; while(*s == ' ') s++; while((c = *s)) { if(spacer(last)) { @@ -190,8 +199,7 @@ rewrite(void) } else r = rules + 1; for(; r < rules_; r++) - if((res = match_rule(r, s)) != NULL) - return write_rule(r, res); + if(run_rule(r, s)) return 1; } *dst_++ = last = c; s++; From 9b034eac9528895e66afc0786b7f5f0151fde918 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 17:43:35 -0700 Subject: [PATCH 26/81] Merged all regs needing functions --- src/modal.c | 69 +++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/src/modal.c b/src/modal.c index 86a888d..4661f8f 100644 --- a/src/modal.c +++ b/src/modal.c @@ -77,41 +77,6 @@ put_reg(char r, char *reg) while(reg < cap) *dst_++ = *reg++; } -static char * -match_rule(Rule *r, char *p) -{ - int i; - char c, *a = r->a; - if(rmax) { - for(i = rmin; i <= rmax; i++) - regs[i] = 0; - rmin = 0xff, rmax = 0x00; - } - while((c = *a)) { - if(c == '?') { - int regid = (int)*(++a); - char *pcap = walk(p), *reg = regs[regid]; - if(reg) { /* reg cmp */ - char *rcap = walk(reg), *pp = p; - while(reg < rcap || pp < pcap) - if(*reg++ != *pp++) return NULL; - } else { /* reg set */ - regs[regid] = p; - if(regid < rmin) rmin = regid; - if(regid > rmax) rmax = regid; - } - a++, p = pcap; - if(!spacer(*a)) - while((c = *a) && !spacer(c)) a++; - continue; - } - if(c != *p) return NULL; - a++, p++; - } - c = *p; - return spacer(c) ? p : NULL; -} - static int commit_rule(Rule *r, char *s, int create) { @@ -168,10 +133,36 @@ parse_frag(char *s) static int run_rule(Rule *r, char *s) { - char *res; - if((res = match_rule(r, s)) != NULL) - return write_rule(r, res); - return 0; + int i; + char c, *a = r->a, *p = s; + if(rmax) { + for(i = rmin; i <= rmax; i++) + regs[i] = 0; + rmin = 0xff, rmax = 0x00; + } + while((c = *a)) { + if(c == '?') { + int regid = (int)*(++a); + char *pcap = walk(p), *reg = regs[regid]; + if(reg) { /* reg cmp */ + char *rcap = walk(reg), *pp = p; + while(reg < rcap || pp < pcap) + if(*reg++ != *pp++) return 0; + } else { /* reg set */ + regs[regid] = p; + if(regid < rmin) rmin = regid; + if(regid > rmax) rmax = regid; + } + a++, p = pcap; + if(!spacer(*a)) + while((c = *a) && !spacer(c)) a++; + continue; + } + if(c != *p) return 0; + a++, p++; + } + c = *p; + return spacer(c) ? write_rule(r, p) : 0; } static int From 7a27c2ca5bf890b27c8b9215167457b3bb622f96 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 17:54:17 -0700 Subject: [PATCH 27/81] Housekeeping --- src/modal.c | 73 +++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/src/modal.c b/src/modal.c index 4661f8f..21f8f6e 100644 --- a/src/modal.c +++ b/src/modal.c @@ -31,7 +31,7 @@ walk(char *s) } static void -put_reg(char r, char *reg) +write_reg(char r, char *reg) { char c, *cap = walk(reg); if(r == '*') { @@ -78,7 +78,7 @@ put_reg(char r, char *reg) } static int -commit_rule(Rule *r, char *s, int create) +write_rule(Rule *r, char *s, int create) { while((*dst_++ = *s++)) ; @@ -96,40 +96,6 @@ commit_rule(Rule *r, char *s, int create) return 1; } -static int -write_rule(Rule *r, char *s) -{ - char c, *b = r->b, *reg, *origin = dst_; - while((c = *b++)) - if(c == '?' && (reg = regs[(int)*b])) - put_reg(*b++, reg); - else - *dst_++ = c; - if(dst_ == origin) { - while(*s == ' ') s++; - if(*s == ')' && *(dst_ - 1) == ' ') dst_--; - } - return commit_rule(r, s, 0); -} - -static char * -parse_frag(char *s) -{ - char c, *cap; - while((c = *s) && c == ' ') s++; - if(c != ')' && !(c == '<' && s[1] == '>')) { - cap = walk(s); - if(c == '(') { - s++; - while(s < cap - 1) *dict_++ = *s++; - s++; - } else - while(s < cap) *dict_++ = *s++; - } - *dict_++ = 0; - return s; -} - static int run_rule(Rule *r, char *s) { @@ -162,7 +128,38 @@ run_rule(Rule *r, char *s) a++, p++; } c = *p; - return spacer(c) ? write_rule(r, p) : 0; + if(spacer(c)) { + char *b = r->b, *reg, *origin = dst_; + while((c = *b++)) + if(c == '?' && (reg = regs[(int)*b])) + write_reg(*b++, reg); + else + *dst_++ = c; + if(dst_ == origin) { + while(*p == ' ') p++; + if(*p == ')' && *(dst_ - 1) == ' ') dst_--; + } + return write_rule(r, p, 0); + } + return 0; +} + +static char * +parse_frag(char *s) +{ + char c, *cap; + while((c = *s) && c == ' ') s++; + if(c != ')' && !(c == '<' && s[1] == '>')) { + cap = walk(s); + if(c == '(') { + s++; + while(s < cap - 1) *dict_++ = *s++; + s++; + } else + while(s < cap) *dict_++ = *s++; + } + *dict_++ = 0; + return s; } static int @@ -178,7 +175,7 @@ rewrite(void) r->a = dict_, s = parse_frag(s + 2); r->b = dict_, s = parse_frag(s); while(*s == ' ') s++; - return commit_rule(r, s, 1); + return write_rule(r, s, 1); } if(c == '?' && s[1] == '(') { /* lambda */ cap = walk(s + 1); From 9c95b4567b636f9a7a59c48ae2d97eb274a4432d Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 18:02:27 -0700 Subject: [PATCH 28/81] Return lambda to its own memory --- src/modal.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/modal.c b/src/modal.c index 21f8f6e..9fd5aff 100644 --- a/src/modal.c +++ b/src/modal.c @@ -6,7 +6,7 @@ typedef struct { } Rule; static int flip, quiet, rmin = 0xff, rmax = 0x00, cycles = 0x10000; -static Rule rules[0x1000], *rules_ = rules + 1; +static Rule rules[0x1000], lambda, *rules_ = rules; static char dict[0x8000], *dict_ = dict; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; @@ -99,47 +99,46 @@ write_rule(Rule *r, char *s, int create) static int run_rule(Rule *r, char *s) { - int i; - char c, *a = r->a, *p = s; - if(rmax) { + char c, *a = r->a; + if(rmax) { /* clean registers */ + int i; for(i = rmin; i <= rmax; i++) regs[i] = 0; rmin = 0xff, rmax = 0x00; } - while((c = *a)) { + while((c = *a)) { /* find match */ if(c == '?') { int regid = (int)*(++a); - char *pcap = walk(p), *reg = regs[regid]; + char *pcap = walk(s), *reg = regs[regid]; if(reg) { /* reg cmp */ - char *rcap = walk(reg), *pp = p; + char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; } else { /* reg set */ - regs[regid] = p; + regs[regid] = s; if(regid < rmin) rmin = regid; if(regid > rmax) rmax = regid; } - a++, p = pcap; + a++, s = pcap; if(!spacer(*a)) while((c = *a) && !spacer(c)) a++; continue; } - if(c != *p) return 0; - a++, p++; + if(c != *s) return 0; + a++, s++; } - c = *p; - if(spacer(c)) { + if((c = *s) && spacer(c)) { /* write match */ char *b = r->b, *reg, *origin = dst_; while((c = *b++)) if(c == '?' && (reg = regs[(int)*b])) write_reg(*b++, reg); else *dst_++ = c; - if(dst_ == origin) { - while(*p == ' ') p++; - if(*p == ')' && *(dst_ - 1) == ' ') dst_--; + if(dst_ == origin) { /* trim */ + while(*s == ' ') s++; + if(*s == ')' && *(dst_ - 1) == ' ') dst_--; } - return write_rule(r, p, 0); + return write_rule(r, s, 0); } return 0; } @@ -179,14 +178,13 @@ rewrite(void) } if(c == '?' && s[1] == '(') { /* lambda */ cap = walk(s + 1); - r = &rules[0], r->id = -1; + r = &lambda, r->id = -1; r->a = dict_, s = parse_frag(s + 2); r->b = dict_, parse_frag(s), s = cap; while(*s == ' ') s++; - r = rules; - } else - r = rules + 1; - for(; r < rules_; r++) + if(run_rule(r, s)) return 1; + } + for(r = rules; r < rules_; r++) if(run_rule(r, s)) return 1; } *dst_++ = last = c; From ba48cfffa65590cd46b10c037d053f6a5b5edaa7 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 20:08:29 -0700 Subject: [PATCH 29/81] Rewind --- src/modal.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/modal.c b/src/modal.c index 9fd5aff..21f8f6e 100644 --- a/src/modal.c +++ b/src/modal.c @@ -6,7 +6,7 @@ typedef struct { } Rule; static int flip, quiet, rmin = 0xff, rmax = 0x00, cycles = 0x10000; -static Rule rules[0x1000], lambda, *rules_ = rules; +static Rule rules[0x1000], *rules_ = rules + 1; static char dict[0x8000], *dict_ = dict; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; @@ -99,46 +99,47 @@ write_rule(Rule *r, char *s, int create) static int run_rule(Rule *r, char *s) { - char c, *a = r->a; - if(rmax) { /* clean registers */ - int i; + int i; + char c, *a = r->a, *p = s; + if(rmax) { for(i = rmin; i <= rmax; i++) regs[i] = 0; rmin = 0xff, rmax = 0x00; } - while((c = *a)) { /* find match */ + while((c = *a)) { if(c == '?') { int regid = (int)*(++a); - char *pcap = walk(s), *reg = regs[regid]; + char *pcap = walk(p), *reg = regs[regid]; if(reg) { /* reg cmp */ - char *rcap = walk(reg), *pp = s; + char *rcap = walk(reg), *pp = p; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; } else { /* reg set */ - regs[regid] = s; + regs[regid] = p; if(regid < rmin) rmin = regid; if(regid > rmax) rmax = regid; } - a++, s = pcap; + a++, p = pcap; if(!spacer(*a)) while((c = *a) && !spacer(c)) a++; continue; } - if(c != *s) return 0; - a++, s++; + if(c != *p) return 0; + a++, p++; } - if((c = *s) && spacer(c)) { /* write match */ + c = *p; + if(spacer(c)) { char *b = r->b, *reg, *origin = dst_; while((c = *b++)) if(c == '?' && (reg = regs[(int)*b])) write_reg(*b++, reg); else *dst_++ = c; - if(dst_ == origin) { /* trim */ - while(*s == ' ') s++; - if(*s == ')' && *(dst_ - 1) == ' ') dst_--; + if(dst_ == origin) { + while(*p == ' ') p++; + if(*p == ')' && *(dst_ - 1) == ' ') dst_--; } - return write_rule(r, s, 0); + return write_rule(r, p, 0); } return 0; } @@ -178,13 +179,14 @@ rewrite(void) } if(c == '?' && s[1] == '(') { /* lambda */ cap = walk(s + 1); - r = &lambda, r->id = -1; + r = &rules[0], r->id = -1; r->a = dict_, s = parse_frag(s + 2); r->b = dict_, parse_frag(s), s = cap; while(*s == ' ') s++; - if(run_rule(r, s)) return 1; - } - for(r = rules; r < rules_; r++) + r = rules; + } else + r = rules + 1; + for(; r < rules_; r++) if(run_rule(r, s)) return 1; } *dst_++ = last = c; From 701d2c43a5df6dc89d1b149abdb9f24509aa5e74 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 20:13:19 -0700 Subject: [PATCH 30/81] Do not continue after lambda rewrite --- src/modal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modal.c b/src/modal.c index 21f8f6e..32836bd 100644 --- a/src/modal.c +++ b/src/modal.c @@ -183,10 +183,10 @@ rewrite(void) r->a = dict_, s = parse_frag(s + 2); r->b = dict_, parse_frag(s), s = cap; while(*s == ' ') s++; - r = rules; - } else - r = rules + 1; - for(; r < rules_; r++) + return run_rule(r, s); + } + + for(r = rules + 1; r < rules_; r++) if(run_rule(r, s)) return 1; } *dst_++ = last = c; From f7e0e74888af4c9ccee68b199eb94650265271f0 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 20:15:33 -0700 Subject: [PATCH 31/81] Moved lambda from rules[0] to its own memory --- src/modal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modal.c b/src/modal.c index 32836bd..83499a2 100644 --- a/src/modal.c +++ b/src/modal.c @@ -6,7 +6,7 @@ typedef struct { } Rule; static int flip, quiet, rmin = 0xff, rmax = 0x00, cycles = 0x10000; -static Rule rules[0x1000], *rules_ = rules + 1; +static Rule rules[0x1000], *rules_ = rules, lambda; static char dict[0x8000], *dict_ = dict; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; @@ -179,14 +179,14 @@ rewrite(void) } if(c == '?' && s[1] == '(') { /* lambda */ cap = walk(s + 1); - r = &rules[0], r->id = -1; - r->a = dict_, s = parse_frag(s + 2); - r->b = dict_, parse_frag(s), s = cap; + lambda.id = -1; + lambda.a = dict_, s = parse_frag(s + 2); + lambda.b = dict_, parse_frag(s), s = cap; while(*s == ' ') s++; - return run_rule(r, s); + return run_rule(&lambda, s); } - for(r = rules + 1; r < rules_; r++) + for(r = rules; r < rules_; r++) if(run_rule(r, s)) return 1; } *dst_++ = last = c; From b67cf12f6019524d165da88f4f007238c273111d Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 20:22:54 -0700 Subject: [PATCH 32/81] Use switch case for special registers --- src/modal.c | 64 +++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/src/modal.c b/src/modal.c index 83499a2..ef791ce 100644 --- a/src/modal.c +++ b/src/modal.c @@ -34,33 +34,8 @@ static void write_reg(char r, char *reg) { char c, *cap = walk(reg); - if(r == '*') { - int i, depth = 0; - if(*reg == '(') { /* special explode tuple */ - reg++; - while(reg < cap) { - while((c = *reg) && !spacer(c)) - *dst_++ = c, reg++; - *dst_++ = ' '; - *dst_++ = '(', reg++, depth++; - } - } else { /* special explode token */ - while((c = *reg++) && !spacer(c)) - *dst_++ = c, *dst_++ = ' ', *dst_++ = '(', depth++; - } - for(i = 0; i < depth; i++) - *dst_++ = ')'; - } else if(r == '.') { /* special unpack */ - if(*reg == '(') reg++, --cap; - while(reg < cap) *dst_++ = *reg++; - } else if(r == '^') { /* special join */ - if(*reg == '(') reg++, --cap; - while(reg < cap && (c = *reg++)) - if(!spacer(c)) *dst_++ = c; - } else if(r == '~') { /* special stdin */ - while(fread(&c, 1, 1, stdin) && c >= ' ') - *dst_++ = c; - } else if(r == ':') { /* special stdout */ + switch(r) { + case ':': /* op: output */ if(*reg == '(') reg++, --cap; while(reg < cap) { c = *reg++; @@ -73,8 +48,40 @@ write_reg(char r, char *reg) } else putc(c, stdout); } - } else + return; + case '~': /* op: input */ + while(fread(&c, 1, 1, stdin) && c >= ' ') + *dst_++ = c; + return; + case '^': /* op: join */ + if(*reg == '(') reg++, --cap; + while(reg < cap && (c = *reg++)) + if(!spacer(c)) *dst_++ = c; + return; + case '.': /* op: unwrap */ + if(*reg == '(') reg++, --cap; while(reg < cap) *dst_++ = *reg++; + return; + case '*': { /* op: explode */ + int i, depth = 0; + if(*reg == '(') { /* tuple */ + reg++; + while(reg < cap) { + while((c = *reg) && !spacer(c)) + *dst_++ = c, reg++; + *dst_++ = ' '; + *dst_++ = '(', reg++, depth++; + } + } else { /* token */ + while((c = *reg++) && !spacer(c)) + *dst_++ = c, *dst_++ = ' ', *dst_++ = '(', depth++; + } + for(i = 0; i < depth; i++) *dst_++ = ')'; + return; + } + default: + while(reg < cap) *dst_++ = *reg++; + } } static int @@ -185,7 +192,6 @@ rewrite(void) while(*s == ' ') s++; return run_rule(&lambda, s); } - for(r = rules; r < rules_; r++) if(run_rule(r, s)) return 1; } From 91150500ddc9df757fdf0a8ce8b81939a2ad3deb Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 20:32:42 -0700 Subject: [PATCH 33/81] Removed unecessary assign --- src/modal.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/modal.c b/src/modal.c index ef791ce..b341e5d 100644 --- a/src/modal.c +++ b/src/modal.c @@ -107,7 +107,7 @@ static int run_rule(Rule *r, char *s) { int i; - char c, *a = r->a, *p = s; + char c, *a = r->a; if(rmax) { for(i = rmin; i <= rmax; i++) regs[i] = 0; @@ -116,25 +116,25 @@ run_rule(Rule *r, char *s) while((c = *a)) { if(c == '?') { int regid = (int)*(++a); - char *pcap = walk(p), *reg = regs[regid]; + char *pcap = walk(s), *reg = regs[regid]; if(reg) { /* reg cmp */ - char *rcap = walk(reg), *pp = p; + char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; } else { /* reg set */ - regs[regid] = p; + regs[regid] = s; if(regid < rmin) rmin = regid; if(regid > rmax) rmax = regid; } - a++, p = pcap; + a++, s = pcap; if(!spacer(*a)) while((c = *a) && !spacer(c)) a++; continue; } - if(c != *p) return 0; - a++, p++; + if(c != *s) return 0; + a++, s++; } - c = *p; + c = *s; if(spacer(c)) { char *b = r->b, *reg, *origin = dst_; while((c = *b++)) @@ -143,10 +143,10 @@ run_rule(Rule *r, char *s) else *dst_++ = c; if(dst_ == origin) { - while(*p == ' ') p++; - if(*p == ')' && *(dst_ - 1) == ' ') dst_--; + while(*s == ' ') s++; + if(*s == ')' && *(dst_ - 1) == ' ') dst_--; } - return write_rule(r, p, 0); + return write_rule(r, s, 0); } return 0; } From 157d1909ea340c77827f395f9debbc108134f713 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 20:50:39 -0700 Subject: [PATCH 34/81] Added comments --- src/modal.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/modal.c b/src/modal.c index b341e5d..2a8594e 100644 --- a/src/modal.c +++ b/src/modal.c @@ -104,7 +104,7 @@ write_rule(Rule *r, char *s, int create) } static int -run_rule(Rule *r, char *s) +apply_rule(Rule *r, char *s) { int i; char c, *a = r->a; @@ -113,7 +113,7 @@ run_rule(Rule *r, char *s) regs[i] = 0; rmin = 0xff, rmax = 0x00; } - while((c = *a)) { + while((c = *a)) { /* phase: match rule */ if(c == '?') { int regid = (int)*(++a); char *pcap = walk(s), *reg = regs[regid]; @@ -134,8 +134,7 @@ run_rule(Rule *r, char *s) if(c != *s) return 0; a++, s++; } - c = *s; - if(spacer(c)) { + if(!(c = *s) || spacer(c)) { /* phase: write rule */ char *b = r->b, *reg, *origin = dst_; while((c = *b++)) if(c == '?' && (reg = regs[(int)*b])) @@ -190,10 +189,10 @@ rewrite(void) lambda.a = dict_, s = parse_frag(s + 2); lambda.b = dict_, parse_frag(s), s = cap; while(*s == ' ') s++; - return run_rule(&lambda, s); + return apply_rule(&lambda, s); } for(r = rules; r < rules_; r++) - if(run_rule(r, s)) return 1; + if(apply_rule(r, s)) return 1; } *dst_++ = last = c; s++; From 95d8bf3d8e2edf83c82c74ea8209975cc64e0cfb Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Mon, 22 Apr 2024 21:37:40 -0700 Subject: [PATCH 35/81] Special registers that are non-emitting should erase themselves --- src/modal.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/modal.c b/src/modal.c index 2a8594e..de55a6c 100644 --- a/src/modal.c +++ b/src/modal.c @@ -30,7 +30,7 @@ walk(char *s) return s; } -static void +static int write_reg(char r, char *reg) { char c, *cap = walk(reg); @@ -48,20 +48,20 @@ write_reg(char r, char *reg) } else putc(c, stdout); } - return; + return 0; case '~': /* op: input */ while(fread(&c, 1, 1, stdin) && c >= ' ') *dst_++ = c; - return; + return 1; case '^': /* op: join */ if(*reg == '(') reg++, --cap; while(reg < cap && (c = *reg++)) if(!spacer(c)) *dst_++ = c; - return; + return 1; case '.': /* op: unwrap */ if(*reg == '(') reg++, --cap; while(reg < cap) *dst_++ = *reg++; - return; + return 1; case '*': { /* op: explode */ int i, depth = 0; if(*reg == '(') { /* tuple */ @@ -77,10 +77,11 @@ write_reg(char r, char *reg) *dst_++ = c, *dst_++ = ' ', *dst_++ = '(', depth++; } for(i = 0; i < depth; i++) *dst_++ = ')'; - return; + return 1; } default: while(reg < cap) *dst_++ = *reg++; + return 1; } } @@ -137,9 +138,9 @@ apply_rule(Rule *r, char *s) if(!(c = *s) || spacer(c)) { /* phase: write rule */ char *b = r->b, *reg, *origin = dst_; while((c = *b++)) - if(c == '?' && (reg = regs[(int)*b])) - write_reg(*b++, reg); - else + if(c == '?' && (reg = regs[(int)*b])) { + if(!write_reg(*b++, reg) && dst_ != origin) dst_--; + } else *dst_++ = c; if(dst_ == origin) { while(*s == ' ') s++; From bb58d295fdacbba447a1852fb72e67604820b8ec Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 08:21:35 -0700 Subject: [PATCH 36/81] Added tests for whitespace --- examples/tests.modal | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/tests.modal b/examples/tests.modal index 77866f2..2c22a40 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -1,5 +1,12 @@ ?(?-) (This example tests various aspects of the implementation.) +?(?-) (Whitespace) + +(a b c ) = (a b c) test +( a b c) = (a b c) test +( a b c ) = (a b c) test +(a b c ( a b c ) ) = (a b c (a b c)) test + ?(?-) (Inline rules) <> ((?x -> ?y)) (<> ?x ?y) @@ -90,4 +97,4 @@ implode (12 (34 (56 ()))) 123456 test <> (reverse (?*)) (reverse List (?*) ()) <> (reverse List (?x ?y) ?z) (reverse List ?y (?x ?z)) -reverse (modal) = ladom test +reverse (modal) = ladom test \ No newline at end of file From 1ed120f569467ae4b2ea8eef8b5013b966478514 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 08:37:40 -0700 Subject: [PATCH 37/81] Added more whitespace tests --- examples/tests.modal | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/tests.modal b/examples/tests.modal index 2c22a40..67dee5a 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -1,5 +1,7 @@ ?(?-) (This example tests various aspects of the implementation.) +<> (ghost) () + ?(?-) (Whitespace) (a b c ) = (a b c) test @@ -7,6 +9,11 @@ ( a b c ) = (a b c) test (a b c ( a b c ) ) = (a b c (a b c)) test +(ab cd () ghost) = (ab cd ()) test +(ab cd ghost ()) = (ab cd ()) test +(ab ghost cd ()) = (ab cd ()) test +(ghost ab cd ()) = (ab cd ()) test + ?(?-) (Inline rules) <> ((?x -> ?y)) (<> ?x ?y) @@ -18,7 +25,6 @@ nap tap test <> (?x rightless/pop) <> (?x pop) () -<> (ghost) () <> (prefix/pop ?x) (ok) <> (?x suffix/pop) (ok) From a11178388716e1166dcf818818f285554a3e04e2 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 09:35:58 -0700 Subject: [PATCH 38/81] Fixed bug with counting parens --- src/modal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modal.c b/src/modal.c index de55a6c..bdc5464 100644 --- a/src/modal.c +++ b/src/modal.c @@ -212,7 +212,7 @@ main(int argc, char **argv) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { - case 'v': /* version */ return !printf("Modal Interpreter, 22 Apr 2024.\n"); + case 'v': /* version */ return !printf("Modal Interpreter, 23 Apr 2024.\n"); case 'q': /* quiet */ quiet = 1; break; case 'n': /* infinite */ cycles = 0xffffffff; break; } @@ -225,9 +225,9 @@ main(int argc, char **argv) if(c == ' ' && *(w - 1) == '(') continue; if(c == ')' && *(w - 1) == ' ') w--; if(c == ' ' && *(w - 1) == ' ') w--; - if(c == '(') pl++; - if(c == ')') pr++; } + if(c == '(') pl++; + if(c == ')') pr++; *w++ = c; } while(*(--w) <= ' ') *w = 0; From 083538ada8a98f3314db144d24fce465c3bd270c Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 10:29:51 -0700 Subject: [PATCH 39/81] Some tests are failing, but nothing to worry about for now --- examples/tests.modal | 46 +++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/examples/tests.modal b/examples/tests.modal index 67dee5a..bceb0cb 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -9,11 +9,6 @@ ( a b c ) = (a b c) test (a b c ( a b c ) ) = (a b c (a b c)) test -(ab cd () ghost) = (ab cd ()) test -(ab cd ghost ()) = (ab cd ()) test -(ab ghost cd ()) = (ab cd ()) test -(ghost ab cd ()) = (ab cd ()) test - ?(?-) (Inline rules) <> ((?x -> ?y)) (<> ?x ?y) @@ -23,16 +18,21 @@ nap tap test ?(?-) (Empty replacements) -<> (?x rightless/pop) -<> (?x pop) () -<> (prefix/pop ?x) (ok) -<> (?x suffix/pop) (ok) +(ab cd () ghost) = (ab cd ()) test +(ab cd ghost ()) = (ab cd ()) test +(ab ghost cd ()) = (ab cd ()) test +(ghost ab cd ()) = (ab cd ()) test +(ghost) = () test + +(q ?((?x ?y ?z) (?x ?y)) a b c) = (q a b) test +(q ?((?x ?y ?z) (?x ?z)) a b c) = (q a c) test +(q ?((?x ?y ?z) (?y ?z)) a b c) = (q b c) test + +<> (prefix/pop ?x) () +<> (?x suffix/pop) () -(abc rightless/pop) = () test (prefix/pop foo) = (ok) test (foo suffix/pop) = (ok) test -(abc def pop) = (abc) test -(ghost) = () test ?(?-) (Basic replacements) @@ -66,30 +66,20 @@ replace-empty abc = ?y test connect foo bar baz = foo-barbaz test prefix-anything = anything-suffix test -?(?-) (Guards setups) - -<> (join (String ?x) (String ?y)) ((?x ?y) =) - -join (String abc) (String def) (abc def) test - ?(?-) (Lambdas) -?((?x) ((?x ?x) =)) abc (abc abc) test +?(?x (?x ?x)) abc = (abc abc) test abc ?(?x) def = abc test ?(?-) (Explode) -<> (explode ?*) ((?*) =) +?(?* ?*) cow = (c (o (w ()))) test +?(?* ?*) (12 34 45) = (12 (34 (45 ()))) test -explode cow (c (o (w ()))) test -explode (12 34 45) (12 (34 (45 ()))) test +?(?-) (op: join) -?(?-) (Implode) - -<> (implode ?^) (?^ =) - -implode (b (a (t ()))) bat test -implode (12 (34 (56 ()))) 123456 test +?(?^ ?^) (b (a (t ()))) = bat test +?(?^ ?^) (12 (34 (56 ()))) = 123456 test ?(?-) (Test Primitives) From c7aad6e21e9932d4252326a2763a46855670811a Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 13:29:30 -0700 Subject: [PATCH 40/81] New tests --- examples/tests.modal | 96 ++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 52 deletions(-) diff --git a/examples/tests.modal b/examples/tests.modal index bceb0cb..822a8dc 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -1,44 +1,35 @@ ?(?-) (This example tests various aspects of the implementation.) +?(?-) (Early Test Primitives) + +<> (?x = ?x ?n test) (?(?: ?:) (#pass ?n\n)) + <> (ghost) () ?(?-) (Whitespace) -(a b c ) = (a b c) test -( a b c) = (a b c) test -( a b c ) = (a b c) test -(a b c ( a b c ) ) = (a b c (a b c)) test - -?(?-) (Inline rules) - -<> ((?x -> ?y)) (<> ?x ?y) -(nap -> (tap =)) - -nap tap test +(a b c ) = (a b c) (whitespace 1) test +( a b c) = (a b c) (whitespace 2) test +( a b c ) = (a b c) (whitespace 3) test +(a b c ( a b c ) ) = (a b c (a b c)) (whitespace 4) test ?(?-) (Empty replacements) -(ab cd () ghost) = (ab cd ()) test -(ab cd ghost ()) = (ab cd ()) test -(ab ghost cd ()) = (ab cd ()) test -(ghost ab cd ()) = (ab cd ()) test -(ghost) = () test +(ab cd () ghost) = (ab cd ()) (empty 1) test +(ab cd ghost ()) = (ab cd ()) (empty 2) test +(ab ghost cd ()) = (ab cd ()) (empty 3) test +(ghost ab cd ()) = (ab cd ()) (empty 4) test +(ghost) = () (empty 5) test -(q ?((?x ?y ?z) (?x ?y)) a b c) = (q a b) test -(q ?((?x ?y ?z) (?x ?z)) a b c) = (q a c) test -(q ?((?x ?y ?z) (?y ?z)) a b c) = (q b c) test +(q ?((?x ?y ?z) (?x ?y)) a b c) = (q a b) (empty 6) test +(q ?((?x ?y ?z) (?x ?z)) a b c) = (q a c) (empty 7) test +(q ?((?x ?y ?z) (?y ?z)) a b c) = (q b c) (empty 8) test <> (prefix/pop ?x) () <> (?x suffix/pop) () -(prefix/pop foo) = (ok) test -(foo suffix/pop) = (ok) test - -?(?-) (Basic replacements) - -<> (replace-name (foo)) ((bar) =) - -replace-name (foo) (bar) test +(ab prefix/pop cd ef) = (ab ef) (empty 9) test +(ab cd suffix/pop ef) = (ab ef) (empty 10) test ?(?-) (Basic register setups) @@ -46,46 +37,36 @@ replace-name (foo) (bar) test <> (swap (?x ?y)) (?y ?x) <> (compare (?x ?x ?x)) (#t) <> (rotate (?x (?y (?z)))) (?y (?z (?x))) +<> (unused ?x) ?y -(dup (abc)) = (abc abc) test -(swap (abc def)) = (def abc) test -compare (abc abc abc) = #t test -(rotate (abc (def (ghi)))) = (def (ghi (abc))) test - -?(?-) (Empty register replacement) - -<> (replace-empty ?x) (?y) - -replace-empty abc = ?y test +(dup (abc)) = (abc abc) (basic 1) test +(swap (abc def)) = (def abc) (basic 2) test +(compare (abc abc abc)) = (#t) (basic 3) test +(rotate (abc (def (ghi)))) = (def (ghi (abc))) (basic 4) test +(unused hey) = (?y) (basic 5) test ?(?-) (Substring registers) <> (connect ?x ?y ?z) (?x-?y?z) <> (prefix-?x) (?x-suffix) -connect foo bar baz = foo-barbaz test -prefix-anything = anything-suffix test +connect foo bar baz = foo-barbaz (substring 1) test +prefix-anything = anything-suffix (substring 2) test ?(?-) (Lambdas) -?(?x (?x ?x)) abc = (abc abc) test -abc ?(?x) def = abc test +(?(?x (?x ?x)) abc) = (abc abc) (lambda 1) test +abc ?(?x) def = abc (lambda 2) test ?(?-) (Explode) -?(?* ?*) cow = (c (o (w ()))) test -?(?* ?*) (12 34 45) = (12 (34 (45 ()))) test +(?(?* ?*) cow) = (c (o (w ()))) (explode 1) test +(?(?* ?*) (12 34 45)) = (12 (34 (45 ()))) (explode 2) test ?(?-) (op: join) -?(?^ ?^) (b (a (t ()))) = bat test -?(?^ ?^) (12 (34 (56 ()))) = 123456 test - -?(?-) (Test Primitives) - -<> (?: print) (?:) -<> (?x = ?x test) (#ok\n print) -<> (?x = ?y test) (#fail\n print) +?(?^ ?^) (b (a (t ()))) = bat (join 1) test +?(?^ ?^) (12 (34 (56 ()))) = 123456 (join 2) test ?(?-) (List reversal) @@ -93,4 +74,15 @@ abc ?(?x) def = abc test <> (reverse (?*)) (reverse List (?*) ()) <> (reverse List (?x ?y) ?z) (reverse List ?y (?x ?z)) -reverse (modal) = ladom test \ No newline at end of file +reverse (modal) = ladom (reverse 1) test + +?(?-) (Inline rules) + +<> ((?x -> ?y)) (<> ?x ?y) +(nap -> (tap =)) + +nap tap (inline 1) test + +?(?-) (Late Test Primitives) + +<> (?x = ?y ?n test) (?(?: ?:) (#fail ?n found: ?x expect: ?y\n)) \ No newline at end of file From 14ce4eb176b05179dbfd467f754df88f8f3fb8cc Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 13:45:03 -0700 Subject: [PATCH 41/81] Added tests --- examples/tests.modal | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/tests.modal b/examples/tests.modal index 822a8dc..8a47786 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -58,15 +58,22 @@ prefix-anything = anything-suffix (substring 2) test (?(?x (?x ?x)) abc) = (abc abc) (lambda 1) test abc ?(?x) def = abc (lambda 2) test -?(?-) (Explode) +?(?-) (op: explode) -(?(?* ?*) cow) = (c (o (w ()))) (explode 1) test -(?(?* ?*) (12 34 45)) = (12 (34 (45 ()))) (explode 2) test +(?(?* ?*) cow) = (c (o (w ()))) (explode word) test +(?(?* ?*) (12 34 45)) = (12 (34 (45 ()))) (explode tuple) test +(?(?* ?*) ()) = () (explode empty) test ?(?-) (op: join) ?(?^ ?^) (b (a (t ()))) = bat (join 1) test ?(?^ ?^) (12 (34 (56 ()))) = 123456 (join 2) test +(?(?^ ?^) ()) = () (join empty) test + +?(?-) (op: unwrap) + +?(?. ?.) (abcd) = abcd (unwrap 1) test +(?(?. ?.) ()) = () (unwrap empty) test ?(?-) (List reversal) From 3c85bbd3b8310924963426a2133112bbc706b363 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 13:51:25 -0700 Subject: [PATCH 42/81] Exploding empty list -> identity --- src/modal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modal.c b/src/modal.c index bdc5464..e8efb35 100644 --- a/src/modal.c +++ b/src/modal.c @@ -64,7 +64,7 @@ write_reg(char r, char *reg) return 1; case '*': { /* op: explode */ int i, depth = 0; - if(*reg == '(') { /* tuple */ + if(*reg == '(' && reg[1] != ')') { /* tuple */ reg++; while(reg < cap) { while((c = *reg) && !spacer(c)) From f18adb503d03b14ce7d752029d3d8f0970a7511a Mon Sep 17 00:00:00 2001 From: Sebastian LaVine Date: Tue, 23 Apr 2024 17:07:28 -0400 Subject: [PATCH 43/81] Replace io_repl.modal with an actual Modal REPL --- examples/io_repl.modal | 11 ----------- examples/repl.modal | 9 +++++++++ 2 files changed, 9 insertions(+), 11 deletions(-) delete mode 100644 examples/io_repl.modal create mode 100644 examples/repl.modal diff --git a/examples/io_repl.modal b/examples/io_repl.modal deleted file mode 100644 index 5e96b63..0000000 --- a/examples/io_repl.modal +++ /dev/null @@ -1,11 +0,0 @@ -?(?-) (This example demonstrates how to keep the runtime active between prompts.) - -<> ((You said: quit\n) send) ((You quit.) print ') -<> (?: print ') (?:) -<> (?: send) (?: wait stdin) -<> (wait ?~) ((You said: ?~\n) send) -<> (' ?x) (?x ') - -(Say something, or type "quit": \n) print ' - -wait stdin \ No newline at end of file diff --git a/examples/repl.modal b/examples/repl.modal new file mode 100644 index 0000000..dac6c3b --- /dev/null +++ b/examples/repl.modal @@ -0,0 +1,9 @@ +?(?-) (This is a fully functional Modal REPL.) + +<> (quit wait stdin) ((You quit.\n) print) +<> (?: print) (?:) +<> (wait ?~) (?~ wait stdin) + +(Say something, or type "quit":\n) print + +wait stdin From 8bb661ced0180c317f86138c6b64dd1c1a6a0c2e Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 19:36:49 -0700 Subject: [PATCH 44/81] Converted regs array to stack --- src/modal.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/modal.c b/src/modal.c index e8efb35..af322ae 100644 --- a/src/modal.c +++ b/src/modal.c @@ -5,14 +5,18 @@ typedef struct { char *a, *b; } Rule; -static int flip, quiet, rmin = 0xff, rmax = 0x00, cycles = 0x10000; +static int flip, quiet, cycles = 0x10000; static Rule rules[0x1000], *rules_ = rules, lambda; static char dict[0x8000], *dict_ = dict; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; -static char *regs[0x100]; + +/* clang-format off */ #define spacer(c) (c <= ' ' || c == '(' || c == ')') +#define get_reg(x) { regid = x; for(i = 0; i < regs_ptr; i++) if(regs_key[i] == regid) { reg = regs_val[i]; break; } } + +/* clang-format on */ static char * walk(char *s) @@ -107,26 +111,18 @@ write_rule(Rule *r, char *s, int create) static int apply_rule(Rule *r, char *s) { - int i; - char c, *a = r->a; - if(rmax) { - for(i = rmin; i <= rmax; i++) - regs[i] = 0; - rmin = 0xff, rmax = 0x00; - } + int i, regid, regs_ptr = 0; + char c, *a = r->a, regs_key[0x10], *regs_val[0x10]; while((c = *a)) { /* phase: match rule */ if(c == '?') { - int regid = (int)*(++a); - char *pcap = walk(s), *reg = regs[regid]; + char *pcap = walk(s), *reg = NULL; + get_reg(*(++a)); if(reg) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; - } else { /* reg set */ - regs[regid] = s; - if(regid < rmin) rmin = regid; - if(regid > rmax) rmax = regid; - } + } else /* reg set */ + regs_key[regs_ptr] = regid, regs_val[regs_ptr++] = s; a++, s = pcap; if(!spacer(*a)) while((c = *a) && !spacer(c)) a++; @@ -136,12 +132,18 @@ apply_rule(Rule *r, char *s) a++, s++; } if(!(c = *s) || spacer(c)) { /* phase: write rule */ - char *b = r->b, *reg, *origin = dst_; - while((c = *b++)) - if(c == '?' && (reg = regs[(int)*b])) { - if(!write_reg(*b++, reg) && dst_ != origin) dst_--; + char *b = r->b, *origin = dst_; + while((c = *b++)) { + if(c == '?') { + char *reg = NULL; + get_reg(*b); + if(reg) { + if(!write_reg(*b++, reg) && dst_ != origin) dst_--; + } else + *dst_++ = c; } else *dst_++ = c; + } if(dst_ == origin) { while(*s == ' ') s++; if(*s == ')' && *(dst_ - 1) == ' ') dst_--; From c73b9f0ad7cd61b673929c5ef1cacdc62092d1d6 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 23 Apr 2024 20:20:31 -0700 Subject: [PATCH 45/81] Housekeeping --- src/modal.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/modal.c b/src/modal.c index af322ae..a4b3001 100644 --- a/src/modal.c +++ b/src/modal.c @@ -14,7 +14,7 @@ static char bank_b[0x4000], *dst_ = bank_b; /* clang-format off */ #define spacer(c) (c <= ' ' || c == '(' || c == ')') -#define get_reg(x) { regid = x; for(i = 0; i < regs_ptr; i++) if(regs_key[i] == regid) { reg = regs_val[i]; break; } } +#define get_reg(x) { regid = x; for(i = 0; i < rptr; i++) if(rkey[i] == regid) { reg = rval[i]; break; } } /* clang-format on */ @@ -76,10 +76,9 @@ write_reg(char r, char *reg) *dst_++ = ' '; *dst_++ = '(', reg++, depth++; } - } else { /* token */ + } else /* token */ while((c = *reg++) && !spacer(c)) *dst_++ = c, *dst_++ = ' ', *dst_++ = '(', depth++; - } for(i = 0; i < depth; i++) *dst_++ = ')'; return 1; } @@ -111,8 +110,8 @@ write_rule(Rule *r, char *s, int create) static int apply_rule(Rule *r, char *s) { - int i, regid, regs_ptr = 0; - char c, *a = r->a, regs_key[0x10], *regs_val[0x10]; + int i, regid, rptr = 0; + char c, *a = r->a, rkey[0x10], *rval[0x10]; while((c = *a)) { /* phase: match rule */ if(c == '?') { char *pcap = walk(s), *reg = NULL; @@ -122,7 +121,7 @@ apply_rule(Rule *r, char *s) while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; } else /* reg set */ - regs_key[regs_ptr] = regid, regs_val[regs_ptr++] = s; + rkey[rptr] = regid, rval[rptr++] = s; a++, s = pcap; if(!spacer(*a)) while((c = *a) && !spacer(c)) a++; @@ -187,8 +186,7 @@ rewrite(void) return write_rule(r, s, 1); } if(c == '?' && s[1] == '(') { /* lambda */ - cap = walk(s + 1); - lambda.id = -1; + cap = walk(s + 1), lambda.id = -1; lambda.a = dict_, s = parse_frag(s + 2); lambda.b = dict_, parse_frag(s), s = cap; while(*s == ' ') s++; From b866c6977680b5dd0424eadef7bedebf7ebd3909 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 10:31:46 -0700 Subject: [PATCH 46/81] Compile rules --- src/modal.c | 70 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/modal.c b/src/modal.c index a4b3001..0a6ba31 100644 --- a/src/modal.c +++ b/src/modal.c @@ -1,8 +1,8 @@ #include typedef struct { - int id, refs; - char *a, *b; + unsigned int id, refs, ptr; + char *a, *b, key[0x10]; } Rule; static int flip, quiet, cycles = 0x10000; @@ -11,12 +11,7 @@ static char dict[0x8000], *dict_ = dict; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; -/* clang-format off */ - #define spacer(c) (c <= ' ' || c == '(' || c == ')') -#define get_reg(x) { regid = x; for(i = 0; i < rptr; i++) if(rkey[i] == regid) { reg = rval[i]; break; } } - -/* clang-format on */ static char * walk(char *s) @@ -110,18 +105,22 @@ write_rule(Rule *r, char *s, int create) static int apply_rule(Rule *r, char *s) { - int i, regid, rptr = 0; - char c, *a = r->a, rkey[0x10], *rval[0x10]; + char c, *a = r->a, *regs[0x10] = {NULL}; while((c = *a)) { /* phase: match rule */ if(c == '?') { char *pcap = walk(s), *reg = NULL; - get_reg(*(++a)); + int id = *(++a); + unsigned int id2 = id - '0'; + if(id2 < r->ptr) { + reg = regs[id2]; + } if(reg) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; - } else /* reg set */ - rkey[rptr] = regid, rval[rptr++] = s; + } else { /* reg set */ + regs[id2] = s; + } a++, s = pcap; if(!spacer(*a)) while((c = *a) && !spacer(c)) a++; @@ -135,9 +134,14 @@ apply_rule(Rule *r, char *s) while((c = *b++)) { if(c == '?') { char *reg = NULL; - get_reg(*b); + int id = *b; + unsigned int id2 = id - '0'; + if(id2 < r->ptr) { + reg = regs[id2]; + } if(reg) { - if(!write_reg(*b++, reg) && dst_ != origin) dst_--; + b++; + if(!write_reg(r->key[id2], reg) && dst_ != origin) dst_--; } else *dst_++ = c; } else @@ -170,6 +174,38 @@ parse_frag(char *s) return s; } +static void +compile_rule(Rule *r) +{ + int i; + char c, *s; + r->ptr = 0; + s = r->a; + while((c = *s++)) { /* left */ + if(c == '?') { + int reg = -1; + for(i = 0; i < (int)r->ptr; i++) + if(r->key[i] == *s) { + reg = i; + break; + } + if(reg < 0 && *s != '(') + r->key[r->ptr] = *s, reg = r->ptr++; + *s = '0' + reg; + } + } + s = r->b; + while((c = *s++)) { /* right */ + if(c == '?') { + for(i = 0; i < (int)r->ptr; i++) + if(r->key[i] == *s) { + *s = '0' + i; + break; + } + } + } +} + static int rewrite(void) { @@ -177,11 +213,12 @@ rewrite(void) while(*s == ' ') s++; while((c = *s)) { if(spacer(last)) { - Rule *r; + Rule *r = NULL; if(c == '<' && s[1] == '>') { /* rule */ r = rules_++, r->id = rules_ - rules - 1; r->a = dict_, s = parse_frag(s + 2); r->b = dict_, s = parse_frag(s); + compile_rule(r); while(*s == ' ') s++; return write_rule(r, s, 1); } @@ -189,6 +226,7 @@ rewrite(void) cap = walk(s + 1), lambda.id = -1; lambda.a = dict_, s = parse_frag(s + 2); lambda.b = dict_, parse_frag(s), s = cap; + compile_rule(&lambda); while(*s == ' ') s++; return apply_rule(&lambda, s); } @@ -212,7 +250,7 @@ main(int argc, char **argv) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { - case 'v': /* version */ return !printf("Modal Interpreter, 23 Apr 2024.\n"); + case 'v': /* version */ return !printf("Modal Interpreter, 24 Apr 2024.\n"); case 'q': /* quiet */ quiet = 1; break; case 'n': /* infinite */ cycles = 0xffffffff; break; } From c63021cf0318d8f952dc5da17d4868bf57cef5a0 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 10:39:14 -0700 Subject: [PATCH 47/81] Houeskeeping --- makefile | 2 +- src/modal.c | 21 +++++++-------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/makefile b/makefile index cf49fed..5fc6c66 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,7 @@ all: dest dest: @ mkdir -p bin run: all bin/modal - @ bin/modal -q examples/hello.modal + @ bin/modal examples/hello.modal debug: all bin/modal-debug @ bin/modal-debug examples/hello.modal test: all bin/modal-debug bin/modal diff --git a/src/modal.c b/src/modal.c index 0a6ba31..3730ac4 100644 --- a/src/modal.c +++ b/src/modal.c @@ -109,18 +109,14 @@ apply_rule(Rule *r, char *s) while((c = *a)) { /* phase: match rule */ if(c == '?') { char *pcap = walk(s), *reg = NULL; - int id = *(++a); - unsigned int id2 = id - '0'; - if(id2 < r->ptr) { - reg = regs[id2]; - } + unsigned int id = *(++a) - '0'; + if(id < r->ptr) reg = regs[id]; if(reg) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; - } else { /* reg set */ - regs[id2] = s; - } + } else /* reg set */ + regs[id] = s; a++, s = pcap; if(!spacer(*a)) while((c = *a) && !spacer(c)) a++; @@ -134,14 +130,11 @@ apply_rule(Rule *r, char *s) while((c = *b++)) { if(c == '?') { char *reg = NULL; - int id = *b; - unsigned int id2 = id - '0'; - if(id2 < r->ptr) { - reg = regs[id2]; - } + unsigned int id = *b - '0'; + if(id < r->ptr) reg = regs[id]; if(reg) { b++; - if(!write_reg(r->key[id2], reg) && dst_ != origin) dst_--; + if(!write_reg(r->key[id], reg) && dst_ != origin) dst_--; } else *dst_++ = c; } else From 4535c11017a9d841383c370b5ebe950588bd8c34 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 11:12:57 -0700 Subject: [PATCH 48/81] Limit matches queries --- makefile | 2 +- src/modal.c | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/makefile b/makefile index 5fc6c66..cf49fed 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,7 @@ all: dest dest: @ mkdir -p bin run: all bin/modal - @ bin/modal examples/hello.modal + @ bin/modal -q examples/hello.modal debug: all bin/modal-debug @ bin/modal-debug examples/hello.modal test: all bin/modal-debug bin/modal diff --git a/src/modal.c b/src/modal.c index 3730ac4..8a1744a 100644 --- a/src/modal.c +++ b/src/modal.c @@ -105,13 +105,13 @@ write_rule(Rule *r, char *s, int create) static int apply_rule(Rule *r, char *s) { - char c, *a = r->a, *regs[0x10] = {NULL}; - while((c = *a)) { /* phase: match rule */ + char c, *a = r->a, *regs[0x08] = {NULL}; + /* phase: match rule */ + while((c = *a)) { if(c == '?') { char *pcap = walk(s), *reg = NULL; unsigned int id = *(++a) - '0'; - if(id < r->ptr) reg = regs[id]; - if(reg) { /* reg cmp */ + if((reg = regs[id])) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; @@ -125,7 +125,8 @@ apply_rule(Rule *r, char *s) if(c != *s) return 0; a++, s++; } - if(!(c = *s) || spacer(c)) { /* phase: write rule */ + /* phase: write rule */ + if(!(c = *s) || spacer(c)) { char *b = r->b, *origin = dst_; while((c = *b++)) { if(c == '?') { From 3136ae834fe67ffa8dcb6421ec1fba6acece3b32 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 11:18:06 -0700 Subject: [PATCH 49/81] Walk over incompiled registers --- src/modal.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/modal.c b/src/modal.c index 8a1744a..8296df0 100644 --- a/src/modal.c +++ b/src/modal.c @@ -105,11 +105,11 @@ write_rule(Rule *r, char *s, int create) static int apply_rule(Rule *r, char *s) { - char c, *a = r->a, *regs[0x08] = {NULL}; + char c, *a = r->a, *regs[0x08] = {NULL}, *reg; /* phase: match rule */ while((c = *a)) { if(c == '?') { - char *pcap = walk(s), *reg = NULL; + char *pcap = walk(s); unsigned int id = *(++a) - '0'; if((reg = regs[id])) { /* reg cmp */ char *rcap = walk(reg), *pp = s; @@ -129,11 +129,9 @@ apply_rule(Rule *r, char *s) if(!(c = *s) || spacer(c)) { char *b = r->b, *origin = dst_; while((c = *b++)) { - if(c == '?') { - char *reg = NULL; + if(c == '?' && (unsigned int)(*b - '0') < 9) { unsigned int id = *b - '0'; - if(id < r->ptr) reg = regs[id]; - if(reg) { + if((reg = regs[id])) { b++; if(!write_reg(r->key[id], reg) && dst_ != origin) dst_--; } else From 986a1b47dde9882e9319e6341fbb827611318ca9 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 11:20:34 -0700 Subject: [PATCH 50/81] Only get reg id once --- makefile | 2 ++ src/modal.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index cf49fed..24e2457 100644 --- a/makefile +++ b/makefile @@ -13,6 +13,8 @@ debug: all bin/modal-debug @ bin/modal-debug examples/hello.modal test: all bin/modal-debug bin/modal @ bin/modal -v + @ bin/modal-debug -q examples/fizzbuzz.modal + @ bin/modal-debug -q examples/sierpinski.modal @ bin/modal-debug -q examples/tests.modal install: bin/modal cp bin/modal ~/bin/ diff --git a/src/modal.c b/src/modal.c index 8296df0..de10d82 100644 --- a/src/modal.c +++ b/src/modal.c @@ -129,9 +129,9 @@ apply_rule(Rule *r, char *s) if(!(c = *s) || spacer(c)) { char *b = r->b, *origin = dst_; while((c = *b++)) { - if(c == '?' && (unsigned int)(*b - '0') < 9) { + if(c == '?') { unsigned int id = *b - '0'; - if((reg = regs[id])) { + if(id < 9 && (reg = regs[id])) { b++; if(!write_reg(r->key[id], reg) && dst_ != origin) dst_--; } else From 76fe5830bed534d446962fa983e56b65e21265f7 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 13:35:12 -0700 Subject: [PATCH 51/81] Abstracted reg lookup --- src/modal.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/modal.c b/src/modal.c index de10d82..571d8ec 100644 --- a/src/modal.c +++ b/src/modal.c @@ -166,6 +166,16 @@ parse_frag(char *s) return s; } +static int +find_register(Rule *r, char reg) +{ + int i; + for(i = 0; i < (int)r->ptr; i++) + if(r->key[i] == reg) + return i; + return -1; +} + static void compile_rule(Rule *r) { @@ -175,12 +185,7 @@ compile_rule(Rule *r) s = r->a; while((c = *s++)) { /* left */ if(c == '?') { - int reg = -1; - for(i = 0; i < (int)r->ptr; i++) - if(r->key[i] == *s) { - reg = i; - break; - } + int reg = find_register(r, *s); if(reg < 0 && *s != '(') r->key[r->ptr] = *s, reg = r->ptr++; *s = '0' + reg; @@ -189,11 +194,9 @@ compile_rule(Rule *r) s = r->b; while((c = *s++)) { /* right */ if(c == '?') { - for(i = 0; i < (int)r->ptr; i++) - if(r->key[i] == *s) { - *s = '0' + i; - break; - } + int reg = find_register(r, *s); + if(reg >= 0) + *s = '0' + reg; } } } From 23ec4856e0c281eb1faed29597e163506c75d312 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 13:41:09 -0700 Subject: [PATCH 52/81] Road to merging frag parsing and rule compilation --- src/modal.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/modal.c b/src/modal.c index 571d8ec..32c3843 100644 --- a/src/modal.c +++ b/src/modal.c @@ -176,11 +176,13 @@ find_register(Rule *r, char reg) return -1; } -static void -compile_rule(Rule *r) +static char * +compile_rule(Rule *r, char *src) { int i; char c, *s; + r->a = dict_, src = parse_frag(src); + r->b = dict_, src = parse_frag(src); r->ptr = 0; s = r->a; while((c = *s++)) { /* left */ @@ -199,6 +201,7 @@ compile_rule(Rule *r) *s = '0' + reg; } } + return src; } static int @@ -211,17 +214,15 @@ rewrite(void) Rule *r = NULL; if(c == '<' && s[1] == '>') { /* rule */ r = rules_++, r->id = rules_ - rules - 1; - r->a = dict_, s = parse_frag(s + 2); - r->b = dict_, s = parse_frag(s); - compile_rule(r); + s = compile_rule(r, s + 2); while(*s == ' ') s++; return write_rule(r, s, 1); } if(c == '?' && s[1] == '(') { /* lambda */ - cap = walk(s + 1), lambda.id = -1; - lambda.a = dict_, s = parse_frag(s + 2); - lambda.b = dict_, parse_frag(s), s = cap; - compile_rule(&lambda); + cap = walk(s + 1); + r = &lambda, r->id = -1; + compile_rule(r, s + 2); + s = cap; while(*s == ' ') s++; return apply_rule(&lambda, s); } From bcbfe0278376920259984e814f2ffe7b069aa3f7 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 13:45:08 -0700 Subject: [PATCH 53/81] Progress in merging parsers --- src/modal.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/modal.c b/src/modal.c index 32c3843..740cd9a 100644 --- a/src/modal.c +++ b/src/modal.c @@ -177,13 +177,11 @@ find_register(Rule *r, char reg) } static char * -compile_rule(Rule *r, char *src) +compile_rule(Rule *r, int id, char *src) { - int i; char c, *s; + r->id = id, r->ptr = 0; r->a = dict_, src = parse_frag(src); - r->b = dict_, src = parse_frag(src); - r->ptr = 0; s = r->a; while((c = *s++)) { /* left */ if(c == '?') { @@ -193,6 +191,7 @@ compile_rule(Rule *r, char *src) *s = '0' + reg; } } + r->b = dict_, src = parse_frag(src); s = r->b; while((c = *s++)) { /* right */ if(c == '?') { @@ -213,15 +212,15 @@ rewrite(void) if(spacer(last)) { Rule *r = NULL; if(c == '<' && s[1] == '>') { /* rule */ - r = rules_++, r->id = rules_ - rules - 1; - s = compile_rule(r, s + 2); + r = rules_++; + s = compile_rule(r,rules_ - rules - 1, s + 2); while(*s == ' ') s++; return write_rule(r, s, 1); } if(c == '?' && s[1] == '(') { /* lambda */ cap = walk(s + 1); - r = &lambda, r->id = -1; - compile_rule(r, s + 2); + r = λ + compile_rule(r, -1, s + 2); s = cap; while(*s == ' ') s++; return apply_rule(&lambda, s); From 9d4d20e5423adf7da9e9eaefaa44250a16086c1c Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 13:49:21 -0700 Subject: [PATCH 54/81] Housekeeping --- src/modal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/modal.c b/src/modal.c index 740cd9a..d6546bd 100644 --- a/src/modal.c +++ b/src/modal.c @@ -213,14 +213,13 @@ rewrite(void) Rule *r = NULL; if(c == '<' && s[1] == '>') { /* rule */ r = rules_++; - s = compile_rule(r,rules_ - rules - 1, s + 2); + s = compile_rule(r, rules_ - rules - 1, s + 2); while(*s == ' ') s++; return write_rule(r, s, 1); } if(c == '?' && s[1] == '(') { /* lambda */ cap = walk(s + 1); - r = λ - compile_rule(r, -1, s + 2); + compile_rule(&lambda, -1, s + 2); s = cap; while(*s == ' ') s++; return apply_rule(&lambda, s); From 53ef87a4b9472d042651c8b7fd494e38d9dd971c Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 14:03:14 -0700 Subject: [PATCH 55/81] Inlined parse_frag --- src/modal.c | 56 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/src/modal.c b/src/modal.c index d6546bd..6f317a5 100644 --- a/src/modal.c +++ b/src/modal.c @@ -148,24 +148,6 @@ apply_rule(Rule *r, char *s) return 0; } -static char * -parse_frag(char *s) -{ - char c, *cap; - while((c = *s) && c == ' ') s++; - if(c != ')' && !(c == '<' && s[1] == '>')) { - cap = walk(s); - if(c == '(') { - s++; - while(s < cap - 1) *dict_++ = *s++; - s++; - } else - while(s < cap) *dict_++ = *s++; - } - *dict_++ = 0; - return s; -} - static int find_register(Rule *r, char reg) { @@ -179,9 +161,25 @@ find_register(Rule *r, char reg) static char * compile_rule(Rule *r, int id, char *src) { - char c, *s; + char c, *cap, *s, *s2; r->id = id, r->ptr = 0; - r->a = dict_, src = parse_frag(src); + + /* left */ + r->a = dict_; + s2 = src; + while((c = *s2) && c == ' ') s2++; + if(c != ')' && !(c == '<' && s2[1] == '>')) { + cap = walk(s2); + if(c == '(') { + s2++; + while(s2 < cap - 1) *dict_++ = *s2++; + s2++; + } else + while(s2 < cap) *dict_++ = *s2++; + } + *dict_++ = 0; + src = s2; + s = r->a; while((c = *s++)) { /* left */ if(c == '?') { @@ -191,7 +189,23 @@ compile_rule(Rule *r, int id, char *src) *s = '0' + reg; } } - r->b = dict_, src = parse_frag(src); + + /* right */ + r->b = dict_; + s2 = src; + while((c = *s2) && c == ' ') s2++; + if(c != ')' && !(c == '<' && s2[1] == '>')) { + cap = walk(s2); + if(c == '(') { + s2++; + while(s2 < cap - 1) *dict_++ = *s2++; + s2++; + } else + while(s2 < cap) *dict_++ = *s2++; + } + *dict_++ = 0; + src = s2; + s = r->b; while((c = *s++)) { /* right */ if(c == '?') { From 97d406c3a8ee44dba7a7da95ceb6e931607cc7ac Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 14:22:23 -0700 Subject: [PATCH 56/81] Progress on rules compilation --- src/modal.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/modal.c b/src/modal.c index 6f317a5..eace724 100644 --- a/src/modal.c +++ b/src/modal.c @@ -161,21 +161,21 @@ find_register(Rule *r, char reg) static char * compile_rule(Rule *r, int id, char *src) { + int wrapped; char c, *cap, *s, *s2; r->id = id, r->ptr = 0; - /* left */ + /* left ==================================== */ + r->a = dict_; s2 = src; while((c = *s2) && c == ' ') s2++; if(c != ')' && !(c == '<' && s2[1] == '>')) { cap = walk(s2); - if(c == '(') { - s2++; - while(s2 < cap - 1) *dict_++ = *s2++; - s2++; - } else - while(s2 < cap) *dict_++ = *s2++; + wrapped = c == '('; + if(wrapped) s2++, cap--; + while(s2 < cap) *dict_++ = *s2++; + s2 += wrapped; } *dict_++ = 0; src = s2; @@ -190,18 +190,17 @@ compile_rule(Rule *r, int id, char *src) } } - /* right */ + /* right ==================================== */ + r->b = dict_; s2 = src; while((c = *s2) && c == ' ') s2++; if(c != ')' && !(c == '<' && s2[1] == '>')) { cap = walk(s2); - if(c == '(') { - s2++; - while(s2 < cap - 1) *dict_++ = *s2++; - s2++; - } else - while(s2 < cap) *dict_++ = *s2++; + wrapped = c == '('; + if(wrapped) s2++, cap--; + while(s2 < cap) *dict_++ = *s2++; + s2 += wrapped; } *dict_++ = 0; src = s2; From dfe9b076dcbe2d16cc11db6071f1c528db9ee274 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 14:31:17 -0700 Subject: [PATCH 57/81] Merged rule compilation for left side --- src/modal.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/modal.c b/src/modal.c index eace724..735e27a 100644 --- a/src/modal.c +++ b/src/modal.c @@ -161,7 +161,7 @@ find_register(Rule *r, char reg) static char * compile_rule(Rule *r, int id, char *src) { - int wrapped; + int wrapped, reg; char c, *cap, *s, *s2; r->id = id, r->ptr = 0; @@ -174,22 +174,21 @@ compile_rule(Rule *r, int id, char *src) cap = walk(s2); wrapped = c == '('; if(wrapped) s2++, cap--; - while(s2 < cap) *dict_++ = *s2++; + while(s2 < cap) { + if(*s2 == '?') { + *dict_++ = *s2++; + reg = find_register(r, *s2); + if(reg < 0 && *s2 != '(') + r->key[r->ptr] = *s2, reg = r->ptr++; + *dict_++ = '0' + reg; + } else + *dict_++ = *s2++; + } s2 += wrapped; } *dict_++ = 0; src = s2; - s = r->a; - while((c = *s++)) { /* left */ - if(c == '?') { - int reg = find_register(r, *s); - if(reg < 0 && *s != '(') - r->key[r->ptr] = *s, reg = r->ptr++; - *s = '0' + reg; - } - } - /* right ==================================== */ r->b = dict_; @@ -208,7 +207,7 @@ compile_rule(Rule *r, int id, char *src) s = r->b; while((c = *s++)) { /* right */ if(c == '?') { - int reg = find_register(r, *s); + reg = find_register(r, *s); if(reg >= 0) *s = '0' + reg; } From 3dbb23319ed01b82c6b805112f5647c4523d7d80 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 14:54:40 -0700 Subject: [PATCH 58/81] Break out of compilation early --- src/modal.c | 65 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/src/modal.c b/src/modal.c index 735e27a..6d962e7 100644 --- a/src/modal.c +++ b/src/modal.c @@ -162,30 +162,36 @@ static char * compile_rule(Rule *r, int id, char *src) { int wrapped, reg; - char c, *cap, *s, *s2; + char c, *cap, *s2; r->id = id, r->ptr = 0; /* left ==================================== */ r->a = dict_; s2 = src; + while((c = *s2) && c == ' ') s2++; - if(c != ')' && !(c == '<' && s2[1] == '>')) { - cap = walk(s2); - wrapped = c == '('; - if(wrapped) s2++, cap--; - while(s2 < cap) { - if(*s2 == '?') { - *dict_++ = *s2++; - reg = find_register(r, *s2); - if(reg < 0 && *s2 != '(') - r->key[r->ptr] = *s2, reg = r->ptr++; - *dict_++ = '0' + reg; - } else - *dict_++ = *s2++; - } - s2 += wrapped; + if(c == ')' || (c == '<' && s2[1] == '>')) { + r->b = dict_; + *dict_++ = 0; + return s2; } + + cap = walk(s2); + wrapped = c == '('; + if(wrapped) s2++, cap--; + while(s2 < cap) { + if(*s2 == '?') { + *dict_++ = *s2++; + reg = find_register(r, *s2); + if(reg < 0 && *s2 != '(') + r->key[r->ptr] = *s2, reg = r->ptr++; + *dict_++ = '0' + reg; + } else + *dict_++ = *s2++; + } + s2 += wrapped; + *dict_++ = 0; src = s2; @@ -193,23 +199,30 @@ compile_rule(Rule *r, int id, char *src) r->b = dict_; s2 = src; + while((c = *s2) && c == ' ') s2++; - if(c != ')' && !(c == '<' && s2[1] == '>')) { - cap = walk(s2); - wrapped = c == '('; - if(wrapped) s2++, cap--; - while(s2 < cap) *dict_++ = *s2++; - s2 += wrapped; + if(c == ')' || (c == '<' && s2[1] == '>')) { + *dict_++ = 0; + return s2; } + + cap = walk(s2); + wrapped = c == '('; + if(wrapped) s2++, cap--; + while(s2 < cap) { + *dict_++ = *s2++; + } + s2 += wrapped; + *dict_++ = 0; src = s2; - s = r->b; - while((c = *s++)) { /* right */ + s2 = r->b; + while((c = *s2++)) { /* right */ if(c == '?') { - reg = find_register(r, *s); + reg = find_register(r, *s2); if(reg >= 0) - *s = '0' + reg; + *s2 = '0' + reg; } } return src; From 3f5e0990515af3d0452c90de3b5f5319792d0824 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 15:01:47 -0700 Subject: [PATCH 59/81] Merged right hand side of compiler --- src/modal.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/modal.c b/src/modal.c index 6d962e7..62b1191 100644 --- a/src/modal.c +++ b/src/modal.c @@ -167,12 +167,11 @@ compile_rule(Rule *r, int id, char *src) /* left ==================================== */ - r->a = dict_; + r->a = r->b = dict_; s2 = src; while((c = *s2) && c == ' ') s2++; if(c == ')' || (c == '<' && s2[1] == '>')) { - r->b = dict_; *dict_++ = 0; return s2; } @@ -210,21 +209,19 @@ compile_rule(Rule *r, int id, char *src) wrapped = c == '('; if(wrapped) s2++, cap--; while(s2 < cap) { - *dict_++ = *s2++; + if(*s2 == '?') { + *dict_++ = *s2++; + reg = find_register(r, *s2); + *dict_++ = reg >= 0 ? ('0' + reg) : *s2; + s2++; + } else + *dict_++ = *s2++; } s2 += wrapped; *dict_++ = 0; src = s2; - s2 = r->b; - while((c = *s2++)) { /* right */ - if(c == '?') { - reg = find_register(r, *s2); - if(reg >= 0) - *s2 = '0' + reg; - } - } return src; } From ca76fdd9c3dcd43b81f7a456ae1fd7dc0956f5ea Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 15:08:09 -0700 Subject: [PATCH 60/81] Removed temporary pointers --- src/modal.c | 73 +++++++++++++++++++++-------------------------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/src/modal.c b/src/modal.c index 62b1191..2e1fd8a 100644 --- a/src/modal.c +++ b/src/modal.c @@ -162,66 +162,51 @@ static char * compile_rule(Rule *r, int id, char *src) { int wrapped, reg; - char c, *cap, *s2; + char c, *cap; r->id = id, r->ptr = 0; - - /* left ==================================== */ - + /* phase: left */ r->a = r->b = dict_; - s2 = src; - - while((c = *s2) && c == ' ') s2++; - if(c == ')' || (c == '<' && s2[1] == '>')) { + while((c = *src) && c == ' ') src++; + if(c == ')' || (c == '<' && src[1] == '>')) { *dict_++ = 0; - return s2; + return src; } - - cap = walk(s2); + cap = walk(src); wrapped = c == '('; - if(wrapped) s2++, cap--; - while(s2 < cap) { - if(*s2 == '?') { - *dict_++ = *s2++; - reg = find_register(r, *s2); - if(reg < 0 && *s2 != '(') - r->key[r->ptr] = *s2, reg = r->ptr++; + if(wrapped) src++, cap--; + while(src < cap) { + if(*src == '?') { + *dict_++ = *src++; + reg = find_register(r, *src); + if(reg < 0 && *src != '(') + r->key[r->ptr] = *src, reg = r->ptr++; *dict_++ = '0' + reg; } else - *dict_++ = *s2++; + *dict_++ = *src++; } - s2 += wrapped; - + src += wrapped; *dict_++ = 0; - src = s2; - - /* right ==================================== */ - + /* phase: right */ r->b = dict_; - s2 = src; - - while((c = *s2) && c == ' ') s2++; - if(c == ')' || (c == '<' && s2[1] == '>')) { + while((c = *src) && c == ' ') src++; + if(c == ')' || (c == '<' && src[1] == '>')) { *dict_++ = 0; - return s2; + return src; } - - cap = walk(s2); + cap = walk(src); wrapped = c == '('; - if(wrapped) s2++, cap--; - while(s2 < cap) { - if(*s2 == '?') { - *dict_++ = *s2++; - reg = find_register(r, *s2); - *dict_++ = reg >= 0 ? ('0' + reg) : *s2; - s2++; + if(wrapped) src++, cap--; + while(src < cap) { + if(*src == '?') { + *dict_++ = *src++; + reg = find_register(r, *src); + *dict_++ = reg >= 0 ? ('0' + reg) : *src; + src++; } else - *dict_++ = *s2++; + *dict_++ = *src++; } - s2 += wrapped; - + src += wrapped; *dict_++ = 0; - src = s2; - return src; } From 399ac8dd1734797013b5b232bf2c313761981f7d Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 15:17:57 -0700 Subject: [PATCH 61/81] Do no allocate empty cells in dict --- src/modal.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/modal.c b/src/modal.c index 2e1fd8a..3944cc6 100644 --- a/src/modal.c +++ b/src/modal.c @@ -7,7 +7,7 @@ typedef struct { static int flip, quiet, cycles = 0x10000; static Rule rules[0x1000], *rules_ = rules, lambda; -static char dict[0x8000], *dict_ = dict; +static char dict[0x8000], *dict_ = dict, empty; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; @@ -163,14 +163,11 @@ compile_rule(Rule *r, int id, char *src) { int wrapped, reg; char c, *cap; - r->id = id, r->ptr = 0; + r->id = id, r->ptr = 0, r->a = &empty, r->b = ∅ /* phase: left */ - r->a = r->b = dict_; while((c = *src) && c == ' ') src++; - if(c == ')' || (c == '<' && src[1] == '>')) { - *dict_++ = 0; - return src; - } + if(c == ')' || (c == '<' && src[1] == '>')) return src; + r->a = dict_; cap = walk(src); wrapped = c == '('; if(wrapped) src++, cap--; @@ -187,12 +184,9 @@ compile_rule(Rule *r, int id, char *src) src += wrapped; *dict_++ = 0; /* phase: right */ - r->b = dict_; while((c = *src) && c == ' ') src++; - if(c == ')' || (c == '<' && src[1] == '>')) { - *dict_++ = 0; - return src; - } + if(c == ')' || (c == '<' && src[1] == '>')) return src; + r->b = dict_; cap = walk(src); wrapped = c == '('; if(wrapped) src++, cap--; From 5ab8e10a6be87e5af7dada13bfe290a580167731 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 15:34:11 -0700 Subject: [PATCH 62/81] Housekeeping --- src/modal.c | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/src/modal.c b/src/modal.c index 3944cc6..641dc90 100644 --- a/src/modal.c +++ b/src/modal.c @@ -153,54 +153,45 @@ find_register(Rule *r, char reg) { int i; for(i = 0; i < (int)r->ptr; i++) - if(r->key[i] == reg) - return i; + if(r->key[i] == reg) return i; return -1; } static char * compile_rule(Rule *r, int id, char *src) { - int wrapped, reg; char c, *cap; + int wrapped, reg; r->id = id, r->ptr = 0, r->a = &empty, r->b = ∅ /* phase: left */ while((c = *src) && c == ' ') src++; if(c == ')' || (c == '<' && src[1] == '>')) return src; - r->a = dict_; - cap = walk(src); - wrapped = c == '('; + r->a = dict_, cap = walk(src), wrapped = c == '('; if(wrapped) src++, cap--; while(src < cap) { - if(*src == '?') { - *dict_++ = *src++; + c = *src, *dict_++ = *src++; + if(c == '?') { reg = find_register(r, *src); - if(reg < 0 && *src != '(') + if(reg == -1 && *src != '(') r->key[r->ptr] = *src, reg = r->ptr++; *dict_++ = '0' + reg; - } else - *dict_++ = *src++; + } } - src += wrapped; - *dict_++ = 0; + src += wrapped, *dict_++ = 0; /* phase: right */ while((c = *src) && c == ' ') src++; if(c == ')' || (c == '<' && src[1] == '>')) return src; - r->b = dict_; - cap = walk(src); - wrapped = c == '('; + r->b = dict_, cap = walk(src), wrapped = c == '('; if(wrapped) src++, cap--; while(src < cap) { - if(*src == '?') { - *dict_++ = *src++; + c = *src, *dict_++ = *src++; + if(c == '?') { reg = find_register(r, *src); - *dict_++ = reg >= 0 ? ('0' + reg) : *src; + *dict_++ = reg != -1 ? '0' + reg : *src; src++; - } else - *dict_++ = *src++; + } } - src += wrapped; - *dict_++ = 0; + src += wrapped, *dict_++ = 0; return src; } From bd6a194e24ace509542006d402660300747f6301 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 15:46:27 -0700 Subject: [PATCH 63/81] Clean only required registers --- src/modal.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/modal.c b/src/modal.c index 641dc90..d52abfd 100644 --- a/src/modal.c +++ b/src/modal.c @@ -2,7 +2,7 @@ typedef struct { unsigned int id, refs, ptr; - char *a, *b, key[0x10]; + char *a, *b, reg[0x10]; } Rule; static int flip, quiet, cycles = 0x10000; @@ -88,7 +88,7 @@ write_rule(Rule *r, char *s, int create) { while((*dst_++ = *s++)) ; - *dst_++ = 0; + *dst_ = 0; if((flip = !flip)) src_ = bank_b, dst_ = bank_a; else @@ -105,7 +105,10 @@ write_rule(Rule *r, char *s, int create) static int apply_rule(Rule *r, char *s) { - char c, *a = r->a, *regs[0x08] = {NULL}, *reg; + unsigned int i; + char c, *a = r->a, *regs[0x08], *reg; + /* phase: clean registers */ + for(i = 0; i < r->ptr; i++) regs[i] = NULL; /* phase: match rule */ while((c = *a)) { if(c == '?') { @@ -133,7 +136,7 @@ apply_rule(Rule *r, char *s) unsigned int id = *b - '0'; if(id < 9 && (reg = regs[id])) { b++; - if(!write_reg(r->key[id], reg) && dst_ != origin) dst_--; + if(!write_reg(r->reg[id], reg) && dst_ != origin) dst_--; } else *dst_++ = c; } else @@ -153,7 +156,7 @@ find_register(Rule *r, char reg) { int i; for(i = 0; i < (int)r->ptr; i++) - if(r->key[i] == reg) return i; + if(r->reg[i] == reg) return i; return -1; } @@ -163,7 +166,7 @@ compile_rule(Rule *r, int id, char *src) char c, *cap; int wrapped, reg; r->id = id, r->ptr = 0, r->a = &empty, r->b = ∅ - /* phase: left */ + /* phase: compile left */ while((c = *src) && c == ' ') src++; if(c == ')' || (c == '<' && src[1] == '>')) return src; r->a = dict_, cap = walk(src), wrapped = c == '('; @@ -173,12 +176,12 @@ compile_rule(Rule *r, int id, char *src) if(c == '?') { reg = find_register(r, *src); if(reg == -1 && *src != '(') - r->key[r->ptr] = *src, reg = r->ptr++; + r->reg[r->ptr] = *src, reg = r->ptr++; *dict_++ = '0' + reg; } } src += wrapped, *dict_++ = 0; - /* phase: right */ + /* phase: compile right */ while((c = *src) && c == ' ') src++; if(c == ')' || (c == '<' && src[1] == '>')) return src; r->b = dict_, cap = walk(src), wrapped = c == '('; From 56bb5969ab1f1f519c86949bd0a818fa4f9ada51 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 15:55:48 -0700 Subject: [PATCH 64/81] Added comments --- src/modal.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/modal.c b/src/modal.c index d52abfd..ab22cb8 100644 --- a/src/modal.c +++ b/src/modal.c @@ -105,15 +105,16 @@ write_rule(Rule *r, char *s, int create) static int apply_rule(Rule *r, char *s) { - unsigned int i; + unsigned int i, id; char c, *a = r->a, *regs[0x08], *reg; /* phase: clean registers */ - for(i = 0; i < r->ptr; i++) regs[i] = NULL; + for(i = 0; i < r->ptr; i++) + regs[i] = NULL; /* phase: match rule */ while((c = *a)) { if(c == '?') { char *pcap = walk(s); - unsigned int id = *(++a) - '0'; + id = *(++a) - '0'; if((reg = regs[id])) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) @@ -133,11 +134,10 @@ apply_rule(Rule *r, char *s) char *b = r->b, *origin = dst_; while((c = *b++)) { if(c == '?') { - unsigned int id = *b - '0'; - if(id < 9 && (reg = regs[id])) { - b++; - if(!write_reg(r->reg[id], reg) && dst_ != origin) dst_--; - } else + id = *b - '0'; + if(id < 9 && (reg = regs[id])) + b++, write_reg(r->reg[id], reg); + else *dst_++ = c; } else *dst_++ = c; @@ -206,19 +206,22 @@ rewrite(void) while((c = *s)) { if(spacer(last)) { Rule *r = NULL; - if(c == '<' && s[1] == '>') { /* rule */ + /* phase: rule */ + if(c == '<' && s[1] == '>') { r = rules_++; s = compile_rule(r, rules_ - rules - 1, s + 2); while(*s == ' ') s++; return write_rule(r, s, 1); } - if(c == '?' && s[1] == '(') { /* lambda */ + /* phase: lambda */ + if(c == '?' && s[1] == '(') { cap = walk(s + 1); compile_rule(&lambda, -1, s + 2); s = cap; while(*s == ' ') s++; return apply_rule(&lambda, s); } + /* phase: match */ for(r = rules; r < rules_; r++) if(apply_rule(r, s)) return 1; } From 97f8cf03ac7b9273425ba035b4be03bd83f76a96 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Wed, 24 Apr 2024 20:26:56 -0700 Subject: [PATCH 65/81] Beta --- src/modal.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/modal.c b/src/modal.c index ab22cb8..684fc10 100644 --- a/src/modal.c +++ b/src/modal.c @@ -111,23 +111,22 @@ apply_rule(Rule *r, char *s) for(i = 0; i < r->ptr; i++) regs[i] = NULL; /* phase: match rule */ - while((c = *a)) { + while((c = *a++)) { if(c == '?') { char *pcap = walk(s); - id = *(++a) - '0'; + id = *a - '0'; if((reg = regs[id])) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; } else /* reg set */ regs[id] = s; - a++, s = pcap; - if(!spacer(*a)) + c = *a++, s = pcap; + if(!spacer(c)) while((c = *a) && !spacer(c)) a++; continue; } - if(c != *s) return 0; - a++, s++; + if(c != *s++) return 0; } /* phase: write rule */ if(!(c = *s) || spacer(c)) { @@ -174,9 +173,9 @@ compile_rule(Rule *r, int id, char *src) while(src < cap) { c = *src, *dict_++ = *src++; if(c == '?') { - reg = find_register(r, *src); - if(reg == -1 && *src != '(') - r->reg[r->ptr] = *src, reg = r->ptr++; + c = *src, reg = find_register(r, c); + if(reg == -1 && c != '(') + r->reg[r->ptr] = c, reg = r->ptr++; *dict_++ = '0' + reg; } } @@ -189,9 +188,8 @@ compile_rule(Rule *r, int id, char *src) while(src < cap) { c = *src, *dict_++ = *src++; if(c == '?') { - reg = find_register(r, *src); - *dict_++ = reg != -1 ? '0' + reg : *src; - src++; + c = *src++, reg = find_register(r, c); + *dict_++ = reg != -1 ? '0' + reg : c; } } src += wrapped, *dict_++ = 0; From d8325fabcc0118d3d7bc2c50393b03f929a87be1 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 09:48:24 -0700 Subject: [PATCH 66/81] Removed extra check from apply_rule --- src/modal.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/modal.c b/src/modal.c index 684fc10..da2d9ec 100644 --- a/src/modal.c +++ b/src/modal.c @@ -103,10 +103,10 @@ write_rule(Rule *r, char *s, int create) } static int -apply_rule(Rule *r, char *s) +apply_rule(Rule *r, char **regs, char *s) { unsigned int i, id; - char c, *a = r->a, *regs[0x08], *reg; + char c, *a = r->a, *b = r->b, *origin = dst_, *reg; /* phase: clean registers */ for(i = 0; i < r->ptr; i++) regs[i] = NULL; @@ -129,25 +129,21 @@ apply_rule(Rule *r, char *s) if(c != *s++) return 0; } /* phase: write rule */ - if(!(c = *s) || spacer(c)) { - char *b = r->b, *origin = dst_; - while((c = *b++)) { - if(c == '?') { - id = *b - '0'; - if(id < 9 && (reg = regs[id])) - b++, write_reg(r->reg[id], reg); - else - *dst_++ = c; - } else + while((c = *b++)) { + if(c == '?') { + id = *b - '0'; + if(id < 9 && (reg = regs[id])) + b++, write_reg(r->reg[id], reg); + else *dst_++ = c; - } - if(dst_ == origin) { - while(*s == ' ') s++; - if(*s == ')' && *(dst_ - 1) == ' ') dst_--; - } - return write_rule(r, s, 0); + } else + *dst_++ = c; } - return 0; + if(dst_ == origin) { + while(*s == ' ') s++; + if(*s == ')' && *(dst_ - 1) == ' ') dst_--; + } + return write_rule(r, s, 0); } static int @@ -199,7 +195,7 @@ compile_rule(Rule *r, int id, char *src) static int rewrite(void) { - char c, last = 0, *cap, *s = src_; + char c, last = 0, *cap, *s = src_, *regs[0x08]; while(*s == ' ') s++; while((c = *s)) { if(spacer(last)) { @@ -217,11 +213,11 @@ rewrite(void) compile_rule(&lambda, -1, s + 2); s = cap; while(*s == ' ') s++; - return apply_rule(&lambda, s); + return apply_rule(&lambda, regs, s); } /* phase: match */ for(r = rules; r < rules_; r++) - if(apply_rule(r, s)) return 1; + if(apply_rule(r, regs, s)) return 1; } *dst_++ = last = c; s++; @@ -240,7 +236,7 @@ main(int argc, char **argv) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { - case 'v': /* version */ return !printf("Modal Interpreter, 24 Apr 2024.\n"); + case 'v': /* version */ return !printf("Modal Interpreter, 25 Apr 2024.\n"); case 'q': /* quiet */ quiet = 1; break; case 'n': /* infinite */ cycles = 0xffffffff; break; } From 6d10bb3b66b9d173ba29c3eb7d7eb0ad5216e755 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 10:12:43 -0700 Subject: [PATCH 67/81] Split apply_rule --- src/modal.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/modal.c b/src/modal.c index da2d9ec..1604ec6 100644 --- a/src/modal.c +++ b/src/modal.c @@ -102,11 +102,11 @@ write_rule(Rule *r, char *s, int create) return 1; } -static int -apply_rule(Rule *r, char **regs, char *s) +static char * +match_rule(Rule *r, char **regs, char *s) { unsigned int i, id; - char c, *a = r->a, *b = r->b, *origin = dst_, *reg; + char c, *a = r->a, *reg; /* phase: clean registers */ for(i = 0; i < r->ptr; i++) regs[i] = NULL; @@ -118,7 +118,7 @@ apply_rule(Rule *r, char **regs, char *s) if((reg = regs[id])) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) - if(*reg++ != *pp++) return 0; + if(*reg++ != *pp++) return NULL; } else /* reg set */ regs[id] = s; c = *a++, s = pcap; @@ -126,8 +126,17 @@ apply_rule(Rule *r, char **regs, char *s) while((c = *a) && !spacer(c)) a++; continue; } - if(c != *s++) return 0; + if(c != *s++) return NULL; } + return s; +} + +static int +apply_rule(Rule *r, char **regs, char *s) +{ + unsigned int id; + char c, *b = r->b, *origin = dst_, *reg; + if((s = match_rule(r, regs, s)) == NULL) return 0; /* phase: write rule */ while((c = *b++)) { if(c == '?') { From 8cb22a99660c14e67d142fa1c12ba6a41866b3b5 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 10:32:39 -0700 Subject: [PATCH 68/81] Completed split from match and apply --- src/modal.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modal.c b/src/modal.c index 1604ec6..b4a97c8 100644 --- a/src/modal.c +++ b/src/modal.c @@ -6,7 +6,7 @@ typedef struct { } Rule; static int flip, quiet, cycles = 0x10000; -static Rule rules[0x1000], *rules_ = rules, lambda; +static Rule rules[0x1000], *rules_ = rules; static char dict[0x8000], *dict_ = dict, empty; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; @@ -136,7 +136,6 @@ apply_rule(Rule *r, char **regs, char *s) { unsigned int id; char c, *b = r->b, *origin = dst_, *reg; - if((s = match_rule(r, regs, s)) == NULL) return 0; /* phase: write rule */ while((c = *b++)) { if(c == '?') { @@ -204,7 +203,7 @@ compile_rule(Rule *r, int id, char *src) static int rewrite(void) { - char c, last = 0, *cap, *s = src_, *regs[0x08]; + char c, last = 0, *cap, *s = src_, *regs[0x08], *res; while(*s == ' ') s++; while((c = *s)) { if(spacer(last)) { @@ -218,15 +217,16 @@ rewrite(void) } /* phase: lambda */ if(c == '?' && s[1] == '(') { - cap = walk(s + 1); - compile_rule(&lambda, -1, s + 2); - s = cap; + Rule lambda; + cap = walk(s + 1), compile_rule(&lambda, -1, s + 2), s = cap; while(*s == ' ') s++; - return apply_rule(&lambda, regs, s); + if((res = match_rule(&lambda, regs, s)) != NULL) + return apply_rule(&lambda, regs, res); } /* phase: match */ for(r = rules; r < rules_; r++) - if(apply_rule(r, regs, s)) return 1; + if((res = match_rule(r, regs, s)) != NULL) + return apply_rule(r, regs, res); } *dst_++ = last = c; s++; From f28444f60e3a013fd0995d6ddb71b5cbedc319c5 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 11:08:14 -0700 Subject: [PATCH 69/81] Isolated rule finding --- src/modal.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/modal.c b/src/modal.c index b4a97c8..6cf5831 100644 --- a/src/modal.c +++ b/src/modal.c @@ -203,7 +203,7 @@ compile_rule(Rule *r, int id, char *src) static int rewrite(void) { - char c, last = 0, *cap, *s = src_, *regs[0x08], *res; + char c, last = 0, *cap, *s = src_, *regs[0x08], *res = NULL; while(*s == ' ') s++; while((c = *s)) { if(spacer(last)) { @@ -220,13 +220,15 @@ rewrite(void) Rule lambda; cap = walk(s + 1), compile_rule(&lambda, -1, s + 2), s = cap; while(*s == ' ') s++; - if((res = match_rule(&lambda, regs, s)) != NULL) + if((res = match_rule(&lambda, regs, s))) return apply_rule(&lambda, regs, res); } /* phase: match */ for(r = rules; r < rules_; r++) - if((res = match_rule(r, regs, s)) != NULL) - return apply_rule(r, regs, res); + if((res = match_rule(r, regs, s))) break; + /* phase: apply */ + if(res) + return apply_rule(r, regs, res); } *dst_++ = last = c; s++; From 88b5c527f4f44d525e111dcb03aed5dd5881066a Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 12:17:31 -0700 Subject: [PATCH 70/81] Beta 2 --- src/modal.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/modal.c b/src/modal.c index 6cf5831..e9d0fca 100644 --- a/src/modal.c +++ b/src/modal.c @@ -6,7 +6,7 @@ typedef struct { } Rule; static int flip, quiet, cycles = 0x10000; -static Rule rules[0x1000], *rules_ = rules; +static Rule rules[0x1000], *rules_ = rules, lambda; static char dict[0x8000], *dict_ = dict, empty; static char bank_a[0x4000], *src_ = bank_a; static char bank_b[0x4000], *dst_ = bank_b; @@ -102,11 +102,11 @@ write_rule(Rule *r, char *s, int create) return 1; } -static char * -match_rule(Rule *r, char **regs, char *s) +static int +apply_rule(Rule *r, char **regs, char *s) { unsigned int i, id; - char c, *a = r->a, *reg; + char c, *a = r->a, *b = r->b, *origin = dst_, *reg; /* phase: clean registers */ for(i = 0; i < r->ptr; i++) regs[i] = NULL; @@ -118,7 +118,7 @@ match_rule(Rule *r, char **regs, char *s) if((reg = regs[id])) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) - if(*reg++ != *pp++) return NULL; + if(*reg++ != *pp++) return 0; } else /* reg set */ regs[id] = s; c = *a++, s = pcap; @@ -126,16 +126,8 @@ match_rule(Rule *r, char **regs, char *s) while((c = *a) && !spacer(c)) a++; continue; } - if(c != *s++) return NULL; + if(c != *s++) return 0; } - return s; -} - -static int -apply_rule(Rule *r, char **regs, char *s) -{ - unsigned int id; - char c, *b = r->b, *origin = dst_, *reg; /* phase: write rule */ while((c = *b++)) { if(c == '?') { @@ -203,7 +195,7 @@ compile_rule(Rule *r, int id, char *src) static int rewrite(void) { - char c, last = 0, *cap, *s = src_, *regs[0x08], *res = NULL; + char c, last = 0, *cap, *s = src_, *regs[0x08]; while(*s == ' ') s++; while((c = *s)) { if(spacer(last)) { @@ -217,18 +209,13 @@ rewrite(void) } /* phase: lambda */ if(c == '?' && s[1] == '(') { - Rule lambda; cap = walk(s + 1), compile_rule(&lambda, -1, s + 2), s = cap; while(*s == ' ') s++; - if((res = match_rule(&lambda, regs, s))) - return apply_rule(&lambda, regs, res); + return apply_rule(&lambda, regs, s); } /* phase: match */ for(r = rules; r < rules_; r++) - if((res = match_rule(r, regs, s))) break; - /* phase: apply */ - if(res) - return apply_rule(r, regs, res); + if(apply_rule(r, regs, s)) return 1; } *dst_++ = last = c; s++; From 47b80e126e6011a71bb205de63c5d29e74becacd Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 18:36:45 -0700 Subject: [PATCH 71/81] Write EOF token via ?~ register --- examples/repl.modal | 1 + src/modal.c | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/repl.modal b/examples/repl.modal index dac6c3b..2f2b8d6 100644 --- a/examples/repl.modal +++ b/examples/repl.modal @@ -1,5 +1,6 @@ ?(?-) (This is a fully functional Modal REPL.) +<> (EOF wait stdin) ((Bye.\n) print) <> (quit wait stdin) ((You quit.\n) print) <> (?: print) (?:) <> (wait ?~) (?~ wait stdin) diff --git a/src/modal.c b/src/modal.c index e9d0fca..c0e5eae 100644 --- a/src/modal.c +++ b/src/modal.c @@ -29,7 +29,7 @@ walk(char *s) return s; } -static int +static void write_reg(char r, char *reg) { char c, *cap = walk(reg); @@ -47,20 +47,23 @@ write_reg(char r, char *reg) } else putc(c, stdout); } - return 0; - case '~': /* op: input */ + return; + case '~': { /* op: input */ while(fread(&c, 1, 1, stdin) && c >= ' ') *dst_++ = c; - return 1; + if(feof(stdin)) + *dst_++ = 'E', *dst_++ = 'O', *dst_++ = 'F'; + return; + } case '^': /* op: join */ if(*reg == '(') reg++, --cap; while(reg < cap && (c = *reg++)) if(!spacer(c)) *dst_++ = c; - return 1; + return; case '.': /* op: unwrap */ if(*reg == '(') reg++, --cap; while(reg < cap) *dst_++ = *reg++; - return 1; + return; case '*': { /* op: explode */ int i, depth = 0; if(*reg == '(' && reg[1] != ')') { /* tuple */ @@ -75,11 +78,11 @@ write_reg(char r, char *reg) while((c = *reg++) && !spacer(c)) *dst_++ = c, *dst_++ = ' ', *dst_++ = '(', depth++; for(i = 0; i < depth; i++) *dst_++ = ')'; - return 1; + return; } default: while(reg < cap) *dst_++ = *reg++; - return 1; + return; } } From eaa1f923473603f0e2b3f4cce34f195f001a9dac Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 18:39:17 -0700 Subject: [PATCH 72/81] Do not pass regs through funciton --- src/modal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modal.c b/src/modal.c index c0e5eae..0e4f055 100644 --- a/src/modal.c +++ b/src/modal.c @@ -106,10 +106,10 @@ write_rule(Rule *r, char *s, int create) } static int -apply_rule(Rule *r, char **regs, char *s) +apply_rule(Rule *r, char *s) { unsigned int i, id; - char c, *a = r->a, *b = r->b, *origin = dst_, *reg; + char c, *a = r->a, *b = r->b, *origin = dst_, *reg, *regs[0x08]; /* phase: clean registers */ for(i = 0; i < r->ptr; i++) regs[i] = NULL; @@ -198,7 +198,7 @@ compile_rule(Rule *r, int id, char *src) static int rewrite(void) { - char c, last = 0, *cap, *s = src_, *regs[0x08]; + char c, last = 0, *cap, *s = src_; while(*s == ' ') s++; while((c = *s)) { if(spacer(last)) { @@ -214,11 +214,11 @@ rewrite(void) if(c == '?' && s[1] == '(') { cap = walk(s + 1), compile_rule(&lambda, -1, s + 2), s = cap; while(*s == ' ') s++; - return apply_rule(&lambda, regs, s); + return apply_rule(&lambda, s); } /* phase: match */ for(r = rules; r < rules_; r++) - if(apply_rule(r, regs, s)) return 1; + if(apply_rule(r, s)) return 1; } *dst_++ = last = c; s++; From 7e9eab04fc25a8918f0ef107219b47deb08d9b84 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 18:53:22 -0700 Subject: [PATCH 73/81] Improved REPL --- examples/repl.modal | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/repl.modal b/examples/repl.modal index 2f2b8d6..e6354c9 100644 --- a/examples/repl.modal +++ b/examples/repl.modal @@ -1,10 +1,8 @@ ?(?-) (This is a fully functional Modal REPL.) -<> (EOF wait stdin) ((Bye.\n) print) -<> (quit wait stdin) ((You quit.\n) print) -<> (?: print) (?:) +<> quit EOF +<> (?: print) ?: <> (wait ?~) (?~ wait stdin) +<> (EOF wait stdin) (Bye.\n print) -(Say something, or type "quit":\n) print - -wait stdin +(Say something, or type "quit":\n) print wait stdin From 2f9f9d7f15242f043aebe800adc9ea696b73d2dd Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 22:35:15 -0700 Subject: [PATCH 74/81] Do not match on substrings --- examples/repl.modal | 6 +++--- examples/tests.modal | 1 + makefile | 2 +- src/modal.c | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/examples/repl.modal b/examples/repl.modal index e6354c9..15cbd7f 100644 --- a/examples/repl.modal +++ b/examples/repl.modal @@ -1,8 +1,8 @@ ?(?-) (This is a fully functional Modal REPL.) <> quit EOF +<> wait?~ (?~ wait!) <> (?: print) ?: -<> (wait ?~) (?~ wait stdin) -<> (EOF wait stdin) (Bye.\n print) +<> (EOF wait!) (Bye.\n print) -(Say something, or type "quit":\n) print wait stdin +(Say something, or type "quit":\n) print wait! \ No newline at end of file diff --git a/examples/tests.modal b/examples/tests.modal index 8a47786..01a175e 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -52,6 +52,7 @@ connect foo bar baz = foo-barbaz (substring 1) test prefix-anything = anything-suffix (substring 2) test +?(foo QQQ) foobar = foobar (substring 3) test ?(?-) (Lambdas) diff --git a/makefile b/makefile index 24e2457..315db9c 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,7 @@ all: dest dest: @ mkdir -p bin run: all bin/modal - @ bin/modal -q examples/hello.modal + @ bin/modal examples/hello.modal debug: all bin/modal-debug @ bin/modal-debug examples/hello.modal test: all bin/modal-debug bin/modal diff --git a/src/modal.c b/src/modal.c index 0e4f055..7190316 100644 --- a/src/modal.c +++ b/src/modal.c @@ -131,6 +131,8 @@ apply_rule(Rule *r, char *s) } if(c != *s++) return 0; } + c = *s; + if(!spacer(c)) return 0; /* phase: write rule */ while((c = *b++)) { if(c == '?') { From 927479bc44b51a366c71a82659f847dc6b7a529f Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 25 Apr 2024 22:39:37 -0700 Subject: [PATCH 75/81] Fixed issue with invalid lambda --- makefile | 2 +- src/modal.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index 315db9c..24e2457 100644 --- a/makefile +++ b/makefile @@ -8,7 +8,7 @@ all: dest dest: @ mkdir -p bin run: all bin/modal - @ bin/modal examples/hello.modal + @ bin/modal -q examples/hello.modal debug: all bin/modal-debug @ bin/modal-debug examples/hello.modal test: all bin/modal-debug bin/modal diff --git a/src/modal.c b/src/modal.c index 7190316..8d99423 100644 --- a/src/modal.c +++ b/src/modal.c @@ -216,7 +216,8 @@ rewrite(void) if(c == '?' && s[1] == '(') { cap = walk(s + 1), compile_rule(&lambda, -1, s + 2), s = cap; while(*s == ' ') s++; - return apply_rule(&lambda, s); + if(!apply_rule(&lambda, s)) write_rule(r, s, 0); + return 1; } /* phase: match */ for(r = rules; r < rules_; r++) From d43eec77f3632fbf7fbdbbcb661ee116dcdf598f Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Fri, 26 Apr 2024 08:05:21 -0700 Subject: [PATCH 76/81] Fixed bug with lambda mismatch --- src/modal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modal.c b/src/modal.c index 8d99423..aafb989 100644 --- a/src/modal.c +++ b/src/modal.c @@ -148,6 +148,7 @@ apply_rule(Rule *r, char *s) while(*s == ' ') s++; if(*s == ')' && *(dst_ - 1) == ' ') dst_--; } + printf("[%s]\n", r->a); return write_rule(r, s, 0); } @@ -216,7 +217,7 @@ rewrite(void) if(c == '?' && s[1] == '(') { cap = walk(s + 1), compile_rule(&lambda, -1, s + 2), s = cap; while(*s == ' ') s++; - if(!apply_rule(&lambda, s)) write_rule(r, s, 0); + if(!apply_rule(&lambda, s)) write_rule(&lambda, s, 0); return 1; } /* phase: match */ @@ -240,7 +241,7 @@ main(int argc, char **argv) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { switch(argv[i][1]) { - case 'v': /* version */ return !printf("Modal Interpreter, 25 Apr 2024.\n"); + case 'v': /* version */ return !printf("Modal Interpreter, 26 Apr 2024.\n"); case 'q': /* quiet */ quiet = 1; break; case 'n': /* infinite */ cycles = 0xffffffff; break; } From 0f576e8972ea53f7e2d8ce3a4afb09bd14e5a123 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Fri, 26 Apr 2024 08:28:47 -0700 Subject: [PATCH 77/81] Removed debug --- src/modal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modal.c b/src/modal.c index aafb989..df2cbaf 100644 --- a/src/modal.c +++ b/src/modal.c @@ -148,7 +148,6 @@ apply_rule(Rule *r, char *s) while(*s == ' ') s++; if(*s == ')' && *(dst_ - 1) == ' ') dst_--; } - printf("[%s]\n", r->a); return write_rule(r, s, 0); } From f546e2e0162944bd491ac16a12f608d770547932 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Fri, 26 Apr 2024 08:54:05 -0700 Subject: [PATCH 78/81] Fixed compilation bug --- src/modal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modal.c b/src/modal.c index df2cbaf..e15a050 100644 --- a/src/modal.c +++ b/src/modal.c @@ -174,7 +174,7 @@ compile_rule(Rule *r, int id, char *src) while(src < cap) { c = *src, *dict_++ = *src++; if(c == '?') { - c = *src, reg = find_register(r, c); + c = *src++, reg = find_register(r, c); if(reg == -1 && c != '(') r->reg[r->ptr] = c, reg = r->ptr++; *dict_++ = '0' + reg; From 13359a79cd8f33b323db768ec37f31bd2cecc548 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Fri, 26 Apr 2024 09:02:03 -0700 Subject: [PATCH 79/81] Fixed issue with catching matches without spaces --- src/modal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modal.c b/src/modal.c index e15a050..b8566df 100644 --- a/src/modal.c +++ b/src/modal.c @@ -203,7 +203,7 @@ rewrite(void) char c, last = 0, *cap, *s = src_; while(*s == ' ') s++; while((c = *s)) { - if(spacer(last)) { + if(c == '(' || spacer(last)) { Rule *r = NULL; /* phase: rule */ if(c == '<' && s[1] == '>') { From 31676987955d3d1487ddabce87ad8327b857133e Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Fri, 26 Apr 2024 10:42:21 -0700 Subject: [PATCH 80/81] Print program left-over --- src/modal.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/modal.c b/src/modal.c index b8566df..32562fc 100644 --- a/src/modal.c +++ b/src/modal.c @@ -117,19 +117,16 @@ apply_rule(Rule *r, char *s) while((c = *a++)) { if(c == '?') { char *pcap = walk(s); - id = *a - '0'; + id = *a++ - '0'; if((reg = regs[id])) { /* reg cmp */ char *rcap = walk(reg), *pp = s; while(reg < rcap || pp < pcap) if(*reg++ != *pp++) return 0; } else /* reg set */ regs[id] = s; - c = *a++, s = pcap; - if(!spacer(c)) - while((c = *a) && !spacer(c)) a++; - continue; + c = *a, s = pcap; } - if(c != *s++) return 0; + else if(c != *s++) return 0; } c = *s; if(!spacer(c)) return 0; @@ -266,5 +263,6 @@ main(int argc, char **argv) if(!cycles--) return !fprintf(stdout, "Modal rewrites exceeded.\n"); while(rules_-- > rules && !quiet) if(!rules_->refs) printf("-- Unused rule: %d <> (%s) (%s)\n", rules_->refs, rules_->a, rules_->b); + if(!quiet) printf(".. %s\n", src_); return 0; } \ No newline at end of file From a7abb9475a6bc1a5aa5c800644466f6c07047cdf Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Fri, 26 Apr 2024 11:06:30 -0700 Subject: [PATCH 81/81] Added tests for formatter --- examples/tests.modal | 12 +++++++----- src/modal.c | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/examples/tests.modal b/examples/tests.modal index 01a175e..cc8a36b 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -6,12 +6,14 @@ <> (ghost) () -?(?-) (Whitespace) +?(?-) (Formatter) -(a b c ) = (a b c) (whitespace 1) test -( a b c) = (a b c) (whitespace 2) test -( a b c ) = (a b c) (whitespace 3) test -(a b c ( a b c ) ) = (a b c (a b c)) (whitespace 4) test +?((?x ?y) one) aaa(bbb) = one (formatter 1) test +?((?x ?y) one) (bbb)aaa = one (formatter 2) test +(a b c ) = (a b c) (formatter 3) test +( a b c) = (a b c) (formatter 4) test +( a b c ) = (a b c) (formatter 5) test +(a b c ( a b c ) ) = (a b c (a b c)) (formatter 6) test ?(?-) (Empty replacements) diff --git a/src/modal.c b/src/modal.c index 32562fc..0c1a83f 100644 --- a/src/modal.c +++ b/src/modal.c @@ -124,9 +124,9 @@ apply_rule(Rule *r, char *s) if(*reg++ != *pp++) return 0; } else /* reg set */ regs[id] = s; - c = *a, s = pcap; - } - else if(c != *s++) return 0; + s = pcap; + } else if(c != *s++) + return 0; } c = *s; if(!spacer(c)) return 0; @@ -232,7 +232,7 @@ main(int argc, char **argv) { FILE *f; int i, pl = 0, pr = 0; - char c, *w = bank_a; + char c, last = 0, *w = bank_a; if(argc < 2) return !printf("usage: modal [-vqn] source.modal\n"); for(i = 1; i < argc && *argv[i] == '-'; i++) { @@ -246,14 +246,14 @@ main(int argc, char **argv) return !fprintf(stdout, "Modal file invalid: %s.\n", argv[i]); while(fread(&c, 1, 1, f)) { c = c <= 0x20 ? 0x20 : c; - if(w > bank_a) { - if(c == ' ' && *(w - 1) == '(') continue; - if(c == ')' && *(w - 1) == ' ') w--; - if(c == ' ' && *(w - 1) == ' ') w--; - } + if(c == ' ' && last == '(') continue; + if(c == ')' && last == ' ') w--; + if(c == ' ' && last == ' ') w--; if(c == '(') pl++; if(c == ')') pr++; - *w++ = c; + if(c == '(' && last != '?' && !spacer(last)) *w++ = ' '; + if(last == ')' && !spacer(c)) *w++ = ' '; + *w++ = last = c; } while(*(--w) <= ' ') *w = 0; fclose(f);