Interp

Struct Interp 

Source
pub struct Interp { /* private fields */ }
Expand description

The Molt Interpreter.

The Interp struct is the primary API for embedding Molt into a Rust application. The application creates an instance of Interp, configures with it the required set of application-specific and standard Molt commands, and then uses it to evaluate Molt scripts and expressions. See the module level documentation for an overview.

§Example

By default, the Interp comes configured with the full set of standard Molt commands.

use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();
let four = interp.eval("expr {2 + 2}")?;
assert_eq!(four, Value::from(4));

Implementations§

Source§

impl Interp

Source

pub fn empty() -> Self

Creates a new Molt interpreter with no commands defined. Use this when crafting command languages that shouldn’t include the normal TCL commands, or as a base to which specific Molt command sets can be added.

§Example
let mut interp = Interp::empty();
assert!(interp.command_names().is_empty());
Source

pub fn new() -> Self

Creates a new Molt interpreter that is pre-populated with the standard Molt commands. Use command_names (or the info commands Molt command) to retrieve the full list, and the add_command family of methods to extend the interpreter with new commands.

TODO: Define command sets (sets of commands that go together, so that clients can add or remove them in groups).

let mut interp = Interp::new();
let four = interp.eval("expr {2 + 2}")?;
assert_eq!(four, Value::from(4));
Source

pub fn eval(&mut self, script: &str) -> MoltResult

Evaluates a script one command at a time. Returns the Value of the last command in the script, or the value of any explicit return call in the script, or any error thrown by the script. Other Exception values are converted to normal errors.

Use this method (or eval_value) to evaluate arbitrary scripts, control structure bodies, and so forth. Prefer eval_value if the script is already stored in a Value, as it will be more efficient if the script is evaluated multiple times.

§Example

The following code shows how to evaluate a script and handle the result, whether it’s a computed Value or an error message (which is also a Value).


let mut interp = Interp::new();

let input = "set a 1";

match interp.eval(input) {
   Ok(val) => {
       // Computed a Value
       println!("Value: {}", val);
   }
   Err(exception) => {
       if exception.is_error() {
           // Got an error; print it out.
           println!("Error: {}", exception.value());
       } else {
           // It's a Return.
           println!("Value: {}", exception.value());
       }
   }
}
Source

pub fn eval_value(&mut self, value: &Value) -> MoltResult

Evaluates the string value of a Value as a script. Returns the Value of the last command in the script, or the value of any explicit return call in the script, or any error thrown by the script. Other Exception values are converted to normal errors.

This method is equivalent to eval, but works on a Value rather than on a string slice. Use it or eval to evaluate arbitrary scripts, control structure bodies, and so forth. Prefer this to eval if the script is already stored in a Value, as it will be more efficient if the script is evaluated multiple times.

Source

pub fn complete(&mut self, script: &str) -> bool

Determines whether or not the script is syntactically complete, e.g., has no unmatched quotes, brackets, or braces.

REPLs use this to determine whether or not to ask for another line of input.

§Example
let mut interp = Interp::new();
assert!(interp.complete("set a [expr {1+1}]"));
assert!(!interp.complete("set a [expr {1+1"));
Source

pub fn expr(&mut self, expr: &Value) -> MoltResult

Evaluates a Molt expression and returns its value. The expression is passed as a Value which is interpreted as a String.

§Example
use molt::Interp;
use molt::types::*;
let mut interp = Interp::new();
let expr = Value::from("2 + 2");
let sum = interp.expr(&expr)?.as_int()?;

assert_eq!(sum, 4);
Source

pub fn expr_bool(&mut self, expr: &Value) -> Result<bool, Exception>

Evaluates a boolean Molt expression and returns its value, or an error if it couldn’t be interpreted as a boolean.

§Example
use molt::Interp;
use molt::types::*;
let mut interp = Interp::new();

let expr = Value::from("1 < 2");
let flag: bool = interp.expr_bool(&expr)?;

assert!(flag);
Source

pub fn expr_int(&mut self, expr: &Value) -> Result<MoltInt, Exception>

Evaluates a Molt expression and returns its value as an integer, or an error if it couldn’t be interpreted as an integer.

§Example
use molt::Interp;
use molt::types::*;
let mut interp = Interp::new();

let expr = Value::from("1 + 2");
let val: MoltInt = interp.expr_int(&expr)?;

assert_eq!(val, 3);
Source

pub fn expr_float(&mut self, expr: &Value) -> Result<MoltFloat, Exception>

Evaluates a Molt expression and returns its value as a float, or an error if it couldn’t be interpreted as a float.

§Example
use molt::Interp;
use molt::types::*;
let mut interp = Interp::new();

let expr = Value::from("1.1 + 2.2");
let val: MoltFloat = interp.expr_float(&expr)?;

assert_eq!(val, 3.3);
Source

pub fn var(&self, var_name: &Value) -> MoltResult

Retrieves the value of the named variable in the current scope. The var_name may name a scalar variable or an array element. This is the normal way to retrieve the value of a variable named by a command argument.

Returns an error if the variable is a scalar and the name names an array element, and vice versa.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the scalar variable "a" using a script.
interp.eval("set a 1")?;

// The value of the scalar variable "a".
let val = interp.var(&Value::from("a"))?;
assert_eq!(val.as_str(), "1");

// Set the value of the array element "b(1)" using a script.
interp.eval("set b(1) Howdy")?;

// The value of the array element "b(1)":
let val = interp.var(&Value::from("b(1)"))?;
assert_eq!(val.as_str(), "Howdy");
Source

pub fn var_exists(&self, var_name: &Value) -> bool

Returns 1 if the named variable is defined and exists, and 0 otherwise.

Source

pub fn set_var( &mut self, var_name: &Value, value: Value, ) -> Result<(), Exception>

Sets the value of the variable in the current scope. The var_name may name a scalar variable or an array element. This is the usual way to assign a value to a variable named by a command argument.

Returns an error if the variable is scalar and the name names an array element, and vice-versa.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the scalar variable "a"
let scalar = Value::from("a");  // The variable name
interp.set_var(&scalar, Value::from("1"))?;
assert_eq!(interp.var(&scalar)?.as_str(), "1");

// Set the value of the array element "b(1)":
let element = Value::from("b(1)");  // The variable name
interp.set_var(&element, Value::from("howdy"))?;
assert_eq!(interp.var(&element)?.as_str(), "howdy");
Source

pub fn set_var_return(&mut self, var_name: &Value, value: Value) -> MoltResult

Sets the value of the variable in the current scope, return its value. The var_name may name a scalar variable or an array element. This is the usual way to assign a value to a variable named by a command argument when the command is expected to return the value.

Returns an error if the variable is scalar and the name names an array element, and vice-versa.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the scalar variable "a"
let scalar = Value::from("a");  // The variable name
assert_eq!(interp.set_var_return(&scalar, Value::from("1"))?.as_str(), "1");

// Set the value of the array element "b(1)":
let element = Value::from("b(1)");  // The variable name
interp.set_var(&element, Value::from("howdy"))?;
assert_eq!(interp.set_var_return(&element, Value::from("1"))?.as_str(), "1");
Source

pub fn scalar(&self, name: &str) -> MoltResult

Retrieves the value of the named scalar variable in the current scope.

Returns an error if the variable is not found, or if the variable is an array variable.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the scalar variable "a" using a script.
interp.eval("set a 1")?;

// The value of the scalar variable "a".
let val = interp.scalar("a")?;
assert_eq!(val.as_str(), "1");
Source

pub fn set_scalar(&mut self, name: &str, value: Value) -> Result<(), Exception>

Sets the value of the named scalar variable in the current scope, creating the variable if necessary.

Returns an error if the variable exists and is an array variable.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the scalar variable "a"
interp.set_scalar("a", Value::from("1"))?;
assert_eq!(interp.scalar("a")?.as_str(), "1");
Source

pub fn set_scalar_return(&mut self, name: &str, value: Value) -> MoltResult

Sets the value of the named scalar variable in the current scope, creating the variable if necessary, and returning the value.

Returns an error if the variable exists and is an array variable.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the scalar variable "a"
assert_eq!(interp.set_scalar_return("a", Value::from("1"))?.as_str(), "1");
Source

pub fn element(&self, name: &str, index: &str) -> MoltResult

Retrieves the value of the named array element in the current scope.

Returns an error if the element is not found, or the variable is not an array variable.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the array element variable "a(1)" using a script.
interp.eval("set a(1) Howdy")?;

// The value of the array element "a(1)".
let val = interp.element("a", "1")?;
assert_eq!(val.as_str(), "Howdy");
Source

