From 65529d28ef54f7974fb1508f596dbf99b7910822 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 12 Dec 2021 18:09:42 +0800 Subject: [PATCH 1/3] Bump fixes version. --- .github/workflows/build.yml | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a3359626..5242963f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: push: branches: - master - - v1.2-fixes + - v1.3-fixes pull_request: {} jobs: diff --git a/Cargo.toml b/Cargo.toml index b2364997..cb0a838c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "codegen"] [package] name = "rhai" -version = "1.3.0" +version = "1.3.1" edition = "2018" authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"] description = "Embedded scripting for Rust" From 93e3c4c10ada0de13ca294cf0b7d2e1b2c715352 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 13 Dec 2021 09:40:43 +0800 Subject: [PATCH 2/3] Compact BLOB display. --- CHANGELOG.md | 9 +++++++++ src/types/dynamic.rs | 11 ++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e07fe18..c0b20648 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ Rhai Release Notes ================== +Version 1.3.1 +============= + +Enhancements +------------ + +* `BLOB`'s are refined to display in a more compact hex format. + + Version 1.3.0 ============= diff --git a/src/types/dynamic.rs b/src/types/dynamic.rs index 9f142049..314dbc4b 100644 --- a/src/types/dynamic.rs +++ b/src/types/dynamic.rs @@ -689,7 +689,16 @@ impl fmt::Debug for Dynamic { #[cfg(not(feature = "no_index"))] Union::Array(ref value, _, _) => fmt::Debug::fmt(value, f), #[cfg(not(feature = "no_index"))] - Union::Blob(ref value, _, _) => fmt::Debug::fmt(value, f), + Union::Blob(ref value, _, _) => { + f.write_str("[")?; + value.iter().enumerate().try_for_each(|(i, v)| { + if i > 0 && i % 8 == 0 { + f.write_str(" ")?; + } + write!(f, "{:02x}", v) + })?; + f.write_str("]") + } #[cfg(not(feature = "no_object"))] Union::Map(ref value, _, _) => { f.write_str("#")?; From 224aa0ea68a89fab94c3f67c6d6462f685e8b0a1 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 16 Dec 2021 16:06:44 +0800 Subject: [PATCH 3/3] Allow custom syntax inside binary operator expressions. --- CHANGELOG.md | 5 +++++ README.md | 2 +- src/parser.rs | 38 ++++++++++++++++++-------------------- src/tokenizer.rs | 28 ++++++++++++---------------- tests/custom_syntax.rs | 34 ++++++++++++++++++++++++++++++++++ tests/serde.rs | 1 + 6 files changed, 71 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0b20648..8c60ac64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ Rhai Release Notes Version 1.3.1 ============= +Bug fixes +--------- + +* Custom syntax now works properly inside binary expressions. + Enhancements ------------ diff --git a/README.md b/README.md index 07a221a4..bfda54e5 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ The [`scripts`](https://github.com/rhaiscript/rhai/tree/master/scripts) subdirec Below is the standard _Fibonacci_ example for scripting languages: -```js +```ts // This Rhai script calculates the n-th Fibonacci number using a // really dumb algorithm to test the speed of the scripting engine. diff --git a/src/parser.rs b/src/parser.rs index 25bc5272..600f0090 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1550,9 +1550,26 @@ fn parse_unary( settings.ensure_level_within_max_limit(state.max_expr_depth)?; let (token, token_pos) = input.peek().expect(NEVER_ENDS); + let token_pos = *token_pos; let mut settings = settings; - settings.pos = *token_pos; + settings.pos = token_pos; + + // Check if it is a custom syntax. + if !state.engine.custom_syntax.is_empty() { + match token { + Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key) => { + if let Some((key, syntax)) = state.engine.custom_syntax.get_key_value(key.as_ref()) + { + input.next().expect(NEVER_ENDS); + return parse_custom_syntax( + input, state, lib, settings, key, syntax, token_pos, + ); + } + } + _ => (), + } + } match token { // -expr @@ -2251,25 +2268,6 @@ fn parse_expr( let mut settings = settings; settings.pos = input.peek().expect(NEVER_ENDS).1; - // Check if it is a custom syntax. - if !state.engine.custom_syntax.is_empty() { - let (token, pos) = input.peek().expect(NEVER_ENDS); - let token_pos = *pos; - - match token { - Token::Custom(key) | Token::Reserved(key) | Token::Identifier(key) => { - if let Some((key, syntax)) = state.engine.custom_syntax.get_key_value(key.as_ref()) - { - input.next().expect(NEVER_ENDS); - return parse_custom_syntax( - input, state, lib, settings, key, syntax, token_pos, - ); - } - } - _ => (), - } - } - // Parse expression normally. let lhs = parse_unary(input, state, lib, settings.level_up())?; parse_binary_op( diff --git a/src/tokenizer.rs b/src/tokenizer.rs index c039a8dc..e5a4905d 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -863,11 +863,6 @@ impl Token { use Token::*; Precedence::new(match self { - // Assignments are not considered expressions - set to zero - Equals | PlusAssign | MinusAssign | MultiplyAssign | DivideAssign | PowerOfAssign - | LeftShiftAssign | RightShiftAssign | AndAssign | OrAssign | XOrAssign - | ModuloAssign => 0, - Or | XOr | Pipe => 30, And | Ampersand => 60, @@ -886,8 +881,6 @@ impl Token { LeftShift | RightShift => 210, - Period => 240, - _ => 0, }) } @@ -898,14 +891,6 @@ impl Token { use Token::*; match self { - // Assignments bind to the right - Equals | PlusAssign | MinusAssign | MultiplyAssign | DivideAssign | PowerOfAssign - | LeftShiftAssign | RightShiftAssign | AndAssign | OrAssign | XOrAssign - | ModuloAssign => true, - - // Property access binds to the right - Period => true, - // Exponentiation binds to the right PowerOf => true, @@ -1662,6 +1647,17 @@ fn get_next_token_inner( // Shebang ('#', '!') => return Some((Token::Reserved("#!".into()), start_pos)), + ('#', ' ') => { + eat_next(stream, pos); + let token = if stream.peek_next() == Some('{') { + eat_next(stream, pos); + "# {" + } else { + "#" + }; + return Some((Token::Reserved(token.into()), start_pos)); + } + ('#', _) => return Some((Token::Reserved("#".into()), start_pos)), // Operators @@ -2182,7 +2178,7 @@ impl<'a> Iterator for TokenIterator<'a> { ("(*", false) | ("*)", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(), "'(* .. *)' is not a valid comment format. This is not Pascal! Should it be '/* .. */'?".to_string(), )), - ("#", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(), + ("# {", false) => Token::LexError(LERR::ImproperSymbol(s.to_string(), "'#' is not a valid symbol. Should it be '#{'?".to_string(), )), // Reserved keyword/operator that is custom. diff --git a/tests/custom_syntax.rs b/tests/custom_syntax.rs index f381bdf0..cbc9962a 100644 --- a/tests/custom_syntax.rs +++ b/tests/custom_syntax.rs @@ -239,3 +239,37 @@ fn test_custom_syntax_raw() -> Result<(), Box> { Ok(()) } + +#[test] +fn test_custom_syntax_raw2() -> Result<(), Box> { + let mut engine = Engine::new(); + + engine + .register_custom_operator("#", 255)? + .register_custom_syntax_raw( + "#", + |symbols, lookahead| match symbols.len() { + 1 if lookahead == "-" => Ok(Some("$symbol$".into())), + 1 => Ok(Some("$int$".into())), + 2 if symbols[1] == "-" => Ok(Some("$int$".into())), + 2 => Ok(None), + 3 => Ok(None), + _ => unreachable!(), + }, + false, + move |_, inputs| { + let id = if inputs.len() == 2 { + -inputs[1].get_literal_value::().unwrap() + } else { + inputs[0].get_literal_value::().unwrap() + }; + Ok(id.into()) + }, + ); + + assert_eq!(engine.eval::("let x = 41; x + #1")?, 42); + assert_eq!(engine.eval::("#42/2")?, 21); + assert_eq!(engine.eval::("#-1")?, -1); + + Ok(()) +} diff --git a/tests/serde.rs b/tests/serde.rs index 25929ac5..b1b76e3a 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -12,6 +12,7 @@ use rhai::Array; use rhai::Map; #[cfg(not(feature = "no_float"))] use rhai::FLOAT; +#[cfg(not(feature = "no_float"))] #[cfg(feature = "decimal")] use rust_decimal::Decimal;