Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse error on multiplying two switch expressions #628

Closed
ttencate opened this issue Aug 26, 2022 · 19 comments
Closed

Parse error on multiplying two switch expressions #628

ttencate opened this issue Aug 26, 2022 · 19 comments

Comments

@ttencate
Copy link

switch 1 {} * switch 2 {}
            ^ Unexpected '*' (line 1, position 13)

It works when I parenthesize the first expression:

(switch 1 {}) * switch 2 {}
@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

It is parsing it as a statement. This works...

let x = switch 1 {} * switch 2 {};

@ttencate
Copy link
Author

That's what I thought. Why is there a non-expression switch statement anyway? 1; 2; 3; is a valid Rhai program, so clearly expressions can be statements too.

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

That's what I thought. Why is there a non-expression switch statement anyway? 1; 2; 3; is a valid Rhai program, so clearly expressions can be statements too.

That's because most normal uses would use it as a statement (if also). Parsing it as an expression will incur an additional indirection every time it is encountered.

@ttencate
Copy link
Author

ttencate commented Aug 26, 2022

It parses as a statement even inside an if expression:

let x = if true { switch 1 {} * switch 2 {} }
                              ^ Unexpected '*'

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

Yes, that's because things inside a block are statements...

Why would you like to multiply two switch statements without assigning the result to anything?

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

Why would you like to multiply two switch statements without assigning the result to anything?

I'm not saying you shouldn't or can't do it... but usually there is no great need.

@ttencate
Copy link
Author

ttencate commented Aug 26, 2022

I'm using https://rhai.rs/book/engine/expressions.html. Edit: actually, I'm not using that anymore because for some reason it disallows if and switch expressions, but my primary purpose is still to evaluate expressions.

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

ctually, I'm not using that anymore because for some reason it disallows if and switch expressions, but my primary purpose is still to evaluate expressions.

Yes, expressions are intended for real expressions without logic flow... so those are disabled.

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

So you want to evaluate expressions which may consist of switch? That would be a bit involved, as the action blocks in a switch may be statements, so you'll end up running statements.

Unless it is also restricted to expressions there.

@ttencate
Copy link
Author

I'm running some Rhai code to compute some value from some inputs. It's intended to be a pure function. I'm exposing no functions to the engine that have side effects, and the scope is truncated afterwards back to its initial size. Whether Rhai thinks my code is an "expression" or a "statement" or a "block of statements" or a "box of chocolates" does not matter to me :)

It's strange to me that if and switch expressions would be disabled while evaluating expressions. We can emulate the same behaviour by exposing a Rust function to the engine.

A ternary condition ? value_if_true : value_if_false, would that be considered a "real expression without logic flow"? How about (condition as f64) * (value_if_true) + (1.0 - (condition as f64)) * (value_if_false)?

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

It's strange to me that if and switch expressions would be disabled while evaluating expressions. We can emulate the same behaviour by exposing a Rust function to the engine.

That's only because, when evaluating expressions, it is more likely to be an error when statements are encountered.

A ternary condition ? value_if_true : value_if_false, would that be considered a "real expression without logic flow"? How about (condition as f64) * (value_if_true) + (1.0 - (condition as f64)) * (value_if_false)?

In Rhai, a form of the tenary operator can be easily implemented as a custom syntax expressions... so yes it is an expression... I know that's not the most ideal...

What I can do is to add an advanced version of compile_expression such that it takes a parameter allowing statements. It is a very small change in the code (changing from false to true), but right now there is no out-of-the-box method to parse an expression with if/switch-expressions.

@ttencate
Copy link
Author

That's okay. Since a statement block also evaluates to the last statement, I can just use that. It also helps with more complex expressions, e.g. if the user wants to introduce helper variables or eve functions. On second thought, I don't really understand the use case of eval_expression, but that might just be me :)

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

I don't really understand the use case of eval_expression, but that might just be me :)

Different use cases. Many people don't need a full-blown scripting language. All they need is to evaluate expressions for customized config. They don't need scripts; they need only expressions.

For these cases, eval_expression is ideal for them as they don't have to worry about users throwing in loops and variable declarations etc.

@ttencate
Copy link
Author

I can see how loops would open you up to DoS attacks if you are running this as e.g. a web service. But if and switch expressions can't be used for that. Nor can variable declarations.

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

That's true, except that they both have blocks which can run anything inside...

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

Maybe I can restrict the blocks to have only expressions... then it is OK to have if and switch in expressions...

@schungx
Copy link
Collaborator

schungx commented Aug 26, 2022

OK. I don't think it would be difficult to add. I'll add that support, then you can use Engine::eval_expression and both if and switch will work as long as their blocks contain only expressions.

@schungx
Copy link
Collaborator

schungx commented Aug 27, 2022

PR #630 does this - it allows if and switch expressions.

@schungx schungx added the wontfix label Nov 4, 2022
@schungx
Copy link
Collaborator

schungx commented Nov 4, 2022

switch 1 {} * switch 2 {} will continue to cause a parse error because the first switch is parsed as a statement. This is by design.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants