diff --git a/README.md b/README.md index 6eb6479..90d65a4 100644 --- a/README.md +++ b/README.md @@ -18,4 +18,4 @@ bin/modal examples/hello.modal ## Credits -Created by [wryl](https://wryl.tech/), Immediate Mode Technologies. +Created by [wryl](https://wryl.tech/), Paradigital. diff --git a/examples/adventure.modal b/examples/adventure.modal deleted file mode 100644 index 26c81f7..0000000 --- a/examples/adventure.modal +++ /dev/null @@ -1,9 +0,0 @@ -<> ((You said: quit\n) send) ((You quit.) print ') -<> (?: print ') (?:) -<> (?: send) (?: wait) -<> (wait) ((You said: ?~\n) send) -<> (' ?x) (?x ') - -(Say something, or type "quit": \n) print ' - -wait \ No newline at end of file diff --git a/examples/arithmetic.modal b/examples/arithmetic.modal deleted file mode 100644 index 7dc5405..0000000 --- a/examples/arithmetic.modal +++ /dev/null @@ -1,20 +0,0 @@ -<> (add (s ?x) (s ?y)) (s (add ?x (s ?y))) -<> (add (s ?x) (0)) (s ?x) -<> (add (0) (s ?y)) (s ?y) -<> (add (0) (0)) (0) -<> (sub (s ?x) (s ?y)) (sub ?x ?y) -<> (sub (s ?x) (0)) (s ?x) -<> (sub (0) (s ?y)) (s ?y) -<> (sub (0) (0)) (0) -<> (mul (s ?x) (s ?y)) (add (s ?x) (mul (s ?x) (sub (s ?y) (s (0))))) -<> (mul (s ?x) (s (0))) (s ?x) -<> (mul (s (0)) (s ?y)) (s ?y) -<> (mul (s ?x) (0)) (0) -<> (mul (0) (s ?x)) (0) -<> (?x + ?y) (add ?x ?y) -<> (?x - ?y) (sub ?x ?y) -<> (?x * ?y) (mul ?x ?y) -<> (factorial (s (0))) ((s (0))) -<> (factorial (s ?x)) (((s ?x) * factorial ((s ?x) - (s (0))))) - -factorial (s (s (s (s (s (0)))))) \ No newline at end of file diff --git a/examples/arithmetic2.modal b/examples/arithmetic2.modal deleted file mode 100644 index 0438471..0000000 --- a/examples/arithmetic2.modal +++ /dev/null @@ -1,158 +0,0 @@ -<> (-- ?x) () --- ( little endian binary integers ) - --- ( constants ) -<> zero ((0 nil)) -<> one ((1 nil)) -<> two ((0 (1 nil))) -<> three ((1 (1 nil))) -<> ten ((0 (1 (0 (1 nil))))) - --- ( decimal digit to binary ) -<> (binary 0) ((0 nil)) -<> (binary 1) ((1 nil)) -<> (binary 2) ((0 (1 nil))) -<> (binary 3) ((1 (1 nil))) -<> (binary 4) ((0 (0 (1 nil)))) -<> (binary 5) ((1 (0 (1 nil)))) -<> (binary 6) ((0 (1 (1 nil)))) -<> (binary 7) ((1 (1 (1 nil)))) -<> (binary 8) ((0 (0 (0 (1 nil))))) -<> (binary 9) ((1 (0 (0 (1 nil))))) - --- ( binary to decimal digit ) -<> (decimal (0 nil)) (0) -<> (decimal (1 nil)) (1) -<> (decimal (0 (1 nil))) (2) -<> (decimal (1 (1 nil))) (3) -<> (decimal (0 (0 (1 nil)))) (4) -<> (decimal (1 (0 (1 nil)))) (5) -<> (decimal (0 (1 (1 nil)))) (6) -<> (decimal (1 (1 (1 nil)))) (7) -<> (decimal (0 (0 (0 (1 nil))))) (8) -<> (decimal (1 (0 (0 (1 nil))))) (9) - --- create nil-terminated list -<> (nilify (?h)) ((?h nil)) -<> (nilify (?h ?t)) ((?h nilify ?t)) - --- reverse nil-terminated list -<> (reverse ?x) (reverse' nil ?x) -<> (reverse' ?a nil) (?a) -<> (reverse' ?a (?h ?t)) (reverse' (?h ?a) ?t) - --- ( normalize, remove trailing zeros ) --- ( currently zero is (0 nil) though arguably it could be nil ) --- ( that change would require auditing our rules ) -<> (normalize (?h ?t)) ((?h normalize' nil ?t)) -<> (normalize' ?s nil) (nil) -<> (normalize' ?s (0 ?t)) (normalize' (0 ?s) ?t) -<> (normalize' nil (1 ?t)) ((1 normalize' nil ?t)) -<> (normalize' (0 ?s) (1 ?t)) ((0 normalize' ?s (1 ?t))) - --- ( to integer ) -<> ((int ?*)) ((sum f (one) g reverse nilify (?*))) -<> (g nil) (nil) -<> (g (?h ?t)) ((binary ?h g ?t)) -<> (f (?u) nil) (nil) -<> (f (?u) (?h ?t)) (((mul ?h ?u) f ((mul ?u ten)) ?t)) - --- ( to string: TODO, need division for this one ) - --- ( comparison operartions ) -<> ((cmp ?x ?y)) ((cmpc #eq ?x ?y)) -<> ((cmpc ?e nil nil)) (?e) -<> ((cmpc ?e (1 ?x) nil)) (#gt) -<> ((cmpc ?e (0 ?x) nil)) ((cmpc ?e ?x nil)) -<> ((cmpc ?e nil (1 ?y))) (#lt) -<> ((cmpc ?e nil (0 ?y))) ((cmpc ?e nil ?y)) -<> ((cmpc ?e (0 ?x) (0 ?y))) ((cmpc ?e ?x ?y)) -<> ((cmpc ?e (1 ?x) (0 ?y))) ((cmpc #gt ?x ?y)) -<> ((cmpc ?e (0 ?x) (1 ?y))) ((cmpc #lt ?x ?y)) -<> ((cmpc ?e (1 ?x) (1 ?y))) ((cmpc ?e ?x ?y)) - --- ( addition ) -<> ((add ?x ?y)) (addc 0 ?x ?y) -<> (addc 0 nil nil) (nil) -<> (addc 1 nil nil) ((1 nil)) -<> (addc ?c ?x nil) (addc ?c ?x (0 nil)) -<> (addc ?c nil ?y) (addc ?c (0 nil) ?y) -<> (addc 0 (0 ?x) (0 ?y)) ((0 addc 0 ?x ?y)) -<> (addc 0 (0 ?x) (1 ?y)) ((1 addc 0 ?x ?y)) -<> (addc 0 (1 ?x) (0 ?y)) ((1 addc 0 ?x ?y)) -<> (addc 0 (1 ?x) (1 ?y)) ((0 addc 1 ?x ?y)) -<> (addc 1 (0 ?x) (0 ?y)) ((1 addc 0 ?x ?y)) -<> (addc 1 (0 ?x) (1 ?y)) ((0 addc 1 ?x ?y)) -<> (addc 1 (1 ?x) (0 ?y)) ((0 addc 1 ?x ?y)) -<> (addc 1 (1 ?x) (1 ?y)) ((1 addc 1 ?x ?y)) - --- ( summation ) -<> ((sum nil)) ((0 nil)) -<> ((sum (?a nil))) (?a) -<> ((sum (?a (?b ?c)))) ((sum ((add ?a ?b) ?c))) - --- ( multiplication ) -<> ((mul ?x ?y)) (mulc nil ?x ?y) -<> (mulc ?t nil ?y) ((sum ?t)) -<> (mulc ?t (0 ?x) ?y) (mulc ?t ?x (0 ?y)) -<> (mulc ?t (1 ?x) ?y) (mulc (?y ?t) ?x (0 ?y)) - --- ( subtraction ) -<> ((sub ?x ?y)) (normalize subc 0 ?x ?y) -<> (subc 0 nil nil) (nil) -<> (subc 1 nil nil) (#err) -<> (subc 0 ?x nil) (?x) -<> (subc 1 ?x nil) (subc 1 ?x (0 nil)) -<> (subc ?c nil ?y) (subc ?c (0 nil) ?y) -<> (subc 0 (0 ?x) (0 ?y)) ((0 subc 0 ?x ?y)) -<> (subc 0 (0 ?x) (1 ?y)) ((1 subc 1 ?x ?y)) -<> (subc 0 (1 ?x) (0 ?y)) ((1 subc 0 ?x ?y)) -<> (subc 0 (1 ?x) (1 ?y)) ((0 subc 0 ?x ?y)) -<> (subc 1 (0 ?x) (0 ?y)) ((1 subc 1 ?x ?y)) -<> (subc 1 (0 ?x) (1 ?y)) ((0 subc 1 ?x ?y)) -<> (subc 1 (1 ?x) (0 ?y)) ((0 subc 0 ?x ?y)) -<> (subc 1 (1 ?x) (1 ?y)) ((1 subc 1 ?x ?y)) - --- ( dec ) -<> (dec (0 nil)) (#err) -<> (dec ?x) (normalize dec' ?x) -<> (dec' (0 ?t)) ((1 dec' ?t)) -<> (dec' (1 ?t)) ((0 ?t)) - --- ( inc ) -<> ((inc nil)) ((1 nil)) -<> ((inc (0 ?t))) ((1 ?t)) -<> ((inc (1 ?t))) ((0 (inc ?t))) - --- ( left shift; lshift x b means x< ((lshift ?x (0 nil))) (?x) -<> ((lshift ?x (1 nil))) ((0 ?x)) -<> ((lshift ?x (?h (?a ?b)))) ((lshift (0 ?x) dec (?h (?a ?b)))) - --- ( divmod, i.e. quotient and remainder ) -<> ((divmod ?x ?y)) ((divmod1 ?x ?y (cmp ?x ?y))) -<> ((divmod1 ?x ?y #lt)) (zero) -<> ((divmod1 ?x ?y #eq)) (one) -<> ((divmod1 ?x ?y #gt)) ((divmod2 ?x ?y zero (0 ?y))) -<> ((divmod2 ?x ?y ?s ?m)) ((divmod3 ?x ?y ?s ?m (cmp ?x ?m))) -<> ((divmod3 ?x ?y ?s ?m #lt)) ((divmod4 ?x ?y ?s zero)) -<> ((divmod3 ?x ?y ?s ?m #eq)) ((divmod4 ?x ?y (inc ?s) zero)) -<> ((divmod3 ?x ?y ?s ?m #gt)) ((divmod2 ?x ?y (inc ?s) (0 ?m))) -<> ((divmod4 ?x ?y (0 nil) ?d)) (((add ?d one) (sub ?x ?y))) -<> ((divmod4 ?x ?y ?s ?d)) ((divmod5 (sub ?x (lshift ?y ?s)) ?y dec ?s (add ?d (lshift one ?s)))) -<> ((divmod5 (0 nil) ?y ?s ?d)) ((?d (0 nil))) -<> ((divmod5 ?x ?y ?s ?d)) ((divmod6 ?x ?y ?s ?d (cmp ?x (lshift ?y ?s)))) -<> ((divmod6 ?x ?y (0 nil) ?d #lt)) ((?d ?x)) -<> ((divmod6 ?x ?y ?s ?d #lt)) ((divmod5 ?x ?y dec ?s ?d)) -<> ((divmod6 ?x ?y ?s ?d #eq)) ((divmod4 ?x ?y ?s ?d)) -<> ((divmod6 ?x ?y ?s ?d #gt)) ((divmod4 ?x ?y ?s ?d)) - --- ( floor divison ) -<> ((div ?x ?y)) ((div' (divmod ?x ?y))) -<> ((div' (?q ?r))) (?q) - --- ( remainder ) -<> ((mod ?x ?y)) ((mod' (divmod ?x ?y))) -<> ((mod' (?q ?r))) (?r) - -(divmod (int 1234567) (int 1357)) \ No newline at end of file diff --git a/examples/combinators.modal b/examples/combinators.modal index 4f3aa96..03278a0 100644 --- a/examples/combinators.modal +++ b/examples/combinators.modal @@ -1,11 +1,13 @@ +?(?-) (This example demonstrates how to implement combinatory calculus.) -define (M ?x) (?x ?x) -define (KI ?x ?y) (?y) -define (T ?x ?y) (?y ?y) -define (W ?x ?y) (?x ?y ?y) -define (K ?x ?y) (?x) -define (C ?x ?y ?z) (?x ?z ?y) -define (B ?x ?y ?z) (?x (?y ?z)) -define (I ?x) (?x) -define (S ?x ?y ?z) (?x ?z (?y ?z)) +<> (M ?x) (?x ?x) +<> (KI ?x ?y) (?y) +<> (T ?x ?y) (?y ?y) +<> (W ?x ?y) (?x ?y ?y) +<> (K ?x ?y) (?x) +<> (C ?x ?y ?z) (?x ?z ?y) +<> (B ?x ?y ?z) (?x (?y ?z)) +<> (I ?x) (?x) +<> (S ?x ?y ?z) (?x ?z (?y ?z)) +C KI x y z diff --git a/examples/concat.modal b/examples/concat.modal deleted file mode 100644 index f175cf2..0000000 --- a/examples/concat.modal +++ /dev/null @@ -1,8 +0,0 @@ -define (: ?x ?y ;) (define ?x ?y) -: (?x dup) (?x ?x) ; -: (?x ?y swap) (?y ?x) ; -: (?x drop) () ; -: (?x ?y p*) (?x * ?y) ; -: square (dup p*) ; - -10 square \ No newline at end of file diff --git a/examples/console_read.modal b/examples/console_read.modal deleted file mode 100644 index d4145e7..0000000 --- a/examples/console_read.modal +++ /dev/null @@ -1,9 +0,0 @@ -<> (read) (?~) -<> (?: print ') (?:) -<> (' ?x) (?x ') - -(Tell me three things: \n) print ' - -' (You said: read -then, you continued: read -finaly, you concluded: read) print diff --git a/examples/console_write.modal b/examples/console_write.modal deleted file mode 100644 index 4035038..0000000 --- a/examples/console_write.modal +++ /dev/null @@ -1,3 +0,0 @@ -<> ((send ?:)) () - -(send (hello world)) \ No newline at end of file diff --git a/examples/flip.modal b/examples/flip.modal deleted file mode 100644 index f8c9e7b..0000000 --- a/examples/flip.modal +++ /dev/null @@ -1,8 +0,0 @@ -<> (explode ?*) (str (?*)) -<> (reverse (str (?h ?t))) (reverse/l ?t (?h)) -<> (reverse (str (?h))) (?h) -<> (reverse/l (?h ?t) ?l) (reverse/l ?t (?h ?l)) -<> (reverse/l (?h) ?l) (str (?h ?l)) -<> (implode str ?*) (?*) - -(implode reverse (explode hello)) \ No newline at end of file diff --git a/examples/hello.modal b/examples/hello.modal index 1ddb7ae..b341550 100644 --- a/examples/hello.modal +++ b/examples/hello.modal @@ -1,5 +1,7 @@ -<> (NAME) (Modal) -<> (?: print $) (?:) -<> ($ ?x) (?x $) +?(?-) (This example prints to the console and demonstrates how to delay the execution of a rule.) -$ (Welcome to NAME \nHave fun!\n\n) print \ No newline at end of file +<> (NAME) (Modal) +<> (?: print String) (?:) +<> (String ?x) (?x String) + +String (Welcome to NAME \nHave fun!\n\n) print diff --git a/examples/io_read.modal b/examples/io_read.modal new file mode 100644 index 0000000..4b5c11b --- /dev/null +++ b/examples/io_read.modal @@ -0,0 +1,11 @@ +?(?-) (This example requests 3 line delimited strings from the console.) + +<> (read ?~) (?~) +<> (?: print ') (?:) +<> (' ?x) (?x ') + +(Tell me three things: \n) print ' + +' (You said: read stdin +\nthen, you continued: read stdin +\nfinaly, you concluded: read stdin \n) print \ No newline at end of file diff --git a/examples/io_repl.modal b/examples/io_repl.modal new file mode 100644 index 0000000..5e96b63 --- /dev/null +++ b/examples/io_repl.modal @@ -0,0 +1,11 @@ +?(?-) (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/io_write.modal b/examples/io_write.modal new file mode 100644 index 0000000..f0f0c4c --- /dev/null +++ b/examples/io_write.modal @@ -0,0 +1,5 @@ +?(?-) (This example prints hello world to the console.) + +<> (send ?:) (?:) + +send (hello world) \ No newline at end of file diff --git a/examples/lambda.modal b/examples/lambda.modal deleted file mode 100644 index 6c90efa..0000000 --- a/examples/lambda.modal +++ /dev/null @@ -1 +0,0 @@ -?((?x ?y) (?y ?x)) foo bar \ No newline at end of file diff --git a/examples/lisp.modal b/examples/lisp.modal deleted file mode 100644 index d082cd4..0000000 --- a/examples/lisp.modal +++ /dev/null @@ -1,13 +0,0 @@ -define nil () -define (pair (?x) (?y)) ((?x ?y)) -define (first (?x ?y)) (?x) -define (second (?x ?y)) (?y) - -define (quote ?x) (quote ?x) -define (if ?c ?t else ?f) (if/else ?c quote ?t quote ?f) -define (if/else (true) quote (?t) quote (?f)) (?t) -define (if/else (false) quote (?t) quote (?f)) (?f) - -define (hello) (bye) - -pair (pair (foo) (nil)) (baz) \ No newline at end of file diff --git a/examples/map.modal b/examples/map.modal deleted file mode 100644 index ba064f7..0000000 --- a/examples/map.modal +++ /dev/null @@ -1,8 +0,0 @@ -<> (foo ?x) (?x) -<> (map ?x (list ?l)) (map/l map/x ?x ?l) -<> (map/x ?x (?h ?t)) (?x ?h (map/x ?x ?t)) -<> (map/x ?x (?h)) (map/r (?x ?h)) -<> (?h (map/r ?t)) (?map/r (?h ?t)) -<> (map/l map/r ?l) (list ?l) - -map foo (list (1 (2 (3 (4 (5)))))) \ No newline at end of file diff --git a/examples/multiply.modal b/examples/multiply.modal deleted file mode 100644 index 790dd09..0000000 --- a/examples/multiply.modal +++ /dev/null @@ -1,199 +0,0 @@ -<> (-- ?x) () --- ( little endian binary integers ) - --- ( constants ) -<> zero ((0 ())) -<> one ((1 ())) -<> ten ((0 (1 (0 (1 ()))))) - --- ( decimal digit to binary ) -<> ((binary 0)) ((0 ())) -<> ((binary 1)) ((1 ())) -<> ((binary 2)) ((0 (1 ()))) -<> ((binary 3)) ((1 (1 ()))) -<> ((binary 4)) ((0 (0 (1 ())))) -<> ((binary 5)) ((1 (0 (1 ())))) -<> ((binary 6)) ((0 (1 (1 ())))) -<> ((binary 7)) ((1 (1 (1 ())))) -<> ((binary 8)) ((0 (0 (0 (1 ()))))) -<> ((binary 9)) ((1 (0 (0 (1 ()))))) - --- ( binary to decimal digit ) -<> ((decimal (0 ()))) (0) -<> ((decimal (1 ()))) (1) -<> ((decimal (0 (1 ())))) (2) -<> ((decimal (1 (1 ())))) (3) -<> ((decimal (0 (0 (1 ()))))) (4) -<> ((decimal (1 (0 (1 ()))))) (5) -<> ((decimal (0 (1 (1 ()))))) (6) -<> ((decimal (1 (1 (1 ()))))) (7) -<> ((decimal (0 (0 (0 (1 ())))))) (8) -<> ((decimal (1 (0 (0 (1 ())))))) (9) - --- reverse ()-terminated list -<> (reverse ?x) (reverse1 () ?x) -<> (reverse1 ?a ()) (?a) -<> (reverse1 ?a (?h ?t)) (reverse1 (?h ?a) ?t) - --- ( to integer ) -<> ((int ?*)) ((sum f (one) g reverse (?*))) -<> (g ()) (()) -<> (g (?h ?t)) (((binary ?h) g ?t)) -<> (f (?u) ()) (()) -<> (f (?u) (?h ?t)) (((mul ?h ?u) f ((mul ?u ten)) ?t)) - --- ( to binary str ) --- ( <> ((bstr ?x)) (emit force (0 (b ?x))) ) --- ( <> ((bstr ?x)) ((bstr1 () ?x)) ) -<> ((bstr ?x)) ((bstr1 force ?x ())) -<> ((bstr1 force/r () ?a)) (emit force/r (0 (b ?a))) -<> ((bstr1 force/r (?h ?t) ?a)) ((bstr1 force/r ?t (?h ?a))) - --- ( to string: TODO, need division for this one ) -<> ((str ?x)) ((str1 ?x ())) -<> ((str1 (0 ()) ?a)) (emit force ?a) -<> ((str1 (?h ?t) ?a)) ((str2 (divmod (?h ?t) ten) ?a)) -<> ((str2 (?q ?r) ?a)) ((str1 ?q ((decimal ?r) ?a))) - --- ( force a list to evaluate to digits/letters ) -<> ((?h force/r ?t)) (force/r (?h ?t)) -<> (force ()) (force/r ()) -<> (force (0 ?t)) ((0 force ?t)) -<> (force (1 ?t)) ((1 force ?t)) -<> (force (2 ?t)) ((2 force ?t)) -<> (force (3 ?t)) ((3 force ?t)) -<> (force (4 ?t)) ((4 force ?t)) -<> (force (5 ?t)) ((5 force ?t)) -<> (force (6 ?t)) ((6 force ?t)) -<> (force (7 ?t)) ((7 force ?t)) -<> (force (8 ?t)) ((8 force ?t)) -<> (force (9 ?t)) ((9 force ?t)) -<> (force (a ?t)) ((a force ?t)) -<> (force (b ?t)) ((b force ?t)) -<> (force (c ?t)) ((c force ?t)) -<> (force (d ?t)) ((d force ?t)) -<> (force (e ?t)) ((e force ?t)) -<> (force (f ?t)) ((f force ?t)) -<> (force (x ?t)) ((x force ?t)) - --- ( emit ) -<> (emit force/r ?*) (?*) - --- ( comparison operartions ) -<> ((cmp ?x ?y)) ((cmpc #eq ?x ?y)) -<> ((cmpc ?e () ())) (?e) -<> ((cmpc ?e (1 ?x) ())) (#gt) -<> ((cmpc ?e (0 ?x) ())) ((cmpc ?e ?x ())) -<> ((cmpc ?e () (1 ?y))) (#lt) -<> ((cmpc ?e () (0 ?y))) ((cmpc ?e () ?y)) -<> ((cmpc ?e (0 ?x) (0 ?y))) ((cmpc ?e ?x ?y)) -<> ((cmpc ?e (1 ?x) (0 ?y))) ((cmpc #gt ?x ?y)) -<> ((cmpc ?e (0 ?x) (1 ?y))) ((cmpc #lt ?x ?y)) -<> ((cmpc ?e (1 ?x) (1 ?y))) ((cmpc ?e ?x ?y)) - --- ( addition ) -<> ((add ?x ?y)) ((addc 0 ?x ?y)) -<> ((addc 0 () ())) (()) -<> ((addc 1 () ())) ((1 ())) --- ( <> ((addc ?c ?x ())) ((addc ?c ?x (0 ()))) ) --- ( <> ((addc ?c () ?y)) ((addc ?c (0 ()) ?y)) ) -<> ((addc 0 ?x ())) (?x) -<> ((addc 0 () ?y)) (?y) -<> ((addc 1 ?x ())) ((addc 1 ?x (0 ()))) -<> ((addc 1 () ?y)) ((addc 1 (0 ()) ?y)) -<> ((addc 0 (0 ?x) (0 ?y))) ((0 (addc 0 ?x ?y))) -<> ((addc 0 (0 ?x) (1 ?y))) ((1 (addc 0 ?x ?y))) -<> ((addc 0 (1 ?x) (0 ?y))) ((1 (addc 0 ?x ?y))) -<> ((addc 0 (1 ?x) (1 ?y))) ((0 (addc 1 ?x ?y))) -<> ((addc 1 (0 ?x) (0 ?y))) ((1 (addc 0 ?x ?y))) -<> ((addc 1 (0 ?x) (1 ?y))) ((0 (addc 1 ?x ?y))) -<> ((addc 1 (1 ?x) (0 ?y))) ((0 (addc 1 ?x ?y))) -<> ((addc 1 (1 ?x) (1 ?y))) ((1 (addc 1 ?x ?y))) - --- ( summation ) -<> ((sum ())) ((0 ())) -<> ((sum (?a ()))) (?a) -<> ((sum (?a (?b ?c)))) ((sum ((add ?a ?b) ?c))) - --- ( multiplication ) -<> ((mul ?x ?y)) ((mulc () ?x ?y)) -<> ((mulc ?t () ?y)) ((sum ?t)) -<> ((mulc ?t (0 ?x) ?y)) ((mulc ?t ?x (0 ?y))) -<> ((mulc ?t (1 ?x) ?y)) ((mulc (?y ?t) ?x (0 ?y))) - --- ( subtraction ) -<> ((sub ?x ?y)) (sub1 0 ?x ?y ()) -<> (sub1 0 () () ?s) (()) -<> (sub1 1 () () ?s) (#err) -<> (sub1 ?c ?x () ?s) (sub1 ?c ?x (0 ()) ?s) -<> (sub1 ?c () ?y ?s) (sub1 ?c (0 ()) ?y ?s) -<> (sub1 0 (0 ?x) (0 ?y) ?s) (sub1 0 ?x ?y (0 ?s)) -<> (sub1 0 (0 ?x) (1 ?y) ?s) (sub2 1 ?x ?y ?s) -<> (sub1 0 (1 ?x) (0 ?y) ?s) (sub2 0 ?x ?y ?s) -<> (sub1 0 (1 ?x) (1 ?y) ?s) (sub1 0 ?x ?y (0 ?s)) -<> (sub1 1 (0 ?x) (0 ?y) ?s) (sub2 1 ?x ?y ?s) -<> (sub1 1 (0 ?x) (1 ?y) ?s) (sub1 1 ?x ?y (0 ?s)) -<> (sub1 1 (1 ?x) (0 ?y) ?s) (sub1 0 ?x ?y (0 ?s)) -<> (sub1 1 (1 ?x) (1 ?y) ?s) (sub2 1 ?x ?y ?s) -<> (sub2 ?c ?x ?y ()) ((1 sub1 ?c ?x ?y ())) -<> (sub2 ?c ?x ?y (?h ?t)) ((0 sub2 ?c ?x ?y ?t)) - -<> (dec (0 ())) (#err) -<> (dec (1 ())) ((0 ())) -<> (dec (1 ?t)) ((0 ?t)) -<> (dec (0 ?t)) (dec1 (0 ?t)) -<> (dec1 (1 ())) (()) -<> (dec1 (1 ?t)) ((0 ?t)) -<> (dec1 (0 ?t)) ((1 dec1 ?t)) - --- ( inc ) -<> ((inc ())) ((1 ())) -<> ((inc (0 ?t))) ((1 ?t)) -<> ((inc (1 ?t))) ((0 (inc ?t))) - --- ( left shift; lshift x b means x< ((lshift ?x (0 ()))) (?x) -<> ((lshift ?x (1 ()))) ((0 ?x)) -<> ((lshift ?x (0 (?a ?b)))) ((lshift (0 ?x) dec (0 (?a ?b)))) -<> ((lshift ?x (1 (?a ?b)))) ((lshift (0 ?x) (0 (?a ?b)))) - -<> ((rshift1 (?a ()))) ((0 ())) -<> ((rshift1 (?a (?b ?c)))) ((?b ?c)) - --- ( divmod, i.e. quotient and remainder ) --- ( x is the dividend, or what's left of it ) --- ( y is the divisor ) --- ( s is the number of bits to shift, so far ) --- ( o is the next valuet o add to the quotient ) --- ( m is the next multiple of y to work with ) --- ( d is the quotient, so far ) -<> ((divmod ?x ?y)) ((divmod1 ?x ?y (cmp ?x ?y))) -<> ((divmod1 ?x ?y #lt)) ((zero ?x)) -<> ((divmod1 ?x ?y #eq)) ((one zero)) -<> ((divmod1 ?x ?y #gt)) ((divmod2 ?x ?y zero ?y)) - -<> ((divmod2 ?x ?y ?s ?m)) ((divmod3 ?x ?y ?s ?m (cmp ?x (0 ?m)))) -<> ((divmod3 ?x ?y ?s ?m #gt)) ((divmod2 ?x ?y (inc ?s) (0 ?m))) -<> ((divmod3 ?x ?y ?s ?m #eq)) ((divmod4 ?x ?y (inc ?s) (0 ?m) zero)) -<> ((divmod3 ?x ?y ?s ?m #lt)) ((divmod4 ?x ?y ?s ?m zero)) - -<> ((divmod4 ?x ?y (0 ()) ?m ?d)) (((add ?d one) (sub ?x ?y))) -<> ((divmod4 ?x ?y ?s ?m ?d)) ((divmod5 (sub ?x ?m) ?y dec ?s (rshift1 ?m) (add ?d (lshift one ?s)))) - -<> ((divmod5 (0 ()) ?y ?s ?m ?d)) ((?d (0 ()))) -<> ((divmod5 ?x ?y ?s ?m ?d)) ((divmod6 ?x ?y ?s ?m ?d (cmp ?x ?m))) - -<> ((divmod6 ?x ?y (0 ()) ?m ?d #lt)) ((?d ?x)) -<> ((divmod6 ?x ?y ?s ?m ?d #lt)) ((divmod5 ?x ?y dec ?s (rshift1 ?m) ?d)) -<> ((divmod6 ?x ?y ?s ?m ?d #eq)) ((divmod4 ?x ?y ?s ?m ?d)) -<> ((divmod6 ?x ?y ?s ?m ?d #gt)) ((divmod4 ?x ?y ?s ?m ?d)) - --- ( floor divison ) -<> ((div ?x ?y)) ((div1 (divmod ?x ?y))) -<> ((div1 (?q ?r))) (?q) - --- ( remainder ) -<> ((mod ?x ?y)) ((mod1 (divmod ?x ?y))) -<> ((mod1 (?q ?r))) (?r) - -(bstr (mul (int 123456789) (int 987654321))) \ No newline at end of file diff --git a/examples/prelude.modal b/examples/prelude.modal deleted file mode 100644 index b2b2f0a..0000000 --- a/examples/prelude.modal +++ /dev/null @@ -1,144 +0,0 @@ -1 -> (s (0)); - - -neg (neg ?x) -> ?x; -neg (0) -> 0; - - -add (s ?x) (s ?y) -> s (add ?x (s ?y)); -add (0) (s ?x) -> s ?x; -add (s ?x) (0) -> s ?x; -add (0) (0) -> 0; - - -?x + ?y + ?z -> (?x + ?y) + ?z; - - -?x + ?y -> add ?x ?y; - - -sub (s ?x) (s ?y) -> sub ?x ?y; -sub (s ?x) (0) -> s ?x; -sub (0) (s ?x) -> neg (s ?x); -sub (0) (0) -> 0; - - -?x - ?y -> sub ?x ?y; - - -mul (s ?x) (s ?y) -> (s ?x) + (mul (s ?x) ((s ?y) - 1)); -mul (s ?x) (s (0)) -> s ?x; -mul (s ?x) (0) -> 0; -mul (0) (s ?x) -> 0; - - -?x * ?y -> mul ?x ?y; - - -Ensures that a list or a number has been reduced to its normal form. ; - -reduced (0) -> true; -reduced (nil) -> true; -reduced (s ?x) -> reduced ?x; -reduced (?h : ?t) -> reduced ?t; -reduced ?x -> false; - - -Because there may be conflicts with expressions that -are currently being reduced, we need to fold over reduced -lists, i.e ones that have already been fully generated. ; - -fold (?f) ?i ?l -> fold reduced ?l (?f) ?i ?l; -fold true (?f) ?i (nil) -> ?i; -fold true (?f) ?i (?h : (nil)) -> ?f ?i ?h; -fold true (?f) ?i (?h : ?t) -> ?f ?i (fold (?f) ?h ?t); -fold false (?f) ?i ?l -> fold (?f) ?i ?l; - - -factorial (s (0)) -> s (0); -factorial (s ?x) -> (s ?x) * (factorial ((s ?x) - 1)); - - -sum (?h : ?t) -> fold (add) (0) (?h : ?t); - - -range ?x (s (0)) -> ?x : (nil); -range ?x (s ?y) -> ?x : (range (?x + 1) ((s ?y) - 1)); - - -Disgusting (yet valid) hack for currying. -We need lambdas. ; - -unpack (?h : nil) -> ?h; -unpack (?h : ?t) -> ?h unpack ?t; -unpack (?x) -> ?x; -unpack (?x . -> ?x unpack (; - - -:: (?f) ?a -> ?f unpack ?a; - - -mapp (?f) ?a (nil) -> nil; -mapp (?f) ?a (?h : (nil)) -> (?f unpack ?a ?h) : (nil); -mapp (?f) ?a (?h : ?t) -> (?f unpack ?a ?h) : (mapp (?f) ?a ?t); - - -map (?f) (nil) -> nil; -map (?f) (?h : nil) -> (?f ?h) : (nil); -map (?f) (?h : ?t) -> (?f ?h) : (map (?f) ?t); - - -product ?x -> fold (mul) 1 ?x; - - -factorial2 ?x -> product (range 1 ?x); - - -contains ?x (nil) -> false; -contains ?x (?x : ?t) -> true; -contains ?x (?h : ?t) -> contains ?x ?t; - - -unique (nil) -> nil; -unique false (?h : ?t) -> ?h : (unique ?t); -unique true (?h : ?t) -> unique ?t; -unique (?h : ?t) -> unique contains ?h ?t (?h : ?t); - - -length (nil) -> 0; -length (?h : ?t) -> s (length ?t); - - -zipWith (?f) (nil) (nil) -> nil; -zipWith (?f) (?h : ?t) (nil) -> nil; -zipWith (?f) (nil) (?h : ?t) -> nil; -zipWith (?f) (?h1 : ?t1) (?h2 : ?t2) -> (?f ?h1 ?h2) : (zipWith (?f) ?t1 ?t2); - - -evens ?x -> zipWith (add) (range (0) ?x) (range (0) ?x); - - -not (not ?x) -> ?x; -not true -> false; -not false -> true; - - -any ?x -> contains true ?x; - - -all ?x -> not contains false ?x; - - -none ?x -> not any ?x; - - -add1 ?x -> add ?x 1; - - -square ?x -> ?x * ?x; - - -reduce (s ?x) -> s (reduce ?x); -reduce (0) -> (0); -reduce (?h : ?t) -> ?h : (reduce ?t); -reduce (nil) -> nil; diff --git a/examples/prelude2.modal b/examples/prelude2.modal deleted file mode 100644 index c24bd29..0000000 --- a/examples/prelude2.modal +++ /dev/null @@ -1,141 +0,0 @@ -define [-- ?x] {} - -define [form ?x ?y] { - define ?x ?y -} - -define [rule ?x ?y] { - define ?x ?y -} - -define [?x -> ?y] { - define ?x ?y -} - -[(?x) = (?x)] -> { - true -} - -[(?x) = (?y)] -> { - false -} - -[false or false] -> { - false -} - -[true or false] -> { - true -} - -[false or true] -> { - true -} - -[true or true] -> { - true -} - -[quote ?x] -> { - quote ?x -} - -[unquote (quote ?x)] -> { - ?x -} - -form [ - if ?condition - ?true - else - ?false -] -{ - if/else ?condition { - quote ?true - } { - quote ?false - } -} - -form [ - if ?condition - ?branch -] -{ - if/q ?condition { - quote ?branch - } -} - -rule [ - if/q (true) - ?branch -] -{ - unquote ?branch -} - -rule [ - if/q (false) - ?branch -] -{} - -rule [ - if/else (true) - ?true - ?false -] -{ - unquote ?true -} - -rule [ - if/else (false) - ?true - ?false -] -{ - unquote ?false -} - - -[factorial (?x)] -> { - if ((?x) = (1)) { - 1 - } - else { - ?x * factorial (?x - 1) - } -} - -[fibonacci (?number)] -> { - if((?number) = (0) or (?number) = (1)) { - ?number - } - else { - fibonacci (?number - 1) + fibonacci (?number - 2) - } -} - -[range (?low) (?high)] -> { - if((?low) = (?high + 1)) { - nil - } - else { - ?low : range (?low + 1) (?high) - } -} - -[fold (?operation) (?initial) (nil)] -> { - ?initial -} - -[fold (?operation) (?initial) (?head : ?tail)] -> { - ?operation ?head (fold (?operation) (?initial) ?tail) -} - -[sum ?list] -> { - fold (add) (0) ?list -} diff --git a/examples/sierpinski.modal b/examples/sierpinski.modal deleted file mode 100644 index 15cc210..0000000 --- a/examples/sierpinski.modal +++ /dev/null @@ -1,50 +0,0 @@ -<> (written by) (capital) -<> (?: print) (?:) - -<> (?* explode) ((List (?*))) -<> ((List ?*) implode) (?*) - -<> (MkEmpty) (_________________________________ explode) - -<> ((List (?1 (?2 ?l))) MkWindow) ((Window (?1 ?2) ?l)) - -<> ((Window (?1 ?2) ( )) roll) ((WindowExhausted)) -<> ((Window (?1 ?2) (?3 )) roll) ((Window (?1 ?2 ?3) ())) -<> ((Window (?1 ?2) (?3 ?l)) roll) ((Window (?1 ?2 ?3) ?l)) - -<> ((Window (?1 ?2 ?3) ( )) roll) ((Window (?2 ?3 ) ())) -<> ((Window (?1 ?2 ?3) (?4 )) roll) ((Window (?2 ?3 ?4) ())) -<> ((Window (?1 ?2 ?3) (?4 ?l)) roll) ((Window (?2 ?3 ?4) ?l)) - - -<> (?p apply-rule) ((Rule (?p explode MkWindow MkEmpty apply-rule)) implode) -<> ((Window (?1 ?2 ?3) ()) (List (?h ?t)) apply-rule) ((?1 ?2 ?3) cell-state ((?2 ?3) cell-state (Rule'))) -<> ((Window ?v ?l) (List (?h ?t)) apply-rule) ( ?v cell-state ((Window ?v ?l) roll (List ?t) apply-rule)) - -<> (Rule (Rule' ?l)) (List ?l) -<> (?y (Rule' )) (Rule' (?y)) -<> (?x (Rule' ?y)) (Rule' (?x ?y)) - -<> ((* * *) cell-state) (_) -<> ((* * _) cell-state) (*) -<> ((* _ *) cell-state) (_) -<> ((* _ _) cell-state) (*) -<> ((_ * *) cell-state) (*) -<> ((_ * _) cell-state) (_) -<> ((_ _ *) cell-state) (*) -<> ((_ _ _) cell-state) (_) - -<> ((* _) cell-state) (*) -<> ((_ *) cell-state) (*) -<> ((_ _) cell-state) (_) - -<> ((Gas ?f) ?p (?r) MkTriangle) ((Triangle ((Gas ?f) ?p (?r) build))) -<> ((Gas (?g ?f)) ?p (?r) build) (?p ((Gas ?f) ?p ?r (?r) build)) -<> ((Gas (Empty)) ?p ?r build) (?p (Triangle')) - -<> (Triangle (Triangle' ?l)) (List (\n ?l)) -<> (?y (Triangle' )) (Triangle' (?y (\n (\n)))) -<> (?x (Triangle' ?y)) (Triangle' (?x (\n ?y))) - - -(Gas (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (Empty))))))))))))))))) ________________*________________ (apply-rule) MkTriangle implode print \ No newline at end of file diff --git a/examples/string_join.modal b/examples/string_join.modal new file mode 100644 index 0000000..8f4b8ea --- /dev/null +++ b/examples/string_join.modal @@ -0,0 +1,11 @@ +?(?-) (This example joins two tokens.) + +<> (join (?a) (?*)) (join reverse (?a) List (?*)) +<> (join List () List ?*) (?*) +<> (join List (?x ?y) List ?z) (join List ?y List (?x ?z)) + +<> (reverse List ()) (List) +<> (reverse (?*)) (reverse List (?*) ()) +<> (reverse List (?x ?y) ?z) (reverse List ?y (?x ?z)) + +join (foo) (bar) \ No newline at end of file diff --git a/examples/string_reverse.modal b/examples/string_reverse.modal new file mode 100644 index 0000000..4e14c75 --- /dev/null +++ b/examples/string_reverse.modal @@ -0,0 +1,7 @@ +?(?-) (This example reverses the string modal, into ladom.) + +<> (reverse List () ?*) (?*) +<> (reverse (?*)) (reverse List (?*) ()) +<> (reverse List (?x ?y) ?z) (reverse List ?y (?x ?z)) + +(reverse (modal)) \ No newline at end of file diff --git a/examples/test.modal b/examples/test.modal deleted file mode 100644 index fe024f6..0000000 --- a/examples/test.modal +++ /dev/null @@ -1,16 +0,0 @@ -<> (explode ?*) (str (?*)) -<> (reverse (str (?h ?t))) (reverse/l ?t (?h)) -<> (reverse (str (?h))) (?h) -<> (reverse/l (?h ?t) ?l) (reverse/l ?t (?h ?l)) -<> (reverse/l (?h) ?l) (str (?h ?l)) -<> (implode str ?*) (?*) -<> (empty-register) (?x) -<> (explode ?*) (str (?*)) -<> (eq ?x ?x) (#t) -<> (eq ?x ?y) (#f) -<> (?x dup) (?x ?x) -<> (?x ?y swap) (?y ?x) -<> (?x pop) () -<> (print ?:) (?:) - -(implode reverse (explode hello)) (explode hello) empty-register (eq abc abc) (eq abc def) (1 2 3) (4 5 6) swap pop dup (hey 1234 pop) (print Done.) diff --git a/examples/tests.modal b/examples/tests.modal new file mode 100644 index 0000000..9d6d20a --- /dev/null +++ b/examples/tests.modal @@ -0,0 +1,73 @@ +?(?-) (This example tests various aspects of the implementation.) + +<> (?: print) (?:) +<> (?x = ?x test) (#ok) +<> (?x = ?y test) (#fail) + +?(?-) (Inline rules) + +<> ((?x -> ?y)) (<> ?x ?y) +(nap -> (tap =)) + +nap tap test + +?(?-) (Empty replacements) + +<> (?x pop-plain) +<> (?x pop) () + +abc def pop-plain = abc test +abc def pop = abc test + +?(?-) (Basic replacements) + +<> (replace-name (foo)) ((bar) =) + +replace-name (foo) (bar) test + +?(?-) (Basic register setups) + +<> (dup (?x)) ((?x ?x) =) +<> (swap (?x ?y)) ((?y ?x) =) +<> (compare (?x ?x ?x)) ((#t) =) + +dup (abc) (abc abc) test +swap (abc def) (def abc) test +compare (abc abc abc) (#t) test + +?(?-) (Empty register replacement) + +<> (replace-empty ?x) (?y) + +replace-empty abc = ?y 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 +abc ?(?x) def = abc test + +?(?-) (Explode) + +<> (explode ?*) ((?*) =) + +explode cow (c (o (w ()))) test + +?(?-) (Implode) + +<> (implode ?*) (?* =) + +implode (b (a (t ()))) bat test + +?(?-) (List reversal) + +<> (reverse List () ?*) (?*) +<> (reverse (?*)) (reverse List (?*) ()) +<> (reverse List (?x ?y) ?z) (reverse List ?y (?x ?z)) + +reverse (modal) = ladom test diff --git a/examples/tictactoe.modal b/examples/tictactoe.modal index 6991bbe..d69b1c3 100644 --- a/examples/tictactoe.modal +++ b/examples/tictactoe.modal @@ -1,7 +1,7 @@ --- (Tic Tac Toe) +?(?-) (This example demonstrates how to implement a 2-players game of Tic Tac Toe) <> (-- ?x) () -<> (READ) (?~) +<> (READ ?~) (?~) -- (Print) @@ -34,8 +34,8 @@ -- (Play) -<> (ready) (display READ play) -<> (?x run wait) (READ play) +<> (ready) (display READ stdin play) +<> (?x run wait) (READ stdin play) <> (?x victory) ((?x wins!\n) put-str) -- (Interface) diff --git a/makefile b/makefile index 748271f..eaf3ae3 100644 --- a/makefile +++ b/makefile @@ -8,11 +8,10 @@ all: dest dest: @ mkdir -p bin run: all bin/modal - @ bin/modal examples/hello.modal + @ bin/modal examples/hello.modal 2> /dev/null test: bin/modal-debug bin/modal @ bin/modal -v - @ bin/modal-debug examples/test.modal "(arg1) (arg2 (arg3))" - @ bin/modal examples/test.modal 2> /dev/null + @ bin/modal-debug examples/tests.modal install: bin/modal cp bin/modal ~/bin/ uninstall: diff --git a/src/modal.c b/src/modal.c index 15d97a2..e159e28 100644 --- a/src/modal.c +++ b/src/modal.c @@ -5,11 +5,11 @@ typedef struct { char *a, *b; } Rule; -static int dst; +static int flip, rmin = 0xff, rmax = 0x00, cycles = 0x10000; static Rule rules[0x1000], lambda, *rules_ = rules; static char dict[0x8000], *dict_ = dict; -static char bank_a[0x4000], *prog_ = bank_a; -static char bank_b[0x4000], *outp_ = bank_b; +static char bank_a[0x4000], *src_ = bank_a; +static char bank_b[0x4000], *dst_ = bank_b; static char *regs[0x100]; #define spacer(c) (c <= ' ' || c == '(' || c == ')') @@ -37,53 +37,52 @@ set_reg(int r, char *b) char *a = regs[r], *aa = walk(a), *bb = walk(b); while(a < aa && b < bb) if(*a++ != *b++) return 0; - } else + } else { regs[r] = b; + if(r < rmin) rmin = r; + if(r > rmax) rmax = r; + } return 1; } static void put_reg(char r) { - char c, *s = regs[(int)r]; - if(r == '~') { - /* special stdin */ + char c, *s = regs[(int)r], *ss; + if(!s) { + *dst_++ = '?', *dst_++ = r; + return; + } + 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; + while((c = *s++) && !spacer(c)) + *dst_++ = c, *dst_++ = ' ', *dst_++ = '(', depth++; + for(i = 0; i < depth; i++) + *dst_++ = ')'; + } + } else if(r == ':') { /* special stdout */ + if(*s == '(') s++, --ss; + while(s < ss) { + c = *s++; + if(c == '\\') { + switch(*s++) { + case 't': putc(0x09, stdout); break; + case 'n': putc(0x0a, stdout); break; + case 's': putc(0x20, stdout); break; + } + } else + putc(c, stdout); + } + } else if(r == '~') { /* special stdin */ while(fread(&c, 1, 1, stdin) && c >= ' ') - *outp_++ = c; - } else if(s) { - char *ss = walk(s); - if(r == '*') { - /* special implode */ - if(*s == '(') { - while(s < ss && (c = *s++)) - if(!spacer(c)) *outp_++ = c; - } - /* special explode */ - else { - int i, depth = 0; - while((c = *s++) && !spacer(c)) - *outp_++ = c, *outp_++ = ' ', *outp_++ = '(', depth++; - for(i = 0; i < depth; i++) - *outp_++ = ')'; - } - } else if(r == ':') { - /* special stdout */ - if(*s == '(') s++, --ss; - while(s < ss) { - c = *s++; - if(c == '\\') { - switch(*s++) { - case 't': putc(0x09, stdout); break; - case 'n': putc(0x0a, stdout); break; - case 's': putc(0x20, stdout); break; - } - } else - putc(c, stdout); - } - } else - while(s < ss) *outp_++ = *s++; + *dst_++ = c; } else - *outp_++ = '?', *outp_++ = r; + while(s < ss) *dst_++ = *s++; } static char * @@ -91,15 +90,18 @@ match_rule(Rule *r, char *p) { int i; char c, last = 0, *a = r->a, *b = p; - for(i = 0x21; i < 0x7f; i++) - regs[i] = 0; + if(rmax) { + for(i = 0; i <= rmax; i++) + regs[i] = 0; + rmin = 0xff, rmax = 0x00; + } while((c = *a)) { if(spacer(last) && c == '?') { if(!set_reg(*(++a), b)) return NULL; a++, b = walk(b); continue; } - if(*a != *b) return NULL; + if(c != *b) return NULL; a++, b++, last = c; } c = *b; @@ -109,30 +111,31 @@ match_rule(Rule *r, char *p) static int commit_rule(Rule *r, char *s, int create) { - while((*outp_++ = *s++)) + while((*dst_++ = *s++)) ; - *outp_++ = 0; - if((dst = !dst)) - prog_ = bank_b, outp_ = bank_a; + *dst_++ = 0; + if((flip = !flip)) + src_ = bank_b, dst_ = bank_a; else - prog_ = bank_a, outp_ = bank_b; + 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, prog_); + fprintf(stderr, "%02d %s\n", r->id, src_); return 1; } static int write_rule(Rule *r, char last, char *res) { - char c, *b = r->b, *origin = outp_; + char c, *b = r->b, *origin = dst_; while((c = *b++)) if(spacer(last) && c == '?') put_reg(*b++); else - *outp_++ = c, last = c; - if(last == ' ' && outp_ - origin == 0) outp_--; + *dst_++ = c, last = c; + if(dst_ == origin) + while(*res == ' ') res++; return commit_rule(r, res, 0); } @@ -141,11 +144,14 @@ parse_frag(char *s) { char c, *ss; while((c = *s) && c <= ' ') s++; - if(*s != ')' && *s != '<' && s[1] != '>') { + if(*s != ')' && !(*s == '<' && s[1] == '>')) { ss = walk(s); - if(*s == '(') s++, ss--; - while(s < ss) *dict_++ = *s++; - s++; + if(*s == '(') { + s++; + while(s < ss - 1) *dict_++ = *s++; + s++; + } else + while(s < ss) *dict_++ = *s++; } *dict_++ = 0; return s; @@ -163,7 +169,7 @@ create_rule(Rule *r, int id, char *s) static int rewrite(void) { - char c, last = 0, *cap, *s = dst ? bank_b : bank_a, *res; + char c, last = 0, *cap, *s = src_, *res; while((c = *s) && c <= ' ') s++; while((c = *s)) { if(spacer(last)) { @@ -185,10 +191,10 @@ rewrite(void) if((res = match_rule(r, s)) != NULL) return write_rule(r, last, res); } - *outp_++ = last = c; + *dst_++ = last = c; s++; } - *outp_++ = 0; + *dst_++ = 0; return 0; } @@ -200,9 +206,9 @@ 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, 13 Apr 2024.\n"); + return !printf("Modal Interpreter, 16 Apr 2024.\n"); if(!(f = fopen(argv[1], "r"))) - return !printf("Invalid Modal file: %s.\n", argv[1]); + return !fprintf(stderr, "Invalid Modal file: %s.\n", argv[1]); while(fread(&c, 1, 1, f)) { c = c <= 0x20 ? 0x20 : c; if(w > bank_a) { @@ -215,6 +221,6 @@ main(int argc, char **argv) while(*(--w) <= ' ') *w = 0; fclose(f); while(rewrite()) - ; + if(!cycles--) return !fprintf(stderr, "Cycle limit exceeded.\n"); return 0; } \ No newline at end of file