pub fn set_element( &mut self, name: &str, index: &str, value: Value, ) -> Result<(), Exception>

Sets the value of an array element in the current scope, creating the variable if necessary.

Returns an error if the variable exists and is not an array variable.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the scalar variable "a"
interp.set_element("b", "1", Value::from("xyz"))?;
assert_eq!(interp.element("b", "1")?.as_str(), "xyz");
Source

pub fn set_element_return( &mut self, name: &str, index: &str, value: Value, ) -> MoltResult

Sets the value of an array element in the current scope, creating the variable if necessary, and returning the value.

Returns an error if the variable exists and is not an array variable.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

// Set the value of the scalar variable "a"
assert_eq!(interp.set_element_return("b", "1", Value::from("xyz"))?.as_str(), "xyz");
Source

pub fn unset(&mut self, name: &str)

Unsets a variable, whether scalar or array, given its name in the current scope. For arrays this is the name of the array proper, e.g., myArray, not the name of an element, e.g., myArray(1).

It is not an error to unset a variable that doesn’t exist.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

interp.set_scalar("a", Value::from("1"))?;
interp.set_element("b", "1", Value::from("2"))?;

interp.unset("a"); // Unset scalar
interp.unset("b"); // Unset entire array
Source

pub fn unset_var(&mut self, name: &Value)

Unsets the value of the named variable or array element in the current scope.

It is not an error to unset a variable that doesn’t exist.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

let scalar = Value::from("a");
let array = Value::from("b");
let elem = Value::from("b(1)");

interp.unset_var(&scalar); // Unset scalar
interp.unset_var(&elem);   // Unset array element
interp.unset_var(&array);  // Unset entire array
Source

pub fn unset_element(&mut self, array_name: &str, index: &str)

Unsets a single element in an array given the array name and index.

It is not an error to unset an array element that doesn’t exist.

§Example
use molt::types::*;
use molt::Interp;
use molt::molt_ok;
let mut interp = Interp::new();

interp.set_element("b", "1", Value::from("2"))?;

interp.unset_element("b", "1");
Source

pub fn vars_in_scope(&self) -> MoltList

Gets a list of the names of the variables that are visible in the current scope. The list includes the names of array variables but not elements within them.

§Example
use molt::Interp;
use molt::types::*;

for name in interp.vars_in_scope() {
    println!("Found variable: {}", name);
}
Source

pub fn vars_in_global_scope(&self) -> MoltList

Gets a list of the names of the variables defined in the global scope. The list includes the names of array variables but not elements within them.

§Example
use molt::Interp;
use molt::types::*;

for name in interp.vars_in_global_scope() {
    println!("Found variable: {}", name);
}
Source

pub fn vars_in_local_scope(&self) -> MoltList

Gets a list of the names of the variables defined in the local scope. This does not include variables brought into scope via global or upvar, or any variables defined in the global scope. The list includes the names of array variables but not elements within them.

§Example
use molt::Interp;
use molt::types::*;

for name in interp.vars_in_local_scope() {
    println!("Found variable: {}", name);
}
Source

pub fn upvar(&mut self, level: usize, name: &str)

Links the variable name in the current scope to the given scope. Note: the level is the absolute level, not the level relative to the current stack level, i.e., level=0 is the global scope.

This method is used to implement the upvar command, which allows variables to be passed by name; client code should rarely need to access it directly.

Source

pub fn push_scope(&mut self)

Pushes a variable scope (i.e., a stack level) onto the scope stack.

Procs use this to define their local scope. Client code should seldom need to call this directly, but it can be useful in a few cases. For example, the Molt test harness’s test command runs its body in a local scope as an aid to test cleanup.

Note: a command that pushes a scope must also call Interp::pop_scope before it exits!

Source

pub fn pop_scope(&mut self)

Pops a variable scope (i.e., a stack level) off of the scope stack. Calls to Interp::push_scope and Interp::pop_scope must exist in pairs.

Source

pub fn scope_level(&self) -> usize

Return the current scope level. The global scope is level 0; each call to Interp::push_scope adds a level, and each call to Interp::pop_scope removes it. This method is used with Interp::upvar to access the caller’s scope when a variable is passed by name.

Source

pub fn array_exists(&self, array_name: &str) -> bool

Determines whether or not the name is the name of an array variable.

§Example
interp.set_scalar("a", Value::from(1))?;
interp.set_element("b", "1", Value::from(2));

