Add context stacks

This commit is contained in:
Jeff 2024-08-29 12:32:48 -04:00
parent d032334635
commit 21b63b5942
5 changed files with 187 additions and 108 deletions

View File

@ -17,7 +17,7 @@ use crate::{
PrimitiveValueExpression, RangeExpression, Span, Statement, StructDefinition, PrimitiveValueExpression, RangeExpression, Span, Statement, StructDefinition,
StructExpression, TupleAccessExpression, StructExpression, TupleAccessExpression,
}, },
core_library, parse, Context, ContextError, DustError, Expression, Identifier, RangeableType, parse, ContextError, ContextStack, DustError, Expression, Identifier, RangeableType,
StructType, Type, TypeConflict, TypeEvaluation, StructType, Type, TypeConflict, TypeEvaluation,
}; };
@ -34,8 +34,8 @@ use crate::{
/// ``` /// ```
pub fn analyze(source: &str) -> Result<(), DustError> { pub fn analyze(source: &str) -> Result<(), DustError> {
let abstract_tree = parse(source)?; let abstract_tree = parse(source)?;
let context = core_library().create_child(); let context_stack = ContextStack::with_core_library();
let mut analyzer = Analyzer::new(&abstract_tree, context); let mut analyzer = Analyzer::new(&abstract_tree, context_stack);
analyzer.analyze(); analyzer.analyze();
@ -54,22 +54,22 @@ pub fn analyze(source: &str) -> Result<(), DustError> {
/// # use dust_lang::*; /// # use dust_lang::*;
/// let input = "x = 1 + false"; /// let input = "x = 1 + false";
/// let abstract_tree = parse(input).unwrap(); /// let abstract_tree = parse(input).unwrap();
/// let context = Context::new(); /// let context_stack = ContextStack::new();
/// let mut analyzer = Analyzer::new(&abstract_tree, context); /// let mut analyzer = Analyzer::new(&abstract_tree, context_stack);
/// let result = analyzer.analyze(); /// let result = analyzer.analyze();
/// ///
/// assert!(!analyzer.errors.is_empty()); /// assert!(!analyzer.errors.is_empty());
pub struct Analyzer<'a> { pub struct Analyzer<'a> {
abstract_tree: &'a AbstractSyntaxTree, abstract_tree: &'a AbstractSyntaxTree,
context: Context, context_stack: ContextStack,
pub errors: Vec<AnalysisError>, pub errors: Vec<AnalysisError>,
} }
impl<'a> Analyzer<'a> { impl<'a> Analyzer<'a> {
pub fn new(abstract_tree: &'a AbstractSyntaxTree, context: Context) -> Self { pub fn new(abstract_tree: &'a AbstractSyntaxTree, context_stack: ContextStack) -> Self {
Self { Self {
abstract_tree, abstract_tree,
context, context_stack,
errors: Vec::new(), errors: Vec::new(),
} }
} }
@ -81,6 +81,8 @@ impl<'a> Analyzer<'a> {
} }
fn analyze_statement(&mut self, statement: &Statement) { fn analyze_statement(&mut self, statement: &Statement) {
let context = self.context_stack.top();
match statement { match statement {
Statement::Expression(expression) => { Statement::Expression(expression) => {
self.analyze_expression(expression, statement.position()) self.analyze_expression(expression, statement.position())
@ -91,14 +93,14 @@ impl<'a> Analyzer<'a> {
Statement::Let(let_statement) => match &let_statement.inner { Statement::Let(let_statement) => match &let_statement.inner {
LetStatement::Let { identifier, value } LetStatement::Let { identifier, value }
| LetStatement::LetMut { identifier, value } => { | LetStatement::LetMut { identifier, value } => {
let r#type = match value.type_evaluation(&self.context) { let r#type = match value.type_evaluation(&context) {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return;
} }
Ok(TypeEvaluation::Constructor(StructType::Unit { name })) => { Ok(TypeEvaluation::Constructor(StructType::Unit { name })) => {
let set_type = self.context.set_variable_type( let set_type = context.set_variable_type(
identifier.inner.clone(), identifier.inner.clone(),
Type::Struct(StructType::Unit { name }), Type::Struct(StructType::Unit { name }),
statement.position(), statement.position(),
@ -119,7 +121,7 @@ impl<'a> Analyzer<'a> {
}; };
if let Some(r#type) = r#type { if let Some(r#type) = r#type {
let set_type = self.context.set_variable_type( let set_type = context.set_variable_type(
identifier.inner.clone(), identifier.inner.clone(),
r#type.clone(), r#type.clone(),
statement.position(), statement.position(),
@ -145,7 +147,7 @@ impl<'a> Analyzer<'a> {
}, },
Statement::StructDefinition(struct_definition) => { Statement::StructDefinition(struct_definition) => {
let set_constructor_type = match &struct_definition.inner { let set_constructor_type = match &struct_definition.inner {
StructDefinition::Unit { name } => self.context.set_constructor_type( StructDefinition::Unit { name } => context.set_constructor_type(
name.inner.clone(), name.inner.clone(),
StructType::Unit { StructType::Unit {
name: name.inner.clone(), name: name.inner.clone(),
@ -155,7 +157,7 @@ impl<'a> Analyzer<'a> {
StructDefinition::Tuple { name, items } => { StructDefinition::Tuple { name, items } => {
let fields = items.iter().map(|item| item.inner.clone()).collect(); let fields = items.iter().map(|item| item.inner.clone()).collect();
self.context.set_constructor_type( context.set_constructor_type(
name.inner.clone(), name.inner.clone(),
StructType::Tuple { StructType::Tuple {
name: name.inner.clone(), name: name.inner.clone(),
@ -172,7 +174,7 @@ impl<'a> Analyzer<'a> {
}) })
.collect(); .collect();
self.context.set_constructor_type( context.set_constructor_type(
name.inner.clone(), name.inner.clone(),
StructType::Fields { StructType::Fields {
name: name.inner.clone(), name: name.inner.clone(),
@ -194,6 +196,8 @@ impl<'a> Analyzer<'a> {
} }
fn analyze_expression(&mut self, expression: &Expression, statement_position: Span) { fn analyze_expression(&mut self, expression: &Expression, statement_position: Span) {
let context = self.context_stack.top();
match expression { match expression {
Expression::Block(block_expression) => self.analyze_block(&block_expression.inner), Expression::Block(block_expression) => self.analyze_block(&block_expression.inner),
Expression::Break(break_node) => { Expression::Break(break_node) => {
@ -206,7 +210,7 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(invoker, statement_position); self.analyze_expression(invoker, statement_position);
let invoker_evaluation = match invoker.type_evaluation(&self.context) { let invoker_evaluation = match invoker.type_evaluation(&context) {
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
@ -219,7 +223,7 @@ impl<'a> Analyzer<'a> {
invoker_evaluation invoker_evaluation
{ {
for (expected_type, argument) in fields.iter().zip(arguments.iter()) { for (expected_type, argument) in fields.iter().zip(arguments.iter()) {
let actual_type = match argument.type_evaluation(&self.context) { let actual_type = match argument.type_evaluation(&context) {
Ok(evaluation) => evaluation.r#type(), Ok(evaluation) => evaluation.r#type(),
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
@ -282,7 +286,7 @@ impl<'a> Analyzer<'a> {
for ((_, expected_type), argument) in value_parameters.iter().zip(arguments) { for ((_, expected_type), argument) in value_parameters.iter().zip(arguments) {
self.analyze_expression(argument, statement_position); self.analyze_expression(argument, statement_position);
let argument_evaluation = match argument.type_evaluation(&self.context) { let argument_evaluation = match argument.type_evaluation(&context) {
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(error) => { Err(error) => {
self.errors.push(AnalysisError::AstError(error)); self.errors.push(AnalysisError::AstError(error));
@ -321,7 +325,7 @@ impl<'a> Analyzer<'a> {
let FieldAccessExpression { container, field } = let FieldAccessExpression { container, field } =
field_access_expression.inner.as_ref(); field_access_expression.inner.as_ref();
let evaluation = match container.type_evaluation(&self.context) { let evaluation = match container.type_evaluation(&context) {
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
@ -355,7 +359,8 @@ impl<'a> Analyzer<'a> {
} }
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let find_identifier = self let find_identifier = self
.context .context_stack
.top()
.update_last_position(&identifier.inner, statement_position); .update_last_position(&identifier.inner, statement_position);
if let Ok(false) = find_identifier { if let Ok(false) = find_identifier {
@ -394,7 +399,7 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(list, statement_position); self.analyze_expression(list, statement_position);
self.analyze_expression(index, statement_position); self.analyze_expression(index, statement_position);
let list_type_evaluation = match list.type_evaluation(&self.context) { let list_type_evaluation = match list.type_evaluation(&context) {
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
@ -413,7 +418,7 @@ impl<'a> Analyzer<'a> {
return; return;
} }
}; };
let index_type_evaluation = match index.type_evaluation(&self.context) { let index_type_evaluation = match index.type_evaluation(&context) {
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
@ -540,22 +545,24 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(assignee, statement_position); self.analyze_expression(assignee, statement_position);
self.analyze_expression(modifier, statement_position); self.analyze_expression(modifier, statement_position);
let assignee_type_evaluation = match assignee.type_evaluation(&self.context) { let assignee_type_evaluation =
Ok(evaluation) => evaluation, match assignee.type_evaluation(&self.context_stack.top()) {
Err(ast_error) => { Ok(evaluation) => evaluation,
self.errors.push(AnalysisError::AstError(ast_error)); Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
return; return;
} }
}; };
let modifier_type_evaluation = match modifier.type_evaluation(&self.context) { let modifier_type_evaluation =
Ok(evaluation) => evaluation, match modifier.type_evaluation(&self.context_stack.top()) {
Err(ast_error) => { Ok(evaluation) => evaluation,
self.errors.push(AnalysisError::AstError(ast_error)); Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
return; return;
} }
}; };
let (expected_type, actual_type) = match ( let (expected_type, actual_type) = match (
assignee_type_evaluation.r#type(), assignee_type_evaluation.r#type(),
@ -608,7 +615,8 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(left, statement_position); self.analyze_expression(left, statement_position);
self.analyze_expression(right, statement_position); self.analyze_expression(right, statement_position);
let left_type_evaluation = match left.type_evaluation(&self.context) { let left_type_evaluation = match left.type_evaluation(&self.context_stack.top())
{
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
@ -616,14 +624,15 @@ impl<'a> Analyzer<'a> {
return; return;
} }
}; };
let right_type_evaluation = match right.type_evaluation(&self.context) { let right_type_evaluation =
Ok(evaluation) => evaluation, match right.type_evaluation(&self.context_stack.top()) {
Err(ast_error) => { Ok(evaluation) => evaluation,
self.errors.push(AnalysisError::AstError(ast_error)); Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
return; return;
} }
}; };
let (left_type, right_type) = match ( let (left_type, right_type) = match (
left_type_evaluation.r#type(), left_type_evaluation.r#type(),
@ -704,7 +713,8 @@ impl<'a> Analyzer<'a> {
self.analyze_expression(left, statement_position); self.analyze_expression(left, statement_position);
self.analyze_expression(right, statement_position); self.analyze_expression(right, statement_position);
let left_type_evaluation = match left.type_evaluation(&self.context) { let left_type_evaluation = match left.type_evaluation(&self.context_stack.top())
{
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
@ -712,14 +722,15 @@ impl<'a> Analyzer<'a> {
return; return;
} }
}; };
let right_type_evaluation = match right.type_evaluation(&self.context) { let right_type_evaluation =
Ok(evaluation) => evaluation, match right.type_evaluation(&self.context_stack.top()) {
Err(ast_error) => { Ok(evaluation) => evaluation,
self.errors.push(AnalysisError::AstError(ast_error)); Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error));
return; return;
} }
}; };
let (left_type, right_type) = match ( let (left_type, right_type) = match (
left_type_evaluation.r#type(), left_type_evaluation.r#type(),
@ -775,7 +786,8 @@ impl<'a> Analyzer<'a> {
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
StructExpression::Fields { name, fields } => { StructExpression::Fields { name, fields } => {
let update_position = self let update_position = self
.context .context_stack
.top()
.update_last_position(&name.inner, statement_position); .update_last_position(&name.inner, statement_position);
if let Err(error) = update_position { if let Err(error) = update_position {
@ -795,7 +807,7 @@ impl<'a> Analyzer<'a> {
Expression::TupleAccess(tuple_access) => { Expression::TupleAccess(tuple_access) => {
let TupleAccessExpression { tuple, index } = tuple_access.inner.as_ref(); let TupleAccessExpression { tuple, index } = tuple_access.inner.as_ref();
let type_evaluation = match tuple.type_evaluation(&self.context) { let type_evaluation = match tuple.type_evaluation(&context) {
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));

View File

@ -5,7 +5,57 @@ use std::{
sync::{Arc, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard}, sync::{Arc, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard},
}; };
use crate::{ast::Span, Constructor, Identifier, StructType, Type, Value}; use crate::{ast::Span, core_library, Constructor, Identifier, StructType, Type, Value};
#[derive(Debug, Clone)]
pub struct ContextStack {
stack: Arc<RwLock<Vec<Context>>>,
}
impl ContextStack {
pub fn new() -> Self {
Self {
stack: Arc::new(RwLock::new(vec![Context::new()])),
}
}
pub fn with_context(context: Context) -> Self {
Self {
stack: Arc::new(RwLock::new(vec![context])),
}
}
pub fn with_core_library() -> Self {
Self::with_context(core_library().create_child())
}
pub fn push(&self) {
let mut stack = self.stack.write().unwrap();
let top = stack.last().unwrap().clone();
stack.push(top.create_child());
}
pub fn pop(&self) {
let removed = self.stack.write().unwrap().pop();
if let Some(removed) = removed {
for (identifier, _) in removed.associations.read().unwrap().iter() {
log::trace!("Dropping context with: {}", identifier);
}
}
}
pub fn top(&self) -> Context {
self.stack.read().unwrap().last().unwrap().clone()
}
}
impl Default for ContextStack {
fn default() -> Self {
Self::new()
}
}
pub type Associations = HashMap<Identifier, (ContextData, Span)>; pub type Associations = HashMap<Identifier, (ContextData, Span)>;
@ -372,10 +422,33 @@ impl Display for ContextError {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::vm::run_with_context; use crate::{parse, Analyzer, DustError, Vm};
use super::*; use super::*;
fn run_vm_with_context(source: &str, context: Context) -> Result<Option<Value>, DustError> {
let context_stack = ContextStack::with_context(context);
let abstract_syntax_tree = parse(source)?;
let mut analyzer = Analyzer::new(&abstract_syntax_tree, context_stack.clone());
analyzer.analyze();
if !analyzer.errors.is_empty() {
return Err(DustError::Analysis {
analysis_errors: analyzer.errors,
source,
});
}
let vm = Vm::new(context_stack);
vm.run(abstract_syntax_tree)
.map_err(|runtime_error| DustError::Runtime {
runtime_error,
source,
})
}
#[test] #[test]
fn context_removes_variables() { fn context_removes_variables() {
let source = " let source = "
@ -387,7 +460,7 @@ mod tests {
let context = Context::new(); let context = Context::new();
assert_eq!( assert_eq!(
run_with_context(source, context.clone()), run_vm_with_context(source, context.clone()),
Ok(Some(Value::integer(15))) Ok(Some(Value::integer(15)))
); );
@ -405,7 +478,7 @@ mod tests {
"; ";
let context = Context::new(); let context = Context::new();
run_with_context(source, context.clone()).unwrap(); run_vm_with_context(source, context.clone()).unwrap();
assert_eq!(context.association_count().unwrap(), 0); assert_eq!(context.association_count().unwrap(), 0);
} }

View File

@ -35,7 +35,7 @@ pub use analyzer::{analyze, AnalysisError, Analyzer};
pub use ast::{AbstractSyntaxTree, AstError, Expression, Node, Span, Statement}; pub use ast::{AbstractSyntaxTree, AstError, Expression, Node, Span, Statement};
pub use built_in_function::{BuiltInFunction, BuiltInFunctionError}; pub use built_in_function::{BuiltInFunction, BuiltInFunctionError};
pub use constructor::Constructor; pub use constructor::Constructor;
pub use context::{Context, ContextData, ContextError}; pub use context::{Context, ContextData, ContextError, ContextStack};
pub use core_library::core_library; pub use core_library::core_library;
pub use dust_error::DustError; pub use dust_error::DustError;
pub use evaluation::{Evaluation, TypeEvaluation}; pub use evaluation::{Evaluation, TypeEvaluation};
@ -45,4 +45,4 @@ pub use parser::{parse, ParseError, Parser};
pub use r#type::*; pub use r#type::*;
pub use token::{Token, TokenKind, TokenOwned}; pub use token::{Token, TokenKind, TokenOwned};
pub use value::*; pub use value::*;
pub use vm::{run, run_with_context, RuntimeError, Vm}; pub use vm::{run, RuntimeError, Vm};

View File

@ -15,8 +15,8 @@ use serde::{
}; };
use crate::{ use crate::{
AbstractSyntaxTree, BuiltInFunction, BuiltInFunctionError, Context, ContextError, EnumType, AbstractSyntaxTree, BuiltInFunction, BuiltInFunctionError, Context, ContextError, ContextStack,
FunctionType, Identifier, RangeableType, RuntimeError, StructType, Type, Vm, EnumType, FunctionType, Identifier, RangeableType, RuntimeError, StructType, Type, Vm,
}; };
/// Dust value representation /// Dust value representation
@ -1405,20 +1405,22 @@ impl Function {
.call(_type_arguments, value_arguments) .call(_type_arguments, value_arguments)
.map_err(FunctionCallError::BuiltInFunction), .map_err(FunctionCallError::BuiltInFunction),
Function::Parsed { r#type, body, .. } => { Function::Parsed { r#type, body, .. } => {
let new_context = let base_context = context.create_child();
Context::with_data_from(context).map_err(FunctionCallError::Context)?; let new_context_stack = ContextStack::with_context(base_context.clone());
if let (Some(value_parameters), Some(value_arguments)) = if let (Some(value_parameters), Some(value_arguments)) =
(&r#type.value_parameters, value_arguments) (&r#type.value_parameters, value_arguments)
{ {
for ((identifier, _), value) in value_parameters.iter().zip(value_arguments) { for ((identifier, _), value) in value_parameters.iter().zip(value_arguments) {
new_context base_context
.set_variable_value(identifier.clone(), value) .set_variable_value(identifier.clone(), value)
.map_err(FunctionCallError::Context)?; .map_err(FunctionCallError::Context)?;
} }
} }
let vm = Vm::new(new_context); drop(base_context);
let vm = Vm::new(new_context_stack);
vm.run(body) vm.run(body)
.map_err(|error| FunctionCallError::Runtime(Box::new(error))) .map_err(|error| FunctionCallError::Runtime(Box::new(error)))

View File

@ -21,9 +21,10 @@ use crate::{
StructDefinition, StructExpression, StructDefinition, StructExpression,
}, },
constructor::ConstructError, constructor::ConstructError,
core_library, parse, Analyzer, BuiltInFunctionError, Context, ContextData, ContextError, context::ContextStack,
DustError, Evaluation, Expression, Function, FunctionCallError, Identifier, ParseError, parse, Analyzer, BuiltInFunctionError, Context, ContextData, ContextError, DustError,
StructType, Type, Value, ValueData, ValueError, Evaluation, Expression, Function, FunctionCallError, Identifier, ParseError, StructType, Type,
Value, ValueData, ValueError,
}; };
/// Run the source code and return the result. /// Run the source code and return the result.
@ -37,28 +38,9 @@ use crate::{
/// assert_eq!(result, Ok(Some(Value::integer(42)))); /// assert_eq!(result, Ok(Some(Value::integer(42))));
/// ``` /// ```
pub fn run(source: &str) -> Result<Option<Value>, DustError> { pub fn run(source: &str) -> Result<Option<Value>, DustError> {
let context = core_library().create_child(); let context_stack = ContextStack::with_core_library();
run_with_context(source, context)
}
/// Run the source code with a context and return the result.
///
/// # Example
/// ```
/// # use dust_lang::*;
/// let context = Context::new();
///
/// context.set_variable_value(Identifier::new("foo"), Value::integer(40));
/// context.update_last_position(&Identifier::new("foo"), (100, 100));
///
/// let result = run_with_context("foo + 2", context);
///
/// assert_eq!(result, Ok(Some(Value::integer(42))));
/// ```
pub fn run_with_context(source: &str, context: Context) -> Result<Option<Value>, DustError> {
let abstract_syntax_tree = parse(source)?; let abstract_syntax_tree = parse(source)?;
let mut analyzer = Analyzer::new(&abstract_syntax_tree, context.clone()); let mut analyzer = Analyzer::new(&abstract_syntax_tree, context_stack.clone());
analyzer.analyze(); analyzer.analyze();
@ -69,7 +51,7 @@ pub fn run_with_context(source: &str, context: Context) -> Result<Option<Value>,
}); });
} }
let vm = Vm::new(context); let vm = Vm::new(context_stack);
vm.run(abstract_syntax_tree) vm.run(abstract_syntax_tree)
.map_err(|runtime_error| DustError::Runtime { .map_err(|runtime_error| DustError::Runtime {
@ -86,12 +68,12 @@ pub fn run_with_context(source: &str, context: Context) -> Result<Option<Value>,
/// ///
/// See the `run_with_context` function for an example of how to use the Analyzer and the VM. /// See the `run_with_context` function for an example of how to use the Analyzer and the VM.
pub struct Vm { pub struct Vm {
context: Context, context_stack: ContextStack,
} }
impl Vm { impl Vm {
pub fn new(context: Context) -> Self { pub fn new(context_stack: ContextStack) -> Self {
Self { context } Self { context_stack }
} }
pub fn run(&self, mut tree: AbstractSyntaxTree) -> Result<Option<Value>, RuntimeError> { pub fn run(&self, mut tree: AbstractSyntaxTree) -> Result<Option<Value>, RuntimeError> {
@ -209,7 +191,8 @@ impl Vm {
}; };
let constructor = struct_type.constructor(); let constructor = struct_type.constructor();
self.context self.context_stack
.top()
.set_constructor(name, constructor) .set_constructor(name, constructor)
.map_err(|error| RuntimeError::ContextError { .map_err(|error| RuntimeError::ContextError {
error, error,
@ -221,7 +204,8 @@ impl Vm {
}; };
if collect_garbage { if collect_garbage {
self.context self.context_stack
.top()
.collect_garbage(position.1) .collect_garbage(position.1)
.map_err(|error| RuntimeError::ContextError { error, position })?; .map_err(|error| RuntimeError::ContextError { error, position })?;
} }
@ -250,7 +234,8 @@ impl Vm {
_ => value, _ => value,
}; };
self.context self.context_stack
.top()
.set_variable_value(identifier.inner, new_value) .set_variable_value(identifier.inner, new_value)
.map_err(|error| RuntimeError::ContextError { error, position })?; .map_err(|error| RuntimeError::ContextError { error, position })?;
@ -263,7 +248,8 @@ impl Vm {
.expect_value(position)? .expect_value(position)?
.into_mutable(); .into_mutable();
self.context self.context_stack
.top()
.set_variable_value(identifier.inner, mutable_value) .set_variable_value(identifier.inner, mutable_value)
.map_err(|error| RuntimeError::ContextError { error, position })?; .map_err(|error| RuntimeError::ContextError { error, position })?;
@ -364,12 +350,14 @@ impl Vm {
} }
fn run_identifier(&self, identifier: Node<Identifier>) -> Result<Evaluation, RuntimeError> { fn run_identifier(&self, identifier: Node<Identifier>) -> Result<Evaluation, RuntimeError> {
let get_data = self.context.get_data(&identifier.inner).map_err(|error| { let get_data = self
RuntimeError::ContextError { .context_stack
.top()
.get_data(&identifier.inner)
.map_err(|error| RuntimeError::ContextError {
error, error,
position: identifier.position, position: identifier.position,
} })?;
})?;
if let Some(ContextData::VariableValue(value)) = get_data { if let Some(ContextData::VariableValue(value)) = get_data {
return Ok(Evaluation::Return(Some(value))); return Ok(Evaluation::Return(Some(value)));
@ -403,7 +391,8 @@ impl Vm {
let position = name.position; let position = name.position;
let constructor = self let constructor = self
.context .context_stack
.top()
.get_constructor(&name.inner) .get_constructor(&name.inner)
.map_err(|error| RuntimeError::ContextError { error, position })?; .map_err(|error| RuntimeError::ContextError { error, position })?;
@ -1020,18 +1009,17 @@ impl Vm {
block: BlockExpression, block: BlockExpression,
collect_garbage: bool, collect_garbage: bool,
) -> Result<Evaluation, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
let block_context = self.context.create_child(); self.context_stack.push();
let vm = Vm::new(block_context);
match block { let evaluation = match block {
BlockExpression::Async(statements) => vm BlockExpression::Async(statements) => self
.run_async(AbstractSyntaxTree::with_statements(statements)) .run_async(AbstractSyntaxTree::with_statements(statements))
.map(Evaluation::Return), .map(Evaluation::Return),
BlockExpression::Sync(statements) => { BlockExpression::Sync(statements) => {
let mut evaluation = Evaluation::Return(None); let mut evaluation = Evaluation::Return(None);
for statement in statements { for statement in statements {
evaluation = vm.run_statement(statement, collect_garbage)?; evaluation = self.run_statement(statement, collect_garbage)?;
if let Evaluation::Break(_) = evaluation { if let Evaluation::Break(_) = evaluation {
return Ok(evaluation); return Ok(evaluation);
@ -1040,7 +1028,11 @@ impl Vm {
Ok(evaluation) Ok(evaluation)
} }
} };
self.context_stack.pop();
evaluation
} }
fn run_if( fn run_if(