[][src]Struct molt::interp::Interp

pub struct Interp { /* fields omitted */ }

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

impl Interp[src]

pub fn empty() -> Self[src]

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());

pub fn new() -> Self[src]

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));

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

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());
       }
   }
}

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

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.

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

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"));

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

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);

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

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);

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

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);

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

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);

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

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");

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

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

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

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");

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

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");

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

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");

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

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");

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

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");

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

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");

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

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");

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

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");

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

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

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

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

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

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");

pub fn vars_in_scope(&self) -> MoltList[src]

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);
}

pub fn vars_in_global_scope(&self) -> MoltList[src]

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);
}

pub fn vars_in_local_scope(&self) -> MoltList[src]

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);
}

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

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.

pub fn push_scope(&mut self)[src]

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!

pub fn pop_scope(&mut self)[src]

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.

pub fn scope_level(&self) -> usize[src]

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.

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

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"));

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

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);
}

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

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()])?;

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

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);
}

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

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);

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

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.

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

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.

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

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

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

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);

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

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"));

pub fn command_names(&self) -> MoltList[src]

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);
}

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

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

pub fn proc_names(&self) -> MoltList[src]

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);
}

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

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

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

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

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

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.

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

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.

pub fn recursion_limit(&self) -> usize[src]

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);

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

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);

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

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);

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

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.

pub fn context_id(&mut self) -> ContextID[src]

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);

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

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);

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

Unstable; use at own risk.

pub fn profile_clear(&mut self)[src]

Unstable; use at own risk.

pub fn profile_dump(&self)[src]

Unstable; use at own risk.

Trait Implementations

impl Default for Interp[src]

Auto Trait Implementations

impl !RefUnwindSafe for Interp

impl !Send for Interp

impl !Sync for Interp

impl Unpin for Interp

impl !UnwindSafe for Interp

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.