assert!(!interp.array_exists("a"));
assert!(interp.array_exists("b"));
Source

pub fn array_get(&self, array_name: &str) -> MoltList

Gets a flat vector of the keys and values from the named array. This is used to implement the array get command.

§Example
use molt::Interp;
use molt::types::*;

for txt in interp.array_get("myArray") {
    println!("Found index or value: {}", txt);
}
Source

pub fn array_set(&mut self, array_name: &str, kvlist: &[Value]) -> MoltResult

Merges a flat vector of keys and values into the named array. It’s an error if the vector has an odd number of elements, or if the named variable is a scalar. This method is used to implement the array set command.

§Example

For example, the following Rust code is equivalent to the following Molt code:

# Set individual elements
set myArray(a) 1
set myArray(b) 2

# Set all at once
array set myArray { a 1 b 2 }
use molt::Interp;
use molt::types::*;

interp.array_set("myArray", &vec!["a".into(), "1".into(), "b".into(), "2".into()])?;
Source

pub fn array_names(&self, array_name: &str) -> MoltList

Gets a list of the indices of the given array. This is used to implement the array names command. If the variable does not exist (or is not an array variable), the method returns the empty list.

§Example
use molt::Interp;
use molt::types::*;

for name in interp.array_names("myArray") {
    println!("Found index : {}", name);
}
Source

pub fn array_size(&self, array_name: &str) -> usize

Gets the number of elements in the named array. Returns 0 if the variable doesn’t exist (or isn’t an array variable).

§Example
use molt::Interp;
use molt::types::*;

let mut interp = Interp::new();

assert_eq!(interp.array_size("a"), 0);

interp.set_element("a", "1", Value::from("xyz"))?;
assert_eq!(interp.array_size("a"), 1);
Source

pub fn add_command(&mut self, name: &str, func: CommandFunc)

Adds a binary command with no related context to the interpreter. This is the normal way to add most commands.

If the command needs access to some form of application or context data, use add_context_command instead. See the module level documentation for an overview and examples.

Source

pub fn add_context_command( &mut self, name: &str, func: CommandFunc, context_id: ContextID, )

Adds a binary command with related context data to the interpreter.

This is the normal way to add commands requiring application context. See the module level documentation for an overview and examples.

Source

pub fn has_command(&self, name: &str) -> bool

Determines whether or not the interpreter contains a command with the given name.

Source

pub fn rename_command(&mut self, old_name: &str, new_name: &str)

Renames the command.

Note: This does not update procedures that reference the command under the old name. This is intentional: it is a common TCL programming technique to wrap an existing command by renaming it and defining a new command with the old name that calls the original command at its new name.

§Example
use molt::Interp;
use molt::types::*;
use molt::molt_ok;
let mut interp = Interp::new();

interp.rename_command("expr", "=");

let sum = interp.eval("= {1 + 1}")?.as_int()?;

assert_eq!(sum, 2);
Source

pub fn remove_command(&mut self, name: &str)

Removes the command with the given name.

This would typically be done when destroying an object command.

§Example
use molt::Interp;
use molt::types::*;
use molt::molt_ok;

let mut interp = Interp::new();

interp.remove_command("set");  // You'll be sorry....

assert!(!interp.has_command("set"));
Source

pub fn command_names(&self) -> MoltList

Gets a vector of the names of the existing commands.

§Example
use molt::Interp;
use molt::types::*;
use molt::molt_ok;

let mut interp = Interp::new();

for name in interp.command_names() {
    println!("Found command: {}", name);
}
Source

pub fn command_type(&self, command: &str) -> MoltResult

Returns the body of the named procedure, or an error if the name doesn’t name a procedure.

Source

pub fn proc_names(&self) -> MoltList

Gets a vector of the names of the existing procedures.

§Example
use molt::Interp;
use molt::types::*;
use molt::molt_ok;

let mut interp = Interp::new();

for name in interp.proc_names() {
    println!("Found procedure: {}", name);
}
Source

pub fn proc_body(&self, procname: &str) -> MoltResult

Returns the body of the named procedure, or an error if the name doesn’t name a procedure.

Source

pub fn proc_args(&self, procname: &str) -> MoltResult

Returns a list of the names of the arguments of the named procedure, or an error if the name doesn’t name a procedure.

Source

