diff --git a/examples/string_join.modal b/examples/string_join.modal index 8f4b8ea..eb3193e 100644 --- a/examples/string_join.modal +++ b/examples/string_join.modal @@ -1,7 +1,7 @@ ?(?-) (This example joins two tokens.) <> (join (?a) (?*)) (join reverse (?a) List (?*)) -<> (join List () List ?*) (?*) +<> (join List () List ?^) (?^) <> (join List (?x ?y) List ?z) (join List ?y List (?x ?z)) <> (reverse List ()) (List) diff --git a/examples/string_reverse.modal b/examples/string_reverse.modal index 4e14c75..a973a80 100644 --- a/examples/string_reverse.modal +++ b/examples/string_reverse.modal @@ -1,6 +1,6 @@ ?(?-) (This example reverses the string modal, into ladom.) -<> (reverse List () ?*) (?*) +<> (reverse List () ?^) (?^) <> (reverse (?*)) (reverse List (?*) ()) <> (reverse List (?x ?y) ?z) (reverse List ?y (?x ?z)) diff --git a/examples/tests.modal b/examples/tests.modal index 9d6d20a..f8e329e 100644 --- a/examples/tests.modal +++ b/examples/tests.modal @@ -1,9 +1,5 @@ ?(?-) (This example tests various aspects of the implementation.) -<> (?: print) (?:) -<> (?x = ?x test) (#ok) -<> (?x = ?y test) (#fail) - ?(?-) (Inline rules) <> ((?x -> ?y)) (<> ?x ?y) @@ -15,9 +11,11 @@ nap tap test <> (?x pop-plain) <> (?x pop) () +<> (ghost) () abc def pop-plain = abc test abc def pop = abc test +(ghost) = () test ?(?-) (Basic replacements) @@ -57,17 +55,26 @@ abc ?(?x) def = abc test <> (explode ?*) ((?*) =) explode cow (c (o (w ()))) test +explode (12 34 45) (12 (34 (45 ()))) test ?(?-) (Implode) -<> (implode ?*) (?* =) +<> (implode ?^) (?^ =) implode (b (a (t ()))) bat test +implode (12 (34 (56 ()))) 123456 test + +?(?-) (Test Primitives) + +<> (?: print) (?:) +<> (?x = ?x test) (#ok) +<> (?x = ?y test) (#fail) ?(?-) (List reversal) -<> (reverse List () ?*) (?*) +<> (reverse List () ?^) (?^) <> (reverse (?*)) (reverse List (?*) ()) <> (reverse List (?x ?y) ?z) (reverse List ?y (?x ?z)) reverse (modal) = ladom test + diff --git a/makefile b/makefile index eaf3ae3..ab918b7 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ RELEASE_flags=-DNDEBUG -O2 -g0 -s DEBUG_flags=-std=c89 -D_POSIX_C_SOURCE=199309L -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined -.PHONY: all debug dest run test install uninstall format clean archive +.PHONY: all debug dest run debug test install uninstall format clean archive all: dest @@ -9,6 +9,8 @@ dest: @ mkdir -p bin run: all bin/modal @ bin/modal examples/hello.modal 2> /dev/null +debug: bin/modal-debug + @ bin/modal-debug examples/hello.modal test: bin/modal-debug bin/modal @ bin/modal -v @ bin/modal-debug examples/tests.modal diff --git a/src/modal.c b/src/modal.c index 71e6569..6b1cb0a 100644 --- a/src/modal.c +++ b/src/modal.c @@ -55,16 +55,31 @@ put_reg(char r) } ss = walk(s); if(r == '*') { - if(*s == '(') { /* special implode */ - while(s < ss && (c = *s++)) - if(!spacer(c)) *dst_++ = c; - } else { /* special explode */ - int i, depth = 0; + int i, depth = 0; + if(*s == '(') { /* special explode tuple */ + s++; + while(s < ss) { + while((c = *s) && !spacer(c)) + *dst_++ = c, s++; + *dst_++ = ' '; + *dst_++ = '(', s++, depth++; + } + } else { /* special explode token */ while((c = *s++) && !spacer(c)) *dst_++ = c, *dst_++ = ' ', *dst_++ = '(', depth++; - for(i = 0; i < depth; i++) - *dst_++ = ')'; } + for(i = 0; i < depth; i++) + *dst_++ = ')'; + } else if(r == '.') { /* special unpack */ + if(*s == '(') s++, --ss; + while(s < ss) *dst_++ = *s++; + } else if(r == '^') { /* special join */ + if(*s == '(') s++, --ss; + while(s < ss && (c = *s++)) + 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) { @@ -78,9 +93,6 @@ put_reg(char r) } else putc(c, stdout); } - } else if(r == '~') { /* special stdin */ - while(fread(&c, 1, 1, stdin) && c >= ' ') - *dst_++ = c; } else while(s < ss) *dst_++ = *s++; } @@ -134,8 +146,10 @@ write_rule(Rule *r, char last, char *res) put_reg(*b++); else *dst_++ = c, last = c; - if(dst_ == origin) + if(dst_ == origin) { while(*res == ' ') res++; + if(*res == ')' && *(dst_ - 1) == ' ') dst_--; + } return commit_rule(r, res, 0); } @@ -206,7 +220,7 @@ main(int argc, char **argv) if(argc < 2) return !printf("usage: modal [-v] source.modal\n"); if(argc < 3 && argv[1][0] == '-' && argv[1][1] == 'v') - return !printf("Modal Interpreter, 16 Apr 2024.\n"); + return !printf("Modal Interpreter, 17 Apr 2024.\n"); if(!(f = fopen(argv[1], "r"))) return !fprintf(stderr, "Invalid Modal file: %s.\n", argv[1]); while(fread(&c, 1, 1, f)) {