Interpreter - Made the interpreter state partially public
* This allows Callable to be public, which is required for Value * State internals are still hidden behind pub(super)
This commit is contained in:
parent
10223cbb4e
commit
c97ad0ad7e
2 changed files with 30 additions and 17 deletions
|
@ -5,7 +5,7 @@ use crate::errors::SloxResult;
|
|||
use super::{InterpreterState, Value};
|
||||
|
||||
/// A callable is some object that supports being called.
|
||||
pub(super) trait Callable: Debug + ToString {
|
||||
pub trait Callable: Debug + ToString {
|
||||
/// Return the amount of arguments supported by the callable.
|
||||
fn arity(&self) -> usize;
|
||||
|
||||
|
@ -15,4 +15,4 @@ pub(super) trait Callable: Debug + ToString {
|
|||
}
|
||||
|
||||
/// A reference to a callable.
|
||||
pub(super) type CallableRef = Rc<RefCell<dyn Callable>>;
|
||||
pub type CallableRef = Rc<RefCell<dyn Callable>>;
|
||||
|
|
|
@ -10,12 +10,7 @@ use crate::{
|
|||
|
||||
/// Evaluate an interpretable, returning its value.
|
||||
pub fn evaluate(ast: &ast::ProgramNode, vars: ResolvedVariables) -> SloxResult<Value> {
|
||||
let env = Rc::new(RefCell::new(Environment::default()));
|
||||
let mut state = InterpreterState{
|
||||
environment: env.clone(),
|
||||
globals: env,
|
||||
variables: &vars,
|
||||
};
|
||||
let mut state = InterpreterState::new(&vars);
|
||||
ast.interpret(&mut state).map(|v| v.result())
|
||||
}
|
||||
|
||||
|
@ -25,12 +20,36 @@ pub fn evaluate(ast: &ast::ProgramNode, vars: ResolvedVariables) -> SloxResult<V
|
|||
|
||||
/// The state of the interpreter.
|
||||
#[derive(Debug)]
|
||||
pub(super) struct InterpreterState<'a> {
|
||||
pub struct InterpreterState<'a> {
|
||||
pub(super) globals: EnvironmentRef,
|
||||
pub(super) environment: EnvironmentRef,
|
||||
pub(super) variables: &'a ResolvedVariables,
|
||||
}
|
||||
|
||||
impl<'a> InterpreterState<'a> {
|
||||
/// Initialize the interpreter state from the resolved variables map.
|
||||
fn new(vars: &'a ResolvedVariables) -> Self {
|
||||
let env = Rc::new(RefCell::new(Environment::default()));
|
||||
Self {
|
||||
environment: env.clone(),
|
||||
globals: env,
|
||||
variables: &vars,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a child state.
|
||||
fn create_child<'b>(parent: &InterpreterState<'b>) -> Self
|
||||
where
|
||||
'b: 'a,
|
||||
{
|
||||
InterpreterState {
|
||||
environment: Environment::create_child(&parent.environment),
|
||||
globals: parent.globals.clone(),
|
||||
variables: parent.variables,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Interpreter flow control, which may be either a value, a loop break or a
|
||||
/// loop continuation.
|
||||
#[derive(Debug)]
|
||||
|
@ -129,9 +148,7 @@ impl Interpretable for ast::StmtNode {
|
|||
is_break,
|
||||
loop_name,
|
||||
} => self.on_loop_control_statemement(*is_break, loop_name),
|
||||
ast::StmtNode::Return { token: _, value } => {
|
||||
self.on_return_statement(es, value)
|
||||
}
|
||||
ast::StmtNode::Return { token: _, value } => self.on_return_statement(es, value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,11 +201,7 @@ impl ast::StmtNode {
|
|||
|
||||
/// Execute the contents of a block.
|
||||
fn on_block(&self, es: &mut InterpreterState, stmts: &[ast::StmtNode]) -> InterpreterResult {
|
||||
let mut child = InterpreterState{
|
||||
environment: Environment::create_child(&es.environment),
|
||||
globals: es.globals.clone(),
|
||||
variables: es.variables,
|
||||
};
|
||||
let mut child = InterpreterState::create_child(es);
|
||||
for stmt in stmts.iter() {
|
||||
let result = stmt.interpret(&mut child)?;
|
||||
if result.is_flow_control() {
|
||||
|
|
Loading…
Reference in a new issue