From 0bf2733e9f1887901e4b94be300fce99d982b83f Mon Sep 17 00:00:00 2001 From: daddinuz Date: Fri, 21 Jun 2024 22:47:24 +0200 Subject: [PATCH 01/17] update parser, builtins and add more examples --- Cargo.lock | 16 +- examples/alice_n_bob.rat | 7 + examples/fact.rat | 2 + examples/fib.rat | 2 +- examples/mergesort.rat | 4 + examples/parallel-mergesort.rat | 13 ++ lib/math.rat | 6 +- lib/seq.rat | 29 +++ lib/std.rat | 6 +- rat-cli/src/error.rs | 7 - rat-cli/src/main.rs | 57 +++--- rat/src/builtin.rs | 313 ++++++++++++++++++++++---------- rat/src/channel.rs | 10 +- rat/src/grammar.pest | 37 ++-- rat/src/lib.rs | 4 - rat/src/parser.rs | 2 +- rat/src/quote.rs | 84 ++++++--- rat/src/vocabulary.rs | 62 ++++--- rat/src/word.rs | 52 ++++-- 19 files changed, 474 insertions(+), 239 deletions(-) create mode 100644 examples/alice_n_bob.rat create mode 100644 examples/fact.rat create mode 100644 examples/mergesort.rat create mode 100644 examples/parallel-mergesort.rat create mode 100644 lib/seq.rat diff --git a/Cargo.lock b/Cargo.lock index f0fc7a9..76ee54b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,9 +23,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" @@ -385,9 +385,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -523,9 +523,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", diff --git a/examples/alice_n_bob.rat b/examples/alice_n_bob.rat new file mode 100644 index 0000000..0fd4a3e --- /dev/null +++ b/examples/alice_n_bob.rat @@ -0,0 +1,7 @@ +: std @ rat\std ; + +: alice ← ["alice\n" produce consume receive say] spawn ; +: bob ← [consume receive say "bob\n" produce] spawn ; + +alice bob std\dup2 swap send send +"press [enter] to continue\n" ask diff --git a/examples/fact.rat b/examples/fact.rat new file mode 100644 index 0000000..56ff0b9 --- /dev/null +++ b/examples/fact.rat @@ -0,0 +1,2 @@ +: fact ← [dup zero?] [incr] [dup decr] [mul] linrec ; +5 fact say diff --git a/examples/fib.rat b/examples/fib.rat index 35271af..2817e2a 100644 --- a/examples/fib.rat +++ b/examples/fib.rat @@ -1,2 +1,2 @@ -: fib ← [3 <] [pop 1] [decr] [2 -] [+] binrec ; +: fib ← [dup 3 lt] [pop 1] [decr dup decr] [add] binrec ; 30 fib say diff --git a/examples/mergesort.rat b/examples/mergesort.rat new file mode 100644 index 0000000..d60e891 --- /dev/null +++ b/examples/mergesort.rat @@ -0,0 +1,4 @@ +: seq @ rat\seq ; + +[-23714 36911 27209 -61081 4487 62986 43562 59953 -6002 -64976 6222 37230 1774 60450 35372 9313 -63141 -10099 -56599 37381 29627 17147 -56774 46348 25159 42717 -10426 -38088 -9482 -51818 -13225 -22274 -52566 -5587 -148 59711 51437 6343 50139 32437 27966 -34985 167 27161 -53411 -6759 -27066 -7772 49899 -24127 7940 61517 -14064 -4433 6018 42197 -24241 4939 23687 -27950 -60335 -483 -51116 -201 21847 -65149 46808 49486 -6132 4372 14587 60525 14700 8373 -48827 -64401 -53524 -28842 -10959 -56034 -64763 -54632 28581 -3277 5279 7684 -26031 32221 1723 59531 -34723 17671 3424 -30493 28938 -12043 -27853 -14788 -34395 -23175 39083 -3314 16725 -14123 5069 -59857 52477 -25028 9931 -27366 41663 10612 -46240 27308 7778 -12942 37028 -18502 59012 53713 60519 -49390 -15897 41667 55977 45961 39978 59934 23858 -23789 -17806 -14129 -36824 -57834 -28443 -22873 26639 -20046 -57731 -16443 -599 -2646 8985 -14817 -10395 -42440 -59983 3357 44965 -44840 36400 -10323 -39719 45791 -27538 15597 7872 -19558 54625 -10621 27469 -61915 -45654 -61333 10374 50181 5656 8559 -9822 -9340 23135 -11774 -28400 -44677 304 37783 -56801 -45383 59955 23509 55993 -61971 16262 -49607 39590 -27209 1339 -56543 -41882 64893 50150 -16153 -317 -16469 7629 19020 15578 46013 53541 -27485 60355 -28348 -63558 -45715 -43954 62904 -8753 29052 -56968 52829 31804 45589 -26416 30184 29918 -38968 19638 -24968 -24088 -9447 48799 -50660 43610 -50411 -47355 -59101 59279 34413 55334 -16776 50629 63673 -44714 -32217 -37943 -21810 -51476 33889 6583 65273 60878 -13805 59344 34343 -43042 25481 40781 -37723 -39856 -19967 -54323 -6219 -24811 -51108 4870 -20829] +seq\mergesort say diff --git a/examples/parallel-mergesort.rat b/examples/parallel-mergesort.rat new file mode 100644 index 0000000..5935dfd --- /dev/null +++ b/examples/parallel-mergesort.rat @@ -0,0 +1,13 @@ +: seq @ rat\seq ; +: math @ rat\math ; + +# with program forming +: p ← quote [seq\mergesort produce] cat spawn ; +: par-ms ← dup len math\halve split [p] unary2 [receive] unary2 seq\merge ; + +# with message passing +: p ← [consume seq\mergesort produce] spawn ; +: par-ms ← dup len math\halve split [p dup rotate send] unary2 [receive] unary2 seq\merge ; + +[-23714 36911 27209 -61081 4487 62986 43562 59953 -6002 -64976 6222 37230 1774 60450 35372 9313 -63141 -10099 -56599 37381 29627 17147 -56774 46348 25159 42717 -10426 -38088 -9482 -51818 -13225 -22274 -52566 -5587 -148 59711 51437 6343 50139 32437 27966 -34985 167 27161 -53411 -6759 -27066 -7772 49899 -24127 7940 61517 -14064 -4433 6018 42197 -24241 4939 23687 -27950 -60335 -483 -51116 -201 21847 -65149 46808 49486 -6132 4372 14587 60525 14700 8373 -48827 -64401 -53524 -28842 -10959 -56034 -64763 -54632 28581 -3277 5279 7684 -26031 32221 1723 59531 -34723 17671 3424 -30493 28938 -12043 -27853 -14788 -34395 -23175 39083 -3314 16725 -14123 5069 -59857 52477 -25028 9931 -27366 41663 10612 -46240 27308 7778 -12942 37028 -18502 59012 53713 60519 -49390 -15897 41667 55977 45961 39978 59934 23858 -23789 -17806 -14129 -36824 -57834 -28443 -22873 26639 -20046 -57731 -16443 -599 -2646 8985 -14817 -10395 -42440 -59983 3357 44965 -44840 36400 -10323 -39719 45791 -27538 15597 7872 -19558 54625 -10621 27469 -61915 -45654 -61333 10374 50181 5656 8559 -9822 -9340 23135 -11774 -28400 -44677 304 37783 -56801 -45383 59955 23509 55993 -61971 16262 -49607 39590 -27209 1339 -56543 -41882 64893 50150 -16153 -317 -16469 7629 19020 15578 46013 53541 -27485 60355 -28348 -63558 -45715 -43954 62904 -8753 29052 -56968 52829 31804 45589 -26416 30184 29918 -38968 19638 -24968 -24088 -9447 48799 -50660 43610 -50411 -47355 -59101 59279 34413 55334 -16776 50629 63673 -44714 -32217 -37943 -21810 -51476 33889 6583 65273 60878 -13805 59344 34343 -43042 25481 40781 -37723 -39856 -19967 -54323 -6219 -24811 -51108 4870 -20829] +par-ms say diff --git a/lib/math.rat b/lib/math.rat index f39c90b..a04c883 100644 --- a/lib/math.rat +++ b/lib/math.rat @@ -2,5 +2,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -÷ abs ← negative? [neg] if ; -÷ square ← dup * ; +÷ abs ← dup negative? [neg] if ; +÷ halve ← 1 shr ; +÷ double ← 1 shl ; +÷ square ← dup mul ; diff --git a/lib/seq.rat b/lib/seq.rat new file mode 100644 index 0000000..6cedbba --- /dev/null +++ b/lib/seq.rat @@ -0,0 +1,29 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +: std @ rat\std ; +: math @ rat\math ; + +÷ empty? ← len zero? ; + +÷ merge ← + [std\dup2 [empty?] unary2 or] + [dup empty? [pop] [std\popd] if-else] + [ + std\dup2 [first] unary2 lt + [[[first quote] [suffix] std\bi] dip] + [[first quote] [suffix] std\bi std\swapd] + if-else + ] + [cat] + linrec +; + +÷ mergesort ← + [dup len 1 le] + [] + [dup len math\halve split] + [merge] + binrec +; diff --git a/lib/std.rat b/lib/std.rat index 88227f4..13390cb 100644 --- a/lib/std.rat +++ b/lib/std.rat @@ -2,11 +2,15 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -÷ popd ← [pop] dip ; +÷ popd ← swap pop ; ÷ dupd ← [dup] dip ; ÷ swapd ← [swap] dip ; ÷ over ← dupd swap ; ÷ overd ← [over] dip ; +÷ dup2 ← over over ; + ÷ bi ← [[quote] dip over [cat] dip] dip cat [i] dip i ; + +÷ case ← swap at i ; diff --git a/rat-cli/src/error.rs b/rat-cli/src/error.rs index 5c4c17c..9a8d625 100644 --- a/rat-cli/src/error.rs +++ b/rat-cli/src/error.rs @@ -10,7 +10,6 @@ use std::io::Error as IoError; use rustyline::error::ReadlineError; -use rat::effect::Effect; use rat::parser::ParseError; pub struct CliError(Box); @@ -27,12 +26,6 @@ impl From for CliError { } } -impl From for CliError { - fn from(effect: Effect) -> Self { - Self(format!("Unhandled effect: {effect:?}").into()) - } -} - impl From for CliError { fn from(error: FmtError) -> Self { Self(error.into()) diff --git a/rat-cli/src/main.rs b/rat-cli/src/main.rs index aa2bb34..410bc0c 100644 --- a/rat-cli/src/main.rs +++ b/rat-cli/src/main.rs @@ -11,6 +11,7 @@ use std::fs::{File, OpenOptions}; use std::io::{ErrorKind, Read}; use std::path::{Path, PathBuf}; +use rat::quote::DisplayAdapter; use rustyline::error::ReadlineError; use rustyline::highlight::MatchingBracketHighlighter; use rustyline::validate::MatchingBracketValidator; @@ -29,35 +30,17 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub fn main() -> Result<(), CliError> { let mut parser = Parser::with_prelude(); let mut evaluator = Evaluator::new(); - - let mut source = String::new(); + let mut source_paths = Vec::new(); + let mut source_buffer = String::new(); let mut interactive = false; let mut show_usage = false; let mut show_license = false; - let mut has_source_files = false; env::args() .skip(1) .try_for_each(|arg| -> Result<(), CliError> { match arg.as_str() { - path if !path.starts_with('-') => { - let mut file = File::open(path)?; - - source.clear(); - file.read_to_string(&mut source)?; - has_source_files |= !source.is_empty(); - - match interpret( - Origin::Path(Path::new(path)), - &source, - &mut parser, - &mut evaluator, - ) { - Err(error) if interactive => error.report(), - error @ Err(_) => return error, - _ => (), - } - } + _ if !arg.starts_with('-') => source_paths.push(arg), "-h" | "--help" => show_usage = true, "-i" | "--interactive" => interactive = true, "--license" => show_license = true, @@ -67,7 +50,25 @@ pub fn main() -> Result<(), CliError> { Ok(()) })?; - if !interactive && !has_source_files { + for path in source_paths.iter() { + let mut file = File::open(path)?; + + source_buffer.clear(); + file.read_to_string(&mut source_buffer)?; + + match interpret( + Origin::Path(Path::new(path)), + &source_buffer, + &mut parser, + &mut evaluator, + ) { + Err(error) if interactive => error.report(), + error @ Err(_) => return error, + _ => (), + } + } + + if !interactive && source_paths.is_empty() { if show_usage { println!("{USAGE}"); return Ok(()); @@ -79,8 +80,8 @@ pub fn main() -> Result<(), CliError> { } } - if interactive || !has_source_files { - repl(&mut parser, &mut evaluator, !has_source_files)?; + if interactive || source_paths.is_empty() { + repl(&mut parser, &mut evaluator, source_paths.is_empty())?; } Ok(()) @@ -160,7 +161,13 @@ fn interpret( evaluator: &mut Evaluator, ) -> Result<(), CliError> { let program = parser.parse(origin, source)?; - evaluator.evaluate(program)?; + evaluator.evaluate(program).map_err(|effect| { + format!( + "unahandled effect: {effect:?}\nstack (top rightmost): {:?}", + DisplayAdapter::new(&evaluator.stack) + ) + })?; + Ok(()) } diff --git a/rat/src/builtin.rs b/rat/src/builtin.rs index 0900d74..8107196 100644 --- a/rat/src/builtin.rs +++ b/rat/src/builtin.rs @@ -227,25 +227,10 @@ pub fn eq(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; match stack[..] { - [.., ref mut lhs @ Expression::Integer(_), Expression::Integer(r)] => match *lhs { - Expression::Integer(l) => { - *lhs = Expression::Boolean(Boolean(l == r)); - stack.pop(); - Ok(()) - } - _ => unreachable!(), - }, - [.., ref mut lhs @ Expression::Decimal(_), Expression::Decimal(r)] => match *lhs { - Expression::Decimal(l) => { - *lhs = Expression::Boolean(Boolean(l == r)); - stack.pop(); - Ok(()) - } - _ => unreachable!(), - }, - [.., _, _] => { - stack.push(signal::type_error().into()); - Err(Effect::Raise) + [.., ref mut lhs, ref rhs] => { + *lhs = Expression::Boolean(Boolean(*lhs == *rhs)); + stack.pop(); + Ok(()) } _ => { stack.push(signal::stack_underflow().into()); @@ -258,25 +243,10 @@ pub fn ne(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; match stack[..] { - [.., ref mut lhs @ Expression::Integer(_), Expression::Integer(r)] => match *lhs { - Expression::Integer(l) => { - *lhs = Expression::Boolean(Boolean(l != r)); - stack.pop(); - Ok(()) - } - _ => unreachable!(), - }, - [.., ref mut lhs @ Expression::Decimal(_), Expression::Decimal(r)] => match *lhs { - Expression::Decimal(l) => { - *lhs = Expression::Boolean(Boolean(l != r)); - stack.pop(); - Ok(()) - } - _ => unreachable!(), - }, - [.., _, _] => { - stack.push(signal::type_error().into()); - Err(Effect::Raise) + [.., ref mut lhs, ref rhs] => { + *lhs = Expression::Boolean(Boolean(*lhs != *rhs)); + stack.pop(); + Ok(()) } _ => { stack.push(signal::stack_underflow().into()); @@ -414,11 +384,11 @@ pub fn positive(evaluator: &mut Evaluator) -> Result<(), Effect> { match &stack[..] { [.., Expression::Integer(n)] => { - stack.push(Expression::Boolean(Boolean(n.is_positive()))); + *stack.last_mut().unwrap() = Expression::Boolean(Boolean(n.is_positive())); Ok(()) } [.., Expression::Decimal(n)] => { - stack.push(Expression::Boolean(Boolean(n.is_positive()))); + *stack.last_mut().unwrap() = Expression::Boolean(Boolean(n.is_positive())); Ok(()) } [.., _] => { @@ -437,11 +407,11 @@ pub fn zero(evaluator: &mut Evaluator) -> Result<(), Effect> { match &stack[..] { [.., Expression::Integer(n)] => { - stack.push(Expression::Boolean(Boolean(n.is_zero()))); + *stack.last_mut().unwrap() = Expression::Boolean(Boolean(n.is_zero())); Ok(()) } [.., Expression::Decimal(n)] => { - stack.push(Expression::Boolean(Boolean(n.is_zero()))); + *stack.last_mut().unwrap() = Expression::Boolean(Boolean(n.is_zero())); Ok(()) } [.., _] => { @@ -460,11 +430,11 @@ pub fn negative(evaluator: &mut Evaluator) -> Result<(), Effect> { match &stack[..] { [.., Expression::Integer(n)] => { - stack.push(Expression::Boolean(Boolean(n.is_negative()))); + *stack.last_mut().unwrap() = Expression::Boolean(Boolean(n.is_negative())); Ok(()) } [.., Expression::Decimal(n)] => { - stack.push(Expression::Boolean(Boolean(n.is_negative()))); + *stack.last_mut().unwrap() = Expression::Boolean(Boolean(n.is_negative())); Ok(()) } [.., _] => { @@ -595,7 +565,7 @@ pub fn bitwise_xor(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., Expression::Boolean(ref mut lhs), Expression::Boolean(rhs)] => { - *lhs = Boolean(*lhs != rhs); + *lhs ^= rhs; stack.pop(); Ok(()) } @@ -791,6 +761,32 @@ pub fn x(evaluator: &mut Evaluator) -> Result<(), Effect> { i(evaluator) } +pub fn unary_two(evaluator: &mut Evaluator) -> Result<(), Effect> { + let stack = &mut evaluator.stack; + let top = stack.len(); + + match stack[..] { + [.., _, ref mut input2, Expression::Quote(ref mut quote)] => { + let quote = std::mem::take(quote); + let input2 = std::mem::replace(input2, Expression::Integer(Integer::ZERO)); + + stack.truncate(top - 2); + evaluator.evaluate(quote.clone())?; + + evaluator.stack.push(input2); + evaluator.evaluate(quote) + } + [.., _, _, _] => { + stack.push(signal::type_error().into()); + Err(Effect::Raise) + } + _ => { + stack.push(signal::stack_underflow().into()); + Err(Effect::Raise) + } + } +} + pub fn dip(evaluator: &mut Evaluator) -> Result<(), Effect> { match &evaluator.stack[..] { [.., _, Expression::Quote(_)] => { @@ -931,7 +927,7 @@ pub fn first(evaluator: &mut Evaluator) -> Result<(), Effect> { stack.push(signal::out_of_range().into()); Effect::Raise })?; - stack.push(expression); + *stack.last_mut().unwrap() = expression; Ok(()) } [.., _] => { @@ -954,7 +950,7 @@ pub fn last(evaluator: &mut Evaluator) -> Result<(), Effect> { stack.push(signal::out_of_range().into()); Effect::Raise })?; - stack.push(expression); + *stack.last_mut().unwrap() = expression; Ok(()) } [.., _] => { @@ -968,25 +964,73 @@ pub fn last(evaluator: &mut Evaluator) -> Result<(), Effect> { } } -pub fn head(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn prefix(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; match &stack[..] { [.., Expression::Quote(quote)] => { let quote_len = quote.len(); + *stack.last_mut().unwrap() = Expression::Quote( + quote + .get(..quote_len - 1) + .unwrap_or_default() + .iter() + .cloned() + .collect(), + ); - if quote_len < 2 { + Ok(()) + } + [.., _] => { + stack.push(signal::type_error().into()); + Err(Effect::Raise) + } + _ => { + stack.push(signal::stack_underflow().into()); + Err(Effect::Raise) + } + } +} + +pub fn suffix(evaluator: &mut Evaluator) -> Result<(), Effect> { + let stack = &mut evaluator.stack; + + match &stack[..] { + [.., Expression::Quote(quote)] => { + *stack.last_mut().unwrap() = + Expression::Quote(quote.get(1..).unwrap_or_default().iter().cloned().collect()); + Ok(()) + } + [.., _] => { + stack.push(signal::type_error().into()); + Err(Effect::Raise) + } + _ => { + stack.push(signal::stack_underflow().into()); + Err(Effect::Raise) + } + } +} + +pub fn at(evaluator: &mut Evaluator) -> Result<(), Effect> { + let stack = &mut evaluator.stack; + + match stack[..] { + [.., Expression::Quote(ref quote), Expression::Integer(Integer(at))] => { + let quote_len = quote.len(); + + if at.is_negative() || (at as usize) >= quote_len { stack.push(signal::out_of_range().into()); return Err(Effect::Raise); } - stack.push(Expression::Quote( - quote[..quote_len - 1].iter().cloned().collect(), - )); + let expression = quote[at as usize].clone(); + stack.pop(); + *stack.last_mut().unwrap() = expression; Ok(()) } - [.., _] => { + [.., _, _] => { stack.push(signal::type_error().into()); Err(Effect::Raise) } @@ -997,20 +1041,42 @@ pub fn head(evaluator: &mut Evaluator) -> Result<(), Effect> { } } -pub fn tail(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn split(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; - match &stack[..] { - [.., Expression::Quote(quote)] => { + match stack[..] { + [.., Expression::Quote(ref mut quote), Expression::Integer(Integer(at))] => { let quote_len = quote.len(); - if quote_len < 2 { + if at.is_negative() || (at as usize) >= quote_len { stack.push(signal::out_of_range().into()); return Err(Effect::Raise); } - stack.push(Expression::Quote(quote[1..].iter().cloned().collect())); + *stack.last_mut().unwrap() = quote.split(at as usize).into(); + Ok(()) + } + [.., _, _] => { + stack.push(signal::type_error().into()); + Err(Effect::Raise) + } + _ => { + stack.push(signal::stack_underflow().into()); + Err(Effect::Raise) + } + } +} + +pub fn len(evaluator: &mut Evaluator) -> Result<(), Effect> { + let stack = &mut evaluator.stack; + match &stack[..] { + [.., Expression::Quote(quote)] => { + *stack.last_mut().unwrap() = Expression::Integer(Integer(quote.len() as _)); + Ok(()) + } + [.., Expression::String(string)] => { + *stack.last_mut().unwrap() = Expression::Integer(Integer(string.len() as _)); Ok(()) } [.., _] => { @@ -1106,19 +1172,19 @@ pub fn dup(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } +// TODO: review pub fn send(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; match stack[..] { - [.., Expression::Channel(ref channel), ref mut expression] => { - let expression = std::mem::replace(expression, Expression::Integer(Integer(0))); - - if channel.send(expression).is_err() { + [.., Expression::Channel(ref channel), ref expression] => { + if channel.send(expression.clone()).is_err() { stack.push(signal::io_error().into()); return Err(Effect::Raise); } - stack.pop(); + let top = stack.len(); + stack.truncate(top - 2); Ok(()) } [.., _, _] => { @@ -1138,7 +1204,7 @@ pub fn receive(evaluator: &mut Evaluator) -> Result<(), Effect> { match stack[..] { [.., Expression::Channel(ref channel)] => match channel.recv() { Ok(expression) => { - stack.push(expression); + *stack.last_mut().unwrap() = expression; Ok(()) } Err(_) => { @@ -1300,25 +1366,82 @@ pub fn show(evaluator: &mut Evaluator) -> Result<(), Effect> { }) } +pub fn linrec(evaluator: &mut Evaluator) -> Result<(), Effect> { + let stack = &mut evaluator.stack; + + match &mut stack[..] { + [.., Expression::Quote(check), Expression::Quote(leave), Expression::Quote(split), Expression::Quote(merge)] => + { + let merge = std::mem::take(merge); + let split = std::mem::take(split); + let leave = std::mem::take(leave); + let check = std::mem::take(check); + + let top = stack.len(); + stack.truncate(top - 4); + + linrec_aux(evaluator, &check, &leave, &split, &merge) + } + [.., _, _, _, _] => { + stack.push(signal::type_error().into()); + Err(Effect::Raise) + } + _ => { + stack.push(signal::stack_underflow().into()); + Err(Effect::Raise) + } + } +} + +fn linrec_aux( + evaluator: &mut Evaluator, + check: &Quote, + leave: &Quote, + split: &Quote, + merge: &Quote, +) -> Result<(), Effect> { + evaluator.evaluate(check.iter().cloned())?; + + match evaluator.stack.pop() { + Some(Expression::Boolean(Boolean(value))) => { + if value { + evaluator.evaluate(leave.iter().cloned()) + } else { + evaluator.evaluate(split.iter().cloned())?; + linrec_aux(evaluator, check, leave, split, merge)?; + evaluator.evaluate(merge.iter().cloned()) + } + } + Some(value) => { + evaluator + .stack + .extend_from_slice(&[value, signal::type_error().into()]); + Err(Effect::Raise) + } + None => { + evaluator.stack.push(signal::stack_underflow().into()); + Err(Effect::Raise) + } + } +} + pub fn binrec(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; match &mut stack[..] { - [.., value, Expression::Quote(case), Expression::Quote(leave), Expression::Quote(left), Expression::Quote(right), Expression::Quote(merge)] => + [.., Expression::Quote(check), Expression::Quote(leave), Expression::Quote(split), Expression::Quote(merge)] => { let merge = std::mem::take(merge); - let right = std::mem::take(right); - let left = std::mem::take(left); + let split = std::mem::take(split); let leave = std::mem::take(leave); - let case = std::mem::take(case); - let value = value.clone(); + let check = std::mem::take(check); let top = stack.len(); - stack.truncate(top - 5); + stack.truncate(top - 4); - binrec_aux(evaluator, value, &case, &leave, &left, &right, &merge) + binrec_aux(evaluator, &check, &leave, &split, &merge) } - [.., _, _, _, _, _, _] => { + [.., _, _, _, _] => { stack.push(signal::type_error().into()); Err(Effect::Raise) } @@ -1331,44 +1454,34 @@ pub fn binrec(evaluator: &mut Evaluator) -> Result<(), Effect> { fn binrec_aux( evaluator: &mut Evaluator, - value: Expression, - case: &Quote, + check: &Quote, leave: &Quote, - left: &Quote, - right: &Quote, + split: &Quote, merge: &Quote, ) -> Result<(), Effect> { - evaluator.evaluate(case.iter().cloned())?; - - match &mut evaluator.stack[..] { - [.., head @ Expression::Boolean(Boolean(false))] => { - *head = value.clone(); - evaluator.evaluate(left.iter().cloned())?; - let last = evaluator.stack.last().cloned().ok_or_else(|| { - evaluator.stack.push(signal::stack_underflow().into()); - Effect::Raise - })?; - binrec_aux(evaluator, last, case, leave, left, right, merge)?; + evaluator.evaluate(check.iter().cloned())?; + + match evaluator.stack.pop() { + Some(Expression::Boolean(Boolean(false))) => { + evaluator.evaluate(split.iter().cloned())?; + + let value = evaluator.stack.pop().unwrap(); + binrec_aux(evaluator, check, leave, split, merge)?; evaluator.stack.push(value); - evaluator.evaluate(right.iter().cloned())?; - let last = evaluator.stack.last().cloned().ok_or_else(|| { - evaluator.stack.push(signal::stack_underflow().into()); - Effect::Raise - })?; - binrec_aux(evaluator, last, case, leave, left, right, merge)?; + binrec_aux(evaluator, check, leave, split, merge)?; evaluator.evaluate(merge.iter().cloned()) } - [.., head @ Expression::Boolean(Boolean(true))] => { - *head = value; - evaluator.evaluate(leave.iter().cloned()) - } - [.., _] => { - evaluator.stack.push(signal::type_error().into()); + Some(Expression::Boolean(Boolean(true))) => evaluator.evaluate(leave.iter().cloned()), + Some(expression) => { + evaluator + .stack + .extend_from_slice(&[expression, signal::type_error().into()]); + Err(Effect::Raise) } - _ => { + None => { evaluator.stack.push(signal::stack_underflow().into()); Err(Effect::Raise) } diff --git a/rat/src/channel.rs b/rat/src/channel.rs index 9241b7a..69eef97 100644 --- a/rat/src/channel.rs +++ b/rat/src/channel.rs @@ -25,21 +25,21 @@ pub struct Channel { impl Channel { pub fn spawn(quote: Quote) -> Self { - let (sender1, receiver1) = channel::unbounded(); - let (sender2, receiver2) = channel::unbounded(); + let (send, consume) = channel::unbounded(); + let (produce, receive) = channel::unbounded(); let handle = thread::spawn(move || { let mut evaluator = Evaluator { stack: Vec::new(), - channel: Some((sender2, receiver1)), + channel: Some((produce, consume)), }; evaluator.evaluate(quote) }); Self { inner: Arc::new(Inner { - sender: sender1, - receiver: receiver2, + sender: send, + receiver: receive, identity: handle.thread().id(), }), } diff --git a/rat/src/grammar.pest b/rat/src/grammar.pest index afb79c8..50b9b72 100644 --- a/rat/src/grammar.pest +++ b/rat/src/grammar.pest @@ -17,17 +17,17 @@ Phrase = { } Word = @{ - _Word ~ &BREAK -} - -_Word = @{ // TODO: this must always be kept in sync with `Word` - ("!" | "%" | "&" | "*" | "+" | "-" | "/" | "<" | "=" | ">" | "?" | 'A'..'Z' | "^" | "_" | 'a'..'z' | "|" | "~")+ + ( ("-" | '0'..'9' | "_")* + ~ ('A'..'Z' | 'a'..'z') + ~ ("-" | '0'..'9' | 'A'..'Z' | "_" | 'a'..'z')* + ~ ("!" | "?")? + ) } Locution = @{ // TODO: this must always be kept in sync with `Locution` - _Word ~ ("\\" ~ _Word)* ~ &BREAK + Word ~ ("\\" ~ Word)* } Expression = { @@ -35,15 +35,15 @@ Expression = { } Boolean = @{ - ("⊥" | "⊤") ~ &BREAK + ("⊥" | "⊤") } Decimal = @{ - ("+" | "-")? ~ "∞" | "0.NaN" | (((ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) | "0") ~ ((^"e" ~ ("+" | "-") ~ ASCII_DIGIT+) | "." ~ ASCII_DIGIT* ~ (^"e" ~ ("+" | "-") ~ ASCII_DIGIT+) | "." ~ ASCII_DIGIT+)) ~ &BREAK + ("+" | "-")? ~ "∞" | "0.NaN" | (((ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) | "0") ~ ((^"e" ~ ("+" | "-") ~ ASCII_DIGIT+) | "." ~ ASCII_DIGIT* ~ (^"e" ~ ("+" | "-") ~ ASCII_DIGIT+) | "." ~ ASCII_DIGIT+)) } Integer = @{ - ("+" | "-")? ~ ((ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) | "0") ~ &BREAK + ("+" | "-")? ~ ((ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) | "0") } Quote = { @@ -51,11 +51,11 @@ Quote = { } Signal = @{ - "$" ~ ('A'..'Z' | 'a'..'z')+ ~ &BREAK + "$" ~ ('A'..'Z' | 'a'..'z')+ } String = ${ - "\"" ~ StringUnicodeScalarValue* ~ "\"" ~ &BREAK + "\"" ~ StringUnicodeScalarValue* ~ "\"" } StringUnicodeScalarValue = @{ @@ -63,7 +63,7 @@ StringUnicodeScalarValue = @{ } Symbol = ${ - "'" ~ SymbolUnicodeScalarValue* ~ "'" ~ &BREAK + "'" ~ SymbolUnicodeScalarValue* ~ "'" } SymbolUnicodeScalarValue = @{ @@ -71,23 +71,23 @@ SymbolUnicodeScalarValue = @{ } At = @{ - "@" ~ &BREAK + "@" } Colon = @{ - ":" ~ &BREAK + ":" } Division = @{ - "÷" ~ &BREAK + "÷" } LeftArrow = @{ - "←" ~ &BREAK + "←" } Semicolon = @{ - ";" ~ &BREAK + ";" } LeftSquareBracket = @{ @@ -95,9 +95,8 @@ LeftSquareBracket = @{ } RightSquareBracket = @{ - "]" ~ &BREAK + "]" } WHITESPACE = _{ NEWLINE | "\t" | " " } COMMENT = _{ "#" ~ (!NEWLINE ~ ANY)* } -BREAK = _{ WHITESPACE | "]" | EOI } diff --git a/rat/src/lib.rs b/rat/src/lib.rs index 7a6ae9d..59efc36 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -160,11 +160,7 @@ mod test { Expression::Verb(Verb(builtin::spawn)), Expression::Verb(Verb(builtin::receive)), Expression::Verb(Verb(builtin::swap)), - Expression::Verb(Verb(builtin::pop)), - Expression::Verb(Verb(builtin::swap)), Expression::Verb(Verb(builtin::receive)), - Expression::Verb(Verb(builtin::swap)), - Expression::Verb(Verb(builtin::pop)), Expression::Verb(Verb(builtin::add)), ]) .unwrap(); diff --git a/rat/src/parser.rs b/rat/src/parser.rs index 5e80f10..06b5375 100644 --- a/rat/src/parser.rs +++ b/rat/src/parser.rs @@ -411,7 +411,7 @@ fn parse_definition(parser: &mut Parser, origin: Origin, pair: PestPair) -> Resu } fn parse_word<'a>(origin: Origin, pair: PestPair<'a>) -> Result<&'a Word, ParseError> { - assert!(matches!(pair.as_rule(), Rule::Word | Rule::_Word)); + assert_eq!(pair.as_rule(), Rule::Word); Word::try_from_literal(pair.as_str()).map_err(|e| parse_error(origin, pair.as_span(), e)) } diff --git a/rat/src/quote.rs b/rat/src/quote.rs index 7a864ba..f5ab713 100644 --- a/rat/src/quote.rs +++ b/rat/src/quote.rs @@ -68,6 +68,16 @@ impl Quote { .map(|v| v.remove(index)) } + pub fn split(&mut self, at: usize) -> Quote { + self.inner + .as_mut() + .map(Arc::make_mut) + .map(|v| Self { + inner: Some(Arc::new(v.split_off(at))), + }) + .unwrap() + } + pub fn as_slice(&self) -> &[Expression] { self.inner.as_deref().map(Deref::deref).unwrap_or(&[]) } @@ -102,33 +112,13 @@ impl Deref for Quote { impl Display for Quote { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.as_slice() { - [] => write!(f, "[]"), - [v] => write!(f, "[{v}]"), - [v, rest @ ..] => { - write!(f, "[{v}")?; - for v in rest { - write!(f, " {v}")?; - } - write!(f, "]") - } - } + DisplayAdapter::new(self.as_slice()).display().fmt(f) } } impl Debug for Quote { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.as_slice() { - [] => write!(f, "[]"), - [v] => write!(f, "[{v:?}]"), - [v, rest @ ..] => { - write!(f, "[{v:?}")?; - for v in rest { - write!(f, " {v:?}")?; - } - write!(f, "]") - } - } + DisplayAdapter::new(self.as_slice()).debug().fmt(f) } } @@ -267,3 +257,53 @@ impl IntoIterator for Quote { ) } } + +pub struct DisplayAdapter<'a> { + slice: &'a [Expression], +} + +impl<'a> DisplayAdapter<'a> { + pub const fn new(slice: &'a [Expression]) -> Self { + Self { slice } + } + + pub fn display(&self) -> impl Display + '_ { + self + } + + pub fn debug(&self) -> impl Debug + '_ { + self + } +} + +impl<'a> Display for DisplayAdapter<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.slice { + [] => write!(f, "[]"), + [v] => write!(f, "[{v}]"), + [v, rest @ ..] => { + write!(f, "[{v}")?; + for v in rest { + write!(f, " {v}")?; + } + write!(f, "]") + } + } + } +} + +impl<'a> Debug for DisplayAdapter<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.slice { + [] => write!(f, "[]"), + [v] => write!(f, "[{v:?}]"), + [v, rest @ ..] => { + write!(f, "[{v:?}")?; + for v in rest { + write!(f, " {v:?}")?; + } + write!(f, "]") + } + } + } +} diff --git a/rat/src/vocabulary.rs b/rat/src/vocabulary.rs index 0d799ff..0cf9cb8 100644 --- a/rat/src/vocabulary.rs +++ b/rat/src/vocabulary.rs @@ -135,7 +135,7 @@ impl Vocabulary { } } -static PRELUDE: [(&Word, &[Expression]); 64] = [ +static PRELUDE: [(&Word, &[Expression]); 69] = [ (word_literal("neg"), &[Expression::Verb(Verb(builtin::neg))]), ( word_literal("incr"), @@ -145,17 +145,17 @@ static PRELUDE: [(&Word, &[Expression]); 64] = [ word_literal("decr"), &[Expression::Verb(Verb(builtin::decr))], ), - (word_literal("+"), &[Expression::Verb(Verb(builtin::add))]), - (word_literal("-"), &[Expression::Verb(Verb(builtin::sub))]), - (word_literal("*"), &[Expression::Verb(Verb(builtin::mul))]), - (word_literal("/"), &[Expression::Verb(Verb(builtin::div))]), - (word_literal("%"), &[Expression::Verb(Verb(builtin::rem))]), - (word_literal("="), &[Expression::Verb(Verb(builtin::eq))]), - (word_literal("<>"), &[Expression::Verb(Verb(builtin::ne))]), - (word_literal(">"), &[Expression::Verb(Verb(builtin::gt))]), - (word_literal(">="), &[Expression::Verb(Verb(builtin::ge))]), - (word_literal("<"), &[Expression::Verb(Verb(builtin::lt))]), - (word_literal("<="), &[Expression::Verb(Verb(builtin::le))]), + (word_literal("add"), &[Expression::Verb(Verb(builtin::add))]), + (word_literal("sub"), &[Expression::Verb(Verb(builtin::sub))]), + (word_literal("mul"), &[Expression::Verb(Verb(builtin::mul))]), + (word_literal("div"), &[Expression::Verb(Verb(builtin::div))]), + (word_literal("rem"), &[Expression::Verb(Verb(builtin::rem))]), + (word_literal("eq"), &[Expression::Verb(Verb(builtin::eq))]), + (word_literal("ne"), &[Expression::Verb(Verb(builtin::ne))]), + (word_literal("gt"), &[Expression::Verb(Verb(builtin::gt))]), + (word_literal("ge"), &[Expression::Verb(Verb(builtin::ge))]), + (word_literal("lt"), &[Expression::Verb(Verb(builtin::lt))]), + (word_literal("le"), &[Expression::Verb(Verb(builtin::le))]), ( word_literal("positive?"), &[Expression::Verb(Verb(builtin::positive))], @@ -186,25 +186,25 @@ static PRELUDE: [(&Word, &[Expression]); 64] = [ (word_literal("and"), &[Expression::Verb(Verb(builtin::and))]), (word_literal("or"), &[Expression::Verb(Verb(builtin::or))]), ( - word_literal("~"), + word_literal("bit-not"), &[Expression::Verb(Verb(builtin::bitwise_not))], ), ( - word_literal("&"), + word_literal("bit-and"), &[Expression::Verb(Verb(builtin::bitwise_and))], ), ( - word_literal("^"), + word_literal("bit-xor"), &[Expression::Verb(Verb(builtin::bitwise_xor))], ), ( - word_literal("|"), + word_literal("bit-or"), &[Expression::Verb(Verb(builtin::bitwise_or))], ), - (word_literal("<<"), &[Expression::Verb(Verb(builtin::shl))]), - (word_literal(">>"), &[Expression::Verb(Verb(builtin::shr))]), + (word_literal("shl"), &[Expression::Verb(Verb(builtin::shl))]), + (word_literal("shr"), &[Expression::Verb(Verb(builtin::shr))]), ( - word_literal(">>>"), + word_literal("ushr"), &[Expression::Verb(Verb(builtin::ushr))], ), (word_literal("cat"), &[Expression::Verb(Verb(builtin::cat))]), @@ -223,13 +223,17 @@ static PRELUDE: [(&Word, &[Expression]); 64] = [ (word_literal("i"), &[Expression::Verb(Verb(builtin::i))]), (word_literal("x"), &[Expression::Verb(Verb(builtin::x))]), (word_literal("dip"), &[Expression::Verb(Verb(builtin::dip))]), + ( + word_literal("unary2"), + &[Expression::Verb(Verb(builtin::unary_two))], + ), (word_literal("if"), &[Expression::Verb(Verb(builtin::r#if))]), ( word_literal("else"), &[Expression::Verb(Verb(builtin::r#else))], ), ( - word_literal("ifElse"), + word_literal("if-else"), &[Expression::Verb(Verb(builtin::if_else))], ), ( @@ -253,13 +257,19 @@ static PRELUDE: [(&Word, &[Expression]); 64] = [ &[Expression::Verb(Verb(builtin::last))], ), ( - word_literal("head"), - &[Expression::Verb(Verb(builtin::head))], + word_literal("prefix"), + &[Expression::Verb(Verb(builtin::prefix))], + ), + ( + word_literal("suffix"), + &[Expression::Verb(Verb(builtin::suffix))], ), + (word_literal("at"), &[Expression::Verb(Verb(builtin::at))]), ( - word_literal("tail"), - &[Expression::Verb(Verb(builtin::tail))], + word_literal("split"), + &[Expression::Verb(Verb(builtin::split))], ), + (word_literal("len"), &[Expression::Verb(Verb(builtin::len))]), ( word_literal("swap"), &[Expression::Verb(Verb(builtin::swap))], @@ -304,6 +314,10 @@ static PRELUDE: [(&Word, &[Expression]); 64] = [ word_literal("show"), &[Expression::Verb(Verb(builtin::show))], ), + ( + word_literal("linrec"), + &[Expression::Verb(Verb(builtin::linrec))], + ), ( word_literal("binrec"), &[Expression::Verb(Verb(builtin::binrec))], diff --git a/rat/src/word.rs b/rat/src/word.rs index 1295739..37b3e26 100644 --- a/rat/src/word.rs +++ b/rat/src/word.rs @@ -30,34 +30,46 @@ impl Word { } let mut i = start; + + while i < end { + let c = bytes[i]; + + if !(c == b'-' || c.is_ascii_digit() || c == b'_') { + break; + } + + i += 1; + } + + while i < end { + let c = bytes[i]; + + if !c.is_ascii_alphabetic() { + break; + } + + i += 1; + } + while i < end { let c = bytes[i]; - if !(b'!' == c - || b'%' == c - || b'&' == c - || b'*' == c - || b'+' == c - || b'-' == c - || b'/' == c - || b'<' == c - || b'=' == c - || b'>' == c - || b'?' == c - || (b'A' <= c && b'Z' >= c) - || b'^' == c - || b'_' == c - || (b'a' <= c && b'z' >= c) - || b'|' == c - || b'~' == c) - { - return false; + if !(c == b'-' || c.is_ascii_alphanumeric() || c == b'_') { + break; } i += 1; } - true + if i < end { + let c = bytes[i]; + + if c == b'!' || c == b'?' { + i += 1; + } + } + + end == i } /// Whitespaces are not allowed in `literal`. From 4da2d2551aafe6d2dda11437086461464d1f2357 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sat, 6 Jul 2024 18:03:18 +0200 Subject: [PATCH 02/17] rebuild if lib changed --- Cargo.lock | 82 +++++++++++++++++++++++----------------------- rat-cli/Cargo.toml | 2 +- rat-cli/build.rs | 2 ++ rat/Cargo.toml | 2 +- 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76ee54b..0cbc0c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -272,9 +272,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" @@ -335,14 +335,14 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "pest" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -351,9 +351,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -361,9 +361,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", @@ -374,9 +374,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -627,7 +627,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -647,18 +647,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -669,9 +669,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -681,9 +681,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -693,15 +693,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -711,9 +711,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -723,9 +723,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -735,9 +735,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -747,24 +747,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", diff --git a/rat-cli/Cargo.toml b/rat-cli/Cargo.toml index ecfbc04..b0d5022 100644 --- a/rat-cli/Cargo.toml +++ b/rat-cli/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["rat", "rust", "programming-language", "concatenative", "concurrency license = "MPL-2.0" name = "rat-cli" repository = "https://github.com/daddinuz/rat" -rust-version = "1.75" +rust-version = "1.77" version = "0.1.0" [build-dependencies] diff --git a/rat-cli/build.rs b/rat-cli/build.rs index 6445696..6dd73bf 100644 --- a/rat-cli/build.rs +++ b/rat-cli/build.rs @@ -7,6 +7,8 @@ fn main() { .unwrap() .join("lib"); + println!("cargo::rerun-if-changed={}", source_path.display()); + let destination_path = rat::home_dir().join("lib"); fs::create_dir_all(&destination_path).unwrap(); diff --git a/rat/Cargo.toml b/rat/Cargo.toml index b5ca3af..b2dc1b6 100644 --- a/rat/Cargo.toml +++ b/rat/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["rat", "rust", "programming-language", "concatenative", "concurrency license = "MPL-2.0" name = "rat" repository = "https://github.com/daddinuz/rat" -rust-version = "1.75" +rust-version = "1.77" version = "0.1.0" [dependencies] From 8f948d3f410b93a4e648abb296104141baec7e65 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sat, 6 Jul 2024 18:27:51 +0200 Subject: [PATCH 03/17] add words to stdlib --- lib/math.rat | 3 +++ lib/std.rat | 2 ++ 2 files changed, 5 insertions(+) diff --git a/lib/math.rat b/lib/math.rat index a04c883..e8ce558 100644 --- a/lib/math.rat +++ b/lib/math.rat @@ -2,7 +2,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +: std @ rat\std ; + ÷ abs ← dup negative? [neg] if ; ÷ halve ← 1 shr ; ÷ double ← 1 shl ; ÷ square ← dup mul ; +÷ pow ← [dup quote [mul] cat] dip std\times ; diff --git a/lib/std.rat b/lib/std.rat index 13390cb..9ba3a15 100644 --- a/lib/std.rat +++ b/lib/std.rat @@ -14,3 +14,5 @@ ÷ bi ← [[quote] dip over [cat] dip] dip cat [i] dip i ; ÷ case ← swap at i ; + +÷ times ← [dup 1 lt] [pop pop] [[dup [i] dip] dip decr] [] linrec ; From be48303c77858d3e4220af933b7dbf3e3b038ea7 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sun, 7 Jul 2024 12:43:49 +0200 Subject: [PATCH 04/17] update builtins + remove Yield effect + update examples --- examples/alice_n_bob.rat | 4 ++-- examples/parallel-mergesort.rat | 10 +++++----- examples/towards_zero.rat | 13 +++++++++++++ rat/src/builtin.rs | 24 ++++-------------------- rat/src/effect.rs | 1 - rat/src/lib.rs | 30 +----------------------------- rat/src/vocabulary.rs | 12 ++++-------- 7 files changed, 29 insertions(+), 65 deletions(-) create mode 100644 examples/towards_zero.rat diff --git a/examples/alice_n_bob.rat b/examples/alice_n_bob.rat index 0fd4a3e..a351a17 100644 --- a/examples/alice_n_bob.rat +++ b/examples/alice_n_bob.rat @@ -1,7 +1,7 @@ : std @ rat\std ; -: alice ← ["alice\n" produce consume receive say] spawn ; -: bob ← [consume receive say "bob\n" produce] spawn ; +: alice ← ["alice" produce consume receive say] spawn ; +: bob ← ["bob" produce consume receive say] spawn ; alice bob std\dup2 swap send send "press [enter] to continue\n" ask diff --git a/examples/parallel-mergesort.rat b/examples/parallel-mergesort.rat index 5935dfd..153bfec 100644 --- a/examples/parallel-mergesort.rat +++ b/examples/parallel-mergesort.rat @@ -2,12 +2,12 @@ : math @ rat\math ; # with program forming -: p ← quote [seq\mergesort produce] cat spawn ; -: par-ms ← dup len math\halve split [p] unary2 [receive] unary2 seq\merge ; +: process ← quote [seq\mergesort produce] cat spawn ; +: parallel-mergesort ← dup len math\halve split [process] unary2 [receive] unary2 seq\merge ; # with message passing -: p ← [consume seq\mergesort produce] spawn ; -: par-ms ← dup len math\halve split [p dup rotate send] unary2 [receive] unary2 seq\merge ; +: process ← [consume seq\mergesort produce] spawn ; +: parallel-mergesort ← dup len math\halve split [process dup rotate send] unary2 [receive] unary2 seq\merge ; [-23714 36911 27209 -61081 4487 62986 43562 59953 -6002 -64976 6222 37230 1774 60450 35372 9313 -63141 -10099 -56599 37381 29627 17147 -56774 46348 25159 42717 -10426 -38088 -9482 -51818 -13225 -22274 -52566 -5587 -148 59711 51437 6343 50139 32437 27966 -34985 167 27161 -53411 -6759 -27066 -7772 49899 -24127 7940 61517 -14064 -4433 6018 42197 -24241 4939 23687 -27950 -60335 -483 -51116 -201 21847 -65149 46808 49486 -6132 4372 14587 60525 14700 8373 -48827 -64401 -53524 -28842 -10959 -56034 -64763 -54632 28581 -3277 5279 7684 -26031 32221 1723 59531 -34723 17671 3424 -30493 28938 -12043 -27853 -14788 -34395 -23175 39083 -3314 16725 -14123 5069 -59857 52477 -25028 9931 -27366 41663 10612 -46240 27308 7778 -12942 37028 -18502 59012 53713 60519 -49390 -15897 41667 55977 45961 39978 59934 23858 -23789 -17806 -14129 -36824 -57834 -28443 -22873 26639 -20046 -57731 -16443 -599 -2646 8985 -14817 -10395 -42440 -59983 3357 44965 -44840 36400 -10323 -39719 45791 -27538 15597 7872 -19558 54625 -10621 27469 -61915 -45654 -61333 10374 50181 5656 8559 -9822 -9340 23135 -11774 -28400 -44677 304 37783 -56801 -45383 59955 23509 55993 -61971 16262 -49607 39590 -27209 1339 -56543 -41882 64893 50150 -16153 -317 -16469 7629 19020 15578 46013 53541 -27485 60355 -28348 -63558 -45715 -43954 62904 -8753 29052 -56968 52829 31804 45589 -26416 30184 29918 -38968 19638 -24968 -24088 -9447 48799 -50660 43610 -50411 -47355 -59101 59279 34413 55334 -16776 50629 63673 -44714 -32217 -37943 -21810 -51476 33889 6583 65273 60878 -13805 59344 34343 -43042 25481 40781 -37723 -39856 -19967 -54323 -6219 -24811 -51108 4870 -20829] -par-ms say +parallel-mergesort say diff --git a/examples/towards_zero.rat b/examples/towards_zero.rat new file mode 100644 index 0000000..ba4acaa --- /dev/null +++ b/examples/towards_zero.rat @@ -0,0 +1,13 @@ +: std @ rat\std ; + +: small? ← 1 lt ; + +# with recursion +: f ← std\over small? [pop] [[dup decr] dip dup i] if-else ; +10 [f] f + +# with combinators +: f ← [dup small?] [] [dup decr] [] linrec ; +10 f + +show diff --git a/rat/src/builtin.rs b/rat/src/builtin.rs index 8107196..7f89a9d 100644 --- a/rat/src/builtin.rs +++ b/rat/src/builtin.rs @@ -699,19 +699,7 @@ pub fn quote(evaluator: &mut Evaluator) -> Result<(), Effect> { pub fn unquote(evaluator: &mut Evaluator) -> Result<(), Effect> { match evaluator.stack.pop() { - Some(Expression::Quote(quote)) => { - let mut continuation = quote.into_iter(); - - match continuation.try_for_each(|e| evaluator.evaluate(e)) { - Err(Effect::Yield) => { - evaluator - .stack - .push(Expression::Quote(continuation.collect())); - Ok(()) - } - flow => flow, - } - } + Some(Expression::Quote(quote)) => evaluator.evaluate(quote), Some(expression) => { evaluator .stack @@ -761,7 +749,7 @@ pub fn x(evaluator: &mut Evaluator) -> Result<(), Effect> { i(evaluator) } -pub fn unary_two(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn unary2(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; let top = stack.len(); @@ -771,7 +759,7 @@ pub fn unary_two(evaluator: &mut Evaluator) -> Result<(), Effect> { let input2 = std::mem::replace(input2, Expression::Integer(Integer::ZERO)); stack.truncate(top - 2); - evaluator.evaluate(quote.clone())?; + evaluator.evaluate(quote.iter().cloned())?; evaluator.stack.push(input2); evaluator.evaluate(quote) @@ -883,15 +871,11 @@ pub fn if_else(evaluator: &mut Evaluator) -> Result<(), Effect> { } } -pub fn r#yield(_: &mut Evaluator) -> Result<(), Effect> { - Err(Effect::Yield) -} - pub fn raise(_: &mut Evaluator) -> Result<(), Effect> { Err(Effect::Raise) } -pub fn catch(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn r#try(evaluator: &mut Evaluator) -> Result<(), Effect> { match &evaluator.stack[..] { [.., Expression::Quote(_), Expression::Quote(_), _] => { let guarded = evaluator.stack.pop(); diff --git a/rat/src/effect.rs b/rat/src/effect.rs index 5702df0..910ef06 100644 --- a/rat/src/effect.rs +++ b/rat/src/effect.rs @@ -6,6 +6,5 @@ #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Effect { - Yield, Raise, } diff --git a/rat/src/lib.rs b/rat/src/lib.rs index 59efc36..9f3b16e 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -80,34 +80,6 @@ mod test { #[test] fn it_works2() { - let mut evaluator = Evaluator::default(); - evaluator - .evaluate([ - Expression::Integer(Integer(1)), - Expression::Quote( - [ - Expression::Integer(Integer(2)), - Expression::Integer(Integer(1)), - Expression::Verb(Verb(builtin::sub)), - Expression::Verb(Verb(builtin::r#yield)), - Expression::Verb(Verb(builtin::sub)), - ] - .into_iter() - .collect(), - ), - Expression::Verb(Verb(builtin::unquote)), - Expression::Verb(Verb(builtin::unquote)), - ]) - .unwrap(); - - assert!(matches!( - evaluator.stack.as_slice(), - &[Expression::Integer(Integer(0))] - )); - } - - #[test] - fn it_works3() { let mut evaluator = Evaluator::default(); evaluator .evaluate([ @@ -121,7 +93,7 @@ mod test { ), Expression::Quote([Expression::Integer(Integer(42))].into_iter().collect()), Expression::Signal(signal::stack_underflow()), - Expression::Verb(Verb(builtin::catch)), + Expression::Verb(Verb(builtin::r#try)), ]) .unwrap(); diff --git a/rat/src/vocabulary.rs b/rat/src/vocabulary.rs index 0cf9cb8..0fd16e1 100644 --- a/rat/src/vocabulary.rs +++ b/rat/src/vocabulary.rs @@ -135,7 +135,7 @@ impl Vocabulary { } } -static PRELUDE: [(&Word, &[Expression]); 69] = [ +static PRELUDE: [(&Word, &[Expression]); 68] = [ (word_literal("neg"), &[Expression::Verb(Verb(builtin::neg))]), ( word_literal("incr"), @@ -225,7 +225,7 @@ static PRELUDE: [(&Word, &[Expression]); 69] = [ (word_literal("dip"), &[Expression::Verb(Verb(builtin::dip))]), ( word_literal("unary2"), - &[Expression::Verb(Verb(builtin::unary_two))], + &[Expression::Verb(Verb(builtin::unary2))], ), (word_literal("if"), &[Expression::Verb(Verb(builtin::r#if))]), ( @@ -236,17 +236,13 @@ static PRELUDE: [(&Word, &[Expression]); 69] = [ word_literal("if-else"), &[Expression::Verb(Verb(builtin::if_else))], ), - ( - word_literal("yield"), - &[Expression::Verb(Verb(builtin::r#yield))], - ), ( word_literal("raise"), &[Expression::Verb(Verb(builtin::raise))], ), ( - word_literal("catch"), - &[Expression::Verb(Verb(builtin::catch))], + word_literal("try"), + &[Expression::Verb(Verb(builtin::r#try))], ), ( word_literal("first"), From b6a8de0be199c1a8d9b74a9007cbd0718ecd698a Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sun, 7 Jul 2024 13:20:16 +0200 Subject: [PATCH 05/17] remove signal from expressions --- rat/src/builtin.rs | 266 ++++++++++++++++++++---------------------- rat/src/expression.rs | 12 -- rat/src/grammar.pest | 6 +- rat/src/lib.rs | 6 +- rat/src/parser.rs | 38 +----- rat/src/signal.rs | 133 --------------------- rat/src/symbol.rs | 20 ++++ 7 files changed, 156 insertions(+), 325 deletions(-) delete mode 100644 rat/src/signal.rs diff --git a/rat/src/builtin.rs b/rat/src/builtin.rs index 7f89a9d..52b738a 100644 --- a/rat/src/builtin.rs +++ b/rat/src/builtin.rs @@ -6,8 +6,6 @@ use std::io::{self, Write}; -use crate::signal; - use crate::effect::Effect; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; @@ -20,6 +18,7 @@ use crate::decimal::Decimal; use crate::integer::Integer; use crate::quote::Quote; use crate::string::String; +use crate::symbol::Symbol; pub fn neg(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; @@ -34,11 +33,11 @@ pub fn neg(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -57,11 +56,11 @@ pub fn incr(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -80,11 +79,11 @@ pub fn decr(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -105,11 +104,11 @@ pub fn add(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -130,11 +129,11 @@ pub fn sub(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -155,11 +154,11 @@ pub fn mul(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -170,7 +169,7 @@ pub fn div(evaluator: &mut Evaluator) -> Result<(), Effect> { match stack[..] { [.., Expression::Integer(_), Expression::Integer(Integer::ZERO)] => { - stack.push(signal::divide_by_zero().into()); + stack.push(Symbol::divide_by_zero().into()); Err(Effect::Raise) } [.., Expression::Integer(ref mut lhs), Expression::Integer(rhs)] => { @@ -184,11 +183,11 @@ pub fn div(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -199,7 +198,7 @@ pub fn rem(evaluator: &mut Evaluator) -> Result<(), Effect> { match stack[..] { [.., Expression::Integer(_), Expression::Integer(Integer::ZERO)] => { - stack.push(signal::divide_by_zero().into()); + stack.push(Symbol::divide_by_zero().into()); Err(Effect::Raise) } [.., Expression::Integer(ref mut lhs), Expression::Integer(rhs)] => { @@ -213,11 +212,11 @@ pub fn rem(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -233,7 +232,7 @@ pub fn eq(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -249,7 +248,7 @@ pub fn ne(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -276,11 +275,11 @@ pub fn gt(evaluator: &mut Evaluator) -> Result<(), Effect> { _ => unreachable!(), }, [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -307,11 +306,11 @@ pub fn ge(evaluator: &mut Evaluator) -> Result<(), Effect> { _ => unreachable!(), }, [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -338,11 +337,11 @@ pub fn lt(evaluator: &mut Evaluator) -> Result<(), Effect> { _ => unreachable!(), }, [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -369,11 +368,11 @@ pub fn le(evaluator: &mut Evaluator) -> Result<(), Effect> { _ => unreachable!(), }, [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -392,11 +391,11 @@ pub fn positive(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -415,11 +414,11 @@ pub fn zero(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -438,11 +437,11 @@ pub fn negative(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -457,11 +456,11 @@ pub fn not(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -477,11 +476,11 @@ pub fn and(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -497,11 +496,11 @@ pub fn or(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -520,11 +519,11 @@ pub fn bitwise_not(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -545,11 +544,11 @@ pub fn bitwise_and(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -570,11 +569,11 @@ pub fn bitwise_xor(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -595,11 +594,11 @@ pub fn bitwise_or(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -615,11 +614,11 @@ pub fn shl(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -635,11 +634,11 @@ pub fn shr(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -655,11 +654,11 @@ pub fn ushr(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -676,11 +675,11 @@ pub fn cat(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -689,7 +688,7 @@ pub fn cat(evaluator: &mut Evaluator) -> Result<(), Effect> { pub fn quote(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; let expression = stack.pop().ok_or_else(|| { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Effect::Raise })?; @@ -703,11 +702,11 @@ pub fn unquote(evaluator: &mut Evaluator) -> Result<(), Effect> { Some(expression) => { evaluator .stack - .extend_from_slice(&[expression, signal::type_error().into()]); + .extend_from_slice(&[expression, Symbol::type_error().into()]); Err(Effect::Raise) } _ => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -719,7 +718,7 @@ pub fn eval(evaluator: &mut Evaluator) -> Result<(), Effect> { match stack.pop() { Some(expression) => evaluator.evaluate(expression), _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -732,7 +731,7 @@ pub fn i(evaluator: &mut Evaluator) -> Result<(), Effect> { [.., Expression::Quote(_)] => unquote(evaluator), [.., _] => eval(evaluator), _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -741,7 +740,7 @@ pub fn i(evaluator: &mut Evaluator) -> Result<(), Effect> { pub fn x(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; let expression = stack.last().cloned().ok_or_else(|| { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Effect::Raise })?; @@ -765,11 +764,11 @@ pub fn unary2(evaluator: &mut Evaluator) -> Result<(), Effect> { evaluator.evaluate(quote) } [.., _, _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -785,11 +784,11 @@ pub fn dip(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - evaluator.stack.push(signal::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -812,11 +811,11 @@ pub fn r#if(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _, _] => { - evaluator.stack.push(signal::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -839,11 +838,11 @@ pub fn r#else(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - evaluator.stack.push(signal::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -861,11 +860,11 @@ pub fn if_else(evaluator: &mut Evaluator) -> Result<(), Effect> { evaluator.evaluate(quote) } [.., _, _, _] => { - evaluator.stack.push(signal::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -892,11 +891,11 @@ pub fn r#try(evaluator: &mut Evaluator) -> Result<(), Effect> { } } [.., _, _, _] => { - evaluator.stack.push(signal::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -908,18 +907,18 @@ pub fn first(evaluator: &mut Evaluator) -> Result<(), Effect> { match &stack[..] { [.., Expression::Quote(quote)] => { let expression = quote.first().cloned().ok_or_else(|| { - stack.push(signal::out_of_range().into()); + stack.push(Symbol::out_of_range().into()); Effect::Raise })?; *stack.last_mut().unwrap() = expression; Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -931,18 +930,18 @@ pub fn last(evaluator: &mut Evaluator) -> Result<(), Effect> { match &stack[..] { [.., Expression::Quote(quote)] => { let expression = quote.last().cloned().ok_or_else(|| { - stack.push(signal::out_of_range().into()); + stack.push(Symbol::out_of_range().into()); Effect::Raise })?; *stack.last_mut().unwrap() = expression; Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -966,11 +965,11 @@ pub fn prefix(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -986,11 +985,11 @@ pub fn suffix(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1004,7 +1003,7 @@ pub fn at(evaluator: &mut Evaluator) -> Result<(), Effect> { let quote_len = quote.len(); if at.is_negative() || (at as usize) >= quote_len { - stack.push(signal::out_of_range().into()); + stack.push(Symbol::out_of_range().into()); return Err(Effect::Raise); } @@ -1015,11 +1014,11 @@ pub fn at(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1033,7 +1032,7 @@ pub fn split(evaluator: &mut Evaluator) -> Result<(), Effect> { let quote_len = quote.len(); if at.is_negative() || (at as usize) >= quote_len { - stack.push(signal::out_of_range().into()); + stack.push(Symbol::out_of_range().into()); return Err(Effect::Raise); } @@ -1041,11 +1040,11 @@ pub fn split(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1064,11 +1063,11 @@ pub fn len(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1079,7 +1078,7 @@ pub fn swap(evaluator: &mut Evaluator) -> Result<(), Effect> { let top = stack.len(); if top < 2 { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); return Err(Effect::Raise); } @@ -1097,7 +1096,7 @@ pub fn rollup(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1113,7 +1112,7 @@ pub fn rolldown(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1128,7 +1127,7 @@ pub fn rotate(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1138,7 +1137,7 @@ pub fn pop(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; if stack.pop().is_none() { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); return Err(Effect::Raise); } @@ -1148,7 +1147,7 @@ pub fn pop(evaluator: &mut Evaluator) -> Result<(), Effect> { pub fn dup(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; let expression = stack.last().cloned().ok_or_else(|| { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Effect::Raise })?; @@ -1163,7 +1162,7 @@ pub fn send(evaluator: &mut Evaluator) -> Result<(), Effect> { match stack[..] { [.., Expression::Channel(ref channel), ref expression] => { if channel.send(expression.clone()).is_err() { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); return Err(Effect::Raise); } @@ -1172,11 +1171,11 @@ pub fn send(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1192,16 +1191,16 @@ pub fn receive(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } Err(_) => { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); Err(Effect::Raise) } }, [.., _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1214,7 +1213,7 @@ pub fn produce(evaluator: &mut Evaluator) -> Result<(), Effect> { Some(expression) => { if let Some(sender) = evaluator.channel.as_ref().map(|(sender, _)| sender) { if sender.send(expression).is_err() { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); return Err(Effect::Raise); } } @@ -1222,7 +1221,7 @@ pub fn produce(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } None => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1238,7 +1237,7 @@ pub fn consume(evaluator: &mut Evaluator) -> Result<(), Effect> { } } - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); Err(Effect::Raise) } @@ -1256,11 +1255,11 @@ pub fn spawn(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } [.., _] => { - evaluator.stack.push(signal::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1274,23 +1273,23 @@ pub fn ask(evaluator: &mut Evaluator) -> Result<(), Effect> { let mut stdout_lock = io::stdout().lock(); write!(stdout_lock, "{prompt}").map_err(|_| { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); Effect::Raise })?; stdout_lock.flush().map_err(|_| { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); Effect::Raise })?; stack.pop(); } [.., _] => { - evaluator.stack.push(signal::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); return Err(Effect::Raise); } _ => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); return Err(Effect::Raise); } } @@ -1298,7 +1297,7 @@ pub fn ask(evaluator: &mut Evaluator) -> Result<(), Effect> { let mut buf = std::string::String::new(); io::stdin().read_line(&mut buf).map_err(|_| { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); Effect::Raise })?; @@ -1310,19 +1309,12 @@ pub fn say(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; let expression = stack.pop().ok_or_else(|| { - stack.push(signal::stack_underflow().into()); - Effect::Raise - })?; - - let mut stdout_lock = io::stdout().lock(); - - write!(stdout_lock, "{expression}").map_err(|_| { - stack.push(signal::io_error().into()); + stack.push(Symbol::stack_underflow().into()); Effect::Raise })?; - stdout_lock.flush().map_err(|_| { - stack.push(signal::io_error().into()); + writeln!(io::stdout(), "{expression}").map_err(|_| { + stack.push(Symbol::io_error().into()); Effect::Raise }) } @@ -1332,7 +1324,7 @@ pub fn show(evaluator: &mut Evaluator) -> Result<(), Effect> { let mut stdout = io::stdout().lock(); write!(stdout, "#>>>").map_err(|_| { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); Effect::Raise })?; @@ -1340,12 +1332,12 @@ pub fn show(evaluator: &mut Evaluator) -> Result<(), Effect> { .iter() .try_for_each(|e| write!(stdout, " {e:?}")) .map_err(|_| { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); Effect::Raise })?; writeln!(stdout).map_err(|_| { - stack.push(signal::io_error().into()); + stack.push(Symbol::io_error().into()); Effect::Raise }) } @@ -1367,11 +1359,11 @@ pub fn linrec(evaluator: &mut Evaluator) -> Result<(), Effect> { linrec_aux(evaluator, &check, &leave, &split, &merge) } [.., _, _, _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1399,11 +1391,11 @@ fn linrec_aux( Some(value) => { evaluator .stack - .extend_from_slice(&[value, signal::type_error().into()]); + .extend_from_slice(&[value, Symbol::type_error().into()]); Err(Effect::Raise) } None => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1426,11 +1418,11 @@ pub fn binrec(evaluator: &mut Evaluator) -> Result<(), Effect> { binrec_aux(evaluator, &check, &leave, &split, &merge) } [.., _, _, _, _] => { - stack.push(signal::type_error().into()); + stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(signal::stack_underflow().into()); + stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } @@ -1461,12 +1453,12 @@ fn binrec_aux( Some(expression) => { evaluator .stack - .extend_from_slice(&[expression, signal::type_error().into()]); + .extend_from_slice(&[expression, Symbol::type_error().into()]); Err(Effect::Raise) } None => { - evaluator.stack.push(signal::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } diff --git a/rat/src/expression.rs b/rat/src/expression.rs index c730a5d..26b08ff 100644 --- a/rat/src/expression.rs +++ b/rat/src/expression.rs @@ -15,7 +15,6 @@ use crate::channel::Channel; use crate::decimal::Decimal; use crate::integer::Integer; use crate::quote::Quote; -use crate::signal::Signal; use crate::string::String; use crate::symbol::Symbol; use crate::verb::Verb; @@ -27,7 +26,6 @@ pub enum Expression { Decimal(Decimal), Integer(Integer), Quote(Quote), - Signal(Signal), String(String), Symbol(Symbol), Verb(Verb), @@ -71,13 +69,6 @@ impl From for Expression { } } -impl From for Expression { - #[inline] - fn from(value: Signal) -> Self { - Self::Signal(value) - } -} - impl From for Expression { #[inline] fn from(value: String) -> Self { @@ -109,7 +100,6 @@ impl Evaluate<&mut Evaluator> for Expression { Expression::Decimal(e) => e.evaluate(evaluator), Expression::Integer(e) => e.evaluate(evaluator), Expression::Quote(e) => e.evaluate(evaluator), - Expression::Signal(e) => e.evaluate(evaluator), Expression::String(e) => e.evaluate(evaluator), Expression::Symbol(e) => e.evaluate(evaluator), Expression::Verb(e) => e.evaluate(evaluator), @@ -125,7 +115,6 @@ impl Display for Expression { Expression::Decimal(e) => Display::fmt(e, f), Expression::Integer(e) => Display::fmt(e, f), Expression::Quote(e) => Display::fmt(e, f), - Expression::Signal(e) => Display::fmt(e, f), Expression::String(e) => Display::fmt(e, f), Expression::Symbol(e) => Display::fmt(e, f), Expression::Verb(e) => Display::fmt(e, f), @@ -141,7 +130,6 @@ impl Debug for Expression { Expression::Decimal(e) => Debug::fmt(e, f), Expression::Integer(e) => Debug::fmt(e, f), Expression::Quote(e) => Debug::fmt(e, f), - Expression::Signal(e) => Debug::fmt(e, f), Expression::String(e) => Debug::fmt(e, f), Expression::Symbol(e) => Debug::fmt(e, f), Expression::Verb(e) => Debug::fmt(e, f), diff --git a/rat/src/grammar.pest b/rat/src/grammar.pest index 50b9b72..01b2e51 100644 --- a/rat/src/grammar.pest +++ b/rat/src/grammar.pest @@ -31,7 +31,7 @@ Locution = @{ } Expression = { - (Boolean | Decimal | Integer | Quote | Signal | String | Symbol) + (Boolean | Decimal | Integer | Quote | String | Symbol) } Boolean = @{ @@ -50,10 +50,6 @@ Quote = { LeftSquareBracket ~ Phrase? ~ RightSquareBracket } -Signal = @{ - "$" ~ ('A'..'Z' | 'a'..'z')+ -} - String = ${ "\"" ~ StringUnicodeScalarValue* ~ "\"" } diff --git a/rat/src/lib.rs b/rat/src/lib.rs index 9f3b16e..5149b7c 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -14,7 +14,6 @@ pub mod channel; pub mod decimal; pub mod integer; pub mod quote; -pub mod signal; pub mod string; pub mod symbol; pub mod verb; @@ -53,12 +52,13 @@ pub fn home_dir() -> &'static Path { #[cfg(test)] mod test { + use crate::builtin; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; use crate::expression::Expression; use crate::integer::Integer; + use crate::symbol::Symbol; use crate::verb::Verb; - use crate::{builtin, signal}; #[test] fn it_works1() { @@ -92,7 +92,7 @@ mod test { .collect(), ), Expression::Quote([Expression::Integer(Integer(42))].into_iter().collect()), - Expression::Signal(signal::stack_underflow()), + Expression::Symbol(Symbol::stack_underflow()), Expression::Verb(Verb(builtin::r#try)), ]) .unwrap(); diff --git a/rat/src/parser.rs b/rat/src/parser.rs index 06b5375..aed6bb5 100644 --- a/rat/src/parser.rs +++ b/rat/src/parser.rs @@ -21,7 +21,6 @@ use crate::expression::Expression; use crate::integer::Integer; use crate::locution::{Locution, OwnedLocution}; use crate::quote::Quote; -use crate::signal::Signal; use crate::string::String; use crate::symbol::Symbol; use crate::vocabulary::{Definition, Visibility, Vocabulary}; @@ -258,19 +257,6 @@ impl FromStr for Quote { } } -impl FromStr for Signal { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - check_token_boundary(s)?; - - let mut pairs = Grammar::parse(Rule::Signal, s).map_err(with_origin(Origin::Unknown))?; - assert_eq!(pairs.len(), 1); - - parse_signal(pairs.next().unwrap()) - } -} - impl FromStr for String { type Err = ParseError; @@ -433,7 +419,6 @@ fn parse_expression( Rule::Decimal => parse_decimal(origin, pair).map(Expression::Decimal), Rule::Integer => parse_integer(origin, pair).map(Expression::Integer), Rule::Quote => parse_quote(parser, origin, pair).map(Expression::Quote), - Rule::Signal => parse_signal(pair).map(Expression::Signal), Rule::String => parse_string(origin, pair).map(Expression::String), Rule::Symbol => parse_symbol(origin, pair).map(Expression::Symbol), rule => unreachable!("unexpected rule: `{rule:?}`"), @@ -520,11 +505,6 @@ fn parse_quote(parser: &mut Parser, origin: Origin, pair: PestPair) -> Result Result { - assert_eq!(pair.as_rule(), Rule::Signal); - Ok(unsafe { Signal::new(&pair.as_str()[1..]) }) -} - fn parse_string(origin: Origin, pair: PestPair) -> Result { assert_eq!(pair.as_rule(), Rule::String); pair.into_inner() @@ -606,7 +586,6 @@ mod test { use crate::integer::Integer; use crate::locution::{Locution, OwnedLocution}; use crate::quote::Quote; - use crate::signal::{self, Signal}; use crate::string::String; use crate::symbol::Symbol; use crate::word::{OwnedWord, Word}; @@ -660,10 +639,10 @@ mod test { #[test] fn parse_quote() { - assert!(" [⊥ ⊤ 42 3.14 $IoError 'hello' \"world\" []]" + assert!(" [⊥ ⊤ 42 3.14 'hello' \"world\" []]" .parse::() .is_err()); - assert!("[⊥ ⊤ 42 3.14 $IoError 'hello' \"world\" []] " + assert!("[⊥ ⊤ 42 3.14 'hello' \"world\" []] " .parse::() .is_err()); assert_eq!( @@ -672,29 +651,18 @@ mod test { Expression::Boolean(Boolean(true)), Expression::Integer(Integer(42)), Expression::Decimal(Decimal(3.14)), - Expression::Signal(unsafe { Signal::new("IoError") }), Expression::Symbol(Symbol::new("hello")), Expression::String(String::from_utf8("world")), Expression::Quote(Quote::default()), ] .into_iter() .collect::(), - "[⊥ ⊤ 42 3.14 $IoError 'hello' \"world\" []]" + "[⊥ ⊤ 42 3.14 'hello' \"world\" []]" .parse::() .unwrap() ); } - #[test] - fn parse_signal() { - assert!(" $StackUnderflow".parse::().is_err()); - assert!("$StackUnderflow ".parse::().is_err()); - assert_eq!( - signal::stack_underflow(), - "$StackUnderflow".parse().unwrap() - ); - } - #[test] fn parse_string() { assert!(" \"hello\"".parse::().is_err()); diff --git a/rat/src/signal.rs b/rat/src/signal.rs deleted file mode 100644 index 2c4bbfa..0000000 --- a/rat/src/signal.rs +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -use std::error::Error; -use std::fmt::{Debug, Display}; - -use ustr::Ustr; - -use crate::effect::Effect; -use crate::evaluate::Evaluate; -use crate::evaluator::Evaluator; -use crate::expression::Expression; - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Signal(Ustr); - -impl Signal { - // FIXME - /** - * SAFETY - * This rat does not validate input string so it can be called with invalid signal literals. - */ - pub(crate) unsafe fn new(literal: &str) -> Self { - Self(Ustr::from(literal)) - } - - pub fn try_trom_literal(literal: &str) -> Result { - if literal.len() > 1 - && literal - .strip_prefix('$') - .map(|s| s.bytes().all(|byte| byte.is_ascii_alphabetic())) - .unwrap_or(false) - { - return Ok(unsafe { Self::new(&literal[1..]) }); - } - - Err(InvalidSignalLiteral) - } -} - -pub fn divide_by_zero() -> Signal { - unsafe { Signal::new("DivideByZero") } -} - -pub fn stack_underflow() -> Signal { - unsafe { Signal::new("StackUnderflow") } -} - -pub fn out_of_range() -> Signal { - unsafe { Signal::new("OutOfRange") } -} - -pub fn type_error() -> Signal { - unsafe { Signal::new("TypeError") } -} - -pub fn io_error() -> Signal { - unsafe { Signal::new("IOError") } -} - -impl Evaluate<&mut Evaluator> for Signal { - type Output = Result<(), Effect>; - - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::Signal(self)); - Ok(()) - } -} - -impl Display for Signal { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self(s) = self; - write!(f, "${s}") - } -} - -impl Debug for Signal { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Display::fmt(self, f) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InvalidSignalLiteral; - -impl Display for InvalidSignalLiteral { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Debug::fmt(self, f) - } -} - -impl Error for InvalidSignalLiteral {} - -#[cfg(test)] -mod test { - use std::collections::hash_map::DefaultHasher; - use std::hash::{BuildHasher, BuildHasherDefault}; - - use super::*; - - #[test] - fn identity() { - let sut1 = stack_underflow(); - let sut2 = stack_underflow(); - let sut3 = io_error(); - - assert_eq!(sut1, sut2); - assert_eq!(sut1, sut2); - - assert_ne!(sut1, sut3); - assert_ne!(sut1, sut3); - - assert_ne!(sut2, sut3); - assert_ne!(sut2, sut3); - - let hash_builder = BuildHasherDefault::::default(); - let h1 = hash_builder.hash_one(sut1); - let h2 = hash_builder.hash_one(sut2); - assert_eq!(h1, h2); - } - - #[test] - fn try_from_literal() { - assert_eq!(io_error(), Signal::try_trom_literal("$IOError").unwrap()); - assert!(Signal::try_trom_literal("$").is_err()); - assert!(Signal::try_trom_literal("$x!").is_err()); - assert!(Signal::try_trom_literal("$x42").is_err()); - assert!(Signal::try_trom_literal("IoError").is_err()); - } -} diff --git a/rat/src/symbol.rs b/rat/src/symbol.rs index 982831f..44f88a2 100644 --- a/rat/src/symbol.rs +++ b/rat/src/symbol.rs @@ -27,6 +27,26 @@ impl Symbol { Symbol(Ustr::from(s)) } + pub fn divide_by_zero() -> Symbol { + Symbol::new("DivideByZero") + } + + pub fn stack_underflow() -> Symbol { + Symbol::new("StackUnderflow") + } + + pub fn out_of_range() -> Symbol { + Symbol::new("OutOfRange") + } + + pub fn type_error() -> Symbol { + Symbol::new("TypeError") + } + + pub fn io_error() -> Symbol { + Symbol::new("IOError") + } + #[inline] pub fn as_str(&self) -> &str { &self.0 From a0c098931fc32f61c0a39db6e7104801792a9cfe Mon Sep 17 00:00:00 2001 From: daddinuz Date: Fri, 12 Jul 2024 23:39:02 +0200 Subject: [PATCH 06/17] add message broker --- Cargo.lock | 16 +++--- examples/alice_n_bob.rat | 8 +-- examples/parallel-mergesort.rat | 10 ++-- rat/src/builtin.rs | 83 +++++++++++++--------------- rat/src/channel.rs | 96 --------------------------------- rat/src/evaluator.rs | 18 +++---- rat/src/expression.rs | 24 ++++----- rat/src/globals.rs | 96 +++++++++++++++++++++++++++++++++ rat/src/lib.rs | 20 ++++--- rat/src/process.rs | 57 ++++++++++++++++++++ rat/src/symbol.rs | 2 +- rat/src/vocabulary.rs | 18 +++---- 12 files changed, 245 insertions(+), 203 deletions(-) delete mode 100644 rat/src/channel.rs create mode 100644 rat/src/globals.rs create mode 100644 rat/src/process.rs diff --git a/Cargo.lock b/Cargo.lock index 0cbc0c1..bece5c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,9 +56,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "clipboard-win" -version = "5.3.1" +version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79f4473f5144e20d9aceaf2972478f06ddf687831eafeeb434fbaf0acc4144ad" +checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" dependencies = [ "error-code", ] @@ -523,9 +523,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.68" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", @@ -534,18 +534,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", diff --git a/examples/alice_n_bob.rat b/examples/alice_n_bob.rat index a351a17..9d99a70 100644 --- a/examples/alice_n_bob.rat +++ b/examples/alice_n_bob.rat @@ -1,7 +1,3 @@ -: std @ rat\std ; - -: alice ← ["alice" produce consume receive say] spawn ; -: bob ← ["bob" produce consume receive say] spawn ; - -alice bob std\dup2 swap send send +["alice" 'bob' send 'alice' recv say] spawn +["bob" 'alice' send 'bob' recv say] spawn "press [enter] to continue\n" ask diff --git a/examples/parallel-mergesort.rat b/examples/parallel-mergesort.rat index 153bfec..666ebaa 100644 --- a/examples/parallel-mergesort.rat +++ b/examples/parallel-mergesort.rat @@ -2,12 +2,12 @@ : math @ rat\math ; # with program forming -: process ← quote [seq\mergesort produce] cat spawn ; -: parallel-mergesort ← dup len math\halve split [process] unary2 [receive] unary2 seq\merge ; +: seq-ms ← quote [seq\mergesort 'out' send] cat detach ; +: par-ms ← dup len math\halve split [seq-ms 'out' recv] unary2 seq\merge ; # with message passing -: process ← [consume seq\mergesort produce] spawn ; -: parallel-mergesort ← dup len math\halve split [process dup rotate send] unary2 [receive] unary2 seq\merge ; +# : seq-ms ← ['in' recv seq\mergesort 'out' send] detach ; +# : par-ms ← dup len math\halve split [seq-ms 'in' send 'out' recv] unary2 seq\merge ; [-23714 36911 27209 -61081 4487 62986 43562 59953 -6002 -64976 6222 37230 1774 60450 35372 9313 -63141 -10099 -56599 37381 29627 17147 -56774 46348 25159 42717 -10426 -38088 -9482 -51818 -13225 -22274 -52566 -5587 -148 59711 51437 6343 50139 32437 27966 -34985 167 27161 -53411 -6759 -27066 -7772 49899 -24127 7940 61517 -14064 -4433 6018 42197 -24241 4939 23687 -27950 -60335 -483 -51116 -201 21847 -65149 46808 49486 -6132 4372 14587 60525 14700 8373 -48827 -64401 -53524 -28842 -10959 -56034 -64763 -54632 28581 -3277 5279 7684 -26031 32221 1723 59531 -34723 17671 3424 -30493 28938 -12043 -27853 -14788 -34395 -23175 39083 -3314 16725 -14123 5069 -59857 52477 -25028 9931 -27366 41663 10612 -46240 27308 7778 -12942 37028 -18502 59012 53713 60519 -49390 -15897 41667 55977 45961 39978 59934 23858 -23789 -17806 -14129 -36824 -57834 -28443 -22873 26639 -20046 -57731 -16443 -599 -2646 8985 -14817 -10395 -42440 -59983 3357 44965 -44840 36400 -10323 -39719 45791 -27538 15597 7872 -19558 54625 -10621 27469 -61915 -45654 -61333 10374 50181 5656 8559 -9822 -9340 23135 -11774 -28400 -44677 304 37783 -56801 -45383 59955 23509 55993 -61971 16262 -49607 39590 -27209 1339 -56543 -41882 64893 50150 -16153 -317 -16469 7629 19020 15578 46013 53541 -27485 60355 -28348 -63558 -45715 -43954 62904 -8753 29052 -56968 52829 31804 45589 -26416 30184 29918 -38968 19638 -24968 -24088 -9447 48799 -50660 43610 -50411 -47355 -59101 59279 34413 55334 -16776 50629 63673 -44714 -32217 -37943 -21810 -51476 33889 6583 65273 60878 -13805 59344 34343 -43042 25481 40781 -37723 -39856 -19967 -54323 -6219 -24811 -51108 4870 -20829] -parallel-mergesort say +par-ms say diff --git a/rat/src/builtin.rs b/rat/src/builtin.rs index 52b738a..7dbc6ef 100644 --- a/rat/src/builtin.rs +++ b/rat/src/builtin.rs @@ -13,9 +13,9 @@ use crate::evaluator::Evaluator; use crate::expression::Expression; use crate::boolean::Boolean; -use crate::channel::Channel; use crate::decimal::Decimal; use crate::integer::Integer; +use crate::process::Process; use crate::quote::Quote; use crate::string::String; use crate::symbol::Symbol; @@ -1155,93 +1155,79 @@ pub fn dup(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } -// TODO: review pub fn send(evaluator: &mut Evaluator) -> Result<(), Effect> { - let stack = &mut evaluator.stack; + match &evaluator.stack[..] { + [.., expression, Expression::Symbol(topic)] => { + let expression = expression.clone(); - match stack[..] { - [.., Expression::Channel(ref channel), ref expression] => { - if channel.send(expression.clone()).is_err() { - stack.push(Symbol::io_error().into()); + if evaluator.globals.broker.send(*topic, expression).is_err() { + evaluator.stack.push(Symbol::io_error().into()); return Err(Effect::Raise); } - let top = stack.len(); - stack.truncate(top - 2); + let top = evaluator.stack.len(); + evaluator.stack.truncate(top - 2); Ok(()) } [.., _, _] => { - stack.push(Symbol::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(Symbol::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } } -pub fn receive(evaluator: &mut Evaluator) -> Result<(), Effect> { - let stack = &mut evaluator.stack; - - match stack[..] { - [.., Expression::Channel(ref channel)] => match channel.recv() { +pub fn recv(evaluator: &mut Evaluator) -> Result<(), Effect> { + match &evaluator.stack[..] { + [.., Expression::Symbol(topic)] => match evaluator.globals.broker.recv(*topic) { Ok(expression) => { - *stack.last_mut().unwrap() = expression; + *evaluator.stack.last_mut().unwrap() = expression; Ok(()) } Err(_) => { - stack.push(Symbol::io_error().into()); + evaluator.stack.push(Symbol::io_error().into()); Err(Effect::Raise) } }, [.., _] => { - stack.push(Symbol::type_error().into()); + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } _ => { - stack.push(Symbol::stack_underflow().into()); + evaluator.stack.push(Symbol::stack_underflow().into()); Err(Effect::Raise) } } } -pub fn produce(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn spawn(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; - match stack.pop() { - Some(expression) => { - if let Some(sender) = evaluator.channel.as_ref().map(|(sender, _)| sender) { - if sender.send(expression).is_err() { - stack.push(Symbol::io_error().into()); - return Err(Effect::Raise); - } - } + match &mut stack[..] { + [.., Expression::Quote(quote)] => { + let quote = std::mem::take(quote); + stack.pop().unwrap(); + + let process = Process::spawn(evaluator.globals.clone(), quote); + stack.push(Expression::Process(process)); Ok(()) } - None => { - stack.push(Symbol::stack_underflow().into()); + [.., _] => { + evaluator.stack.push(Symbol::type_error().into()); Err(Effect::Raise) } - } -} - -pub fn consume(evaluator: &mut Evaluator) -> Result<(), Effect> { - let stack = &mut evaluator.stack; - - if let Some(receiver) = evaluator.channel.as_ref().map(|(_, receiver)| receiver) { - if let Ok(expression) = receiver.recv() { - stack.push(expression); - return Ok(()); + _ => { + evaluator.stack.push(Symbol::stack_underflow().into()); + Err(Effect::Raise) } } - - stack.push(Symbol::io_error().into()); - Err(Effect::Raise) } -pub fn spawn(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn detach(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -1249,8 +1235,11 @@ pub fn spawn(evaluator: &mut Evaluator) -> Result<(), Effect> { let quote = std::mem::take(quote); stack.pop().unwrap(); - let channel = Channel::spawn(quote); - stack.push(Expression::Channel(channel)); + let globals = evaluator.globals.clone(); + std::thread::spawn(move || { + let mut evaluator = Evaluator::with_globals(globals); + evaluator.evaluate(quote) + }); Ok(()) } diff --git a/rat/src/channel.rs b/rat/src/channel.rs deleted file mode 100644 index 69eef97..0000000 --- a/rat/src/channel.rs +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -use crossbeam::channel::{self, Receiver, Sender}; - -use std::error::Error; -use std::fmt::{Debug, Display}; -use std::hash::Hash; -use std::sync::Arc; -use std::thread::{self, ThreadId}; - -use crate::effect::Effect; -use crate::evaluate::Evaluate; -use crate::evaluator::Evaluator; -use crate::expression::Expression; -use crate::quote::Quote; - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct Channel { - inner: Arc, -} - -impl Channel { - pub fn spawn(quote: Quote) -> Self { - let (send, consume) = channel::unbounded(); - let (produce, receive) = channel::unbounded(); - - let handle = thread::spawn(move || { - let mut evaluator = Evaluator { - stack: Vec::new(), - channel: Some((produce, consume)), - }; - evaluator.evaluate(quote) - }); - - Self { - inner: Arc::new(Inner { - sender: send, - receiver: receive, - identity: handle.thread().id(), - }), - } - } - - pub fn send(&self, expr: Expression) -> Result<(), impl Error> { - self.inner.sender.send(expr) - } - - pub fn recv(&self) -> Result { - self.inner.receiver.recv() - } -} - -impl Evaluate<&mut Evaluator> for Channel { - type Output = Result<(), Effect>; - - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::Channel(self)); - Ok(()) - } -} - -impl Display for Channel { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Debug::fmt(self, f) - } -} - -impl Debug for Channel { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "↯{:?}", self.inner.identity) - } -} - -struct Inner { - sender: Sender, - receiver: Receiver, - identity: ThreadId, -} - -impl PartialEq for Inner { - fn eq(&self, other: &Self) -> bool { - self.identity == other.identity - } -} - -impl Eq for Inner {} - -impl Hash for Inner { - fn hash(&self, state: &mut H) { - self.identity.hash(state) - } -} diff --git a/rat/src/evaluator.rs b/rat/src/evaluator.rs index bfe3644..b4b13f1 100644 --- a/rat/src/evaluator.rs +++ b/rat/src/evaluator.rs @@ -4,28 +4,28 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use crossbeam::channel::{Receiver, Sender}; +use std::sync::Arc; use crate::effect::Effect; use crate::evaluate::Evaluate; use crate::expression::Expression; +use crate::globals::Globals; +#[derive(Default)] pub struct Evaluator { pub stack: Vec, - pub channel: Option<(Sender, Receiver)>, + pub globals: Arc, } -impl Default for Evaluator { - fn default() -> Self { - Self::new() +impl Evaluator { + pub fn new() -> Self { + Default::default() } -} -impl Evaluator { - pub const fn new() -> Self { + pub fn with_globals(globals: Arc) -> Self { Self { stack: Vec::new(), - channel: None, + globals, } } } diff --git a/rat/src/expression.rs b/rat/src/expression.rs index 26b08ff..404dc5f 100644 --- a/rat/src/expression.rs +++ b/rat/src/expression.rs @@ -11,9 +11,9 @@ use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; use crate::boolean::Boolean; -use crate::channel::Channel; use crate::decimal::Decimal; use crate::integer::Integer; +use crate::process::Process; use crate::quote::Quote; use crate::string::String; use crate::symbol::Symbol; @@ -22,9 +22,9 @@ use crate::verb::Verb; #[derive(Clone, PartialEq, Eq, Hash)] pub enum Expression { Boolean(Boolean), - Channel(Channel), Decimal(Decimal), Integer(Integer), + Process(Process), Quote(Quote), String(String), Symbol(Symbol), @@ -41,13 +41,6 @@ impl From for Expression { } } -impl From for Expression { - #[inline] - fn from(value: Channel) -> Self { - Self::Channel(value) - } -} - impl From for Expression { #[inline] fn from(value: Decimal) -> Self { @@ -62,6 +55,13 @@ impl From for Expression { } } +impl From for Expression { + #[inline] + fn from(value: Process) -> Self { + Self::Process(value) + } +} + impl From for Expression { #[inline] fn from(value: Quote) -> Self { @@ -96,9 +96,9 @@ impl Evaluate<&mut Evaluator> for Expression { fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { match self { Expression::Boolean(e) => e.evaluate(evaluator), - Expression::Channel(e) => e.evaluate(evaluator), Expression::Decimal(e) => e.evaluate(evaluator), Expression::Integer(e) => e.evaluate(evaluator), + Expression::Process(e) => e.evaluate(evaluator), Expression::Quote(e) => e.evaluate(evaluator), Expression::String(e) => e.evaluate(evaluator), Expression::Symbol(e) => e.evaluate(evaluator), @@ -111,9 +111,9 @@ impl Display for Expression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Expression::Boolean(e) => Display::fmt(e, f), - Expression::Channel(e) => Display::fmt(e, f), Expression::Decimal(e) => Display::fmt(e, f), Expression::Integer(e) => Display::fmt(e, f), + Expression::Process(e) => Display::fmt(e, f), Expression::Quote(e) => Display::fmt(e, f), Expression::String(e) => Display::fmt(e, f), Expression::Symbol(e) => Display::fmt(e, f), @@ -126,9 +126,9 @@ impl Debug for Expression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Expression::Boolean(e) => Debug::fmt(e, f), - Expression::Channel(e) => Debug::fmt(e, f), Expression::Decimal(e) => Debug::fmt(e, f), Expression::Integer(e) => Debug::fmt(e, f), + Expression::Process(e) => Debug::fmt(e, f), Expression::Quote(e) => Debug::fmt(e, f), Expression::String(e) => Debug::fmt(e, f), Expression::Symbol(e) => Debug::fmt(e, f), diff --git a/rat/src/globals.rs b/rat/src/globals.rs new file mode 100644 index 0000000..694e1fa --- /dev/null +++ b/rat/src/globals.rs @@ -0,0 +1,96 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +use std::collections::HashMap; +use std::error::Error; +use std::sync::RwLock; + +use crossbeam::channel::{self, Receiver, Sender}; + +use crate::expression::Expression; +use crate::symbol::Symbol; + +#[derive(Default)] +pub struct Globals { + pub broker: Broker, +} + +impl Globals { + pub fn new() -> Self { + Default::default() + } +} + +#[derive(Default)] +pub struct Broker { + channels: RwLock>, +} + +impl Broker { + pub fn new() -> Self { + Default::default() + } + + pub fn send(&self, topic: Symbol, expression: Expression) -> Result<(), impl Error> { + // IMPORTANT: we must release any lock before performing send or recv operations. + // keeping any lock active while performing a recv operation may lead to deadlocks. + // we must to minimize the scope of active locks. + + let sender = 'block: { + // optimistically try to get the channel if it exists. + if let Some(channel) = self.channels.read().unwrap().get(&topic) { + break 'block channel.sender.clone(); + } + + // if it does not exist, create it. + self.channels + .write() + .unwrap() + .entry(topic) + .or_default() + .sender + .clone() + }; + + sender.send(expression) + } + + pub fn recv(&self, topic: Symbol) -> Result { + // IMPORTANT: we must release any lock before performing send or recv operations. + // keeping any lock active while performing a recv operation may lead to deadlocks. + // we must to minimize the scope of active locks. + + let receiver = 'block: { + // optimistically try to get the channel if it exists. + if let Some(channel) = self.channels.read().unwrap().get(&topic) { + break 'block channel.receiver.clone(); + } + + // if it does not exist, create it. + self.channels + .write() + .unwrap() + .entry(topic) + .or_default() + .receiver + .clone() + }; + + receiver.recv() + } +} + +struct Channel { + sender: Sender, + receiver: Receiver, +} + +impl Default for Channel { + fn default() -> Self { + let (sender, receiver) = channel::unbounded(); + Self { sender, receiver } + } +} diff --git a/rat/src/lib.rs b/rat/src/lib.rs index 5149b7c..92ed179 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -10,9 +10,9 @@ extern crate pest_derive; pub(crate) mod codegen; pub mod boolean; -pub mod channel; pub mod decimal; pub mod integer; +pub mod process; pub mod quote; pub mod string; pub mod symbol; @@ -24,6 +24,7 @@ pub mod builtin; pub mod effect; pub mod evaluate; pub mod evaluator; +pub mod globals; pub mod locution; pub mod parser; pub mod vocabulary; @@ -113,26 +114,29 @@ mod test { Expression::Integer(Integer(8)), Expression::Integer(Integer(12)), Expression::Verb(Verb(builtin::add)), - Expression::Verb(Verb(builtin::produce)), + Expression::Symbol(Symbol::new("out")), + Expression::Verb(Verb(builtin::send)), ] .into_iter() .collect(), ), - Expression::Verb(Verb(builtin::spawn)), + Expression::Verb(Verb(builtin::detach)), Expression::Quote( [ Expression::Integer(Integer(10)), Expression::Integer(Integer(12)), Expression::Verb(Verb(builtin::add)), - Expression::Verb(Verb(builtin::produce)), + Expression::Symbol(Symbol::new("out")), + Expression::Verb(Verb(builtin::send)), ] .into_iter() .collect(), ), - Expression::Verb(Verb(builtin::spawn)), - Expression::Verb(Verb(builtin::receive)), - Expression::Verb(Verb(builtin::swap)), - Expression::Verb(Verb(builtin::receive)), + Expression::Verb(Verb(builtin::detach)), + Expression::Symbol(Symbol::new("out")), + Expression::Verb(Verb(builtin::recv)), + Expression::Symbol(Symbol::new("out")), + Expression::Verb(Verb(builtin::recv)), Expression::Verb(Verb(builtin::add)), ]) .unwrap(); diff --git a/rat/src/process.rs b/rat/src/process.rs new file mode 100644 index 0000000..97490dd --- /dev/null +++ b/rat/src/process.rs @@ -0,0 +1,57 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +use std::fmt::{Debug, Display}; +use std::hash::Hash; +use std::sync::Arc; +use std::thread::{self}; + +use crate::effect::Effect; +use crate::evaluate::Evaluate; +use crate::evaluator::Evaluator; +use crate::expression::Expression; +use crate::globals::Globals; +use crate::quote::Quote; + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct Process { + quote: Quote, +} + +impl Process { + pub fn spawn(globals: Arc, quote: Quote) -> Self { + { + let quote = quote.clone(); + thread::spawn(move || { + let mut evaluator = Evaluator::with_globals(globals); + evaluator.evaluate(quote) + }); + } + + Self { quote } + } +} + +impl Evaluate<&mut Evaluator> for Process { + type Output = Result<(), Effect>; + + fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { + evaluator.stack.push(Expression::Process(self)); + Ok(()) + } +} + +impl Display for Process { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Debug::fmt(self, f) + } +} + +impl Debug for Process { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "${:?}", self.quote) + } +} diff --git a/rat/src/symbol.rs b/rat/src/symbol.rs index 44f88a2..e17e877 100644 --- a/rat/src/symbol.rs +++ b/rat/src/symbol.rs @@ -13,7 +13,7 @@ use crate::expression::Expression; use std::fmt::{Debug, Display}; -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Symbol(Ustr); impl FromIterator for Symbol { diff --git a/rat/src/vocabulary.rs b/rat/src/vocabulary.rs index 0fd16e1..dbf8443 100644 --- a/rat/src/vocabulary.rs +++ b/rat/src/vocabulary.rs @@ -135,7 +135,7 @@ impl Vocabulary { } } -static PRELUDE: [(&Word, &[Expression]); 68] = [ +static PRELUDE: [(&Word, &[Expression]); 67] = [ (word_literal("neg"), &[Expression::Verb(Verb(builtin::neg))]), ( word_literal("incr"), @@ -289,21 +289,17 @@ static PRELUDE: [(&Word, &[Expression]); 68] = [ &[Expression::Verb(Verb(builtin::send))], ), ( - word_literal("receive"), - &[Expression::Verb(Verb(builtin::receive))], - ), - ( - word_literal("produce"), - &[Expression::Verb(Verb(builtin::produce))], - ), - ( - word_literal("consume"), - &[Expression::Verb(Verb(builtin::consume))], + word_literal("recv"), + &[Expression::Verb(Verb(builtin::recv))], ), ( word_literal("spawn"), &[Expression::Verb(Verb(builtin::spawn))], ), + ( + word_literal("detach"), + &[Expression::Verb(Verb(builtin::detach))], + ), (word_literal("ask"), &[Expression::Verb(Verb(builtin::ask))]), (word_literal("say"), &[Expression::Verb(Verb(builtin::say))]), ( From 27b18f6b49b2c86941818905889941d0f4836dff Mon Sep 17 00:00:00 2001 From: daddinuz Date: Mon, 15 Jul 2024 22:21:52 +0200 Subject: [PATCH 07/17] review evaluator impl and add parbinrec --- rat-cli/src/main.rs | 4 +- rat/src/boolean.rs | 6 +- rat/src/builtin.rs | 144 +++++++++++++++++++++++++++++-------- rat/src/decimal.rs | 6 +- rat/src/evaluator.rs | 16 ++--- rat/src/expression.rs | 54 +++++++------- rat/src/integer.rs | 6 +- rat/src/lib.rs | 163 ++++++++++++++++++++++++++++-------------- rat/src/process.rs | 6 +- rat/src/quote.rs | 6 +- rat/src/string.rs | 6 +- rat/src/symbol.rs | 6 +- rat/src/verb.rs | 7 +- rat/src/vocabulary.rs | 6 +- 14 files changed, 286 insertions(+), 150 deletions(-) diff --git a/rat-cli/src/main.rs b/rat-cli/src/main.rs index 410bc0c..24e22b4 100644 --- a/rat-cli/src/main.rs +++ b/rat-cli/src/main.rs @@ -11,7 +11,6 @@ use std::fs::{File, OpenOptions}; use std::io::{ErrorKind, Read}; use std::path::{Path, PathBuf}; -use rat::quote::DisplayAdapter; use rustyline::error::ReadlineError; use rustyline::highlight::MatchingBracketHighlighter; use rustyline::validate::MatchingBracketValidator; @@ -22,6 +21,7 @@ use rustyline_derive::{Completer, Highlighter, Hinter, Validator}; use rat::evaluate::Evaluate; use rat::evaluator::Evaluator; use rat::parser::{Origin, Parser}; +use rat::quote::DisplayAdapter; use error::{CliError, Consume, Report}; @@ -161,7 +161,7 @@ fn interpret( evaluator: &mut Evaluator, ) -> Result<(), CliError> { let program = parser.parse(origin, source)?; - evaluator.evaluate(program).map_err(|effect| { + evaluator.evaluate(program.into_iter()).map_err(|effect| { format!( "unahandled effect: {effect:?}\nstack (top rightmost): {:?}", DisplayAdapter::new(&evaluator.stack) diff --git a/rat/src/boolean.rs b/rat/src/boolean.rs index a7e318c..0412269 100644 --- a/rat/src/boolean.rs +++ b/rat/src/boolean.rs @@ -30,11 +30,11 @@ impl From for bool { } } -impl Evaluate<&mut Evaluator> for Boolean { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::Boolean(self)); + fn evaluate(self, value: Boolean) -> Self::Output { + self.stack.push(Expression::Boolean(value)); Ok(()) } } diff --git a/rat/src/builtin.rs b/rat/src/builtin.rs index 7dbc6ef..3dea91a 100644 --- a/rat/src/builtin.rs +++ b/rat/src/builtin.rs @@ -698,7 +698,7 @@ pub fn quote(evaluator: &mut Evaluator) -> Result<(), Effect> { pub fn unquote(evaluator: &mut Evaluator) -> Result<(), Effect> { match evaluator.stack.pop() { - Some(Expression::Quote(quote)) => evaluator.evaluate(quote), + Some(Expression::Quote(quote)) => evaluator.evaluate(quote.iter().cloned()), Some(expression) => { evaluator .stack @@ -761,7 +761,7 @@ pub fn unary2(evaluator: &mut Evaluator) -> Result<(), Effect> { evaluator.evaluate(quote.iter().cloned())?; evaluator.stack.push(input2); - evaluator.evaluate(quote) + evaluator.evaluate(quote.iter().cloned()) } [.., _, _, _] => { stack.push(Symbol::type_error().into()); @@ -803,7 +803,7 @@ pub fn r#if(evaluator: &mut Evaluator) -> Result<(), Effect> { let quote = std::mem::take(truthy); let top = stack.len(); stack.truncate(top - 2); - return evaluator.evaluate(quote); + return evaluator.evaluate(quote.iter().cloned()); } let top = stack.len(); @@ -830,7 +830,7 @@ pub fn r#else(evaluator: &mut Evaluator) -> Result<(), Effect> { let quote = std::mem::take(falsy); let top = stack.len(); stack.truncate(top - 2); - return evaluator.evaluate(quote); + return evaluator.evaluate(quote.iter().cloned()); } let top = stack.len(); @@ -857,7 +857,7 @@ pub fn if_else(evaluator: &mut Evaluator) -> Result<(), Effect> { let quote = std::mem::take(if condition { truthy } else { falsy }); let top = stack.len(); stack.truncate(top - 3); - evaluator.evaluate(quote) + evaluator.evaluate(quote.iter().cloned()) } [.., _, _, _] => { evaluator.stack.push(Symbol::type_error().into()); @@ -1238,7 +1238,7 @@ pub fn detach(evaluator: &mut Evaluator) -> Result<(), Effect> { let globals = evaluator.globals.clone(); std::thread::spawn(move || { let mut evaluator = Evaluator::with_globals(globals); - evaluator.evaluate(quote) + evaluator.evaluate(quote.iter().cloned()) }); Ok(()) @@ -1335,17 +1335,17 @@ pub fn linrec(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; match &mut stack[..] { - [.., Expression::Quote(check), Expression::Quote(leave), Expression::Quote(split), Expression::Quote(merge)] => + [.., Expression::Quote(check), Expression::Quote(leave), Expression::Quote(shard), Expression::Quote(merge)] => { let merge = std::mem::take(merge); - let split = std::mem::take(split); + let shard = std::mem::take(shard); let leave = std::mem::take(leave); let check = std::mem::take(check); let top = stack.len(); stack.truncate(top - 4); - linrec_aux(evaluator, &check, &leave, &split, &merge) + linrec_aux(evaluator, &check, &leave, &shard, &merge) } [.., _, _, _, _] => { stack.push(Symbol::type_error().into()); @@ -1362,25 +1362,23 @@ fn linrec_aux( evaluator: &mut Evaluator, check: &Quote, leave: &Quote, - split: &Quote, + shard: &Quote, merge: &Quote, ) -> Result<(), Effect> { evaluator.evaluate(check.iter().cloned())?; match evaluator.stack.pop() { - Some(Expression::Boolean(Boolean(value))) => { - if value { - evaluator.evaluate(leave.iter().cloned()) - } else { - evaluator.evaluate(split.iter().cloned())?; - linrec_aux(evaluator, check, leave, split, merge)?; - evaluator.evaluate(merge.iter().cloned()) - } + Some(Expression::Boolean(Boolean(false))) => { + evaluator.evaluate(shard.iter().cloned())?; + linrec_aux(evaluator, check, leave, shard, merge)?; + evaluator.evaluate(merge.iter().cloned()) } - Some(value) => { + Some(Expression::Boolean(Boolean(true))) => evaluator.evaluate(leave.iter().cloned()), + Some(expression) => { evaluator .stack - .extend_from_slice(&[value, Symbol::type_error().into()]); + .extend_from_slice(&[expression, Symbol::type_error().into()]); + Err(Effect::Raise) } None => { @@ -1394,17 +1392,17 @@ pub fn binrec(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; match &mut stack[..] { - [.., Expression::Quote(check), Expression::Quote(leave), Expression::Quote(split), Expression::Quote(merge)] => + [.., Expression::Quote(check), Expression::Quote(leave), Expression::Quote(shard), Expression::Quote(merge)] => { let merge = std::mem::take(merge); - let split = std::mem::take(split); + let shard = std::mem::take(shard); let leave = std::mem::take(leave); let check = std::mem::take(check); let top = stack.len(); stack.truncate(top - 4); - binrec_aux(evaluator, &check, &leave, &split, &merge) + binrec_aux(evaluator, &check, &leave, &shard, &merge) } [.., _, _, _, _] => { stack.push(Symbol::type_error().into()); @@ -1421,21 +1419,109 @@ fn binrec_aux( evaluator: &mut Evaluator, check: &Quote, leave: &Quote, - split: &Quote, + shard: &Quote, merge: &Quote, ) -> Result<(), Effect> { evaluator.evaluate(check.iter().cloned())?; match evaluator.stack.pop() { Some(Expression::Boolean(Boolean(false))) => { - evaluator.evaluate(split.iter().cloned())?; + evaluator.evaluate(shard.iter().cloned())?; + + let expression = evaluator.stack.pop().unwrap(); + binrec_aux(evaluator, check, leave, shard, merge)?; + + evaluator.stack.push(expression); + binrec_aux(evaluator, check, leave, shard, merge)?; + + evaluator.evaluate(merge.iter().cloned()) + } + Some(Expression::Boolean(Boolean(true))) => evaluator.evaluate(leave.iter().cloned()), + Some(expression) => { + evaluator + .stack + .extend_from_slice(&[expression, Symbol::type_error().into()]); - let value = evaluator.stack.pop().unwrap(); - binrec_aux(evaluator, check, leave, split, merge)?; + Err(Effect::Raise) + } + None => { + evaluator.stack.push(Symbol::stack_underflow().into()); + Err(Effect::Raise) + } + } +} - evaluator.stack.push(value); - binrec_aux(evaluator, check, leave, split, merge)?; +pub fn parbinrec(evaluator: &mut Evaluator) -> Result<(), Effect> { + let stack = &mut evaluator.stack; + + match &mut stack[..] { + [.., Expression::Quote(check), Expression::Quote(leave), Expression::Quote(shard), Expression::Quote(merge)] => + { + let merge = std::mem::take(merge); + let shard = std::mem::take(shard); + let leave = std::mem::take(leave); + let check = std::mem::take(check); + + let top = stack.len(); + stack.truncate(top - 4); + + parbinrec_aux(evaluator, &check, &leave, &shard, &merge) + } + [.., _, _, _, _] => { + stack.push(Symbol::type_error().into()); + Err(Effect::Raise) + } + _ => { + stack.push(Symbol::stack_underflow().into()); + Err(Effect::Raise) + } + } +} + +fn parbinrec_aux( + evaluator: &mut Evaluator, + check: &Quote, + leave: &Quote, + shard: &Quote, + merge: &Quote, +) -> Result<(), Effect> { + evaluator.evaluate(check.iter().cloned())?; + + match evaluator.stack.pop() { + Some(Expression::Boolean(Boolean(false))) => { + evaluator.evaluate(shard.iter().cloned())?; + + let [expression1, expression2] = [ + evaluator.stack.pop().unwrap(), + evaluator.stack.pop().unwrap(), + ]; + + let [result1, result2] = std::thread::scope(|s| { + let globals = evaluator.globals.clone(); + let handle1 = s.spawn(|| { + let mut evaluator = Evaluator { + stack: vec![expression1], + globals, + }; + parbinrec_aux(&mut evaluator, check, leave, shard, merge)?; + Ok(evaluator.stack) + }); + + let globals = evaluator.globals.clone(); + let handle2 = s.spawn(|| { + let mut evaluator = Evaluator { + stack: vec![expression2], + globals, + }; + parbinrec_aux(&mut evaluator, check, leave, shard, merge)?; + Ok(evaluator.stack) + }); + + [handle1.join().unwrap(), handle2.join().unwrap()] + }); + evaluator.stack.extend(result1?); + evaluator.stack.extend(result2?); evaluator.evaluate(merge.iter().cloned()) } Some(Expression::Boolean(Boolean(true))) => evaluator.evaluate(leave.iter().cloned()), diff --git a/rat/src/decimal.rs b/rat/src/decimal.rs index e81f261..248c9bf 100644 --- a/rat/src/decimal.rs +++ b/rat/src/decimal.rs @@ -76,11 +76,11 @@ impl Decimal { } } -impl Evaluate<&mut Evaluator> for Decimal { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::Decimal(self)); + fn evaluate(self, value: Decimal) -> Self::Output { + self.stack.push(Expression::Decimal(value)); Ok(()) } } diff --git a/rat/src/evaluator.rs b/rat/src/evaluator.rs index b4b13f1..b347db3 100644 --- a/rat/src/evaluator.rs +++ b/rat/src/evaluator.rs @@ -30,21 +30,13 @@ impl Evaluator { } } -impl

