[][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.

Example

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

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

Methods

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, 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 ResultCode values are converted to normal errors.

Use this method (or eval_value to evaluate arbitrary scripts. Use eval_body to evaluate the body of control structures.

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(ResultCode::Error(msg)) => {
       // Got an error; print it out.
       println!("Error: {}", msg);
   }
   _ => {
       // Won't ever happen, but the compiler doesn't know that.
       // panic!() if you like.
   }
}

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

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

Evaluates a script one command at a time, returning whatever MoltResult arises.

This is the method to use when evaluating a control structure's script body; the control structure must handle the special result codes appropriately.

Example

The following code could be used to process the body of one of the Molt looping commands, e.g., while or foreach. ResultCode::Return and ResultCode::Error return out of the looping command altogether, returning control to the caller. ResultCode::Break breaks out of the loop. Ok and ResultCode::Continue continue with the next iteration.

This example is not tested
...
while (...) {
    let result = interp.eval_body(&body);

    match result {
        Ok(_) => (),
        Err(ResultCode::Return(_)) => return result,
        Err(ResultCode::Error(_)) => return result,
        Err(ResultCode::Break) => break,
        Err(ResultCode::Continue) => (),
    }
}

molt_ok!()

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 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, ResultCode>[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, ResultCode>[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, ResultCode>[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 add_command(&mut self, name: &str, func: CommandFunc)[src]

Adds a command defined by a CommandFunc to the interpreter. This is the normal way to add commands to the interpreter.

Accessing Application Data

When embedding Molt in an application, it is common to define commands that require mutable or immutable access to application data. If the command requires access to data other than that provided by the Interp itself, e.g., application data, consider adding the relevant data structure to the context cache and then use add_context_command. Alternatively, define a struct that implements Command and use add_command_object.

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

Adds a command defined by a ContextCommandFunc to the interpreter.

This is the normal way to add commands requiring application context to the interpreter. It is up to the module creating the context to free it when it is no longer required.

Warning: Do not use this method to define a TCL object, i.e., a command with its own data and lifetime. Use a type that implements Command and Drop.

pub fn add_command_object<T: 'static + Command>(
    &mut self,
    name: &str,
    command: T
)
[src]

Adds a command to the interpreter using a Command object.

Use this when defining a command that requires application context.

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

Determines whether 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.

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

Removes the command with the given name.

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

Gets a vector of the names of the existing commands.

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

Gets the interpreter's recursion limit.

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. The default is 1000.

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 context data in the interpreter's context cache, returning a generated context ID. Client commands can retrieve the data given the ID.

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 given the context ID.

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 forget_context(&mut self, id: ContextID)[src]

Removes a context record from the context cache. Clears the data from the cache when it is no longer needed.

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...
interp.forget_context(id);

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 var(&self, name: &str) -> MoltResult[src]

Retrieves the value of the named variable in the current scope, if any.

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

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

pub fn set_var(&mut self, name: &str, value: &Value)[src]

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

Ultimately, this should be set_var.

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

Unsets the value of the named variable in the current scope

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

Gets a vector of the visible var names.

pub fn push_scope(&mut self)[src]

Pushes a variable scope on to the scope stack. Procs use this to define their local scope.

pub fn pop_scope(&mut self)[src]

Pops a variable scope off of the scope stack.

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

Return the current scope level

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

Links the variable name in the current scope to the given scope.

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

pub fn profile_clear(&mut self)[src]

pub fn profile_dump(&self)[src]

Trait Implementations

impl Default for Interp[src]

Auto Trait Implementations

impl !Send for Interp

impl Unpin for Interp

impl !Sync for Interp

impl !UnwindSafe for Interp

impl !RefUnwindSafe for Interp

Blanket Implementations

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

impl<T> From<T> for 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.

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

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

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