rhaiscript / rhai

Rhai - An embedded scripting language for Rust.
https://crates.io/crates/rhai
Apache License 2.0
3.8k stars 177 forks source link

Exporting variables in module by default using custom syntax #535

Closed ltabis closed 2 years ago

ltabis commented 2 years ago

Hello !

I am currently writing a DSL using rhai. I want to create a syntax to declare exportable constants in modules:

// --- scripts/consts.rhai
// this loads a file & declares a variable called "my_file".
object file "my_file" "/home/user/file.txt";
// this parses the ip string into a rust Ipv4Addr type and store it under the "localhost" name.
object ip4 "localhost" "127.0.0.1";

export my_file;
export localhost;
// --- main.rs
import "scripts/consts.rhai" as consts;

print(consts::my_file);
print(consts::localhost);

The purpose of this custom syntax is to allow the user to declare special configuration variables.

There is one problem: the export keyword. As I understood, you cannot export variables by default in a script, and each variable need to have the export keyword to be exported successfully. This could be problematic because the user could declare a lot of variables for my use case, and writing export variable_name for each of them is not conceivable.

As a DSL, I want to make the syntax easier for the user by removing the export keyword and exporting all variables using the above syntax by default in a module. I did not find any solution to do this, as there does not seem to be a way to "add" tokens while parsing the syntax tree, or simply exporting the variable once it has been parsed.

Is there any workaround for this ?

schungx commented 2 years ago

The Scope has methods to set export aliases. However, those methods are private.

I can make them public... essentially export var but in code.

schungx commented 2 years ago

A small suggestion, you may want to do the syntax this way:

object $ident$ : $ident$ = $expr$

So you can put expressions into the text string etc.

object my_file : file = "..."; object localhost : ip4 = "...";

and the syntax will look more like a natural extension of a C-style language.

Alternatively, some other styles are:

object my_file = "..." as file; object localhost = "..." as ip4;

JavaScript like:

use file "..." as my_file; use ip4 "..." as localhost;

schungx commented 2 years ago

You can pull from https://github.com/schungx/rhai to test out Scope::set_alias which should allow you to export a variable under a particular name (put in an empty string to export under its own name).

ltabis commented 2 years ago

You can pull from https://github.com/schungx/rhai to test out Scope::set_alias which should allow you to export a variable under a particular name (put in an empty string to export under its own name).

I've tested it out, it's perfect.

Thanks for the syntax recommandations, I'll look into it. If you're able to make Scope::set_alias in the next release, that would be awesome !

Thanks again for your help. Should I close this ?

schungx commented 2 years ago

Thanks again for your help. Should I close this ?

No prob! Glad to see different usages! Please close when you have no more issues.

Later today I'll push it to the main repo so you can pull from https://github.com/rhaiscript/rhai instead of my dev repo.

schungx commented 2 years ago

By the way, do you find custom syntax working out for you?

Because it is just as easy to create a function that does exactly the same thing, with a syntax that is not too bad:

const my_file = load("file", "...");
const localhost = load("ip4", "...");
ltabis commented 2 years ago

By the way, do you find custom syntax working out for you?

Well, I'm not sure.

The DSL that I'm trying to create is a mix of a configuration language will providing the programming side of rhai. It is targeted for system administrator looking for configuring a MTA server.

The programming side is supposed to be reserved to the "power user" that wants to make really special stuff with his configuration, but the "regular user" will mostly just use the configuration side of the DSL, being config variables declared using the object keyword. I assume that the "regular user" does not necessarily know about programming, hence the custom syntax looking like a config language.

I was inspired by HCL's syntax. The object declaration looks a bit like it and I thought it was nice to have the same kind of object declaration for multiple types (ip address, but also files loaded under the hood etc ...), instead of using functions like in your comment.

I really get that it could be better to just not use a custom syntax, because it makes the language harder to understand. But here I'm trying to target a user that mostly use configuration WHILE being able to add logic to it's script.

Thank you for your time ! I'm closing the issue.

schungx commented 2 years ago

The changes is now merged into the main repo. You can pull from https://github.com/rhaiscript/rhai