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:
Emmanuel BENOîT 2023-01-06 07:46:44 +01:00
parent 10223cbb4e
commit c97ad0ad7e
2 changed files with 30 additions and 17 deletions

View file

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

View file

@ -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() {