pub fn proc_default( &self, procname: &str, arg: &str, ) -> Result<Option<Value>, Exception>

Returns the default value of the named argument of the named procedure, if it has one. Returns an error if the procedure has no such argument, or the procname doesn’t name a procedure.

Source

pub fn call_subcommand( &mut self, context_id: ContextID, argv: &[Value], subc: usize, subcommands: &[Subcommand], ) -> MoltResult

Calls a subcommand of the current command, looking up its name in an array of Subcommand tuples.

The subcommand, if found, is called with the same context_id and argv as its parent ensemble. subc is the index of the subcommand’s name in the argv array; in most cases it will be 1, but it is possible to define subcommands with subcommands of their own. The subcommands argument is a borrow of an array of Subcommand records, each defining a subcommand’s name and CommandFunc.

If the subcommand name is found in the array, the matching CommandFunc is called. otherwise, the error message gives the ensemble syntax. If an invalid subcommand name was provided, the error message includes the valid options.

See the implementation of the array command in commands.rs and the module level documentation for examples.

Source

pub fn recursion_limit(&self) -> usize

Gets the interpreter’s recursion limit: how deep the stack of script evaluations may be.

A script stack level is added by each nested script evaluation (i.e., by each call) to eval or eval_value.

§Example
let mut interp = Interp::new();
assert_eq!(interp.recursion_limit(), 1000);
Source

pub fn set_recursion_limit(&mut self, limit: usize)

Sets the interpreter’s recursion limit: how deep the stack of script evaluations may be. The default is 1000.

A script stack level is added by each nested script evaluation (i.e., by each call) to eval or eval_value.

§Example
let mut interp = Interp::new();
interp.set_recursion_limit(100);
assert_eq!(interp.recursion_limit(), 100);
Source

pub fn save_context<T: 'static>(&mut self, data: T) -> ContextID

Saves the client’s context data in the interpreter’s context cache, returning a generated context ID. Client commands can retrieve the data given the ID.

See the module level documentation for an overview and examples.

§Example
use molt::types::*;
use molt::interp::Interp;

let mut interp = Interp::new();
let data: Vec<String> = Vec::new();
let id = interp.save_context(data);
Source

pub fn context<T: 'static>(&mut self, id: ContextID) -> &mut T

Retrieves mutable client context data given the context ID.

See the module level documentation for an overview and examples.

§Example
use molt::types::*;
use molt::interp::Interp;

let mut interp = Interp::new();
let data: Vec<String> = Vec::new();
let id = interp.save_context(data);

// Later...
let data: &mut Vec<String> = interp.context(id);
data.push("New Value".into());

// Or
let data = interp.context::<Vec<String>>(id);
data.push("New Value".into());
§Panics

This call panics if the context ID is unknown, or if the retrieved data has an unexpected type.

Source

pub fn context_id(&mut self) -> ContextID

Generates a unique context ID for command context data.

Normally the client will use save_context to save the context data and generate the client ID in one operation, rather than call this explicitly.

§Example
use molt::types::*;
use molt::interp::Interp;

let mut interp = Interp::new();
let id1 = interp.context_id();
let id2 = interp.context_id();
assert_ne!(id1, id2);
Source

pub fn set_context<T: 'static>(&mut self, id: ContextID, data: T)

Saves a client context value in the interpreter for the given context ID. Client commands can retrieve the data given the context ID.

Normally the client will use save_context to save the context data and generate the client ID in one operation, rather than call this explicitly.

TODO: This method allows the user to generate a context ID and put data into the context cache as two separate steps; and to update the the data in the context cache for a given ID. I’m not at all sure that either of those things is a good idea. Waiting to see.

§Example
use molt::types::*;
use molt::interp::Interp;

let mut interp = Interp::new();
let id = interp.context_id();
let data: Vec<String> = Vec::new();
interp.set_context(id, data);
Source

pub fn profile_save(&mut self, name: &str, start: Instant)

Unstable; use at own risk.

Source

pub fn profile_clear(&mut self)

Unstable; use at own risk.

Source

pub fn profile_dump(&self)

Unstable; use at own risk.

Trait Implementations§

Source§

impl Default for Interp

Source§

fn default() -> Interp

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Interp

§

impl !RefUnwindSafe for Interp

§

impl !Send for Interp

§

impl !Sync for Interp

§

impl Unpin for Interp

§

impl !UnwindSafe for Interp

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.