Evaluate

for &mut Evaluator +impl Evaluate for &mut Evaluator where - P: IntoIterator, + I: Iterator, { type Output = Result<(), Effect>; - fn evaluate(self, program: P) -> Self::Output { - program.into_iter().try_for_each(|e| e.evaluate(self)) - } -} - -impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; - - fn evaluate(self, expression: Expression) -> Self::Output { - expression.evaluate(self) + fn evaluate(self, mut expressions: I) -> Self::Output { + expressions.try_for_each(|e| self.evaluate(e)) } } diff --git a/rat/src/expression.rs b/rat/src/expression.rs index 404dc5f..ede4b60 100644 --- a/rat/src/expression.rs +++ b/rat/src/expression.rs @@ -90,19 +90,19 @@ impl From for Expression { } } -impl Evaluate<&mut Evaluator> for Expression { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - match self { - Expression::Boolean(e) => e.evaluate(evaluator), - Expression::Decimal(e) => e.evaluate(evaluator), - Expression::Integer(e) => e.evaluate(evaluator), - Expression::Process(e) => e.evaluate(evaluator), - Expression::Quote(e) => e.evaluate(evaluator), - Expression::String(e) => e.evaluate(evaluator), - Expression::Symbol(e) => e.evaluate(evaluator), - Expression::Verb(e) => e.evaluate(evaluator), + fn evaluate(self, expression: Expression) -> Self::Output { + match expression { + Expression::Boolean(v) => self.evaluate(v), + Expression::Decimal(v) => self.evaluate(v), + Expression::Integer(v) => self.evaluate(v), + Expression::Process(v) => self.evaluate(v), + Expression::Quote(v) => self.evaluate(v), + Expression::String(v) => self.evaluate(v), + Expression::Symbol(v) => self.evaluate(v), + Expression::Verb(v) => self.evaluate(v), } } } @@ -110,14 +110,14 @@ impl Evaluate<&mut Evaluator> for Expression { impl Display for Expression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Expression::Boolean(e) => Display::fmt(e, f), - Expression::Decimal(e) => Display::fmt(e, f), - Expression::Integer(e) => Display::fmt(e, f), - Expression::Process(e) => Display::fmt(e, f), - Expression::Quote(e) => Display::fmt(e, f), - Expression::String(e) => Display::fmt(e, f), - Expression::Symbol(e) => Display::fmt(e, f), - Expression::Verb(e) => Display::fmt(e, f), + Expression::Boolean(v) => Display::fmt(v, f), + Expression::Decimal(v) => Display::fmt(v, f), + Expression::Integer(v) => Display::fmt(v, f), + Expression::Process(v) => Display::fmt(v, f), + Expression::Quote(v) => Display::fmt(v, f), + Expression::String(v) => Display::fmt(v, f), + Expression::Symbol(v) => Display::fmt(v, f), + Expression::Verb(v) => Display::fmt(v, f), } } } @@ -125,14 +125,14 @@ impl Display for Expression { impl Debug for Expression { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Expression::Boolean(e) => Debug::fmt(e, f), - Expression::Decimal(e) => Debug::fmt(e, f), - Expression::Integer(e) => Debug::fmt(e, f), - Expression::Process(e) => Debug::fmt(e, f), - Expression::Quote(e) => Debug::fmt(e, f), - Expression::String(e) => Debug::fmt(e, f), - Expression::Symbol(e) => Debug::fmt(e, f), - Expression::Verb(e) => Debug::fmt(e, f), + Expression::Boolean(v) => Debug::fmt(v, f), + Expression::Decimal(v) => Debug::fmt(v, f), + Expression::Integer(v) => Debug::fmt(v, f), + Expression::Process(v) => Debug::fmt(v, f), + Expression::Quote(v) => Debug::fmt(v, f), + Expression::String(v) => Debug::fmt(v, f), + Expression::Symbol(v) => Debug::fmt(v, f), + Expression::Verb(v) => Debug::fmt(v, f), } } } diff --git a/rat/src/integer.rs b/rat/src/integer.rs index f245ca3..faa1c45 100644 --- a/rat/src/integer.rs +++ b/rat/src/integer.rs @@ -76,11 +76,11 @@ impl Integer { } } -impl Evaluate<&mut Evaluator> for Integer { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::Integer(self)); + fn evaluate(self, value: Integer) -> Self::Output { + self.stack.push(Expression::Integer(value)); Ok(()) } } diff --git a/rat/src/lib.rs b/rat/src/lib.rs index 92ed179..441b147 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -53,6 +53,7 @@ pub fn home_dir() -> &'static Path { #[cfg(test)] mod test { + use crate::boolean::Boolean; use crate::builtin; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; @@ -65,80 +66,89 @@ mod test { fn it_works1() { let mut evaluator = Evaluator::default(); evaluator - .evaluate([ - Expression::Integer(Integer(64)), - Expression::Integer(Integer(22)), - Expression::Quote([Expression::Verb(Verb(builtin::sub))].into_iter().collect()), - Expression::Verb(Verb(builtin::unquote)), - ]) + .evaluate( + [ + Expression::Integer(Integer(64)), + Expression::Integer(Integer(22)), + Expression::Quote([Expression::Verb(Verb(builtin::sub))].into_iter().collect()), + Expression::Verb(Verb(builtin::unquote)), + ] + .into_iter(), + ) .unwrap(); - assert!(matches!( + assert_eq!( evaluator.stack.as_slice(), &[Expression::Integer(Integer(42))] - )); + ); } #[test] fn it_works2() { let mut evaluator = Evaluator::default(); evaluator - .evaluate([ - Expression::Quote( - [ - Expression::Integer(Integer(1)), - Expression::Verb(Verb(builtin::sub)), - ] - .into_iter() - .collect(), - ), - Expression::Quote([Expression::Integer(Integer(42))].into_iter().collect()), - Expression::Symbol(Symbol::stack_underflow()), - Expression::Verb(Verb(builtin::r#try)), - ]) + .evaluate( + [ + Expression::Quote( + [ + Expression::Integer(Integer(1)), + Expression::Verb(Verb(builtin::sub)), + ] + .into_iter() + .collect(), + ), + Expression::Quote([Expression::Integer(Integer(42))].into_iter().collect()), + Expression::Symbol(Symbol::stack_underflow()), + Expression::Verb(Verb(builtin::r#try)), + ] + .into_iter(), + ) .unwrap(); - assert!(matches!( + assert_eq!( evaluator.stack.as_slice(), &[Expression::Integer(Integer(42))] - )); + ); } #[test] fn it_works4() { let mut evaluator = Evaluator::default(); evaluator - .evaluate([ - Expression::Quote( - [ - Expression::Integer(Integer(8)), - Expression::Integer(Integer(12)), - Expression::Verb(Verb(builtin::add)), - Expression::Symbol(Symbol::new("out")), - Expression::Verb(Verb(builtin::send)), - ] - .into_iter() - .collect(), - ), - Expression::Verb(Verb(builtin::detach)), - Expression::Quote( - [ - Expression::Integer(Integer(10)), - Expression::Integer(Integer(12)), - Expression::Verb(Verb(builtin::add)), - Expression::Symbol(Symbol::new("out")), - Expression::Verb(Verb(builtin::send)), - ] - .into_iter() - .collect(), - ), - Expression::Verb(Verb(builtin::detach)), - Expression::Symbol(Symbol::new("out")), - Expression::Verb(Verb(builtin::recv)), - Expression::Symbol(Symbol::new("out")), - Expression::Verb(Verb(builtin::recv)), - Expression::Verb(Verb(builtin::add)), - ]) + .evaluate( + [ + Expression::Quote( + [ + Expression::Integer(Integer(8)), + Expression::Integer(Integer(12)), + Expression::Verb(Verb(builtin::add)), + Expression::Symbol(Symbol::new("out")), + Expression::Verb(Verb(builtin::send)), + ] + .into_iter() + .collect(), + ), + Expression::Verb(Verb(builtin::detach)), + Expression::Quote( + [ + Expression::Integer(Integer(10)), + Expression::Integer(Integer(12)), + Expression::Verb(Verb(builtin::add)), + Expression::Symbol(Symbol::new("out")), + Expression::Verb(Verb(builtin::send)), + ] + .into_iter() + .collect(), + ), + Expression::Verb(Verb(builtin::detach)), + Expression::Symbol(Symbol::new("out")), + Expression::Verb(Verb(builtin::recv)), + Expression::Symbol(Symbol::new("out")), + Expression::Verb(Verb(builtin::recv)), + Expression::Verb(Verb(builtin::add)), + ] + .into_iter(), + ) .unwrap(); assert!(matches!( @@ -146,4 +156,49 @@ mod test { &[Expression::Integer(Integer(42))] )); } + + #[test] + fn it_works5() { + let mut evaluator = Evaluator::default(); + evaluator + .evaluate( + [ + // if + Expression::Boolean(Boolean(true)), + Expression::Quote([Expression::Integer(42.into())].into_iter().collect()), + Expression::Verb(Verb(builtin::r#if)), + Expression::Boolean(Boolean(false)), + Expression::Quote([Expression::Integer(42.into())].into_iter().collect()), + Expression::Verb(Verb(builtin::r#if)), + // else + Expression::Boolean(Boolean(true)), + Expression::Quote([Expression::Integer(42.into())].into_iter().collect()), + Expression::Verb(Verb(builtin::r#else)), + Expression::Boolean(Boolean(false)), + Expression::Quote([Expression::Integer(42.into())].into_iter().collect()), + Expression::Verb(Verb(builtin::r#else)), + // if-else + Expression::Boolean(Boolean(true)), + Expression::Quote([Expression::Integer(42.into())].into_iter().collect()), + Expression::Quote([Expression::Integer(24.into())].into_iter().collect()), + Expression::Verb(Verb(builtin::if_else)), + Expression::Boolean(Boolean(false)), + Expression::Quote([Expression::Integer(24.into())].into_iter().collect()), + Expression::Quote([Expression::Integer(42.into())].into_iter().collect()), + Expression::Verb(Verb(builtin::if_else)), + ] + .into_iter(), + ) + .unwrap(); + + assert_eq!( + evaluator.stack.as_slice(), + &[ + Expression::Integer(Integer(42)), + Expression::Integer(Integer(42)), + Expression::Integer(Integer(42)), + Expression::Integer(Integer(42)) + ] + ); + } } diff --git a/rat/src/process.rs b/rat/src/process.rs index 97490dd..34c7990 100644 --- a/rat/src/process.rs +++ b/rat/src/process.rs @@ -35,11 +35,11 @@ impl Process { } } -impl Evaluate<&mut Evaluator> for Process { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::Process(self)); + fn evaluate(self, value: Process) -> Self::Output { + self.stack.push(Expression::Process(value)); Ok(()) } } diff --git a/rat/src/quote.rs b/rat/src/quote.rs index f5ab713..029f581 100644 --- a/rat/src/quote.rs +++ b/rat/src/quote.rs @@ -93,11 +93,11 @@ impl Quote { } } -impl Evaluate<&mut Evaluator> for Quote { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::Quote(self)); + fn evaluate(self, value: Quote) -> Self::Output { + self.stack.push(Expression::Quote(value)); Ok(()) } } diff --git a/rat/src/string.rs b/rat/src/string.rs index 75008d3..4cc90b5 100644 --- a/rat/src/string.rs +++ b/rat/src/string.rs @@ -68,11 +68,11 @@ impl String { } } -impl Evaluate<&mut Evaluator> for String { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::String(self)); + fn evaluate(self, value: String) -> Self::Output { + self.stack.push(Expression::String(value)); Ok(()) } } diff --git a/rat/src/symbol.rs b/rat/src/symbol.rs index e17e877..e4533f5 100644 --- a/rat/src/symbol.rs +++ b/rat/src/symbol.rs @@ -53,11 +53,11 @@ impl Symbol { } } -impl Evaluate<&mut Evaluator> for Symbol { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - evaluator.stack.push(Expression::Symbol(self)); + fn evaluate(self, value: Symbol) -> Self::Output { + self.stack.push(Expression::Symbol(value)); Ok(()) } } diff --git a/rat/src/verb.rs b/rat/src/verb.rs index c49d796..f7e59dc 100644 --- a/rat/src/verb.rs +++ b/rat/src/verb.rs @@ -13,12 +13,11 @@ use crate::evaluator::Evaluator; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Verb(pub fn(&mut Evaluator) -> Result<(), Effect>); -impl Evaluate<&mut Evaluator> for Verb { +impl Evaluate for &mut Evaluator { type Output = Result<(), Effect>; - fn evaluate(self, evaluator: &mut Evaluator) -> Self::Output { - let Self(verb) = self; - verb(evaluator) + fn evaluate(self, Verb(verb): Verb) -> Self::Output { + verb(self) } } diff --git a/rat/src/vocabulary.rs b/rat/src/vocabulary.rs index dbf8443..028a1f3 100644 --- a/rat/src/vocabulary.rs +++ b/rat/src/vocabulary.rs @@ -135,7 +135,7 @@ impl Vocabulary { } } -static PRELUDE: [(&Word, &[Expression]); 67] = [ +static PRELUDE: [(&Word, &[Expression]); 68] = [ (word_literal("neg"), &[Expression::Verb(Verb(builtin::neg))]), ( word_literal("incr"), @@ -314,6 +314,10 @@ static PRELUDE: [(&Word, &[Expression]); 67] = [ word_literal("binrec"), &[Expression::Verb(Verb(builtin::binrec))], ), + ( + word_literal("parbinrec"), + &[Expression::Verb(Verb(builtin::parbinrec))], + ), ]; const fn word_literal(literal: &str) -> &Word { From 678d5d15ca01a9ebb9608346a10f6f07017c252e Mon Sep 17 00:00:00 2001 From: daddinuz Date: Wed, 24 Jul 2024 18:49:28 +0200 Subject: [PATCH 08/17] update dependencies --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bece5c1..33b30a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -433,9 +433,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags", ] @@ -523,9 +523,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.71" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -534,18 +534,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", From 8503437446196aea8ed093610fde8f96c5e6dd93 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Mon, 29 Jul 2024 22:06:10 +0200 Subject: [PATCH 09/17] update dependencies --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 33b30a5..54ac9ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -602,9 +602,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" From d9e17af6b8207cbe701b1c88b634b19e8dfb0e27 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sat, 3 Aug 2024 17:38:36 +0200 Subject: [PATCH 10/17] remove DisplayAdapter from Quote --- rat-cli/src/main.rs | 20 +++++++++--- rat/src/quote.rs | 74 ++++++++++++++------------------------------- 2 files changed, 37 insertions(+), 57 deletions(-) diff --git a/rat-cli/src/main.rs b/rat-cli/src/main.rs index 24e22b4..a20c532 100644 --- a/rat-cli/src/main.rs +++ b/rat-cli/src/main.rs @@ -7,6 +7,7 @@ mod error; use std::env; +use std::fmt::Write; use std::fs::{File, OpenOptions}; use std::io::{ErrorKind, Read}; use std::path::{Path, PathBuf}; @@ -21,7 +22,6 @@ use rustyline_derive::{Completer, Highlighter, Hinter, Validator}; use rat::evaluate::Evaluate; use rat::evaluator::Evaluator; use rat::parser::{Origin, Parser}; -use rat::quote::DisplayAdapter; use error::{CliError, Consume, Report}; @@ -116,7 +116,7 @@ fn repl( if show_greeting { println!( - "{}\nRat {} CLI {}\nEnter Ctrl+D to exit.\nThis software is licensed under MPL-2.0 terms, visit https://www.mozilla.org/MPL/2.0/ for more information.\n", + "{}{NEWLINE}Rat {} CLI {}{NEWLINE}Enter Ctrl+D to exit.{NEWLINE}This software is licensed under MPL-2.0 terms, visit https://www.mozilla.org/MPL/2.0/ for more information.{NEWLINE}", REPL_GREET, rat::VERSION, VERSION, @@ -161,10 +161,14 @@ fn interpret( evaluator: &mut Evaluator, ) -> Result<(), CliError> { let program = parser.parse(origin, source)?; + evaluator.evaluate(program.into_iter()).map_err(|effect| { - format!( - "unahandled effect: {effect:?}\nstack (top rightmost): {:?}", - DisplayAdapter::new(&evaluator.stack) + evaluator.stack.iter().fold( + format!("unhandled effect: {effect:?}{NEWLINE}stack (top rightmost):"), + |mut acc, exp| { + let _ = write!(acc, " {exp:?}"); + acc + }, ) })?; @@ -595,3 +599,9 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. "###; + +#[cfg(windows)] +const NEWLINE: &str = "\r\n"; + +#[cfg(not(windows))] +const NEWLINE: &str = "\n"; diff --git a/rat/src/quote.rs b/rat/src/quote.rs index 029f581..3514b24 100644 --- a/rat/src/quote.rs +++ b/rat/src/quote.rs @@ -112,13 +112,33 @@ impl Deref for Quote { impl Display for Quote { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - DisplayAdapter::new(self.as_slice()).display().fmt(f) + match self.as_slice() { + [] => write!(f, "[]"), + [v] => write!(f, "[{v}]"), + [v, rest @ ..] => { + write!(f, "[{v}")?; + for v in rest { + write!(f, " {v}")?; + } + write!(f, "]") + } + } } } impl Debug for Quote { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - DisplayAdapter::new(self.as_slice()).debug().fmt(f) + match self.as_slice() { + [] => write!(f, "[]"), + [v] => write!(f, "[{v:?}]"), + [v, rest @ ..] => { + write!(f, "[{v:?}")?; + for v in rest { + write!(f, " {v:?}")?; + } + write!(f, "]") + } + } } } @@ -257,53 +277,3 @@ impl IntoIterator for Quote { ) } } - -pub struct DisplayAdapter<'a> { - slice: &'a [Expression], -} - -impl<'a> DisplayAdapter<'a> { - pub const fn new(slice: &'a [Expression]) -> Self { - Self { slice } - } - - pub fn display(&self) -> impl Display + '_ { - self - } - - pub fn debug(&self) -> impl Debug + '_ { - self - } -} - -impl<'a> Display for DisplayAdapter<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.slice { - [] => write!(f, "[]"), - [v] => write!(f, "[{v}]"), - [v, rest @ ..] => { - write!(f, "[{v}")?; - for v in rest { - write!(f, " {v}")?; - } - write!(f, "]") - } - } - } -} - -impl<'a> Debug for DisplayAdapter<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.slice { - [] => write!(f, "[]"), - [v] => write!(f, "[{v:?}]"), - [v, rest @ ..] => { - write!(f, "[{v:?}")?; - for v in rest { - write!(f, " {v:?}")?; - } - write!(f, "]") - } - } - } -} From ac0b1f94a29d1c75c165ddd51a4a14209aa9fb4e Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sat, 3 Aug 2024 18:01:08 +0200 Subject: [PATCH 11/17] add Record - wip --- rat/src/expression.rs | 12 + rat/src/grammar.pest | 22 +- rat/src/lib.rs | 1 + rat/src/parser.rs | 49 ++++ rat/src/record.rs | 506 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 589 insertions(+), 1 deletion(-) create mode 100644 rat/src/record.rs diff --git a/rat/src/expression.rs b/rat/src/expression.rs index ede4b60..b0037bd 100644 --- a/rat/src/expression.rs +++ b/rat/src/expression.rs @@ -15,6 +15,7 @@ use crate::decimal::Decimal; use crate::integer::Integer; use crate::process::Process; use crate::quote::Quote; +use crate::record::Record; use crate::string::String; use crate::symbol::Symbol; use crate::verb::Verb; @@ -26,6 +27,7 @@ pub enum Expression { Integer(Integer), Process(Process), Quote(Quote), + Record(Record), String(String), Symbol(Symbol), Verb(Verb), @@ -69,6 +71,13 @@ impl From for Expression { } } +impl From for Expression { + #[inline] + fn from(value: Record) -> Self { + Self::Record(value) + } +} + impl From for Expression { #[inline] fn from(value: String) -> Self { @@ -100,6 +109,7 @@ impl Evaluate for &mut Evaluator { Expression::Integer(v) => self.evaluate(v), Expression::Process(v) => self.evaluate(v), Expression::Quote(v) => self.evaluate(v), + Expression::Record(v) => self.evaluate(v), Expression::String(v) => self.evaluate(v), Expression::Symbol(v) => self.evaluate(v), Expression::Verb(v) => self.evaluate(v), @@ -115,6 +125,7 @@ impl Display for Expression { Expression::Integer(v) => Display::fmt(v, f), Expression::Process(v) => Display::fmt(v, f), Expression::Quote(v) => Display::fmt(v, f), + Expression::Record(v) => Display::fmt(v, f), Expression::String(v) => Display::fmt(v, f), Expression::Symbol(v) => Display::fmt(v, f), Expression::Verb(v) => Display::fmt(v, f), @@ -130,6 +141,7 @@ impl Debug for Expression { Expression::Integer(v) => Debug::fmt(v, f), Expression::Process(v) => Debug::fmt(v, f), Expression::Quote(v) => Debug::fmt(v, f), + Expression::Record(v) => Debug::fmt(v, f), Expression::String(v) => Debug::fmt(v, f), Expression::Symbol(v) => Debug::fmt(v, f), Expression::Verb(v) => Debug::fmt(v, f), diff --git a/rat/src/grammar.pest b/rat/src/grammar.pest index 01b2e51..e6ff776 100644 --- a/rat/src/grammar.pest +++ b/rat/src/grammar.pest @@ -31,7 +31,7 @@ Locution = @{ } Expression = { - (Boolean | Decimal | Integer | Quote | String | Symbol) + (Boolean | Decimal | Integer | Quote | Record | String | Symbol) } Boolean = @{ @@ -50,6 +50,10 @@ Quote = { LeftSquareBracket ~ Phrase? ~ RightSquareBracket } +Record = { + LeftCurlyBracket ~ (Expression ~ Equal ~ Expression)? ~ (Comma ~ Expression ~ Equal ~ Expression)* ~ Comma? ~ RightCurlyBracket +} + String = ${ "\"" ~ StringUnicodeScalarValue* ~ "\"" } @@ -74,10 +78,18 @@ Colon = @{ ":" } +Comma = @{ + "," +} + Division = @{ "÷" } +Equal = @{ + "=" +} + LeftArrow = @{ "←" } @@ -86,6 +98,14 @@ Semicolon = @{ ";" } +LeftCurlyBracket = @{ + "{" +} + +RightCurlyBracket = @{ + "}" +} + LeftSquareBracket = @{ "[" } diff --git a/rat/src/lib.rs b/rat/src/lib.rs index 441b147..d533111 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -14,6 +14,7 @@ pub mod decimal; pub mod integer; pub mod process; pub mod quote; +pub mod record; pub mod string; pub mod symbol; pub mod verb; diff --git a/rat/src/parser.rs b/rat/src/parser.rs index aed6bb5..3ecb36a 100644 --- a/rat/src/parser.rs +++ b/rat/src/parser.rs @@ -21,6 +21,7 @@ use crate::expression::Expression; use crate::integer::Integer; use crate::locution::{Locution, OwnedLocution}; use crate::quote::Quote; +use crate::record::Record; use crate::string::String; use crate::symbol::Symbol; use crate::vocabulary::{Definition, Visibility, Vocabulary}; @@ -257,6 +258,23 @@ impl FromStr for Quote { } } +impl FromStr for Record { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + check_token_boundary(s)?; + + let mut pairs = Grammar::parse(Rule::Record, s).map_err(with_origin(Origin::Unknown))?; + assert_eq!(pairs.len(), 1); + + parse_record( + &mut Default::default(), + Origin::Unknown, + pairs.next().unwrap(), + ) + } +} + impl FromStr for String { type Err = ParseError; @@ -419,6 +437,7 @@ fn parse_expression( Rule::Decimal => parse_decimal(origin, pair).map(Expression::Decimal), Rule::Integer => parse_integer(origin, pair).map(Expression::Integer), Rule::Quote => parse_quote(parser, origin, pair).map(Expression::Quote), + Rule::Record => parse_record(parser, origin, pair).map(Expression::Record), Rule::String => parse_string(origin, pair).map(Expression::String), Rule::Symbol => parse_symbol(origin, pair).map(Expression::Symbol), rule => unreachable!("unexpected rule: `{rule:?}`"), @@ -505,6 +524,36 @@ fn parse_quote(parser: &mut Parser, origin: Origin, pair: PestPair) -> Result Result { + assert_eq!(pair.as_rule(), Rule::Record); + + let mut key = None; + let mut value = None; + let mut record = Record::new(); + + for pair in pair.into_inner() { + match pair.as_rule() { + Rule::Expression => { + let exp = parse_expression(parser, origin, pair)?; + if key.is_none() { + key = Some(exp); + } else { + value = Some(exp); + } + } + Rule::RightCurlyBracket => break, + Rule::Comma | Rule::Equal | Rule::LeftCurlyBracket => (), + rule => unreachable!("unexpected rule: `{rule:?}`"), + } + + if value.is_some() { + record.insert(key.take().unwrap(), value.take().unwrap()); + } + } + + Ok(record) +} + fn parse_string(origin: Origin, pair: PestPair) -> Result { assert_eq!(pair.as_rule(), Rule::String); pair.into_inner() diff --git a/rat/src/record.rs b/rat/src/record.rs new file mode 100644 index 0000000..ee87c02 --- /dev/null +++ b/rat/src/record.rs @@ -0,0 +1,506 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +use std::borrow::Borrow; +use std::collections::HashMap; +use std::fmt::{Debug, Display}; +use std::hash::{BuildHasher, DefaultHasher, Hash, Hasher, RandomState}; +use std::sync::{Arc, OnceLock}; + +use crate::effect::Effect; +use crate::evaluate::Evaluate; +use crate::evaluator::Evaluator; +use crate::expression::Expression; + +#[derive(Clone, PartialEq, Eq)] +pub struct Record { + entries: Option>>, +} + +impl FromIterator<(Expression, Expression)> for Record { + fn from_iter>(entries: T) -> Self { + let mut entries = entries.into_iter().peekable(); + Self { + entries: entries + .peek() + .is_some() + .then(|| Arc::new(entries.collect())), + } + } +} + +impl Default for Record { + fn default() -> Self { + Self::new() + } +} + +impl Record { + pub const fn new() -> Self { + Self { entries: None } + } + + pub fn insert(&mut self, key: Expression, value: Expression) -> Option { + Arc::make_mut(self.entries.get_or_insert_with(Default::default)).insert(key, value) + } + + pub fn contains_key(&self, key: &Q) -> bool + where + Expression: Borrow, + Q: ?Sized + Hash + Eq, + { + self.entries + .as_ref() + .map(|e| e.contains_key(key)) + .unwrap_or(false) + } + + pub fn get(&self, key: &Q) -> Option<&Expression> + where + Expression: Borrow, + Q: ?Sized + Hash + Eq, + { + self.entries.as_ref().and_then(|e| e.get(key)) + } + + pub fn remove(&mut self, key: &Q) -> Option + where + Expression: Borrow, + Q: ?Sized + Hash + Eq, + { + self.entries + .as_mut() + .map(Arc::make_mut) + .and_then(|e| e.remove(key)) + } + + pub fn len(&self) -> usize { + self.entries.as_deref().map(HashMap::len).unwrap_or(0) + } + + pub fn is_empty(&self) -> bool { + self.entries + .as_deref() + .map(HashMap::is_empty) + .unwrap_or(true) + } + + pub fn keys(&self) -> Keys { + Keys::from_delegate( + self.entries + .as_deref() + .unwrap_or_else(empty_hash_map) + .keys(), + ) + } + + pub fn values(&self) -> Values { + Values::from_delegate( + self.entries + .as_deref() + .unwrap_or_else(empty_hash_map) + .values(), + ) + } + + pub fn iter(&self) -> Iter { + Iter::from_delegate( + self.entries + .as_deref() + .unwrap_or_else(empty_hash_map) + .iter(), + ) + } + + pub fn into_keys(self) -> IntoKeys { + IntoKeys::from_delegate( + self.entries + .map(|arc| Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())) + .unwrap_or_default() + .into_keys(), + ) + } + + pub fn into_values(self) -> IntoValues { + IntoValues::from_delegate( + self.entries + .map(|arc| Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())) + .unwrap_or_default() + .into_values(), + ) + } +} + +impl Extend<(Expression, Expression)> for Record { + fn extend>(&mut self, iter: T) { + Arc::make_mut(self.entries.get_or_insert_with(Default::default)).extend(iter); + } +} + +impl Hash for Record { + fn hash(&self, state: &mut H) { + let hasher_builder = global_hasher_builder(); + let hash = self + .entries + .iter() + .flat_map(|e| e.iter()) + .map(|pair| hasher_builder.hash_one(pair)) + .fold(18446744073709551557_u64, |l, r| l ^ r); + state.write_u64(hash); + } +} + +impl Evaluate for &mut Evaluator { + type Output = Result<(), Effect>; + + fn evaluate(self, value: Record) -> Self::Output { + self.stack.push(Expression::Record(value)); + Ok(()) + } +} + +impl Display for Record { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{{")?; + + let mut items = self.iter(); + items.next().map(|(k, v)| write!(f, "{k} = {v}")); + items.try_for_each(|(k, v)| write!(f, ", {k} = {v}"))?; + + write!(f, "}}") + } +} + +impl Debug for Record { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{{")?; + + let mut items = self.iter(); + items.next().map(|(k, v)| write!(f, "{k:?} = {v:?}")); + items.try_for_each(|(k, v)| write!(f, ", {k:?} = {v:?}"))?; + + write!(f, "}}") + } +} + +fn global_hasher_builder<'a>() -> &'a impl BuildHasher { + static INSTANCE: OnceLock = OnceLock::new(); + INSTANCE.get_or_init(Default::default) +} + +fn empty_hash_map<'a>() -> &'a HashMap { + static INSTANCE: OnceLock> = OnceLock::new(); + INSTANCE.get_or_init(Default::default) +} + +pub struct Keys<'a> { + delegate: std::collections::hash_map::Keys<'a, Expression, Expression>, +} + +impl<'a> Keys<'a> { + fn from_delegate( + delegate: std::collections::hash_map::Keys<'a, Expression, Expression>, + ) -> Self { + Self { delegate } + } +} + +impl<'a> Iterator for Keys<'a> { + type Item = as Iterator>::Item; + + fn next(&mut self) -> Option { + self.delegate.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.delegate.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.delegate.count() + } + + fn last(self) -> Option + where + Self: Sized, + { + self.delegate.last() + } + + fn nth(&mut self, n: usize) -> Option { + self.delegate.nth(n) + } +} + +impl<'a> std::iter::FusedIterator for Keys<'a> {} + +impl<'a> ExactSizeIterator for Keys<'a> { + fn len(&self) -> usize { + self.delegate.len() + } +} + +pub struct Values<'a> { + delegate: std::collections::hash_map::Values<'a, Expression, Expression>, +} + +impl<'a> Values<'a> { + fn from_delegate( + delegate: std::collections::hash_map::Values<'a, Expression, Expression>, + ) -> Self { + Self { delegate } + } +} + +impl<'a> Iterator for Values<'a> { + type Item = as Iterator>::Item; + fn next(&mut self) -> Option { + self.delegate.next() + } + fn size_hint(&self) -> (usize, Option) { + self.delegate.size_hint() + } + fn count(self) -> usize + where + Self: Sized, + { + self.delegate.count() + } + fn last(self) -> Option + where + Self: Sized, + { + self.delegate.last() + } + fn nth(&mut self, n: usize) -> Option { + self.delegate.nth(n) + } +} + +impl<'a> std::iter::FusedIterator for Values<'a> {} + +impl<'a> ExactSizeIterator for Values<'a> { + fn len(&self) -> usize { + self.delegate.len() + } +} + +pub struct Iter<'a> { + delegate: std::collections::hash_map::Iter<'a, Expression, Expression>, +} + +impl<'a> Iter<'a> { + fn from_delegate( + delegate: std::collections::hash_map::Iter<'a, Expression, Expression>, + ) -> Self { + Self { delegate } + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = as Iterator>::Item; + + fn next(&mut self) -> Option { + self.delegate.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.delegate.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.delegate.count() + } + + fn last(self) -> Option + where + Self: Sized, + { + self.delegate.last() + } + + fn nth(&mut self, n: usize) -> Option { + self.delegate.nth(n) + } +} + +impl<'a> std::iter::FusedIterator for Iter<'a> {} + +impl<'a> ExactSizeIterator for Iter<'a> { + fn len(&self) -> usize { + self.delegate.len() + } +} + +pub struct IntoKeys { + delegate: std::collections::hash_map::IntoKeys, +} + +impl IntoKeys { + fn from_delegate( + delegate: std::collections::hash_map::IntoKeys, + ) -> Self { + Self { delegate } + } +} + +impl Iterator for IntoKeys { + type Item = as Iterator>::Item; + + fn next(&mut self) -> Option { + self.delegate.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.delegate.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.delegate.count() + } + + fn last(self) -> Option + where + Self: Sized, + { + self.delegate.last() + } + + fn nth(&mut self, n: usize) -> Option { + self.delegate.nth(n) + } +} + +impl std::iter::FusedIterator for IntoKeys {} + +impl ExactSizeIterator for IntoKeys { + fn len(&self) -> usize { + self.delegate.len() + } +} + +pub struct IntoValues { + delegate: std::collections::hash_map::IntoValues, +} + +impl IntoValues { + fn from_delegate( + delegate: std::collections::hash_map::IntoValues, + ) -> Self { + Self { delegate } + } +} + +impl Iterator for IntoValues { + type Item = as Iterator>::Item; + + fn next(&mut self) -> Option { + self.delegate.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.delegate.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.delegate.count() + } + + fn last(self) -> Option + where + Self: Sized, + { + self.delegate.last() + } + + fn nth(&mut self, n: usize) -> Option { + self.delegate.nth(n) + } +} + +impl std::iter::FusedIterator for IntoValues {} + +impl ExactSizeIterator for IntoValues { + fn len(&self) -> usize { + self.delegate.len() + } +} + +pub struct IntoIter { + delegate: std::collections::hash_map::IntoIter, +} + +impl IntoIter { + fn from_delegate( + delegate: std::collections::hash_map::IntoIter, + ) -> Self { + Self { delegate } + } +} + +impl Iterator for IntoIter { + type Item = as Iterator>::Item; + + fn next(&mut self) -> Option { + self.delegate.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.delegate.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.delegate.count() + } + + fn last(self) -> Option + where + Self: Sized, + { + self.delegate.last() + } + + fn nth(&mut self, n: usize) -> Option { + self.delegate.nth(n) + } +} + +impl std::iter::FusedIterator for IntoIter {} + +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.delegate.len() + } +} + +impl IntoIterator for Record { + type Item = (Expression, Expression); + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter::from_delegate( + self.entries + .map(|arc| Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())) + .unwrap_or_default() + .into_iter(), + ) + } +} From cf9eed1091317235bbf1adaa768d9eeab4950507 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sun, 11 Aug 2024 17:38:04 +0200 Subject: [PATCH 12/17] add dependencies --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54ac9ef..f02edf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -240,9 +240,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.156" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a" [[package]] name = "libredox" @@ -523,9 +523,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", From 2b2a7fc2e7d150c8df53add34346d24bb4240229 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sat, 17 Aug 2024 00:31:50 +0200 Subject: [PATCH 13/17] remove Process and channels --- Cargo.lock | 57 ---------- examples/alice_n_bob.rat | 3 - examples/parallel-mergesort.rat | 13 --- rat/Cargo.toml | 1 - rat/src/builtin.rs | 188 -------------------------------- rat/src/evaluator.rs | 15 +-- rat/src/expression.rs | 12 -- rat/src/globals.rs | 96 ---------------- rat/src/lib.rs | 50 +-------- rat/src/process.rs | 57 ---------- rat/src/vocabulary.rs | 22 +--- 11 files changed, 4 insertions(+), 510 deletions(-) delete mode 100644 examples/alice_n_bob.rat delete mode 100644 examples/parallel-mergesort.rat delete mode 100644 rat/src/globals.rs delete mode 100644 rat/src/process.rs diff --git a/Cargo.lock b/Cargo.lock index f02edf6..ae41644 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,62 +72,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - [[package]] name = "crypto-common" version = "0.1.6" @@ -415,7 +359,6 @@ dependencies = [ name = "rat" version = "0.1.0" dependencies = [ - "crossbeam", "dirs", "pest", "pest_derive", diff --git a/examples/alice_n_bob.rat b/examples/alice_n_bob.rat deleted file mode 100644 index 9d99a70..0000000 --- a/examples/alice_n_bob.rat +++ /dev/null @@ -1,3 +0,0 @@ -["alice" 'bob' send 'alice' recv say] spawn -["bob" 'alice' send 'bob' recv say] spawn -"press [enter] to continue\n" ask diff --git a/examples/parallel-mergesort.rat b/examples/parallel-mergesort.rat deleted file mode 100644 index 666ebaa..0000000 --- a/examples/parallel-mergesort.rat +++ /dev/null @@ -1,13 +0,0 @@ -: seq @ rat\seq ; -: math @ rat\math ; - -# with program forming -: seq-ms ← quote [seq\mergesort 'out' send] cat detach ; -: par-ms ← dup len math\halve split [seq-ms 'out' recv] unary2 seq\merge ; - -# with message passing -# : seq-ms ← ['in' recv seq\mergesort 'out' send] detach ; -# : par-ms ← dup len math\halve split [seq-ms 'in' send 'out' recv] unary2 seq\merge ; - -[-23714 36911 27209 -61081 4487 62986 43562 59953 -6002 -64976 6222 37230 1774 60450 35372 9313 -63141 -10099 -56599 37381 29627 17147 -56774 46348 25159 42717 -10426 -38088 -9482 -51818 -13225 -22274 -52566 -5587 -148 59711 51437 6343 50139 32437 27966 -34985 167 27161 -53411 -6759 -27066 -7772 49899 -24127 7940 61517 -14064 -4433 6018 42197 -24241 4939 23687 -27950 -60335 -483 -51116 -201 21847 -65149 46808 49486 -6132 4372 14587 60525 14700 8373 -48827 -64401 -53524 -28842 -10959 -56034 -64763 -54632 28581 -3277 5279 7684 -26031 32221 1723 59531 -34723 17671 3424 -30493 28938 -12043 -27853 -14788 -34395 -23175 39083 -3314 16725 -14123 5069 -59857 52477 -25028 9931 -27366 41663 10612 -46240 27308 7778 -12942 37028 -18502 59012 53713 60519 -49390 -15897 41667 55977 45961 39978 59934 23858 -23789 -17806 -14129 -36824 -57834 -28443 -22873 26639 -20046 -57731 -16443 -599 -2646 8985 -14817 -10395 -42440 -59983 3357 44965 -44840 36400 -10323 -39719 45791 -27538 15597 7872 -19558 54625 -10621 27469 -61915 -45654 -61333 10374 50181 5656 8559 -9822 -9340 23135 -11774 -28400 -44677 304 37783 -56801 -45383 59955 23509 55993 -61971 16262 -49607 39590 -27209 1339 -56543 -41882 64893 50150 -16153 -317 -16469 7629 19020 15578 46013 53541 -27485 60355 -28348 -63558 -45715 -43954 62904 -8753 29052 -56968 52829 31804 45589 -26416 30184 29918 -38968 19638 -24968 -24088 -9447 48799 -50660 43610 -50411 -47355 -59101 59279 34413 55334 -16776 50629 63673 -44714 -32217 -37943 -21810 -51476 33889 6583 65273 60878 -13805 59344 34343 -43042 25481 40781 -37723 -39856 -19967 -54323 -6219 -24811 -51108 4870 -20829] -par-ms say diff --git a/rat/Cargo.toml b/rat/Cargo.toml index b2dc1b6..2c3331f 100644 --- a/rat/Cargo.toml +++ b/rat/Cargo.toml @@ -12,7 +12,6 @@ rust-version = "1.77" version = "0.1.0" [dependencies] -crossbeam = { version = "0.8", features = ["crossbeam-channel"] } dirs = "5" pest = "2" pest_derive = "2" diff --git a/rat/src/builtin.rs b/rat/src/builtin.rs index 3dea91a..a6b36ba 100644 --- a/rat/src/builtin.rs +++ b/rat/src/builtin.rs @@ -15,7 +15,6 @@ use crate::expression::Expression; use crate::boolean::Boolean; use crate::decimal::Decimal; use crate::integer::Integer; -use crate::process::Process; use crate::quote::Quote; use crate::string::String; use crate::symbol::Symbol; @@ -1155,105 +1154,6 @@ pub fn dup(evaluator: &mut Evaluator) -> Result<(), Effect> { Ok(()) } -pub fn send(evaluator: &mut Evaluator) -> Result<(), Effect> { - match &evaluator.stack[..] { - [.., expression, Expression::Symbol(topic)] => { - let expression = expression.clone(); - - if evaluator.globals.broker.send(*topic, expression).is_err() { - evaluator.stack.push(Symbol::io_error().into()); - return Err(Effect::Raise); - } - - let top = evaluator.stack.len(); - evaluator.stack.truncate(top - 2); - Ok(()) - } - [.., _, _] => { - evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) - } - _ => { - evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) - } - } -} - -pub fn recv(evaluator: &mut Evaluator) -> Result<(), Effect> { - match &evaluator.stack[..] { - [.., Expression::Symbol(topic)] => match evaluator.globals.broker.recv(*topic) { - Ok(expression) => { - *evaluator.stack.last_mut().unwrap() = expression; - Ok(()) - } - Err(_) => { - evaluator.stack.push(Symbol::io_error().into()); - Err(Effect::Raise) - } - }, - [.., _] => { - evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) - } - _ => { - evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) - } - } -} - -pub fn spawn(evaluator: &mut Evaluator) -> Result<(), Effect> { - let stack = &mut evaluator.stack; - - match &mut stack[..] { - [.., Expression::Quote(quote)] => { - let quote = std::mem::take(quote); - stack.pop().unwrap(); - - let process = Process::spawn(evaluator.globals.clone(), quote); - stack.push(Expression::Process(process)); - - Ok(()) - } - [.., _] => { - evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) - } - _ => { - evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) - } - } -} - -pub fn detach(evaluator: &mut Evaluator) -> Result<(), Effect> { - let stack = &mut evaluator.stack; - - match &mut stack[..] { - [.., Expression::Quote(quote)] => { - let quote = std::mem::take(quote); - stack.pop().unwrap(); - - let globals = evaluator.globals.clone(); - std::thread::spawn(move || { - let mut evaluator = Evaluator::with_globals(globals); - evaluator.evaluate(quote.iter().cloned()) - }); - - Ok(()) - } - [.., _] => { - evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) - } - _ => { - evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) - } - } -} - pub fn ask(evaluator: &mut Evaluator) -> Result<(), Effect> { let stack = &mut evaluator.stack; @@ -1450,91 +1350,3 @@ fn binrec_aux( } } } - -pub fn parbinrec(evaluator: &mut Evaluator) -> Result<(), Effect> { - let stack = &mut evaluator.stack; - - match &mut stack[..] { - [.., Expression::Quote(check), Expression::Quote(leave), Expression::Quote(shard), Expression::Quote(merge)] => - { - let merge = std::mem::take(merge); - let shard = std::mem::take(shard); - let leave = std::mem::take(leave); - let check = std::mem::take(check); - - let top = stack.len(); - stack.truncate(top - 4); - - parbinrec_aux(evaluator, &check, &leave, &shard, &merge) - } - [.., _, _, _, _] => { - stack.push(Symbol::type_error().into()); - Err(Effect::Raise) - } - _ => { - stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) - } - } -} - -fn parbinrec_aux( - evaluator: &mut Evaluator, - check: &Quote, - leave: &Quote, - shard: &Quote, - merge: &Quote, -) -> Result<(), Effect> { - evaluator.evaluate(check.iter().cloned())?; - - match evaluator.stack.pop() { - Some(Expression::Boolean(Boolean(false))) => { - evaluator.evaluate(shard.iter().cloned())?; - - let [expression1, expression2] = [ - evaluator.stack.pop().unwrap(), - evaluator.stack.pop().unwrap(), - ]; - - let [result1, result2] = std::thread::scope(|s| { - let globals = evaluator.globals.clone(); - let handle1 = s.spawn(|| { - let mut evaluator = Evaluator { - stack: vec![expression1], - globals, - }; - parbinrec_aux(&mut evaluator, check, leave, shard, merge)?; - Ok(evaluator.stack) - }); - - let globals = evaluator.globals.clone(); - let handle2 = s.spawn(|| { - let mut evaluator = Evaluator { - stack: vec![expression2], - globals, - }; - parbinrec_aux(&mut evaluator, check, leave, shard, merge)?; - Ok(evaluator.stack) - }); - - [handle1.join().unwrap(), handle2.join().unwrap()] - }); - - evaluator.stack.extend(result1?); - evaluator.stack.extend(result2?); - evaluator.evaluate(merge.iter().cloned()) - } - Some(Expression::Boolean(Boolean(true))) => evaluator.evaluate(leave.iter().cloned()), - Some(expression) => { - evaluator - .stack - .extend_from_slice(&[expression, Symbol::type_error().into()]); - - Err(Effect::Raise) - } - None => { - evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) - } - } -} diff --git a/rat/src/evaluator.rs b/rat/src/evaluator.rs index b347db3..ca27a25 100644 --- a/rat/src/evaluator.rs +++ b/rat/src/evaluator.rs @@ -4,29 +4,18 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use std::sync::Arc; - use crate::effect::Effect; use crate::evaluate::Evaluate; use crate::expression::Expression; -use crate::globals::Globals; #[derive(Default)] pub struct Evaluator { pub stack: Vec, - pub globals: Arc, } impl Evaluator { - pub fn new() -> Self { - Default::default() - } - - pub fn with_globals(globals: Arc) -> Self { - Self { - stack: Vec::new(), - globals, - } + pub const fn new() -> Self { + Self { stack: Vec::new() } } } diff --git a/rat/src/expression.rs b/rat/src/expression.rs index b0037bd..5ba9080 100644 --- a/rat/src/expression.rs +++ b/rat/src/expression.rs @@ -13,7 +13,6 @@ use crate::evaluator::Evaluator; use crate::boolean::Boolean; use crate::decimal::Decimal; use crate::integer::Integer; -use crate::process::Process; use crate::quote::Quote; use crate::record::Record; use crate::string::String; @@ -25,7 +24,6 @@ pub enum Expression { Boolean(Boolean), Decimal(Decimal), Integer(Integer), - Process(Process), Quote(Quote), Record(Record), String(String), @@ -57,13 +55,6 @@ impl From for Expression { } } -impl From for Expression { - #[inline] - fn from(value: Process) -> Self { - Self::Process(value) - } -} - impl From for Expression { #[inline] fn from(value: Quote) -> Self { @@ -107,7 +98,6 @@ impl Evaluate for &mut Evaluator { Expression::Boolean(v) => self.evaluate(v), Expression::Decimal(v) => self.evaluate(v), Expression::Integer(v) => self.evaluate(v), - Expression::Process(v) => self.evaluate(v), Expression::Quote(v) => self.evaluate(v), Expression::Record(v) => self.evaluate(v), Expression::String(v) => self.evaluate(v), @@ -123,7 +113,6 @@ impl Display for Expression { Expression::Boolean(v) => Display::fmt(v, f), Expression::Decimal(v) => Display::fmt(v, f), Expression::Integer(v) => Display::fmt(v, f), - Expression::Process(v) => Display::fmt(v, f), Expression::Quote(v) => Display::fmt(v, f), Expression::Record(v) => Display::fmt(v, f), Expression::String(v) => Display::fmt(v, f), @@ -139,7 +128,6 @@ impl Debug for Expression { Expression::Boolean(v) => Debug::fmt(v, f), Expression::Decimal(v) => Debug::fmt(v, f), Expression::Integer(v) => Debug::fmt(v, f), - Expression::Process(v) => Debug::fmt(v, f), Expression::Quote(v) => Debug::fmt(v, f), Expression::Record(v) => Debug::fmt(v, f), Expression::String(v) => Debug::fmt(v, f), diff --git a/rat/src/globals.rs b/rat/src/globals.rs deleted file mode 100644 index 694e1fa..0000000 --- a/rat/src/globals.rs +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -use std::collections::HashMap; -use std::error::Error; -use std::sync::RwLock; - -use crossbeam::channel::{self, Receiver, Sender}; - -use crate::expression::Expression; -use crate::symbol::Symbol; - -#[derive(Default)] -pub struct Globals { - pub broker: Broker, -} - -impl Globals { - pub fn new() -> Self { - Default::default() - } -} - -#[derive(Default)] -pub struct Broker { - channels: RwLock>, -} - -impl Broker { - pub fn new() -> Self { - Default::default() - } - - pub fn send(&self, topic: Symbol, expression: Expression) -> Result<(), impl Error> { - // IMPORTANT: we must release any lock before performing send or recv operations. - // keeping any lock active while performing a recv operation may lead to deadlocks. - // we must to minimize the scope of active locks. - - let sender = 'block: { - // optimistically try to get the channel if it exists. - if let Some(channel) = self.channels.read().unwrap().get(&topic) { - break 'block channel.sender.clone(); - } - - // if it does not exist, create it. - self.channels - .write() - .unwrap() - .entry(topic) - .or_default() - .sender - .clone() - }; - - sender.send(expression) - } - - pub fn recv(&self, topic: Symbol) -> Result { - // IMPORTANT: we must release any lock before performing send or recv operations. - // keeping any lock active while performing a recv operation may lead to deadlocks. - // we must to minimize the scope of active locks. - - let receiver = 'block: { - // optimistically try to get the channel if it exists. - if let Some(channel) = self.channels.read().unwrap().get(&topic) { - break 'block channel.receiver.clone(); - } - - // if it does not exist, create it. - self.channels - .write() - .unwrap() - .entry(topic) - .or_default() - .receiver - .clone() - }; - - receiver.recv() - } -} - -struct Channel { - sender: Sender, - receiver: Receiver, -} - -impl Default for Channel { - fn default() -> Self { - let (sender, receiver) = channel::unbounded(); - Self { sender, receiver } - } -} diff --git a/rat/src/lib.rs b/rat/src/lib.rs index d533111..ca29c56 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -12,7 +12,6 @@ pub(crate) mod codegen; pub mod boolean; pub mod decimal; pub mod integer; -pub mod process; pub mod quote; pub mod record; pub mod string; @@ -25,7 +24,6 @@ pub mod builtin; pub mod effect; pub mod evaluate; pub mod evaluator; -pub mod globals; pub mod locution; pub mod parser; pub mod vocabulary; @@ -113,53 +111,7 @@ mod test { } #[test] - fn it_works4() { - let mut evaluator = Evaluator::default(); - evaluator - .evaluate( - [ - Expression::Quote( - [ - Expression::Integer(Integer(8)), - Expression::Integer(Integer(12)), - Expression::Verb(Verb(builtin::add)), - Expression::Symbol(Symbol::new("out")), - Expression::Verb(Verb(builtin::send)), - ] - .into_iter() - .collect(), - ), - Expression::Verb(Verb(builtin::detach)), - Expression::Quote( - [ - Expression::Integer(Integer(10)), - Expression::Integer(Integer(12)), - Expression::Verb(Verb(builtin::add)), - Expression::Symbol(Symbol::new("out")), - Expression::Verb(Verb(builtin::send)), - ] - .into_iter() - .collect(), - ), - Expression::Verb(Verb(builtin::detach)), - Expression::Symbol(Symbol::new("out")), - Expression::Verb(Verb(builtin::recv)), - Expression::Symbol(Symbol::new("out")), - Expression::Verb(Verb(builtin::recv)), - Expression::Verb(Verb(builtin::add)), - ] - .into_iter(), - ) - .unwrap(); - - assert!(matches!( - evaluator.stack.as_slice(), - &[Expression::Integer(Integer(42))] - )); - } - - #[test] - fn it_works5() { + fn it_works3() { let mut evaluator = Evaluator::default(); evaluator .evaluate( diff --git a/rat/src/process.rs b/rat/src/process.rs deleted file mode 100644 index 34c7990..0000000 --- a/rat/src/process.rs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -use std::fmt::{Debug, Display}; -use std::hash::Hash; -use std::sync::Arc; -use std::thread::{self}; - -use crate::effect::Effect; -use crate::evaluate::Evaluate; -use crate::evaluator::Evaluator; -use crate::expression::Expression; -use crate::globals::Globals; -use crate::quote::Quote; - -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct Process { - quote: Quote, -} - -impl Process { - pub fn spawn(globals: Arc, quote: Quote) -> Self { - { - let quote = quote.clone(); - thread::spawn(move || { - let mut evaluator = Evaluator::with_globals(globals); - evaluator.evaluate(quote) - }); - } - - Self { quote } - } -} - -impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; - - fn evaluate(self, value: Process) -> Self::Output { - self.stack.push(Expression::Process(value)); - Ok(()) - } -} - -impl Display for Process { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Debug::fmt(self, f) - } -} - -impl Debug for Process { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "${:?}", self.quote) - } -} diff --git a/rat/src/vocabulary.rs b/rat/src/vocabulary.rs index 028a1f3..9909309 100644 --- a/rat/src/vocabulary.rs +++ b/rat/src/vocabulary.rs @@ -135,7 +135,7 @@ impl Vocabulary { } } -static PRELUDE: [(&Word, &[Expression]); 68] = [ +static PRELUDE: [(&Word, &[Expression]); 63] = [ (word_literal("neg"), &[Expression::Verb(Verb(builtin::neg))]), ( word_literal("incr"), @@ -284,22 +284,6 @@ static PRELUDE: [(&Word, &[Expression]); 68] = [ ), (word_literal("pop"), &[Expression::Verb(Verb(builtin::pop))]), (word_literal("dup"), &[Expression::Verb(Verb(builtin::dup))]), - ( - word_literal("send"), - &[Expression::Verb(Verb(builtin::send))], - ), - ( - word_literal("recv"), - &[Expression::Verb(Verb(builtin::recv))], - ), - ( - word_literal("spawn"), - &[Expression::Verb(Verb(builtin::spawn))], - ), - ( - word_literal("detach"), - &[Expression::Verb(Verb(builtin::detach))], - ), (word_literal("ask"), &[Expression::Verb(Verb(builtin::ask))]), (word_literal("say"), &[Expression::Verb(Verb(builtin::say))]), ( @@ -314,10 +298,6 @@ static PRELUDE: [(&Word, &[Expression]); 68] = [ word_literal("binrec"), &[Expression::Verb(Verb(builtin::binrec))], ), - ( - word_literal("parbinrec"), - &[Expression::Verb(Verb(builtin::parbinrec))], - ), ]; const fn word_literal(literal: &str) -> &Word { From 62a740a10fb472eb47b47ac7cbf5146854f9c7b7 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sat, 17 Aug 2024 13:29:29 +0200 Subject: [PATCH 14/17] update build.rs --- rat-cli/build.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rat-cli/build.rs b/rat-cli/build.rs index 6dd73bf..ec10bb7 100644 --- a/rat-cli/build.rs +++ b/rat-cli/build.rs @@ -2,22 +2,22 @@ use std::fs; use std::path::Path; fn main() { - let source_path = Path::new(env!("CARGO_MANIFEST_DIR")) + let crate_lib_path = Path::new(env!("CARGO_MANIFEST_DIR")) .parent() .unwrap() .join("lib"); - println!("cargo::rerun-if-changed={}", source_path.display()); + println!("cargo::rerun-if-changed={}", crate_lib_path.display()); - let destination_path = rat::home_dir().join("lib"); + let host_lib_path = rat::home_dir().join("lib"); - fs::create_dir_all(&destination_path).unwrap(); + fs::create_dir_all(&host_lib_path).unwrap(); - for entry in fs::read_dir(source_path).unwrap() { + for entry in fs::read_dir(crate_lib_path).unwrap() { let entry = entry.unwrap(); if entry.file_type().unwrap().is_file() { - fs::copy(entry.path(), destination_path.join(entry.file_name())).unwrap(); + fs::copy(entry.path(), host_lib_path.join(entry.file_name())).unwrap(); } } } From e2ab479d25204adc66e83871561bd416244f4901 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Fri, 23 Aug 2024 22:44:38 +0200 Subject: [PATCH 15/17] remove record --- Cargo.lock | 60 ++--- rat/src/expression.rs | 12 - rat/src/grammar.pest | 14 +- rat/src/lib.rs | 1 - rat/src/parser.rs | 49 ---- rat/src/record.rs | 506 ------------------------------------------ 6 files changed, 31 insertions(+), 611 deletions(-) delete mode 100644 rat/src/record.rs diff --git a/Cargo.lock b/Cargo.lock index ae41644..fb02f8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -131,9 +131,9 @@ dependencies = [ [[package]] name = "error-code" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" +checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" [[package]] name = "fd-lock" @@ -184,9 +184,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.156" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libredox" @@ -284,9 +284,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.7.11" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" dependencies = [ "memchr", "thiserror", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" dependencies = [ "pest", "pest_generator", @@ -305,9 +305,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" dependencies = [ "pest", "pest_meta", @@ -318,9 +318,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" dependencies = [ "once_cell", "pest", @@ -338,9 +338,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -376,18 +376,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -396,9 +396,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags", "errno", @@ -466,9 +466,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.74" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -509,21 +509,21 @@ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "ustr" diff --git a/rat/src/expression.rs b/rat/src/expression.rs index 5ba9080..d7c44c2 100644 --- a/rat/src/expression.rs +++ b/rat/src/expression.rs @@ -14,7 +14,6 @@ use crate::boolean::Boolean; use crate::decimal::Decimal; use crate::integer::Integer; use crate::quote::Quote; -use crate::record::Record; use crate::string::String; use crate::symbol::Symbol; use crate::verb::Verb; @@ -25,7 +24,6 @@ pub enum Expression { Decimal(Decimal), Integer(Integer), Quote(Quote), - Record(Record), String(String), Symbol(Symbol), Verb(Verb), @@ -62,13 +60,6 @@ impl From for Expression { } } -impl From for Expression { - #[inline] - fn from(value: Record) -> Self { - Self::Record(value) - } -} - impl From for Expression { #[inline] fn from(value: String) -> Self { @@ -99,7 +90,6 @@ impl Evaluate for &mut Evaluator { Expression::Decimal(v) => self.evaluate(v), Expression::Integer(v) => self.evaluate(v), Expression::Quote(v) => self.evaluate(v), - Expression::Record(v) => self.evaluate(v), Expression::String(v) => self.evaluate(v), Expression::Symbol(v) => self.evaluate(v), Expression::Verb(v) => self.evaluate(v), @@ -114,7 +104,6 @@ impl Display for Expression { Expression::Decimal(v) => Display::fmt(v, f), Expression::Integer(v) => Display::fmt(v, f), Expression::Quote(v) => Display::fmt(v, f), - Expression::Record(v) => Display::fmt(v, f), Expression::String(v) => Display::fmt(v, f), Expression::Symbol(v) => Display::fmt(v, f), Expression::Verb(v) => Display::fmt(v, f), @@ -129,7 +118,6 @@ impl Debug for Expression { Expression::Decimal(v) => Debug::fmt(v, f), Expression::Integer(v) => Debug::fmt(v, f), Expression::Quote(v) => Debug::fmt(v, f), - Expression::Record(v) => Debug::fmt(v, f), Expression::String(v) => Debug::fmt(v, f), Expression::Symbol(v) => Debug::fmt(v, f), Expression::Verb(v) => Debug::fmt(v, f), diff --git a/rat/src/grammar.pest b/rat/src/grammar.pest index e6ff776..7b4812c 100644 --- a/rat/src/grammar.pest +++ b/rat/src/grammar.pest @@ -31,7 +31,7 @@ Locution = @{ } Expression = { - (Boolean | Decimal | Integer | Quote | Record | String | Symbol) + (Boolean | Decimal | Integer | Quote | String | Symbol) } Boolean = @{ @@ -50,10 +50,6 @@ Quote = { LeftSquareBracket ~ Phrase? ~ RightSquareBracket } -Record = { - LeftCurlyBracket ~ (Expression ~ Equal ~ Expression)? ~ (Comma ~ Expression ~ Equal ~ Expression)* ~ Comma? ~ RightCurlyBracket -} - String = ${ "\"" ~ StringUnicodeScalarValue* ~ "\"" } @@ -98,14 +94,6 @@ Semicolon = @{ ";" } -LeftCurlyBracket = @{ - "{" -} - -RightCurlyBracket = @{ - "}" -} - LeftSquareBracket = @{ "[" } diff --git a/rat/src/lib.rs b/rat/src/lib.rs index ca29c56..c249e9f 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -13,7 +13,6 @@ pub mod boolean; pub mod decimal; pub mod integer; pub mod quote; -pub mod record; pub mod string; pub mod symbol; pub mod verb; diff --git a/rat/src/parser.rs b/rat/src/parser.rs index 3ecb36a..aed6bb5 100644 --- a/rat/src/parser.rs +++ b/rat/src/parser.rs @@ -21,7 +21,6 @@ use crate::expression::Expression; use crate::integer::Integer; use crate::locution::{Locution, OwnedLocution}; use crate::quote::Quote; -use crate::record::Record; use crate::string::String; use crate::symbol::Symbol; use crate::vocabulary::{Definition, Visibility, Vocabulary}; @@ -258,23 +257,6 @@ impl FromStr for Quote { } } -impl FromStr for Record { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - check_token_boundary(s)?; - - let mut pairs = Grammar::parse(Rule::Record, s).map_err(with_origin(Origin::Unknown))?; - assert_eq!(pairs.len(), 1); - - parse_record( - &mut Default::default(), - Origin::Unknown, - pairs.next().unwrap(), - ) - } -} - impl FromStr for String { type Err = ParseError; @@ -437,7 +419,6 @@ fn parse_expression( Rule::Decimal => parse_decimal(origin, pair).map(Expression::Decimal), Rule::Integer => parse_integer(origin, pair).map(Expression::Integer), Rule::Quote => parse_quote(parser, origin, pair).map(Expression::Quote), - Rule::Record => parse_record(parser, origin, pair).map(Expression::Record), Rule::String => parse_string(origin, pair).map(Expression::String), Rule::Symbol => parse_symbol(origin, pair).map(Expression::Symbol), rule => unreachable!("unexpected rule: `{rule:?}`"), @@ -524,36 +505,6 @@ fn parse_quote(parser: &mut Parser, origin: Origin, pair: PestPair) -> Result Result { - assert_eq!(pair.as_rule(), Rule::Record); - - let mut key = None; - let mut value = None; - let mut record = Record::new(); - - for pair in pair.into_inner() { - match pair.as_rule() { - Rule::Expression => { - let exp = parse_expression(parser, origin, pair)?; - if key.is_none() { - key = Some(exp); - } else { - value = Some(exp); - } - } - Rule::RightCurlyBracket => break, - Rule::Comma | Rule::Equal | Rule::LeftCurlyBracket => (), - rule => unreachable!("unexpected rule: `{rule:?}`"), - } - - if value.is_some() { - record.insert(key.take().unwrap(), value.take().unwrap()); - } - } - - Ok(record) -} - fn parse_string(origin: Origin, pair: PestPair) -> Result { assert_eq!(pair.as_rule(), Rule::String); pair.into_inner() diff --git a/rat/src/record.rs b/rat/src/record.rs deleted file mode 100644 index ee87c02..0000000 --- a/rat/src/record.rs +++ /dev/null @@ -1,506 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -use std::borrow::Borrow; -use std::collections::HashMap; -use std::fmt::{Debug, Display}; -use std::hash::{BuildHasher, DefaultHasher, Hash, Hasher, RandomState}; -use std::sync::{Arc, OnceLock}; - -use crate::effect::Effect; -use crate::evaluate::Evaluate; -use crate::evaluator::Evaluator; -use crate::expression::Expression; - -#[derive(Clone, PartialEq, Eq)] -pub struct Record { - entries: Option>>, -} - -impl FromIterator<(Expression, Expression)> for Record { - fn from_iter>(entries: T) -> Self { - let mut entries = entries.into_iter().peekable(); - Self { - entries: entries - .peek() - .is_some() - .then(|| Arc::new(entries.collect())), - } - } -} - -impl Default for Record { - fn default() -> Self { - Self::new() - } -} - -impl Record { - pub const fn new() -> Self { - Self { entries: None } - } - - pub fn insert(&mut self, key: Expression, value: Expression) -> Option { - Arc::make_mut(self.entries.get_or_insert_with(Default::default)).insert(key, value) - } - - pub fn contains_key(&self, key: &Q) -> bool - where - Expression: Borrow, - Q: ?Sized + Hash + Eq, - { - self.entries - .as_ref() - .map(|e| e.contains_key(key)) - .unwrap_or(false) - } - - pub fn get(&self, key: &Q) -> Option<&Expression> - where - Expression: Borrow, - Q: ?Sized + Hash + Eq, - { - self.entries.as_ref().and_then(|e| e.get(key)) - } - - pub fn remove(&mut self, key: &Q) -> Option - where - Expression: Borrow, - Q: ?Sized + Hash + Eq, - { - self.entries - .as_mut() - .map(Arc::make_mut) - .and_then(|e| e.remove(key)) - } - - pub fn len(&self) -> usize { - self.entries.as_deref().map(HashMap::len).unwrap_or(0) - } - - pub fn is_empty(&self) -> bool { - self.entries - .as_deref() - .map(HashMap::is_empty) - .unwrap_or(true) - } - - pub fn keys(&self) -> Keys { - Keys::from_delegate( - self.entries - .as_deref() - .unwrap_or_else(empty_hash_map) - .keys(), - ) - } - - pub fn values(&self) -> Values { - Values::from_delegate( - self.entries - .as_deref() - .unwrap_or_else(empty_hash_map) - .values(), - ) - } - - pub fn iter(&self) -> Iter { - Iter::from_delegate( - self.entries - .as_deref() - .unwrap_or_else(empty_hash_map) - .iter(), - ) - } - - pub fn into_keys(self) -> IntoKeys { - IntoKeys::from_delegate( - self.entries - .map(|arc| Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())) - .unwrap_or_default() - .into_keys(), - ) - } - - pub fn into_values(self) -> IntoValues { - IntoValues::from_delegate( - self.entries - .map(|arc| Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())) - .unwrap_or_default() - .into_values(), - ) - } -} - -impl Extend<(Expression, Expression)> for Record { - fn extend>(&mut self, iter: T) { - Arc::make_mut(self.entries.get_or_insert_with(Default::default)).extend(iter); - } -} - -impl Hash for Record { - fn hash(&self, state: &mut H) { - let hasher_builder = global_hasher_builder(); - let hash = self - .entries - .iter() - .flat_map(|e| e.iter()) - .map(|pair| hasher_builder.hash_one(pair)) - .fold(18446744073709551557_u64, |l, r| l ^ r); - state.write_u64(hash); - } -} - -impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; - - fn evaluate(self, value: Record) -> Self::Output { - self.stack.push(Expression::Record(value)); - Ok(()) - } -} - -impl Display for Record { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{{")?; - - let mut items = self.iter(); - items.next().map(|(k, v)| write!(f, "{k} = {v}")); - items.try_for_each(|(k, v)| write!(f, ", {k} = {v}"))?; - - write!(f, "}}") - } -} - -impl Debug for Record { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{{")?; - - let mut items = self.iter(); - items.next().map(|(k, v)| write!(f, "{k:?} = {v:?}")); - items.try_for_each(|(k, v)| write!(f, ", {k:?} = {v:?}"))?; - - write!(f, "}}") - } -} - -fn global_hasher_builder<'a>() -> &'a impl BuildHasher { - static INSTANCE: OnceLock = OnceLock::new(); - INSTANCE.get_or_init(Default::default) -} - -fn empty_hash_map<'a>() -> &'a HashMap { - static INSTANCE: OnceLock> = OnceLock::new(); - INSTANCE.get_or_init(Default::default) -} - -pub struct Keys<'a> { - delegate: std::collections::hash_map::Keys<'a, Expression, Expression>, -} - -impl<'a> Keys<'a> { - fn from_delegate( - delegate: std::collections::hash_map::Keys<'a, Expression, Expression>, - ) -> Self { - Self { delegate } - } -} - -impl<'a> Iterator for Keys<'a> { - type Item = as Iterator>::Item; - - fn next(&mut self) -> Option { - self.delegate.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.delegate.size_hint() - } - - fn count(self) -> usize - where - Self: Sized, - { - self.delegate.count() - } - - fn last(self) -> Option - where - Self: Sized, - { - self.delegate.last() - } - - fn nth(&mut self, n: usize) -> Option { - self.delegate.nth(n) - } -} - -impl<'a> std::iter::FusedIterator for Keys<'a> {} - -impl<'a> ExactSizeIterator for Keys<'a> { - fn len(&self) -> usize { - self.delegate.len() - } -} - -pub struct Values<'a> { - delegate: std::collections::hash_map::Values<'a, Expression, Expression>, -} - -impl<'a> Values<'a> { - fn from_delegate( - delegate: std::collections::hash_map::Values<'a, Expression, Expression>, - ) -> Self { - Self { delegate } - } -} - -impl<'a> Iterator for Values<'a> { - type Item = as Iterator>::Item; - fn next(&mut self) -> Option { - self.delegate.next() - } - fn size_hint(&self) -> (usize, Option) { - self.delegate.size_hint() - } - fn count(self) -> usize - where - Self: Sized, - { - self.delegate.count() - } - fn last(self) -> Option - where - Self: Sized, - { - self.delegate.last() - } - fn nth(&mut self, n: usize) -> Option { - self.delegate.nth(n) - } -} - -impl<'a> std::iter::FusedIterator for Values<'a> {} - -impl<'a> ExactSizeIterator for Values<'a> { - fn len(&self) -> usize { - self.delegate.len() - } -} - -pub struct Iter<'a> { - delegate: std::collections::hash_map::Iter<'a, Expression, Expression>, -} - -impl<'a> Iter<'a> { - fn from_delegate( - delegate: std::collections::hash_map::Iter<'a, Expression, Expression>, - ) -> Self { - Self { delegate } - } -} - -impl<'a> Iterator for Iter<'a> { - type Item = as Iterator>::Item; - - fn next(&mut self) -> Option { - self.delegate.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.delegate.size_hint() - } - - fn count(self) -> usize - where - Self: Sized, - { - self.delegate.count() - } - - fn last(self) -> Option - where - Self: Sized, - { - self.delegate.last() - } - - fn nth(&mut self, n: usize) -> Option { - self.delegate.nth(n) - } -} - -impl<'a> std::iter::FusedIterator for Iter<'a> {} - -impl<'a> ExactSizeIterator for Iter<'a> { - fn len(&self) -> usize { - self.delegate.len() - } -} - -pub struct IntoKeys { - delegate: std::collections::hash_map::IntoKeys, -} - -impl IntoKeys { - fn from_delegate( - delegate: std::collections::hash_map::IntoKeys, - ) -> Self { - Self { delegate } - } -} - -impl Iterator for IntoKeys { - type Item = as Iterator>::Item; - - fn next(&mut self) -> Option { - self.delegate.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.delegate.size_hint() - } - - fn count(self) -> usize - where - Self: Sized, - { - self.delegate.count() - } - - fn last(self) -> Option - where - Self: Sized, - { - self.delegate.last() - } - - fn nth(&mut self, n: usize) -> Option { - self.delegate.nth(n) - } -} - -impl std::iter::FusedIterator for IntoKeys {} - -impl ExactSizeIterator for IntoKeys { - fn len(&self) -> usize { - self.delegate.len() - } -} - -pub struct IntoValues { - delegate: std::collections::hash_map::IntoValues, -} - -impl IntoValues { - fn from_delegate( - delegate: std::collections::hash_map::IntoValues, - ) -> Self { - Self { delegate } - } -} - -impl Iterator for IntoValues { - type Item = as Iterator>::Item; - - fn next(&mut self) -> Option { - self.delegate.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.delegate.size_hint() - } - - fn count(self) -> usize - where - Self: Sized, - { - self.delegate.count() - } - - fn last(self) -> Option - where - Self: Sized, - { - self.delegate.last() - } - - fn nth(&mut self, n: usize) -> Option { - self.delegate.nth(n) - } -} - -impl std::iter::FusedIterator for IntoValues {} - -impl ExactSizeIterator for IntoValues { - fn len(&self) -> usize { - self.delegate.len() - } -} - -pub struct IntoIter { - delegate: std::collections::hash_map::IntoIter, -} - -impl IntoIter { - fn from_delegate( - delegate: std::collections::hash_map::IntoIter, - ) -> Self { - Self { delegate } - } -} - -impl Iterator for IntoIter { - type Item = as Iterator>::Item; - - fn next(&mut self) -> Option { - self.delegate.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.delegate.size_hint() - } - - fn count(self) -> usize - where - Self: Sized, - { - self.delegate.count() - } - - fn last(self) -> Option - where - Self: Sized, - { - self.delegate.last() - } - - fn nth(&mut self, n: usize) -> Option { - self.delegate.nth(n) - } -} - -impl std::iter::FusedIterator for IntoIter {} - -impl ExactSizeIterator for IntoIter { - fn len(&self) -> usize { - self.delegate.len() - } -} - -impl IntoIterator for Record { - type Item = (Expression, Expression); - type IntoIter = IntoIter; - - fn into_iter(self) -> Self::IntoIter { - IntoIter::from_delegate( - self.entries - .map(|arc| Arc::try_unwrap(arc).unwrap_or_else(|arc| (*arc).clone())) - .unwrap_or_default() - .into_iter(), - ) - } -} From 33deedac4202a5a764be9bcd328ef3f8c503e444 Mon Sep 17 00:00:00 2001 From: daddinuz Date: Sun, 22 Sep 2024 11:55:23 +0200 Subject: [PATCH 16/17] rename Effect to RuntimeError, rename Vocabulary to Definition --- rat/src/boolean.rs | 4 +- rat/src/builtin.rs | 358 +++++++++++++++++++++--------------------- rat/src/decimal.rs | 4 +- rat/src/dictionary.rs | 308 ++++++++++++++++++++++++++++++++++++ rat/src/error.rs | 8 + rat/src/evaluator.rs | 8 +- rat/src/expression.rs | 6 +- rat/src/integer.rs | 4 +- rat/src/lib.rs | 4 +- rat/src/parser.rs | 42 ++--- rat/src/quote.rs | 4 +- rat/src/string.rs | 4 +- rat/src/symbol.rs | 4 +- rat/src/verb.rs | 6 +- 14 files changed, 540 insertions(+), 224 deletions(-) create mode 100644 rat/src/dictionary.rs create mode 100644 rat/src/error.rs diff --git a/rat/src/boolean.rs b/rat/src/boolean.rs index 0412269..aa5f33d 100644 --- a/rat/src/boolean.rs +++ b/rat/src/boolean.rs @@ -8,7 +8,7 @@ use std::fmt::{Debug, Display}; use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not}; use crate::codegen; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; use crate::expression::Expression; @@ -31,7 +31,7 @@ impl From for bool { } impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, value: Boolean) -> Self::Output { self.stack.push(Expression::Boolean(value)); diff --git a/rat/src/builtin.rs b/rat/src/builtin.rs index a6b36ba..3d32e6c 100644 --- a/rat/src/builtin.rs +++ b/rat/src/builtin.rs @@ -6,7 +6,7 @@ use std::io::{self, Write}; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; @@ -19,7 +19,7 @@ use crate::quote::Quote; use crate::string::String; use crate::symbol::Symbol; -pub fn neg(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn neg(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -33,16 +33,16 @@ pub fn neg(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn incr(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn incr(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -56,16 +56,16 @@ pub fn incr(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn decr(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn decr(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -79,16 +79,16 @@ pub fn decr(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn add(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn add(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -104,16 +104,16 @@ pub fn add(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn sub(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn sub(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -129,16 +129,16 @@ pub fn sub(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn mul(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn mul(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -154,22 +154,22 @@ pub fn mul(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn div(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn div(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { [.., Expression::Integer(_), Expression::Integer(Integer::ZERO)] => { stack.push(Symbol::divide_by_zero().into()); - Err(Effect::Raise) + Err(RuntimeError) } [.., Expression::Integer(ref mut lhs), Expression::Integer(rhs)] => { *lhs /= rhs; @@ -183,22 +183,22 @@ pub fn div(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn rem(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn rem(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { [.., Expression::Integer(_), Expression::Integer(Integer::ZERO)] => { stack.push(Symbol::divide_by_zero().into()); - Err(Effect::Raise) + Err(RuntimeError) } [.., Expression::Integer(ref mut lhs), Expression::Integer(rhs)] => { *lhs %= rhs; @@ -212,16 +212,16 @@ pub fn rem(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn eq(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn eq(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -232,12 +232,12 @@ pub fn eq(evaluator: &mut Evaluator) -> Result<(), Effect> { } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn ne(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn ne(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -248,12 +248,12 @@ pub fn ne(evaluator: &mut Evaluator) -> Result<(), Effect> { } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn gt(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn gt(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -275,16 +275,16 @@ pub fn gt(evaluator: &mut Evaluator) -> Result<(), Effect> { }, [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn ge(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn ge(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -306,16 +306,16 @@ pub fn ge(evaluator: &mut Evaluator) -> Result<(), Effect> { }, [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn lt(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn lt(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -337,16 +337,16 @@ pub fn lt(evaluator: &mut Evaluator) -> Result<(), Effect> { }, [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn le(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn le(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -368,16 +368,16 @@ pub fn le(evaluator: &mut Evaluator) -> Result<(), Effect> { }, [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn positive(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn positive(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { @@ -391,16 +391,16 @@ pub fn positive(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn zero(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn zero(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { @@ -414,16 +414,16 @@ pub fn zero(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn negative(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn negative(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { @@ -437,16 +437,16 @@ pub fn negative(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn not(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn not(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -456,16 +456,16 @@ pub fn not(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn and(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn and(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -476,16 +476,16 @@ pub fn and(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn or(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn or(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -496,16 +496,16 @@ pub fn or(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn bitwise_not(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn bitwise_not(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -519,16 +519,16 @@ pub fn bitwise_not(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn bitwise_and(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn bitwise_and(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -544,16 +544,16 @@ pub fn bitwise_and(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn bitwise_xor(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn bitwise_xor(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -569,16 +569,16 @@ pub fn bitwise_xor(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn bitwise_or(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn bitwise_or(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -594,16 +594,16 @@ pub fn bitwise_or(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn shl(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn shl(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -614,16 +614,16 @@ pub fn shl(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn shr(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn shr(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -634,16 +634,16 @@ pub fn shr(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn ushr(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn ushr(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -654,16 +654,16 @@ pub fn ushr(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn cat(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn cat(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -675,55 +675,55 @@ pub fn cat(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn quote(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn quote(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; let expression = stack.pop().ok_or_else(|| { stack.push(Symbol::stack_underflow().into()); - Effect::Raise + RuntimeError })?; stack.push(Expression::Quote(Quote::from([expression]))); Ok(()) } -pub fn unquote(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn unquote(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { match evaluator.stack.pop() { Some(Expression::Quote(quote)) => evaluator.evaluate(quote.iter().cloned()), Some(expression) => { evaluator .stack .extend_from_slice(&[expression, Symbol::type_error().into()]); - Err(Effect::Raise) + Err(RuntimeError) } _ => { evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn eval(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn eval(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack.pop() { Some(expression) => evaluator.evaluate(expression), _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn i(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn i(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { @@ -731,23 +731,23 @@ pub fn i(evaluator: &mut Evaluator) -> Result<(), Effect> { [.., _] => eval(evaluator), _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn x(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn x(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; let expression = stack.last().cloned().ok_or_else(|| { stack.push(Symbol::stack_underflow().into()); - Effect::Raise + RuntimeError })?; stack.push(expression); i(evaluator) } -pub fn unary2(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn unary2(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; let top = stack.len(); @@ -764,16 +764,16 @@ pub fn unary2(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn dip(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn dip(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { match &evaluator.stack[..] { [.., _, Expression::Quote(_)] => { let top = evaluator.stack.len(); @@ -784,16 +784,16 @@ pub fn dip(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn r#if(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn r#if(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -811,16 +811,16 @@ pub fn r#if(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _, _] => { evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn r#else(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn r#else(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -838,16 +838,16 @@ pub fn r#else(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn if_else(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn if_else(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -860,20 +860,20 @@ pub fn if_else(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _, _] => { evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn raise(_: &mut Evaluator) -> Result<(), Effect> { - Err(Effect::Raise) +pub fn raise(_: &mut Evaluator) -> Result<(), RuntimeError> { + Err(RuntimeError) } -pub fn r#try(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn r#try(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { match &evaluator.stack[..] { [.., Expression::Quote(_), Expression::Quote(_), _] => { let guarded = evaluator.stack.pop(); @@ -881,7 +881,7 @@ pub fn r#try(evaluator: &mut Evaluator) -> Result<(), Effect> { let len = evaluator.stack.len(); match unquote(evaluator) { - Err(Effect::Raise) if evaluator.stack.last() == guarded.as_ref() => { + Err(RuntimeError) if evaluator.stack.last() == guarded.as_ref() => { evaluator.stack.truncate(len); evaluator.stack[len - 1] = guard; unquote(evaluator) @@ -891,62 +891,62 @@ pub fn r#try(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _, _] => { evaluator.stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn first(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn first(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { [.., Expression::Quote(quote)] => { let expression = quote.first().cloned().ok_or_else(|| { stack.push(Symbol::out_of_range().into()); - Effect::Raise + RuntimeError })?; *stack.last_mut().unwrap() = expression; Ok(()) } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn last(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn last(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { [.., Expression::Quote(quote)] => { let expression = quote.last().cloned().ok_or_else(|| { stack.push(Symbol::out_of_range().into()); - Effect::Raise + RuntimeError })?; *stack.last_mut().unwrap() = expression; Ok(()) } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn prefix(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn prefix(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { @@ -965,16 +965,16 @@ pub fn prefix(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn suffix(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn suffix(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { @@ -985,16 +985,16 @@ pub fn suffix(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn at(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn at(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -1003,7 +1003,7 @@ pub fn at(evaluator: &mut Evaluator) -> Result<(), Effect> { if at.is_negative() || (at as usize) >= quote_len { stack.push(Symbol::out_of_range().into()); - return Err(Effect::Raise); + return Err(RuntimeError); } let expression = quote[at as usize].clone(); @@ -1014,16 +1014,16 @@ pub fn at(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn split(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn split(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match stack[..] { @@ -1032,7 +1032,7 @@ pub fn split(evaluator: &mut Evaluator) -> Result<(), Effect> { if at.is_negative() || (at as usize) >= quote_len { stack.push(Symbol::out_of_range().into()); - return Err(Effect::Raise); + return Err(RuntimeError); } *stack.last_mut().unwrap() = quote.split(at as usize).into(); @@ -1040,16 +1040,16 @@ pub fn split(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn len(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn len(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { @@ -1063,29 +1063,29 @@ pub fn len(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn swap(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn swap(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; let top = stack.len(); if top < 2 { stack.push(Symbol::stack_underflow().into()); - return Err(Effect::Raise); + return Err(RuntimeError); } stack.swap(top - 1, top - 2); Ok(()) } -pub fn rollup(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn rollup(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -1096,12 +1096,12 @@ pub fn rollup(evaluator: &mut Evaluator) -> Result<(), Effect> { } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn rolldown(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn rolldown(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -1112,12 +1112,12 @@ pub fn rolldown(evaluator: &mut Evaluator) -> Result<(), Effect> { } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn rotate(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn rotate(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -1127,34 +1127,34 @@ pub fn rotate(evaluator: &mut Evaluator) -> Result<(), Effect> { } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn pop(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn pop(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; if stack.pop().is_none() { stack.push(Symbol::stack_underflow().into()); - return Err(Effect::Raise); + return Err(RuntimeError); } Ok(()) } -pub fn dup(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn dup(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; let expression = stack.last().cloned().ok_or_else(|| { stack.push(Symbol::stack_underflow().into()); - Effect::Raise + RuntimeError })?; stack.push(expression); Ok(()) } -pub fn ask(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn ask(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &stack[..] { @@ -1163,23 +1163,23 @@ pub fn ask(evaluator: &mut Evaluator) -> Result<(), Effect> { write!(stdout_lock, "{prompt}").map_err(|_| { stack.push(Symbol::io_error().into()); - Effect::Raise + RuntimeError })?; stdout_lock.flush().map_err(|_| { stack.push(Symbol::io_error().into()); - Effect::Raise + RuntimeError })?; stack.pop(); } [.., _] => { evaluator.stack.push(Symbol::type_error().into()); - return Err(Effect::Raise); + return Err(RuntimeError); } _ => { evaluator.stack.push(Symbol::stack_underflow().into()); - return Err(Effect::Raise); + return Err(RuntimeError); } } @@ -1187,34 +1187,34 @@ pub fn ask(evaluator: &mut Evaluator) -> Result<(), Effect> { io::stdin().read_line(&mut buf).map_err(|_| { stack.push(Symbol::io_error().into()); - Effect::Raise + RuntimeError })?; stack.push(Expression::String(String::from_utf8(&buf))); Ok(()) } -pub fn say(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn say(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; let expression = stack.pop().ok_or_else(|| { stack.push(Symbol::stack_underflow().into()); - Effect::Raise + RuntimeError })?; writeln!(io::stdout(), "{expression}").map_err(|_| { stack.push(Symbol::io_error().into()); - Effect::Raise + RuntimeError }) } -pub fn show(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn show(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; let mut stdout = io::stdout().lock(); write!(stdout, "#>>>").map_err(|_| { stack.push(Symbol::io_error().into()); - Effect::Raise + RuntimeError })?; stack @@ -1222,16 +1222,16 @@ pub fn show(evaluator: &mut Evaluator) -> Result<(), Effect> { .try_for_each(|e| write!(stdout, " {e:?}")) .map_err(|_| { stack.push(Symbol::io_error().into()); - Effect::Raise + RuntimeError })?; writeln!(stdout).map_err(|_| { stack.push(Symbol::io_error().into()); - Effect::Raise + RuntimeError }) } -pub fn linrec(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn linrec(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -1249,11 +1249,11 @@ pub fn linrec(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _, _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } @@ -1264,7 +1264,7 @@ fn linrec_aux( leave: &Quote, shard: &Quote, merge: &Quote, -) -> Result<(), Effect> { +) -> Result<(), RuntimeError> { evaluator.evaluate(check.iter().cloned())?; match evaluator.stack.pop() { @@ -1279,16 +1279,16 @@ fn linrec_aux( .stack .extend_from_slice(&[expression, Symbol::type_error().into()]); - Err(Effect::Raise) + Err(RuntimeError) } None => { evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } -pub fn binrec(evaluator: &mut Evaluator) -> Result<(), Effect> { +pub fn binrec(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { let stack = &mut evaluator.stack; match &mut stack[..] { @@ -1306,11 +1306,11 @@ pub fn binrec(evaluator: &mut Evaluator) -> Result<(), Effect> { } [.., _, _, _, _] => { stack.push(Symbol::type_error().into()); - Err(Effect::Raise) + Err(RuntimeError) } _ => { stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } @@ -1321,7 +1321,7 @@ fn binrec_aux( leave: &Quote, shard: &Quote, merge: &Quote, -) -> Result<(), Effect> { +) -> Result<(), RuntimeError> { evaluator.evaluate(check.iter().cloned())?; match evaluator.stack.pop() { @@ -1342,11 +1342,11 @@ fn binrec_aux( .stack .extend_from_slice(&[expression, Symbol::type_error().into()]); - Err(Effect::Raise) + Err(RuntimeError) } None => { evaluator.stack.push(Symbol::stack_underflow().into()); - Err(Effect::Raise) + Err(RuntimeError) } } } diff --git a/rat/src/decimal.rs b/rat/src/decimal.rs index 248c9bf..3dfc724 100644 --- a/rat/src/decimal.rs +++ b/rat/src/decimal.rs @@ -13,7 +13,7 @@ use std::ops::{ }; use crate::codegen; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; use crate::expression::Expression; @@ -77,7 +77,7 @@ impl Decimal { } impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, value: Decimal) -> Self::Output { self.stack.push(Expression::Decimal(value)); diff --git a/rat/src/dictionary.rs b/rat/src/dictionary.rs new file mode 100644 index 0000000..c189036 --- /dev/null +++ b/rat/src/dictionary.rs @@ -0,0 +1,308 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +use std::borrow::Borrow; +use std::collections::HashMap; +use std::fmt::Debug; +use std::hash::Hash; +use std::sync::Arc; + +use crate::boolean::Boolean; +use crate::builtin; +use crate::decimal::Decimal; +use crate::expression::Expression; +use crate::locution::Locution; +use crate::verb::Verb; +use crate::word::{OwnedWord, Word}; + +#[derive(Debug)] +pub enum Definition { + Phrase { + phrase: Arc<[Expression]>, + visibility: Visibility, + }, + Dictionary { + dictionary: Arc, + visibility: Visibility, + }, +} + +impl Definition { + pub fn is_intern(&self) -> bool { + Visibility::Intern + == match self { + Definition::Phrase { visibility, .. } => *visibility, + Definition::Dictionary { visibility, .. } => *visibility, + } + } + + pub fn is_extern(&self) -> bool { + !self.is_intern() + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Visibility { + Extern, + Intern, +} + +#[derive(Debug, Default)] +pub struct Dictionary { + definitions: HashMap, +} + +impl Dictionary { + pub fn new() -> Self { + Self { + definitions: HashMap::new(), + } + } + + pub fn with_prelude() -> Self { + Self { + definitions: PRELUDE + .into_iter() + .map(|(word, phrase)| { + ( + word.into(), + Definition::Phrase { + phrase: phrase.into(), + visibility: Visibility::Intern, + }, + ) + }) + .collect(), + } + } + + pub fn define(&mut self, word: OwnedWord, definition: Definition) -> Option { + self.definitions.insert(word, definition) + } + + pub fn get(&self, word: &W) -> Option<&Definition> + where + OwnedWord: Borrow, + W: ?Sized + Eq + Hash, + { + self.definitions.get(word) + } + + pub fn lookup(&self, locution: &Locution) -> Option<&[Expression]> { + let mut words = locution.words(); + let mut dictionary = self; + let mut is_first_word = true; + + while let Some(word) = words.next() { + let definition = dictionary.get(word)?; + + if !is_first_word && definition.is_intern() { + break; + } + + match definition { + Definition::Phrase { phrase, .. } => { + if words.next().is_some() { + break; + } + + return Some(phrase); + } + Definition::Dictionary { + dictionary: next_dictionary, + .. + } => dictionary = next_dictionary, + } + + is_first_word = false; + } + + None + } + + pub fn definitions(&self) -> impl Iterator { + self.definitions.iter() + } + + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&Word, &Definition) -> bool, + { + self.definitions.retain(|w, d| f(w, d)); + } +} + +static PRELUDE: [(&Word, &[Expression]); 63] = [ + (word_literal("neg"), &[Expression::Verb(Verb(builtin::neg))]), + ( + word_literal("incr"), + &[Expression::Verb(Verb(builtin::incr))], + ), + ( + word_literal("decr"), + &[Expression::Verb(Verb(builtin::decr))], + ), + (word_literal("add"), &[Expression::Verb(Verb(builtin::add))]), + (word_literal("sub"), &[Expression::Verb(Verb(builtin::sub))]), + (word_literal("mul"), &[Expression::Verb(Verb(builtin::mul))]), + (word_literal("div"), &[Expression::Verb(Verb(builtin::div))]), + (word_literal("rem"), &[Expression::Verb(Verb(builtin::rem))]), + (word_literal("eq"), &[Expression::Verb(Verb(builtin::eq))]), + (word_literal("ne"), &[Expression::Verb(Verb(builtin::ne))]), + (word_literal("gt"), &[Expression::Verb(Verb(builtin::gt))]), + (word_literal("ge"), &[Expression::Verb(Verb(builtin::ge))]), + (word_literal("lt"), &[Expression::Verb(Verb(builtin::lt))]), + (word_literal("le"), &[Expression::Verb(Verb(builtin::le))]), + ( + word_literal("positive?"), + &[Expression::Verb(Verb(builtin::positive))], + ), + ( + word_literal("zero?"), + &[Expression::Verb(Verb(builtin::zero))], + ), + ( + word_literal("negative?"), + &[Expression::Verb(Verb(builtin::negative))], + ), + (word_literal("nan"), &[Expression::Decimal(Decimal::NAN)]), + ( + word_literal("inf"), + &[Expression::Decimal(Decimal::INFINITY)], + ), + ( + word_literal("-inf"), + &[Expression::Decimal(Decimal::NEG_INFINITY)], + ), + ( + word_literal("false"), + &[Expression::Boolean(Boolean(false))], + ), + (word_literal("true"), &[Expression::Boolean(Boolean(true))]), + (word_literal("not"), &[Expression::Verb(Verb(builtin::not))]), + (word_literal("and"), &[Expression::Verb(Verb(builtin::and))]), + (word_literal("or"), &[Expression::Verb(Verb(builtin::or))]), + ( + word_literal("bit-not"), + &[Expression::Verb(Verb(builtin::bitwise_not))], + ), + ( + word_literal("bit-and"), + &[Expression::Verb(Verb(builtin::bitwise_and))], + ), + ( + word_literal("bit-xor"), + &[Expression::Verb(Verb(builtin::bitwise_xor))], + ), + ( + word_literal("bit-or"), + &[Expression::Verb(Verb(builtin::bitwise_or))], + ), + (word_literal("shl"), &[Expression::Verb(Verb(builtin::shl))]), + (word_literal("shr"), &[Expression::Verb(Verb(builtin::shr))]), + ( + word_literal("ushr"), + &[Expression::Verb(Verb(builtin::ushr))], + ), + (word_literal("cat"), &[Expression::Verb(Verb(builtin::cat))]), + ( + word_literal("quote"), + &[Expression::Verb(Verb(builtin::quote))], + ), + ( + word_literal("unquote"), + &[Expression::Verb(Verb(builtin::unquote))], + ), + ( + word_literal("eval"), + &[Expression::Verb(Verb(builtin::eval))], + ), + (word_literal("i"), &[Expression::Verb(Verb(builtin::i))]), + (word_literal("x"), &[Expression::Verb(Verb(builtin::x))]), + (word_literal("dip"), &[Expression::Verb(Verb(builtin::dip))]), + ( + word_literal("unary2"), + &[Expression::Verb(Verb(builtin::unary2))], + ), + (word_literal("if"), &[Expression::Verb(Verb(builtin::r#if))]), + ( + word_literal("else"), + &[Expression::Verb(Verb(builtin::r#else))], + ), + ( + word_literal("if-else"), + &[Expression::Verb(Verb(builtin::if_else))], + ), + ( + word_literal("raise"), + &[Expression::Verb(Verb(builtin::raise))], + ), + ( + word_literal("try"), + &[Expression::Verb(Verb(builtin::r#try))], + ), + ( + word_literal("first"), + &[Expression::Verb(Verb(builtin::first))], + ), + ( + word_literal("last"), + &[Expression::Verb(Verb(builtin::last))], + ), + ( + word_literal("prefix"), + &[Expression::Verb(Verb(builtin::prefix))], + ), + ( + word_literal("suffix"), + &[Expression::Verb(Verb(builtin::suffix))], + ), + (word_literal("at"), &[Expression::Verb(Verb(builtin::at))]), + ( + word_literal("split"), + &[Expression::Verb(Verb(builtin::split))], + ), + (word_literal("len"), &[Expression::Verb(Verb(builtin::len))]), + ( + word_literal("swap"), + &[Expression::Verb(Verb(builtin::swap))], + ), + ( + word_literal("rollup"), + &[Expression::Verb(Verb(builtin::rollup))], + ), + ( + word_literal("rolldown"), + &[Expression::Verb(Verb(builtin::rolldown))], + ), + ( + word_literal("rotate"), + &[Expression::Verb(Verb(builtin::rotate))], + ), + (word_literal("pop"), &[Expression::Verb(Verb(builtin::pop))]), + (word_literal("dup"), &[Expression::Verb(Verb(builtin::dup))]), + (word_literal("ask"), &[Expression::Verb(Verb(builtin::ask))]), + (word_literal("say"), &[Expression::Verb(Verb(builtin::say))]), + ( + word_literal("show"), + &[Expression::Verb(Verb(builtin::show))], + ), + ( + word_literal("linrec"), + &[Expression::Verb(Verb(builtin::linrec))], + ), + ( + word_literal("binrec"), + &[Expression::Verb(Verb(builtin::binrec))], + ), +]; + +const fn word_literal(literal: &str) -> &Word { + match Word::try_from_literal(literal) { + Ok(word) => word, + Err(_) => panic!("invalid word literal"), + } +} diff --git a/rat/src/error.rs b/rat/src/error.rs new file mode 100644 index 0000000..de14ab4 --- /dev/null +++ b/rat/src/error.rs @@ -0,0 +1,8 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct RuntimeError; diff --git a/rat/src/evaluator.rs b/rat/src/evaluator.rs index ca27a25..bf38c82 100644 --- a/rat/src/evaluator.rs +++ b/rat/src/evaluator.rs @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::expression::Expression; @@ -14,8 +14,8 @@ pub struct Evaluator { } impl Evaluator { - pub const fn new() -> Self { - Self { stack: Vec::new() } + pub fn new() -> Self { + Default::default() } } @@ -23,7 +23,7 @@ impl Evaluate for &mut Evaluator where I: Iterator, { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, mut expressions: I) -> Self::Output { expressions.try_for_each(|e| self.evaluate(e)) diff --git a/rat/src/expression.rs b/rat/src/expression.rs index d7c44c2..76c365d 100644 --- a/rat/src/expression.rs +++ b/rat/src/expression.rs @@ -6,7 +6,7 @@ use std::fmt::{Debug, Display}; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; @@ -30,7 +30,7 @@ pub enum Expression { } const _: [(); 16] = [(); std::mem::size_of::()]; -const _: [(); 1] = [(); std::mem::size_of::>()]; +const _: [(); 1] = [(); std::mem::size_of::>()]; impl From for Expression { #[inline] @@ -82,7 +82,7 @@ impl From for Expression { } impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, expression: Expression) -> Self::Output { match expression { diff --git a/rat/src/integer.rs b/rat/src/integer.rs index faa1c45..7f08d65 100644 --- a/rat/src/integer.rs +++ b/rat/src/integer.rs @@ -12,7 +12,7 @@ use std::ops::{ use crate::codegen; use crate::decimal::Decimal; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; use crate::expression::Expression; @@ -77,7 +77,7 @@ impl Integer { } impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, value: Integer) -> Self::Output { self.stack.push(Expression::Integer(value)); diff --git a/rat/src/lib.rs b/rat/src/lib.rs index c249e9f..c875533 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -20,12 +20,12 @@ pub mod verb; pub mod expression; pub mod builtin; -pub mod effect; +pub mod dictionary; +pub mod error; pub mod evaluate; pub mod evaluator; pub mod locution; pub mod parser; -pub mod vocabulary; pub mod word; use std::env; diff --git a/rat/src/parser.rs b/rat/src/parser.rs index aed6bb5..38aabcb 100644 --- a/rat/src/parser.rs +++ b/rat/src/parser.rs @@ -17,25 +17,25 @@ use std::{env, fs}; use crate::boolean::Boolean; use crate::decimal::Decimal; +use crate::dictionary::{Definition, Dictionary, Visibility}; use crate::expression::Expression; use crate::integer::Integer; use crate::locution::{Locution, OwnedLocution}; use crate::quote::Quote; use crate::string::String; use crate::symbol::Symbol; -use crate::vocabulary::{Definition, Visibility, Vocabulary}; use crate::word::{OwnedWord, Word}; #[derive(Debug, Default)] pub struct Parser { - vocabulary: Vocabulary, - cache: HashMap>, + dictionary: Dictionary, + cache: HashMap>, } -impl From for Parser { - fn from(vocabulary: Vocabulary) -> Self { +impl From for Parser { + fn from(dictionary: Dictionary) -> Self { Self { - vocabulary, + dictionary, cache: Default::default(), } } @@ -48,13 +48,13 @@ impl Parser { pub fn with_prelude() -> Self { Self { - vocabulary: Vocabulary::with_prelude(), + dictionary: Dictionary::with_prelude(), cache: Default::default(), } } - pub fn vocabulary(&self) -> &Vocabulary { - &self.vocabulary + pub fn dictionary(&self) -> &Dictionary { + &self.dictionary } pub fn parse(&mut self, origin: Origin, source: &str) -> Result, ParseError> { @@ -82,11 +82,11 @@ impl Parser { locution: &Locution, visibility: Visibility, ) -> Result<(), ImportError> { - if let Some(vocabulary) = self.cache.get(locution) { - self.vocabulary.define( + if let Some(dictionary) = self.cache.get(locution) { + self.dictionary.define( word.to_owned(), - Definition::Vocabulary { - vocabulary: vocabulary.clone(), + Definition::Dictionary { + dictionary: dictionary.clone(), visibility, }, ); @@ -135,15 +135,15 @@ impl Parser { .parse(Origin::Path(path.as_path()), &source) .map_err(|e| ImportError::new(format!("`{}`\n{}", locution, e)))?; - parser.vocabulary.retain(|_, d| d.is_extern()); + parser.dictionary.retain(|_, d| d.is_extern()); - let vocabulary = Arc::new(parser.vocabulary); + let dictionary = Arc::new(parser.dictionary); - self.cache.insert(locution.to_owned(), vocabulary.clone()); - self.vocabulary.define( + self.cache.insert(locution.to_owned(), dictionary.clone()); + self.dictionary.define( word.to_owned(), - Definition::Vocabulary { - vocabulary, + Definition::Dictionary { + dictionary, visibility, }, ); @@ -382,7 +382,7 @@ fn parse_definition(parser: &mut Parser, origin: Origin, pair: PestPair) -> Resu Rule::LeftArrow => { let phrase = parse_phrase(parser, origin, pairs.next().unwrap())?; - parser.vocabulary.define( + parser.dictionary.define( word.to_owned(), Definition::Phrase { phrase: phrase.into(), @@ -439,7 +439,7 @@ fn parse_phrase( let span = pair.as_span(); let locution = parse_locution(origin, pair)?; parser - .vocabulary + .dictionary .lookup(locution) .map(|expressions| phrase.extend_from_slice(expressions)) .ok_or_else(|| parse_error(origin, span, undefined_locution(locution)))?; diff --git a/rat/src/quote.rs b/rat/src/quote.rs index 3514b24..1e3a792 100644 --- a/rat/src/quote.rs +++ b/rat/src/quote.rs @@ -8,7 +8,7 @@ use std::fmt::{Debug, Display}; use std::ops::Deref; use std::sync::Arc; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; use crate::expression::Expression; @@ -94,7 +94,7 @@ impl Quote { } impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, value: Quote) -> Self::Output { self.stack.push(Expression::Quote(value)); diff --git a/rat/src/string.rs b/rat/src/string.rs index 4cc90b5..b906754 100644 --- a/rat/src/string.rs +++ b/rat/src/string.rs @@ -8,7 +8,7 @@ use std::fmt::{Debug, Display}; use std::ops::Deref; use std::sync::Arc; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; use crate::expression::Expression; @@ -69,7 +69,7 @@ impl String { } impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, value: String) -> Self::Output { self.stack.push(Expression::String(value)); diff --git a/rat/src/symbol.rs b/rat/src/symbol.rs index e4533f5..0ff5695 100644 --- a/rat/src/symbol.rs +++ b/rat/src/symbol.rs @@ -6,7 +6,7 @@ use ustr::Ustr; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; use crate::expression::Expression; @@ -54,7 +54,7 @@ impl Symbol { } impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, value: Symbol) -> Self::Output { self.stack.push(Expression::Symbol(value)); diff --git a/rat/src/verb.rs b/rat/src/verb.rs index f7e59dc..51497c1 100644 --- a/rat/src/verb.rs +++ b/rat/src/verb.rs @@ -6,15 +6,15 @@ use std::fmt::{Debug, Display}; -use crate::effect::Effect; +use crate::error::RuntimeError; use crate::evaluate::Evaluate; use crate::evaluator::Evaluator; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Verb(pub fn(&mut Evaluator) -> Result<(), Effect>); +pub struct Verb(pub fn(&mut Evaluator) -> Result<(), RuntimeError>); impl Evaluate for &mut Evaluator { - type Output = Result<(), Effect>; + type Output = Result<(), RuntimeError>; fn evaluate(self, Verb(verb): Verb) -> Self::Output { verb(self) From 5743fc5c1540038e570f3f138d13d2a4e20b1cbd Mon Sep 17 00:00:00 2001 From: daddinuz Date: Tue, 15 Oct 2024 00:05:55 +0200 Subject: [PATCH 17/17] refactored grammar --- .cargo/config.toml | 2 + .github/workflows/rust.yml | 20 ++ Cargo.lock | 52 ++--- examples/closure.rat | 2 + examples/fact.rat | 2 +- examples/fib.rat | 2 +- examples/mergesort.rat | 4 +- examples/person.rat | 4 + examples/towards_zero.rat | 8 +- lib/math.rat | 12 +- lib/seq.rat | 24 +- lib/std.rat | 18 +- rat-cli/Cargo.toml | 2 +- rat/Cargo.toml | 2 +- rat/src/builtin.rs | 44 ++++ rat/src/dictionary.rs | 42 ++-- rat/src/grammar.pest | 83 ++----- rat/src/{locution.rs => identifier.rs} | 83 ++++--- rat/src/lib.rs | 26 ++- rat/src/parser.rs | 252 ++++++++++---------- rat/src/quote.rs | 8 + rat/src/symbol.rs | 2 +- rat/src/vocabulary.rs | 308 ------------------------- rat/src/word.rs | 31 +-- 24 files changed, 400 insertions(+), 633 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 .github/workflows/rust.yml create mode 100644 examples/closure.rat create mode 100644 examples/person.rat rename rat/src/{locution.rs => identifier.rs} (56%) delete mode 100644 rat/src/vocabulary.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..4768414 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[env] +CARGO_WORKSPACE_DIR = { value = "", relative = true } diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..8d2a520 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,20 @@ +name: Rust + +on: + push: + branches: [ "main", "dev" ] + pull_request: + branches: [ "main", "dev" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/Cargo.lock b/Cargo.lock index fb02f8b..2ccbea0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,9 +17,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" @@ -184,9 +184,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libredox" @@ -249,9 +249,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "option-ext" @@ -284,9 +284,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.7.13" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", "thiserror", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.13" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" dependencies = [ "pest", "pest_generator", @@ -305,9 +305,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.13" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ "pest", "pest_meta", @@ -318,9 +318,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.13" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" dependencies = [ "once_cell", "pest", @@ -329,9 +329,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -376,9 +376,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags", ] @@ -466,9 +466,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -477,18 +477,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -503,9 +503,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicode-ident" diff --git a/examples/closure.rat b/examples/closure.rat new file mode 100644 index 0000000..6bb2c0f --- /dev/null +++ b/examples/closure.rat @@ -0,0 +1,2 @@ +: make-adder = [$x add] bind ; +40 2 make-adder i say diff --git a/examples/fact.rat b/examples/fact.rat index 56ff0b9..35f4592 100644 --- a/examples/fact.rat +++ b/examples/fact.rat @@ -1,2 +1,2 @@ -: fact ← [dup zero?] [incr] [dup decr] [mul] linrec ; +: fact = [dup zero?] [incr] [dup decr] [mul] linrec ; 5 fact say diff --git a/examples/fib.rat b/examples/fib.rat index 2817e2a..9dfa846 100644 --- a/examples/fib.rat +++ b/examples/fib.rat @@ -1,2 +1,2 @@ -: fib ← [dup 3 lt] [pop 1] [decr dup decr] [add] binrec ; +: fib = [dup 3 lt?] [pop 1] [decr dup decr] [add] binrec ; 30 fib say diff --git a/examples/mergesort.rat b/examples/mergesort.rat index d60e891..dc96152 100644 --- a/examples/mergesort.rat +++ b/examples/mergesort.rat @@ -1,4 +1,4 @@ -: seq @ rat\seq ; +: seq & rat/seq ; [-23714 36911 27209 -61081 4487 62986 43562 59953 -6002 -64976 6222 37230 1774 60450 35372 9313 -63141 -10099 -56599 37381 29627 17147 -56774 46348 25159 42717 -10426 -38088 -9482 -51818 -13225 -22274 -52566 -5587 -148 59711 51437 6343 50139 32437 27966 -34985 167 27161 -53411 -6759 -27066 -7772 49899 -24127 7940 61517 -14064 -4433 6018 42197 -24241 4939 23687 -27950 -60335 -483 -51116 -201 21847 -65149 46808 49486 -6132 4372 14587 60525 14700 8373 -48827 -64401 -53524 -28842 -10959 -56034 -64763 -54632 28581 -3277 5279 7684 -26031 32221 1723 59531 -34723 17671 3424 -30493 28938 -12043 -27853 -14788 -34395 -23175 39083 -3314 16725 -14123 5069 -59857 52477 -25028 9931 -27366 41663 10612 -46240 27308 7778 -12942 37028 -18502 59012 53713 60519 -49390 -15897 41667 55977 45961 39978 59934 23858 -23789 -17806 -14129 -36824 -57834 -28443 -22873 26639 -20046 -57731 -16443 -599 -2646 8985 -14817 -10395 -42440 -59983 3357 44965 -44840 36400 -10323 -39719 45791 -27538 15597 7872 -19558 54625 -10621 27469 -61915 -45654 -61333 10374 50181 5656 8559 -9822 -9340 23135 -11774 -28400 -44677 304 37783 -56801 -45383 59955 23509 55993 -61971 16262 -49607 39590 -27209 1339 -56543 -41882 64893 50150 -16153 -317 -16469 7629 19020 15578 46013 53541 -27485 60355 -28348 -63558 -45715 -43954 62904 -8753 29052 -56968 52829 31804 45589 -26416 30184 29918 -38968 19638 -24968 -24088 -9447 48799 -50660 43610 -50411 -47355 -59101 59279 34413 55334 -16776 50629 63673 -44714 -32217 -37943 -21810 -51476 33889 6583 65273 60878 -13805 59344 34343 -43042 25481 40781 -37723 -39856 -19967 -54323 -6219 -24811 -51108 4870 -20829] -seq\mergesort say +seq/mergesort say diff --git a/examples/person.rat b/examples/person.rat new file mode 100644 index 0000000..f65f70a --- /dev/null +++ b/examples/person.rat @@ -0,0 +1,4 @@ +: ^new = [$first-name $last-name $age] bind ; +: ^first-name = 0 at ; +: ^last-name = 1 at ; +: ^age = 2 at ; diff --git a/examples/towards_zero.rat b/examples/towards_zero.rat index ba4acaa..8397684 100644 --- a/examples/towards_zero.rat +++ b/examples/towards_zero.rat @@ -1,13 +1,13 @@ -: std @ rat\std ; +: std & rat/std ; -: small? ← 1 lt ; +: small? = 1 lt? ; # with recursion -: f ← std\over small? [pop] [[dup decr] dip dup i] if-else ; +: f = std/over small? [pop] [[dup decr] dip dup i] if-else ; 10 [f] f # with combinators -: f ← [dup small?] [] [dup decr] [] linrec ; +: f = [dup small?] [] [dup decr] [] linrec ; 10 f show diff --git a/lib/math.rat b/lib/math.rat index e8ce558..7480c2d 100644 --- a/lib/math.rat +++ b/lib/math.rat @@ -2,10 +2,10 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -: std @ rat\std ; +: std & rat/std ; -÷ abs ← dup negative? [neg] if ; -÷ halve ← 1 shr ; -÷ double ← 1 shl ; -÷ square ← dup mul ; -÷ pow ← [dup quote [mul] cat] dip std\times ; +: ^abs = dup negative? [neg] if ; +: ^halve = 1 shr ; +: ^double = 1 shl ; +: ^square = dup mul ; +: ^pow = [dup quote [mul] cat] dip std/times ; diff --git a/lib/seq.rat b/lib/seq.rat index 6cedbba..d3a786d 100644 --- a/lib/seq.rat +++ b/lib/seq.rat @@ -2,28 +2,28 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -: std @ rat\std ; -: math @ rat\math ; +: std & rat/std ; +: math & rat/math ; -÷ empty? ← len zero? ; +: ^empty? = len zero? ; -÷ merge ← - [std\dup2 [empty?] unary2 or] - [dup empty? [pop] [std\popd] if-else] +: ^merge = + [std/dup2 [empty?] unary2 or] + [dup empty? [pop] [std/popd] if-else] [ - std\dup2 [first] unary2 lt - [[[first quote] [suffix] std\bi] dip] - [[first quote] [suffix] std\bi std\swapd] + std/dup2 [first] unary2 lt? + [[[first quote] [suffix] std/bi] dip] + [[first quote] [suffix] std/bi std/swapd] if-else ] [cat] linrec ; -÷ mergesort ← - [dup len 1 le] +: ^mergesort = + [dup len 1 le?] [] - [dup len math\halve split] + [dup len math/halve split] [merge] binrec ; diff --git a/lib/std.rat b/lib/std.rat index 9ba3a15..9ef9d11 100644 --- a/lib/std.rat +++ b/lib/std.rat @@ -2,17 +2,17 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -÷ popd ← swap pop ; -÷ dupd ← [dup] dip ; -÷ swapd ← [swap] dip ; +: ^popd = swap pop ; +: ^dupd = [dup] dip ; +: ^swapd = [swap] dip ; -÷ over ← dupd swap ; -÷ overd ← [over] dip ; +: ^over = dupd swap ; +: ^overd = [over] dip ; -÷ dup2 ← over over ; +: ^dup2 = over over ; -÷ bi ← [[quote] dip over [cat] dip] dip cat [i] dip i ; +: ^bi = [[quote] dip over [cat] dip] dip cat [i] dip i ; -÷ case ← swap at i ; +: ^case = swap at i ; -÷ times ← [dup 1 lt] [pop pop] [[dup [i] dip] dip decr] [] linrec ; +: ^times = [dup 1 lt?] [pop pop] [[dup [i] dip] dip decr] [] linrec ; diff --git a/rat-cli/Cargo.toml b/rat-cli/Cargo.toml index b0d5022..bf4de66 100644 --- a/rat-cli/Cargo.toml +++ b/rat-cli/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["rat", "rust", "programming-language", "concatenative", "concurrency license = "MPL-2.0" name = "rat-cli" repository = "https://github.com/daddinuz/rat" -rust-version = "1.77" +rust-version = "1.80" version = "0.1.0" [build-dependencies] diff --git a/rat/Cargo.toml b/rat/Cargo.toml index 2c3331f..153c3e9 100644 --- a/rat/Cargo.toml +++ b/rat/Cargo.toml @@ -8,7 +8,7 @@ keywords = ["rat", "rust", "programming-language", "concatenative", "concurrency license = "MPL-2.0" name = "rat" repository = "https://github.com/daddinuz/rat" -rust-version = "1.77" +rust-version = "1.80" version = "0.1.0" [dependencies] diff --git a/rat/src/builtin.rs b/rat/src/builtin.rs index 3d32e6c..af9367f 100644 --- a/rat/src/builtin.rs +++ b/rat/src/builtin.rs @@ -1350,3 +1350,47 @@ fn binrec_aux( } } } + +pub fn bind(evaluator: &mut Evaluator) -> Result<(), RuntimeError> { + match evaluator.stack.pop() { + Some(Expression::Quote(quote)) => { + let mut top = evaluator.stack.len(); + let expression = quote + .iter() + .rev() + .map(|e| match e { + Expression::Symbol(_) => { + top -= 1; + evaluator.stack.get(top).cloned().ok_or(RuntimeError) + } + _ => Ok(e.clone()), + }) + .collect::, _>>() + .map(|mut q| { + q.reverse(); + Expression::Quote(Quote::from(q)) + }) + .inspect_err(|_| { + evaluator.stack.extend_from_slice(&[ + Expression::Quote(quote), + Symbol::stack_underflow().into(), + ]); + })?; + + evaluator.stack.truncate(top); + evaluator.stack.push(expression); + Ok(()) + } + Some(expression) => { + evaluator + .stack + .extend_from_slice(&[expression, Symbol::type_error().into()]); + + Err(RuntimeError) + } + None => { + evaluator.stack.push(Symbol::stack_underflow().into()); + Err(RuntimeError) + } + } +} diff --git a/rat/src/dictionary.rs b/rat/src/dictionary.rs index c189036..85f48c3 100644 --- a/rat/src/dictionary.rs +++ b/rat/src/dictionary.rs @@ -14,14 +14,14 @@ use crate::boolean::Boolean; use crate::builtin; use crate::decimal::Decimal; use crate::expression::Expression; -use crate::locution::Locution; +use crate::identifier::Identifier; use crate::verb::Verb; use crate::word::{OwnedWord, Word}; #[derive(Debug)] pub enum Definition { - Phrase { - phrase: Arc<[Expression]>, + Body { + body: Arc<[Expression]>, visibility: Visibility, }, Dictionary { @@ -34,7 +34,7 @@ impl Definition { pub fn is_intern(&self) -> bool { Visibility::Intern == match self { - Definition::Phrase { visibility, .. } => *visibility, + Definition::Body { visibility, .. } => *visibility, Definition::Dictionary { visibility, .. } => *visibility, } } @@ -66,11 +66,11 @@ impl Dictionary { Self { definitions: PRELUDE .into_iter() - .map(|(word, phrase)| { + .map(|(word, body)| { ( word.into(), - Definition::Phrase { - phrase: phrase.into(), + Definition::Body { + body: body.into(), visibility: Visibility::Intern, }, ) @@ -91,8 +91,8 @@ impl Dictionary { self.definitions.get(word) } - pub fn lookup(&self, locution: &Locution) -> Option<&[Expression]> { - let mut words = locution.words(); + pub fn lookup(&self, identifier: &Identifier) -> Option<&[Expression]> { + let mut words = identifier.words(); let mut dictionary = self; let mut is_first_word = true; @@ -104,12 +104,12 @@ impl Dictionary { } match definition { - Definition::Phrase { phrase, .. } => { + Definition::Body { body, .. } => { if words.next().is_some() { break; } - return Some(phrase); + return Some(body); } Definition::Dictionary { dictionary: next_dictionary, @@ -135,7 +135,7 @@ impl Dictionary { } } -static PRELUDE: [(&Word, &[Expression]); 63] = [ +static PRELUDE: [(&Word, &[Expression]); 64] = [ (word_literal("neg"), &[Expression::Verb(Verb(builtin::neg))]), ( word_literal("incr"), @@ -150,12 +150,12 @@ static PRELUDE: [(&Word, &[Expression]); 63] = [ (word_literal("mul"), &[Expression::Verb(Verb(builtin::mul))]), (word_literal("div"), &[Expression::Verb(Verb(builtin::div))]), (word_literal("rem"), &[Expression::Verb(Verb(builtin::rem))]), - (word_literal("eq"), &[Expression::Verb(Verb(builtin::eq))]), - (word_literal("ne"), &[Expression::Verb(Verb(builtin::ne))]), - (word_literal("gt"), &[Expression::Verb(Verb(builtin::gt))]), - (word_literal("ge"), &[Expression::Verb(Verb(builtin::ge))]), - (word_literal("lt"), &[Expression::Verb(Verb(builtin::lt))]), - (word_literal("le"), &[Expression::Verb(Verb(builtin::le))]), + (word_literal("eq?"), &[Expression::Verb(Verb(builtin::eq))]), + (word_literal("ne?"), &[Expression::Verb(Verb(builtin::ne))]), + (word_literal("gt?"), &[Expression::Verb(Verb(builtin::gt))]), + (word_literal("ge?"), &[Expression::Verb(Verb(builtin::ge))]), + (word_literal("lt?"), &[Expression::Verb(Verb(builtin::lt))]), + (word_literal("le?"), &[Expression::Verb(Verb(builtin::le))]), ( word_literal("positive?"), &[Expression::Verb(Verb(builtin::positive))], @@ -174,7 +174,7 @@ static PRELUDE: [(&Word, &[Expression]); 63] = [ &[Expression::Decimal(Decimal::INFINITY)], ), ( - word_literal("-inf"), + word_literal("neg-inf"), &[Expression::Decimal(Decimal::NEG_INFINITY)], ), ( @@ -298,6 +298,10 @@ static PRELUDE: [(&Word, &[Expression]); 63] = [ word_literal("binrec"), &[Expression::Verb(Verb(builtin::binrec))], ), + ( + word_literal("bind"), + &[Expression::Verb(Verb(builtin::bind))], + ), ]; const fn word_literal(literal: &str) -> &Word { diff --git a/rat/src/grammar.pest b/rat/src/grammar.pest index 7b4812c..5f38251 100644 --- a/rat/src/grammar.pest +++ b/rat/src/grammar.pest @@ -5,33 +5,38 @@ */ Program = _{ - SOI ~ (Definition | Phrase)* ~ EOI + SOI ~ (Statement | Expression)* ~ EOI } -Definition = { - (Division | Colon) ~ Word ~ ((At ~ Locution) | (LeftArrow ~ Phrase)) ~ Semicolon +Statement = { + (Define | Import) } -Phrase = { - (Locution | Expression)+ +Define = { + // equal sign is optional for backward compatibility with forth + ":" ~ Export? ~ Word ~ "="? ~ Expression+ ~ ";" +} + +Import = { + ":" ~ Export? ~ Word ~ "&" ~ Identifier ~ ";" +} + +Export = @{ + ("^" | "↑") } Word = @{ - // TODO: this must always be kept in sync with `Word` - ( ("-" | '0'..'9' | "_")* - ~ ('A'..'Z' | 'a'..'z') - ~ ("-" | '0'..'9' | 'A'..'Z' | "_" | 'a'..'z')* - ~ ("!" | "?")? - ) + ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "-" | "_")* ~ ("!" | "?")? } -Locution = @{ - // TODO: this must always be kept in sync with `Locution` - Word ~ ("\\" ~ Word)* +Identifier = @{ + Word ~ ("/" ~ Word)* } Expression = { (Boolean | Decimal | Integer | Quote | String | Symbol) + | /* actually not part of expression */ + Identifier } Boolean = @{ @@ -39,7 +44,7 @@ Boolean = @{ } Decimal = @{ - ("+" | "-")? ~ "∞" | "0.NaN" | (((ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) | "0") ~ ((^"e" ~ ("+" | "-") ~ ASCII_DIGIT+) | "." ~ ASCII_DIGIT* ~ (^"e" ~ ("+" | "-") ~ ASCII_DIGIT+) | "." ~ ASCII_DIGIT+)) + ("+" | "-")? ~ ("∞" | "0.NaN" | (((ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) | "0") ~ ((^"e" ~ ("+" | "-") ~ ASCII_DIGIT+) | "." ~ ASCII_DIGIT* ~ (^"e" ~ ("+" | "-") ~ ASCII_DIGIT+) | "." ~ ASCII_DIGIT+))) } Integer = @{ @@ -47,59 +52,19 @@ Integer = @{ } Quote = { - LeftSquareBracket ~ Phrase? ~ RightSquareBracket + "[" ~ Expression* ~ "]" } String = ${ - "\"" ~ StringUnicodeScalarValue* ~ "\"" + "\"" ~ UnicodeScalarValue* ~ "\"" } -StringUnicodeScalarValue = @{ +UnicodeScalarValue = @{ (!("\"" | "\\" | NEWLINE) ~ ANY | "\\" ~ ("\"" | "'" | "\\" | "n" | "r" | "t" | ("u{" ~ ASCII_HEX_DIGIT{1, 4} ~ "}"))) } Symbol = ${ - "'" ~ SymbolUnicodeScalarValue* ~ "'" -} - -SymbolUnicodeScalarValue = @{ - (!("'" | "\\" | NEWLINE) ~ ANY | "\\" ~ ("\"" | "'" | "\\" | "n" | "r" | "t" | ("u{" ~ ASCII_HEX_DIGIT{1, 4} ~ "}"))) -} - -At = @{ - "@" -} - -Colon = @{ - ":" -} - -Comma = @{ - "," -} - -Division = @{ - "÷" -} - -Equal = @{ - "=" -} - -LeftArrow = @{ - "←" -} - -Semicolon = @{ - ";" -} - -LeftSquareBracket = @{ - "[" -} - -RightSquareBracket = @{ - "]" + "$" ~ (Identifier | String) } WHITESPACE = _{ NEWLINE | "\t" | " " } diff --git a/rat/src/locution.rs b/rat/src/identifier.rs similarity index 56% rename from rat/src/locution.rs rename to rat/src/identifier.rs index ba417df..08c8048 100644 --- a/rat/src/locution.rs +++ b/rat/src/identifier.rs @@ -14,26 +14,26 @@ use crate::word::Word; #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] -pub struct Locution(str); +pub struct Identifier(str); -impl ToOwned for Locution { - type Owned = OwnedLocution; +impl ToOwned for Identifier { + type Owned = OwnedIdentifier; fn to_owned(&self) -> Self::Owned { let Self(inner) = self; - OwnedLocution { + OwnedIdentifier { inner: inner.into(), } } } -impl Locution { +impl Identifier { /// Whitespaces are not allowed in `literal`. // TODO: this must always be kept in sync with `grammar.pest` - pub const fn try_from_literal(literal: &str) -> Result<&Self, InvalidLocutionLiteral> { + pub const fn try_from_literal(literal: &str) -> Result<&Self, InvalidIdentifierLiteral> { let bytes = literal.as_bytes(); if bytes.is_empty() { - return Err(InvalidLocutionLiteral); + return Err(InvalidIdentifierLiteral); } let mut start = 0; @@ -41,9 +41,9 @@ impl Locution { while end < bytes.len() { let c = bytes[end]; - if b'\\' == c { + if b'/' == c { if !Word::is_valid(bytes, start, end) { - return Err(InvalidLocutionLiteral); + return Err(InvalidIdentifierLiteral); } start = end + 1; @@ -53,13 +53,13 @@ impl Locution { } if !Word::is_valid(bytes, start, end) { - return Err(InvalidLocutionLiteral); + return Err(InvalidIdentifierLiteral); } - let locution = literal as *const str as *const Self; - // Safety: `Locution` is a `repr(transparent)` wrapper around `str` + let identifier = literal as *const str as *const Self; + // Safety: `Identifier` is a `repr(transparent)` wrapper around `str` // have a look at: https://stackoverflow.com/a/72106272 - Ok(unsafe { &*locution }) + Ok(unsafe { &*identifier }) } #[inline] @@ -69,70 +69,89 @@ impl Locution { pub fn words(&self) -> impl Iterator { self.as_str() - .split('\\') + .split('/') .map(|s| Word::try_from_literal(s).unwrap()) } } -impl Display for Locution { +impl Display for Identifier { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.as_str()) } } -impl Debug for Locution { +impl Debug for Identifier { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self.as_str()) } } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct OwnedLocution { +pub struct OwnedIdentifier { inner: Arc, } -impl From<&Locution> for OwnedLocution { - fn from(locution: &Locution) -> Self { - locution.to_owned() +impl From<&Identifier> for OwnedIdentifier { + fn from(identifier: &Identifier) -> Self { + identifier.to_owned() } } -impl Deref for OwnedLocution { - type Target = Locution; +impl Deref for OwnedIdentifier { + type Target = Identifier; fn deref(&self) -> &Self::Target { self.borrow() } } -impl Borrow for OwnedLocution { - fn borrow(&self) -> &Locution { - let locution = self.inner.as_ref() as *const str as *const Locution; - // Safety: `Locution` is a `repr(transparent)` wrapper around `str` +impl Borrow for OwnedIdentifier { + fn borrow(&self) -> &Identifier { + let identifier = self.inner.as_ref() as *const str as *const Identifier; + // Safety: `Identifier` is a `repr(transparent)` wrapper around `str` // have a look at: https://stackoverflow.com/a/72106272 - unsafe { &*locution } + unsafe { &*identifier } } } -impl Display for OwnedLocution { +impl Display for OwnedIdentifier { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.as_str()) } } -impl Debug for OwnedLocution { +impl Debug for OwnedIdentifier { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self.as_str()) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct InvalidLocutionLiteral; +pub struct InvalidIdentifierLiteral; -impl Display for InvalidLocutionLiteral { +impl Display for InvalidIdentifierLiteral { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(self, f) } } -impl Error for InvalidLocutionLiteral {} +impl Error for InvalidIdentifierLiteral {} + +#[cfg(test)] +mod test { + use crate::word::Word; + + use super::Identifier; + + #[test] + fn identifier_words() { + let sut = Identifier::try_from_literal("a/very/long/identifier").unwrap(); + assert!(sut.words().eq([ + Word::try_from_literal("a").unwrap(), + Word::try_from_literal("very").unwrap(), + Word::try_from_literal("long").unwrap(), + Word::try_from_literal("identifier").unwrap() + ] + .into_iter())); + } +} diff --git a/rat/src/lib.rs b/rat/src/lib.rs index c875533..94a1ea7 100644 --- a/rat/src/lib.rs +++ b/rat/src/lib.rs @@ -24,7 +24,7 @@ pub mod dictionary; pub mod error; pub mod evaluate; pub mod evaluator; -pub mod locution; +pub mod identifier; pub mod parser; pub mod word; @@ -60,6 +60,9 @@ mod test { use crate::symbol::Symbol; use crate::verb::Verb; + use std::path::Path; + use std::process::Command; + #[test] fn it_works1() { let mut evaluator = Evaluator::default(); @@ -153,4 +156,25 @@ mod test { ] ); } + + #[test] + fn word_and_grammar_are_aligned() { + let grammar_path = Path::new(env!("CARGO_WORKSPACE_DIR")).join("rat/src/grammar.pest"); + let word_path = Path::new(env!("CARGO_WORKSPACE_DIR")).join("rat/src/word.rs"); + let output = Command::new("md5sum") + .arg(&grammar_path) + .arg(&word_path) + .output() + .unwrap(); + + assert_eq!( + &output.stdout, + format!( + "c55d29c3dd9298a203dfc945d9c238cc {}\nab5aa40ceddd0bc08fbf445cd9fe054e {}\n", + grammar_path.display(), + word_path.display() + ) + .as_bytes() + ); + } } diff --git a/rat/src/parser.rs b/rat/src/parser.rs index 38aabcb..9e1a8d7 100644 --- a/rat/src/parser.rs +++ b/rat/src/parser.rs @@ -19,8 +19,8 @@ use crate::boolean::Boolean; use crate::decimal::Decimal; use crate::dictionary::{Definition, Dictionary, Visibility}; use crate::expression::Expression; +use crate::identifier::{Identifier, OwnedIdentifier}; use crate::integer::Integer; -use crate::locution::{Locution, OwnedLocution}; use crate::quote::Quote; use crate::string::String; use crate::symbol::Symbol; @@ -29,7 +29,7 @@ use crate::word::{OwnedWord, Word}; #[derive(Debug, Default)] pub struct Parser { dictionary: Dictionary, - cache: HashMap>, + cache: HashMap>, } impl From for Parser { @@ -63,11 +63,8 @@ impl Parser { for pair in pairs { match pair.as_rule() { - Rule::Definition => parse_definition(self, origin, pair)?, - Rule::Phrase => { - let phrase = parse_phrase(self, origin, pair)?; - program.extend(phrase.into_iter()); - } + Rule::Statement => parse_statement(self, origin, pair)?, + Rule::Expression => parse_expressions(self, origin, pair, &mut program)?, Rule::EOI => break, rule => unreachable!("unexpected rule: `{rule:?}`"), } @@ -79,10 +76,10 @@ impl Parser { fn import( &mut self, word: &Word, - locution: &Locution, + identifier: &Identifier, visibility: Visibility, ) -> Result<(), ImportError> { - if let Some(dictionary) = self.cache.get(locution) { + if let Some(dictionary) = self.cache.get(identifier) { self.dictionary.define( word.to_owned(), Definition::Dictionary { @@ -94,21 +91,21 @@ impl Parser { return Ok(()); } - let mut words = locution.words(); + let mut words = identifier.words(); - let mut path = if locution.as_str().starts_with("rat\\") { + let mut path = if identifier.as_str().starts_with("rat/") { words.next(); crate::home_dir().join("lib") } else { env::current_dir() - .map_err(|error| ImportError::new(format!("`{}` {}", locution, error)))? + .map_err(|error| ImportError::new(format!("`{}` {}", identifier, error)))? }; for word in words { if !path.is_dir() { return Err(ImportError::new(format!( "`{}` {} is not a directory", - locution, + identifier, path.display() ))); } @@ -121,25 +118,25 @@ impl Parser { if !path.is_file() { return Err(ImportError::new(format!( "`{}` {} is not a regular file", - locution, + identifier, path.display() ))); } let source = fs::read_to_string(&path) - .map_err(|e| ImportError::new(format!("`{}` {} {}", locution, path.display(), e)))?; + .map_err(|e| ImportError::new(format!("`{}` {} {}", identifier, path.display(), e)))?; let mut parser = Parser::with_prelude(); parser .parse(Origin::Path(path.as_path()), &source) - .map_err(|e| ImportError::new(format!("`{}`\n{}", locution, e)))?; + .map_err(|e| ImportError::new(format!("`{}`\n{}", identifier, e)))?; parser.dictionary.retain(|_, d| d.is_extern()); let dictionary = Arc::new(parser.dictionary); - self.cache.insert(locution.to_owned(), dictionary.clone()); + self.cache.insert(identifier.to_owned(), dictionary.clone()); self.dictionary.define( word.to_owned(), Definition::Dictionary { @@ -188,16 +185,17 @@ impl FromStr for OwnedWord { } } -impl FromStr for OwnedLocution { +impl FromStr for OwnedIdentifier { type Err = ParseError; fn from_str(s: &str) -> Result { check_token_boundary(s)?; - let mut pairs = Grammar::parse(Rule::Locution, s).map_err(with_origin(Origin::Unknown))?; + let mut pairs = + Grammar::parse(Rule::Identifier, s).map_err(with_origin(Origin::Unknown))?; assert_eq!(pairs.len(), 1); - parse_locution(Origin::Unknown, pairs.next().unwrap()).map(ToOwned::to_owned) + parse_identifier(Origin::Unknown, pairs.next().unwrap()).map(ToOwned::to_owned) } } @@ -358,42 +356,63 @@ fn parse_error(origin: Origin, span: PestSpan, message: impl Display) -> ParseEr .into() } -fn parse_definition(parser: &mut Parser, origin: Origin, pair: PestPair) -> Result<(), ParseError> { - assert_eq!(pair.as_rule(), Rule::Definition); - let span = pair.as_span(); - let mut pairs = pair.into_inner(); +fn parse_statement(parser: &mut Parser, origin: Origin, pair: PestPair) -> Result<(), ParseError> { + assert_eq!(pair.as_rule(), Rule::Statement); + let pair = pair.into_inner().next().unwrap(); - let visibility = match pairs.next().unwrap().as_rule() { - Rule::Division => Visibility::Extern, - Rule::Colon => Visibility::Intern, + match pair.as_rule() { + Rule::Define => parse_define(parser, origin, pair), + Rule::Import => parse_import(parser, origin, pair), rule => unreachable!("unexpected rule: `{rule:?}`"), + } +} + +fn parse_define(parser: &mut Parser, origin: Origin, pair: PestPair) -> Result<(), ParseError> { + assert_eq!(pair.as_rule(), Rule::Define); + let mut pairs = pair.into_inner().peekable(); + + let visibility = match pairs.peek().unwrap().as_rule() { + Rule::Export => { + pairs.next().unwrap(); + Visibility::Extern + } + _ => Visibility::Intern, }; let word = pairs.next().map(|p| parse_word(origin, p)).unwrap()?; + let mut expressions = Vec::new(); + pairs.try_for_each(|p| parse_expressions(parser, origin, p, &mut expressions))?; + + parser.dictionary.define( + word.to_owned(), + Definition::Body { + body: expressions.into(), + visibility, + }, + ); - match pairs.next().unwrap().as_rule() { - Rule::At => { - let locution = parse_locution(origin, pairs.next().unwrap())?; + Ok(()) +} - parser - .import(word, locution, visibility) - .map_err(|e| parse_error(origin, span, e)) +fn parse_import(parser: &mut Parser, origin: Origin, pair: PestPair) -> Result<(), ParseError> { + assert_eq!(pair.as_rule(), Rule::Import); + let span = pair.as_span(); + let mut pairs = pair.into_inner().peekable(); + + let visibility = match pairs.peek().unwrap().as_rule() { + Rule::Export => { + pairs.next().unwrap(); + Visibility::Extern } - Rule::LeftArrow => { - let phrase = parse_phrase(parser, origin, pairs.next().unwrap())?; + _ => Visibility::Intern, + }; - parser.dictionary.define( - word.to_owned(), - Definition::Phrase { - phrase: phrase.into(), - visibility, - }, - ); + let word = pairs.next().map(|p| parse_word(origin, p)).unwrap()?; + let identifier = parse_identifier(origin, pairs.next().unwrap())?; - Ok(()) - } - rule => unreachable!("unexpected rule: `{rule:?}`"), - } + parser + .import(word, identifier, visibility) + .map_err(|e| parse_error(origin, span, e)) } fn parse_word<'a>(origin: Origin, pair: PestPair<'a>) -> Result<&'a Word, ParseError> { @@ -401,58 +420,38 @@ fn parse_word<'a>(origin: Origin, pair: PestPair<'a>) -> Result<&'a Word, ParseE Word::try_from_literal(pair.as_str()).map_err(|e| parse_error(origin, pair.as_span(), e)) } -fn parse_locution<'a>(origin: Origin, pair: PestPair<'a>) -> Result<&'a Locution, ParseError> { - assert_eq!(pair.as_rule(), Rule::Locution); - Locution::try_from_literal(pair.as_str()).map_err(|e| parse_error(origin, pair.as_span(), e)) +fn parse_identifier<'a>(origin: Origin, pair: PestPair<'a>) -> Result<&'a Identifier, ParseError> { + assert_eq!(pair.as_rule(), Rule::Identifier); + Identifier::try_from_literal(pair.as_str()).map_err(|e| parse_error(origin, pair.as_span(), e)) } -fn parse_expression( +fn parse_expressions( parser: &mut Parser, origin: Origin, pair: PestPair, -) -> Result { + buf: &mut Vec, +) -> Result<(), ParseError> { assert_eq!(pair.as_rule(), Rule::Expression); let pair = pair.into_inner().next().unwrap(); match pair.as_rule() { - Rule::Boolean => parse_boolean(origin, pair).map(Expression::Boolean), - Rule::Decimal => parse_decimal(origin, pair).map(Expression::Decimal), - Rule::Integer => parse_integer(origin, pair).map(Expression::Integer), - Rule::Quote => parse_quote(parser, origin, pair).map(Expression::Quote), - Rule::String => parse_string(origin, pair).map(Expression::String), - Rule::Symbol => parse_symbol(origin, pair).map(Expression::Symbol), - rule => unreachable!("unexpected rule: `{rule:?}`"), - } -} - -fn parse_phrase( - parser: &mut Parser, - origin: Origin, - pair: PestPair, -) -> Result, ParseError> { - assert_eq!(pair.as_rule(), Rule::Phrase); - let mut phrase = Vec::new(); - - for pair in pair.into_inner() { - match pair.as_rule() { - Rule::Locution => { - let span = pair.as_span(); - let locution = parse_locution(origin, pair)?; - parser - .dictionary - .lookup(locution) - .map(|expressions| phrase.extend_from_slice(expressions)) - .ok_or_else(|| parse_error(origin, span, undefined_locution(locution)))?; - } - Rule::Expression => { - let expression = parse_expression(parser, origin, pair)?; - phrase.push(expression); - } - rule => unreachable!("unexpected rule: `{rule:?}`"), + Rule::Boolean => parse_boolean(origin, pair).map(|e| buf.push(Expression::Boolean(e))), + Rule::Decimal => parse_decimal(origin, pair).map(|e| buf.push(Expression::Decimal(e))), + Rule::Integer => parse_integer(origin, pair).map(|e| buf.push(Expression::Integer(e))), + Rule::Quote => parse_quote(parser, origin, pair).map(|e| buf.push(Expression::Quote(e))), + Rule::String => parse_string(origin, pair).map(|e| buf.push(Expression::String(e))), + Rule::Symbol => parse_symbol(origin, pair).map(|e| buf.push(Expression::Symbol(e))), + Rule::Identifier => { + let span = pair.as_span(); + let identifier = parse_identifier(origin, pair)?; + parser + .dictionary + .lookup(identifier) + .map(|expressions| buf.extend_from_slice(expressions)) + .ok_or_else(|| parse_error(origin, span, undefined_identifier(identifier))) } + rule => unreachable!("unexpected rule: `{rule:?}`"), } - - Ok(phrase) } fn parse_boolean(_: Origin, pair: PestPair) -> Result { @@ -488,21 +487,11 @@ fn parse_integer(origin: Origin, pair: PestPair) -> Result fn parse_quote(parser: &mut Parser, origin: Origin, pair: PestPair) -> Result { assert_eq!(pair.as_rule(), Rule::Quote); - let mut quote = Quote::new(); - - for pair in pair.into_inner() { - match pair.as_rule() { - Rule::Phrase => { - let phrase = parse_phrase(parser, origin, pair)?; - quote.extend(phrase.into_iter()); - } - Rule::LeftSquareBracket => (), - Rule::RightSquareBracket => break, - rule => unreachable!("unexpected rule: `{rule:?}`"), - } - } + let mut expressions = Vec::new(); + pair.into_inner() + .try_for_each(|pair| parse_expressions(parser, origin, pair, &mut expressions))?; - Ok(quote) + Ok(expressions.into_iter().collect()) } fn parse_string(origin: Origin, pair: PestPair) -> Result { @@ -514,16 +503,19 @@ fn parse_string(origin: Origin, pair: PestPair) -> Result { fn parse_symbol(origin: Origin, pair: PestPair) -> Result { assert_eq!(pair.as_rule(), Rule::Symbol); - pair.into_inner() - .map(|p| parse_unicode_scalar_value(origin, p)) - .collect() + let pair = pair.into_inner().next().unwrap(); + match pair.as_rule() { + Rule::Identifier => Ok(pair.as_str().chars().collect()), + Rule::String => pair + .into_inner() + .map(|p| parse_unicode_scalar_value(origin, p)) + .collect(), + rule => unreachable!("unexpected rule: `{rule:?}`"), + } } fn parse_unicode_scalar_value(origin: Origin, pair: PestPair) -> Result { - assert!( - Rule::StringUnicodeScalarValue == pair.as_rule() - || Rule::SymbolUnicodeScalarValue == pair.as_rule() - ); + assert_eq!(pair.as_rule(), Rule::UnicodeScalarValue); match pair.as_str() { "\\n" => Ok('\n'), @@ -572,8 +564,8 @@ fn check_token_boundary(s: &str) -> Result<(), ParseError> { Ok(()) } -fn undefined_locution(locution: &Locution) -> StdString { - format!("undefined locution: `{locution}`") +fn undefined_identifier(identifier: &Identifier) -> StdString { + format!("undefined identifier: `{identifier}`") } #[cfg(test)] @@ -583,8 +575,8 @@ mod test { use crate::boolean::Boolean; use crate::decimal::Decimal; use crate::expression::Expression; + use crate::identifier::{Identifier, OwnedIdentifier}; use crate::integer::Integer; - use crate::locution::{Locution, OwnedLocution}; use crate::quote::Quote; use crate::string::String; use crate::symbol::Symbol; @@ -601,14 +593,14 @@ mod test { } #[test] - fn parse_locution() { - assert!(Locution::try_from_literal(" math\\abs").is_err()); - assert!(Locution::try_from_literal("math\\abs ").is_err()); - assert!(Locution::try_from_literal("math\\").is_err()); - assert!(Locution::try_from_literal("\\abs").is_err()); + fn parse_identifier() { + assert!(Identifier::try_from_literal(" math/abs").is_err()); + assert!(Identifier::try_from_literal("math/abs ").is_err()); + assert!(Identifier::try_from_literal("math/").is_err()); + assert!(Identifier::try_from_literal("/abs").is_err()); assert_eq!( - Locution::try_from_literal("math\\abs").unwrap(), - "math\\abs".parse::().unwrap().borrow() + Identifier::try_from_literal("math/abs").unwrap(), + "math/abs".parse::().unwrap().borrow() ); } @@ -639,10 +631,10 @@ mod test { #[test] fn parse_quote() { - assert!(" [⊥ ⊤ 42 3.14 'hello' \"world\" []]" + assert!(" [⊥ ⊤ 42 3.14 $hello \"world\" []]" .parse::() .is_err()); - assert!("[⊥ ⊤ 42 3.14 'hello' \"world\" []] " + assert!("[⊥ ⊤ 42 3.14 $hello \"world\" []] " .parse::() .is_err()); assert_eq!( @@ -657,7 +649,7 @@ mod test { ] .into_iter() .collect::(), - "[⊥ ⊤ 42 3.14 'hello' \"world\" []]" + "[⊥ ⊤ 42 3.14 $hello \"world\" []]" .parse::() .unwrap() ); @@ -682,14 +674,22 @@ mod test { #[test] fn parse_symbol() { - assert!(" 'hello'".parse::().is_err()); - assert!("'hello' ".parse::().is_err()); + assert!(" $hello".parse::().is_err()); + assert!("$hello ".parse::().is_err()); + assert!(" $\"hello\"".parse::().is_err()); + assert!("$\"hello\" ".parse::().is_err()); assert_eq!( Symbol::from_iter("hello".chars()), - "'hello'".parse().unwrap() + "$hello".parse().unwrap() ); - assert_eq!(Symbol::from_iter("a\"a".chars()), "'a\"a'".parse().unwrap()); - assert_eq!(Symbol::from_iter("a'a".chars()), "'a\\'a'".parse().unwrap()); + assert_eq!( + Symbol::from_iter("a\tstring".chars()), + "$\"a\tstring\"".parse().unwrap() + ); + assert_eq!( + Symbol::from_iter("a\tstring".chars()), + r#"$"a\tstring""#.parse().unwrap() + ); } } diff --git a/rat/src/quote.rs b/rat/src/quote.rs index 1e3a792..8319b62 100644 --- a/rat/src/quote.rs +++ b/rat/src/quote.rs @@ -31,6 +31,14 @@ impl FromIterator for Quote { } } +impl From> for Quote { + fn from(value: Vec) -> Self { + Self { + inner: Some(Arc::new(value)), + } + } +} + impl From<[Expression; N]> for Quote { fn from(value: [Expression; N]) -> Self { Self::from_iter(value) diff --git a/rat/src/symbol.rs b/rat/src/symbol.rs index 0ff5695..16b94ce 100644 --- a/rat/src/symbol.rs +++ b/rat/src/symbol.rs @@ -72,7 +72,7 @@ impl Display for Symbol { impl Debug for Symbol { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self(s) = self; - write!(f, "'{}'", s) + write!(f, "$\"{}\"", s) } } diff --git a/rat/src/vocabulary.rs b/rat/src/vocabulary.rs deleted file mode 100644 index 9909309..0000000 --- a/rat/src/vocabulary.rs +++ /dev/null @@ -1,308 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -use std::borrow::Borrow; -use std::collections::HashMap; -use std::fmt::Debug; -use std::hash::Hash; -use std::sync::Arc; - -use crate::boolean::Boolean; -use crate::builtin; -use crate::decimal::Decimal; -use crate::expression::Expression; -use crate::locution::Locution; -use crate::verb::Verb; -use crate::word::{OwnedWord, Word}; - -#[derive(Debug)] -pub enum Definition { - Phrase { - phrase: Arc<[Expression]>, - visibility: Visibility, - }, - Vocabulary { - vocabulary: Arc, - visibility: Visibility, - }, -} - -impl Definition { - pub fn is_intern(&self) -> bool { - Visibility::Intern - == match self { - Definition::Phrase { visibility, .. } => *visibility, - Definition::Vocabulary { visibility, .. } => *visibility, - } - } - - pub fn is_extern(&self) -> bool { - !self.is_intern() - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Visibility { - Extern, - Intern, -} - -#[derive(Debug, Default)] -pub struct Vocabulary { - definitions: HashMap, -} - -impl Vocabulary { - pub fn new() -> Self { - Self { - definitions: HashMap::new(), - } - } - - pub fn with_prelude() -> Self { - Self { - definitions: PRELUDE - .into_iter() - .map(|(word, phrase)| { - ( - word.into(), - Definition::Phrase { - phrase: phrase.into(), - visibility: Visibility::Intern, - }, - ) - }) - .collect(), - } - } - - pub fn define(&mut self, word: OwnedWord, definition: Definition) -> Option { - self.definitions.insert(word, definition) - } - - pub fn get(&self, word: &W) -> Option<&Definition> - where - OwnedWord: Borrow, - W: ?Sized + Eq + Hash, - { - self.definitions.get(word) - } - - pub fn lookup(&self, locution: &Locution) -> Option<&[Expression]> { - let mut words = locution.words(); - let mut vocabulary = self; - let mut is_first_word = true; - - while let Some(word) = words.next() { - let definition = vocabulary.get(word)?; - - if !is_first_word && definition.is_intern() { - break; - } - - match definition { - Definition::Phrase { phrase, .. } => { - if words.next().is_some() { - break; - } - - return Some(phrase); - } - Definition::Vocabulary { - vocabulary: next_vocabulary, - .. - } => vocabulary = next_vocabulary, - } - - is_first_word = false; - } - - None - } - - pub fn definitions(&self) -> impl Iterator { - self.definitions.iter() - } - - pub fn retain(&mut self, mut f: F) - where - F: FnMut(&Word, &Definition) -> bool, - { - self.definitions.retain(|w, d| f(w, d)); - } -} - -static PRELUDE: [(&Word, &[Expression]); 63] = [ - (word_literal("neg"), &[Expression::Verb(Verb(builtin::neg))]), - ( - word_literal("incr"), - &[Expression::Verb(Verb(builtin::incr))], - ), - ( - word_literal("decr"), - &[Expression::Verb(Verb(builtin::decr))], - ), - (word_literal("add"), &[Expression::Verb(Verb(builtin::add))]), - (word_literal("sub"), &[Expression::Verb(Verb(builtin::sub))]), - (word_literal("mul"), &[Expression::Verb(Verb(builtin::mul))]), - (word_literal("div"), &[Expression::Verb(Verb(builtin::div))]), - (word_literal("rem"), &[Expression::Verb(Verb(builtin::rem))]), - (word_literal("eq"), &[Expression::Verb(Verb(builtin::eq))]), - (word_literal("ne"), &[Expression::Verb(Verb(builtin::ne))]), - (word_literal("gt"), &[Expression::Verb(Verb(builtin::gt))]), - (word_literal("ge"), &[Expression::Verb(Verb(builtin::ge))]), - (word_literal("lt"), &[Expression::Verb(Verb(builtin::lt))]), - (word_literal("le"), &[Expression::Verb(Verb(builtin::le))]), - ( - word_literal("positive?"), - &[Expression::Verb(Verb(builtin::positive))], - ), - ( - word_literal("zero?"), - &[Expression::Verb(Verb(builtin::zero))], - ), - ( - word_literal("negative?"), - &[Expression::Verb(Verb(builtin::negative))], - ), - (word_literal("nan"), &[Expression::Decimal(Decimal::NAN)]), - ( - word_literal("inf"), - &[Expression::Decimal(Decimal::INFINITY)], - ), - ( - word_literal("-inf"), - &[Expression::Decimal(Decimal::NEG_INFINITY)], - ), - ( - word_literal("false"), - &[Expression::Boolean(Boolean(false))], - ), - (word_literal("true"), &[Expression::Boolean(Boolean(true))]), - (word_literal("not"), &[Expression::Verb(Verb(builtin::not))]), - (word_literal("and"), &[Expression::Verb(Verb(builtin::and))]), - (word_literal("or"), &[Expression::Verb(Verb(builtin::or))]), - ( - word_literal("bit-not"), - &[Expression::Verb(Verb(builtin::bitwise_not))], - ), - ( - word_literal("bit-and"), - &[Expression::Verb(Verb(builtin::bitwise_and))], - ), - ( - word_literal("bit-xor"), - &[Expression::Verb(Verb(builtin::bitwise_xor))], - ), - ( - word_literal("bit-or"), - &[Expression::Verb(Verb(builtin::bitwise_or))], - ), - (word_literal("shl"), &[Expression::Verb(Verb(builtin::shl))]), - (word_literal("shr"), &[Expression::Verb(Verb(builtin::shr))]), - ( - word_literal("ushr"), - &[Expression::Verb(Verb(builtin::ushr))], - ), - (word_literal("cat"), &[Expression::Verb(Verb(builtin::cat))]), - ( - word_literal("quote"), - &[Expression::Verb(Verb(builtin::quote))], - ), - ( - word_literal("unquote"), - &[Expression::Verb(Verb(builtin::unquote))], - ), - ( - word_literal("eval"), - &[Expression::Verb(Verb(builtin::eval))], - ), - (word_literal("i"), &[Expression::Verb(Verb(builtin::i))]), - (word_literal("x"), &[Expression::Verb(Verb(builtin::x))]), - (word_literal("dip"), &[Expression::Verb(Verb(builtin::dip))]), - ( - word_literal("unary2"), - &[Expression::Verb(Verb(builtin::unary2))], - ), - (word_literal("if"), &[Expression::Verb(Verb(builtin::r#if))]), - ( - word_literal("else"), - &[Expression::Verb(Verb(builtin::r#else))], - ), - ( - word_literal("if-else"), - &[Expression::Verb(Verb(builtin::if_else))], - ), - ( - word_literal("raise"), - &[Expression::Verb(Verb(builtin::raise))], - ), - ( - word_literal("try"), - &[Expression::Verb(Verb(builtin::r#try))], - ), - ( - word_literal("first"), - &[Expression::Verb(Verb(builtin::first))], - ), - ( - word_literal("last"), - &[Expression::Verb(Verb(builtin::last))], - ), - ( - word_literal("prefix"), - &[Expression::Verb(Verb(builtin::prefix))], - ), - ( - word_literal("suffix"), - &[Expression::Verb(Verb(builtin::suffix))], - ), - (word_literal("at"), &[Expression::Verb(Verb(builtin::at))]), - ( - word_literal("split"), - &[Expression::Verb(Verb(builtin::split))], - ), - (word_literal("len"), &[Expression::Verb(Verb(builtin::len))]), - ( - word_literal("swap"), - &[Expression::Verb(Verb(builtin::swap))], - ), - ( - word_literal("rollup"), - &[Expression::Verb(Verb(builtin::rollup))], - ), - ( - word_literal("rolldown"), - &[Expression::Verb(Verb(builtin::rolldown))], - ), - ( - word_literal("rotate"), - &[Expression::Verb(Verb(builtin::rotate))], - ), - (word_literal("pop"), &[Expression::Verb(Verb(builtin::pop))]), - (word_literal("dup"), &[Expression::Verb(Verb(builtin::dup))]), - (word_literal("ask"), &[Expression::Verb(Verb(builtin::ask))]), - (word_literal("say"), &[Expression::Verb(Verb(builtin::say))]), - ( - word_literal("show"), - &[Expression::Verb(Verb(builtin::show))], - ), - ( - word_literal("linrec"), - &[Expression::Verb(Verb(builtin::linrec))], - ), - ( - word_literal("binrec"), - &[Expression::Verb(Verb(builtin::binrec))], - ), -]; - -const fn word_literal(literal: &str) -> &Word { - match Word::try_from_literal(literal) { - Ok(word) => word, - Err(_) => panic!("invalid word literal"), - } -} diff --git a/rat/src/word.rs b/rat/src/word.rs index 37b3e26..87f447e 100644 --- a/rat/src/word.rs +++ b/rat/src/word.rs @@ -25,36 +25,19 @@ impl ToOwned for Word { impl Word { pub(crate) const fn is_valid(bytes: &[u8], start: usize, end: usize) -> bool { - if !(start < end && start < bytes.len() && end <= bytes.len()) { + if !(start < end + && start < bytes.len() + && end <= bytes.len() + && bytes[start].is_ascii_alphabetic()) + { return false; } - let mut i = start; - - while i < end { - let c = bytes[i]; - - if !(c == b'-' || c.is_ascii_digit() || c == b'_') { - break; - } - - i += 1; - } - - while i < end { - let c = bytes[i]; - - if !c.is_ascii_alphabetic() { - break; - } - - i += 1; - } - + let mut i = start + 1; while i < end { let c = bytes[i]; - if !(c == b'-' || c.is_ascii_alphanumeric() || c == b'_') { + if !(c.is_ascii_alphanumeric() || c == b'-' || c == b'_') { break; }