From 012728b00a9f6247609c2839162bccc779a56f62 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 30 Aug 2024 18:06:58 -0400 Subject: [PATCH] Try embedding contexts in the AST --- dust-lang/src/analyzer.rs | 196 +++++++++++++----------- dust-lang/src/ast/expression.rs | 24 +-- dust-lang/src/ast/mod.rs | 29 +++- dust-lang/src/context.rs | 44 +++--- dust-lang/src/lib.rs | 2 +- dust-lang/src/parser.rs | 192 +++++++++++++---------- dust-lang/src/value.rs | 4 +- dust-lang/src/vm.rs | 261 ++++++++++++++++---------------- 8 files changed, 405 insertions(+), 347 deletions(-) diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index 52aca99..a6f99c3 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -17,8 +17,8 @@ use crate::{ PrimitiveValueExpression, RangeExpression, Span, Statement, StructDefinition, StructExpression, TupleAccessExpression, }, - core_library, parse, Context, ContextError, DustError, Expression, Identifier, RangeableType, - StructType, Type, TypeConflict, TypeEvaluation, + parse, ContextError, DustError, Expression, Identifier, RangeableType, StructType, Type, + TypeConflict, TypeEvaluation, }; /// Analyzes the abstract syntax tree for errors. @@ -34,8 +34,7 @@ use crate::{ /// ``` pub fn analyze(source: &str) -> Result<(), DustError> { let abstract_tree = parse(source)?; - let context = core_library().create_child(); - let mut analyzer = Analyzer::new(&abstract_tree, context); + let mut analyzer = Analyzer::new(&abstract_tree); analyzer.analyze(); @@ -61,15 +60,13 @@ pub fn analyze(source: &str) -> Result<(), DustError> { /// assert!(!analyzer.errors.is_empty()); pub struct Analyzer<'a> { abstract_tree: &'a AbstractSyntaxTree, - context: Context, pub errors: Vec, } impl<'a> Analyzer<'a> { - pub fn new(abstract_tree: &'a AbstractSyntaxTree, context: Context) -> Self { + pub fn new(abstract_tree: &'a AbstractSyntaxTree) -> Self { Self { abstract_tree, - context, errors: Vec::new(), } } @@ -91,14 +88,14 @@ impl<'a> Analyzer<'a> { Statement::Let(let_statement) => match &let_statement.inner { LetStatement::Let { identifier, value } | LetStatement::LetMut { identifier, value } => { - let r#type = match value.type_evaluation(&self.context) { + let r#type = match value.type_evaluation(&self.abstract_tree.context) { Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); return; } Ok(TypeEvaluation::Constructor(StructType::Unit { name })) => { - let set_type = self.context.set_variable_type( + let set_type = self.abstract_tree.context.set_variable_type( identifier.inner.clone(), Type::Struct(StructType::Unit { name }), statement.position(), @@ -119,7 +116,7 @@ impl<'a> Analyzer<'a> { }; if let Some(r#type) = r#type { - let set_type = self.context.set_variable_type( + let set_type = self.abstract_tree.context.set_variable_type( identifier.inner.clone(), r#type.clone(), statement.position(), @@ -145,17 +142,19 @@ impl<'a> Analyzer<'a> { }, Statement::StructDefinition(struct_definition) => { let set_constructor_type = match &struct_definition.inner { - StructDefinition::Unit { name } => self.context.set_constructor_type( - name.inner.clone(), - StructType::Unit { - name: name.inner.clone(), - }, - statement.position(), - ), + StructDefinition::Unit { name } => { + self.abstract_tree.context.set_constructor_type( + name.inner.clone(), + StructType::Unit { + name: name.inner.clone(), + }, + statement.position(), + ) + } StructDefinition::Tuple { name, items } => { let fields = items.iter().map(|item| item.inner.clone()).collect(); - self.context.set_constructor_type( + self.abstract_tree.context.set_constructor_type( name.inner.clone(), StructType::Tuple { name: name.inner.clone(), @@ -172,7 +171,7 @@ impl<'a> Analyzer<'a> { }) .collect(); - self.context.set_constructor_type( + self.abstract_tree.context.set_constructor_type( name.inner.clone(), StructType::Fields { name: name.inner.clone(), @@ -206,7 +205,8 @@ impl<'a> Analyzer<'a> { self.analyze_expression(invoker, statement_position); - let invoker_evaluation = match invoker.type_evaluation(&self.context) { + let invoker_evaluation = match invoker.type_evaluation(&self.abstract_tree.context) + { Ok(evaluation) => evaluation, Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); @@ -219,14 +219,15 @@ impl<'a> Analyzer<'a> { invoker_evaluation { for (expected_type, argument) in fields.iter().zip(arguments.iter()) { - let actual_type = match argument.type_evaluation(&self.context) { - Ok(evaluation) => evaluation.r#type(), - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); + let actual_type = + match argument.type_evaluation(&self.abstract_tree.context) { + Ok(evaluation) => evaluation.r#type(), + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - }; + return; + } + }; if let Some(r#type) = actual_type { let check = expected_type.check(&r#type); @@ -282,14 +283,15 @@ impl<'a> Analyzer<'a> { for ((_, expected_type), argument) in value_parameters.iter().zip(arguments) { self.analyze_expression(argument, statement_position); - let argument_evaluation = match argument.type_evaluation(&self.context) { - Ok(evaluation) => evaluation, - Err(error) => { - self.errors.push(AnalysisError::AstError(error)); + let argument_evaluation = + match argument.type_evaluation(&self.abstract_tree.context) { + Ok(evaluation) => evaluation, + Err(error) => { + self.errors.push(AnalysisError::AstError(error)); - continue; - } - }; + continue; + } + }; let actual_type = if let Some(r#type) = argument_evaluation.r#type() { r#type @@ -321,7 +323,7 @@ impl<'a> Analyzer<'a> { let FieldAccessExpression { container, field } = field_access_expression.inner.as_ref(); - let evaluation = match container.type_evaluation(&self.context) { + let evaluation = match container.type_evaluation(&self.abstract_tree.context) { Ok(evaluation) => evaluation, Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); @@ -355,6 +357,7 @@ impl<'a> Analyzer<'a> { } Expression::Identifier(identifier) => { let find_identifier = self + .abstract_tree .context .update_last_position(&identifier.inner, statement_position); @@ -394,7 +397,7 @@ impl<'a> Analyzer<'a> { self.analyze_expression(list, 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(&self.abstract_tree.context) { Ok(evaluation) => evaluation, Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); @@ -413,7 +416,8 @@ impl<'a> Analyzer<'a> { return; } }; - let index_type_evaluation = match index.type_evaluation(&self.context) { + let index_type_evaluation = match index.type_evaluation(&self.abstract_tree.context) + { Ok(evaluation) => evaluation, Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); @@ -540,22 +544,24 @@ impl<'a> Analyzer<'a> { self.analyze_expression(assignee, statement_position); self.analyze_expression(modifier, statement_position); - let assignee_type_evaluation = match assignee.type_evaluation(&self.context) { - Ok(evaluation) => evaluation, - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); + let assignee_type_evaluation = + match assignee.type_evaluation(&self.abstract_tree.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - }; - let modifier_type_evaluation = match modifier.type_evaluation(&self.context) { - Ok(evaluation) => evaluation, - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); + return; + } + }; + let modifier_type_evaluation = + match modifier.type_evaluation(&self.abstract_tree.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - }; + return; + } + }; let (expected_type, actual_type) = match ( assignee_type_evaluation.r#type(), @@ -608,22 +614,24 @@ impl<'a> Analyzer<'a> { self.analyze_expression(left, statement_position); self.analyze_expression(right, statement_position); - let left_type_evaluation = match left.type_evaluation(&self.context) { - Ok(evaluation) => evaluation, - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); + let left_type_evaluation = + match left.type_evaluation(&self.abstract_tree.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - }; - let right_type_evaluation = match right.type_evaluation(&self.context) { - Ok(evaluation) => evaluation, - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); + return; + } + }; + let right_type_evaluation = + match right.type_evaluation(&self.abstract_tree.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - }; + return; + } + }; let (left_type, right_type) = match ( left_type_evaluation.r#type(), @@ -704,22 +712,24 @@ impl<'a> Analyzer<'a> { self.analyze_expression(left, statement_position); self.analyze_expression(right, statement_position); - let left_type_evaluation = match left.type_evaluation(&self.context) { - Ok(evaluation) => evaluation, - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); + let left_type_evaluation = + match left.type_evaluation(&self.abstract_tree.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - }; - let right_type_evaluation = match right.type_evaluation(&self.context) { - Ok(evaluation) => evaluation, - Err(ast_error) => { - self.errors.push(AnalysisError::AstError(ast_error)); + return; + } + }; + let right_type_evaluation = + match right.type_evaluation(&self.abstract_tree.context) { + Ok(evaluation) => evaluation, + Err(ast_error) => { + self.errors.push(AnalysisError::AstError(ast_error)); - return; - } - }; + return; + } + }; let (left_type, right_type) = match ( left_type_evaluation.r#type(), @@ -775,6 +785,7 @@ impl<'a> Analyzer<'a> { Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { StructExpression::Fields { name, fields } => { let update_position = self + .abstract_tree .context .update_last_position(&name.inner, statement_position); @@ -795,7 +806,7 @@ impl<'a> Analyzer<'a> { Expression::TupleAccess(tuple_access) => { 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(&self.abstract_tree.context) { Ok(evaluation) => evaluation, Err(ast_error) => { self.errors.push(AnalysisError::AstError(ast_error)); @@ -840,18 +851,19 @@ impl<'a> Analyzer<'a> { } fn analyze_block(&mut self, block_expression: &BlockExpression) { - match block_expression { - BlockExpression::Async(statements) => { - for statement in statements { - self.analyze_statement(statement); - } - } - BlockExpression::Sync(statements) => { - for statement in statements { - self.analyze_statement(statement); - } - } - } + let ast = match block_expression { + BlockExpression::Async(ast) => ast, + BlockExpression::Sync(ast) => ast, + }; + + ast.context + .assign_parent(self.abstract_tree.context.clone()); + + let mut analyzer = Analyzer::new(ast); + + analyzer.analyze(); + + self.errors.append(&mut analyzer.errors); } fn analyze_if(&mut self, if_expression: &IfExpression, statement_position: Span) { diff --git a/dust-lang/src/ast/expression.rs b/dust-lang/src/ast/expression.rs index 932c79a..05665f9 100644 --- a/dust-lang/src/ast/expression.rs +++ b/dust-lang/src/ast/expression.rs @@ -1,6 +1,6 @@ use std::{ cmp::Ordering, - collections::{HashMap, VecDeque}, + collections::HashMap, fmt::{self, Display, Formatter}, }; @@ -11,7 +11,7 @@ use crate::{ TypeEvaluation, ValueData, }; -use super::{AstError, Node, Span, Statement}; +use super::{AbstractSyntaxTree, AstError, Node, Span}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum Expression { @@ -1139,16 +1139,16 @@ impl Display for ElseExpression { #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum BlockExpression { - Async(VecDeque), - Sync(VecDeque), + Async(AbstractSyntaxTree), + Sync(AbstractSyntaxTree), } impl BlockExpression { - fn type_evaluation(&self, context: &Context) -> Result { + fn type_evaluation(&self, _: &Context) -> Result { match self { - BlockExpression::Async(statements) | BlockExpression::Sync(statements) => { - if let Some(statement) = statements.back() { - statement.type_evaluation(context) + BlockExpression::Async(ast) | BlockExpression::Sync(ast) => { + if let Some(statement) = ast.statements.back() { + statement.type_evaluation(&ast.context) } else { Ok(TypeEvaluation::Return(None)) } @@ -1160,10 +1160,10 @@ impl BlockExpression { impl Display for BlockExpression { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - BlockExpression::Async(statements) => { + BlockExpression::Async(ast) => { write!(f, "async {{ ")?; - for (i, statement) in statements.iter().enumerate() { + for (i, statement) in ast.statements.iter().enumerate() { if i > 0 { write!(f, " ")?; } @@ -1173,10 +1173,10 @@ impl Display for BlockExpression { write!(f, " }}") } - BlockExpression::Sync(statements) => { + BlockExpression::Sync(ast) => { write!(f, "{{ ")?; - for (i, statement) in statements.iter().enumerate() { + for (i, statement) in ast.statements.iter().enumerate() { if i > 0 { write!(f, " ")?; } diff --git a/dust-lang/src/ast/mod.rs b/dust-lang/src/ast/mod.rs index b980fd9..4aab44e 100644 --- a/dust-lang/src/ast/mod.rs +++ b/dust-lang/src/ast/mod.rs @@ -13,26 +13,51 @@ use std::{ use serde::{Deserialize, Serialize}; -use crate::ContextError; +use crate::{Context, ContextError}; pub type Span = (usize, usize); /// In-memory representation of a Dust program. -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct AbstractSyntaxTree { pub statements: VecDeque, + + #[serde(skip)] + pub context: Context, +} + +impl Eq for AbstractSyntaxTree {} + +impl PartialEq for AbstractSyntaxTree { + fn eq(&self, other: &Self) -> bool { + self.statements == other.statements + } +} + +impl PartialOrd for AbstractSyntaxTree { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for AbstractSyntaxTree { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.statements.cmp(&other.statements) + } } impl AbstractSyntaxTree { pub fn new() -> Self { Self { statements: VecDeque::new(), + context: Context::new(), } } pub fn with_statements>>(statements: T) -> Self { Self { statements: statements.into(), + context: Context::new(), } } } diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index ed32ad1..207bdf7 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -13,7 +13,7 @@ pub type Associations = HashMap; #[derive(Debug, Clone)] pub struct Context { associations: Arc>, - parent: Option>, + parent: Arc>>, } impl Context { @@ -24,7 +24,7 @@ impl Context { pub fn with_data(data: Associations) -> Self { Self { associations: Arc::new(RwLock::new(data)), - parent: None, + parent: Arc::new(RwLock::new(None)), } } @@ -36,10 +36,14 @@ impl Context { pub fn create_child(&self) -> Self { Self { associations: Arc::new(RwLock::new(HashMap::new())), - parent: Some(Box::new(self.clone())), + parent: Arc::new(RwLock::new(Some(self.clone()))), } } + pub fn assign_parent(&self, parent: Self) { + self.parent.write().unwrap().replace(parent); + } + /// Returns the number of associated identifiers in the context. pub fn association_count(&self) -> Result { Ok(self.associations.read()?.len()) @@ -49,7 +53,7 @@ impl Context { pub fn contains(&self, identifier: &Identifier) -> Result { if self.associations.read()?.contains_key(identifier) { Ok(true) - } else if let Some(parent) = &self.parent { + } else if let Some(parent) = self.parent.read().unwrap().as_ref() { parent.contains(identifier) } else { Ok(false) @@ -77,7 +81,7 @@ impl Context { _ => {} } - if let Some(parent) = &self.parent { + if let Some(parent) = self.parent.read().unwrap().as_ref() { parent.get_type(identifier) } else { Ok(None) @@ -88,7 +92,7 @@ impl Context { pub fn get_data(&self, identifier: &Identifier) -> Result, ContextError> { if let Some((variable_data, _)) = self.associations.read()?.get(identifier) { Ok(Some(variable_data.clone())) - } else if let Some(parent) = &self.parent { + } else if let Some(parent) = self.parent.read().unwrap().as_ref() { parent.get_data(identifier) } else { Ok(None) @@ -104,7 +108,7 @@ impl Context { self.associations.read()?.get(identifier) { Ok(Some(value.clone())) - } else if let Some(parent) = &self.parent { + } else if let Some(parent) = self.parent.read().unwrap().as_ref() { parent.get_variable_value(identifier) } else { Ok(None) @@ -120,7 +124,7 @@ impl Context { self.associations.read()?.get(identifier) { Ok(Some(constructor.clone())) - } else if let Some(parent) = &self.parent { + } else if let Some(parent) = self.parent.read().unwrap().as_ref() { parent.get_constructor(identifier) } else { Ok(None) @@ -140,7 +144,7 @@ impl Context { ContextData::ConstructorType(struct_type) => Ok(Some(struct_type.clone())), _ => Ok(None), } - } else if let Some(parent) = &self.parent { + } else if let Some(parent) = self.parent.read().unwrap().as_ref() { parent.get_constructor_type(identifier) } else { Ok(None) @@ -285,7 +289,7 @@ impl Context { log::trace!("Updating {identifier}'s last position to {position:?}"); Ok(true) - } else if let Some(parent) = &self.parent { + } else if let Some(parent) = self.parent.read().unwrap().as_ref() { parent.contains(identifier) } else { Ok(false) @@ -372,7 +376,7 @@ impl Display for ContextError { #[cfg(test)] mod tests { - use crate::vm::run_with_context; + use crate::{parse, run, Vm}; use super::*; @@ -384,29 +388,25 @@ mod tests { let z = x + y; z "; - let context = Context::new(); - - assert_eq!( - run_with_context(source, context.clone()), - Ok(Some(Value::integer(15))) - ); + let ast = parse(source).unwrap(); + let context = ast.context.clone(); + assert_eq!(Vm.run(ast), Ok(Some(Value::integer(15)))); assert_eq!(context.association_count().unwrap(), 0); } #[test] fn garbage_collector_does_not_break_loops() { let source = " - let y = 1; let mut z = 0; while z < 10 { - z = z + y + z += 1; } "; - let context = Context::new(); - - run_with_context(source, context.clone()).unwrap(); + let ast = parse(source).unwrap(); + let context = ast.context.clone(); + assert_eq!(Vm.run(ast), Ok(None)); assert_eq!(context.association_count().unwrap(), 0); } } diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index e5e0159..2556826 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -45,4 +45,4 @@ pub use parser::{parse, ParseError, Parser}; pub use r#type::*; pub use token::{Token, TokenKind, TokenOwned}; pub use value::*; -pub use vm::{run, run_with_context, RuntimeError, Vm}; +pub use vm::{run, RuntimeError, Vm}; diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 790de83..ffaf8c9 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -10,7 +10,9 @@ use std::{ str::ParseBoolError, }; -use crate::{ast::*, DustError, Identifier, LexError, Lexer, Token, TokenKind, TokenOwned, Type}; +use crate::{ + ast::*, Context, DustError, Identifier, LexError, Lexer, Token, TokenKind, TokenOwned, Type, +}; /// Parses the input into an abstract syntax tree. /// @@ -96,6 +98,7 @@ pub struct Parser<'src> { current_token: Token<'src>, current_position: Span, mode: ParserMode, + context: Context, } impl<'src> Parser<'src> { @@ -107,6 +110,7 @@ impl<'src> Parser<'src> { current_token, current_position, mode: ParserMode::Normal, + context: Context::new(), } } @@ -1011,10 +1015,15 @@ impl<'src> Parser<'src> { self.next_token()?; + let ast = AbstractSyntaxTree { + statements, + context: self.context.create_child(), + }; + return if is_async { - Ok(Node::new(BlockExpression::Async(statements), position)) + Ok(Node::new(BlockExpression::Async(ast), position)) } else { - Ok(Node::new(BlockExpression::Sync(statements), position)) + Ok(Node::new(BlockExpression::Sync(ast), position)) }; } @@ -1201,9 +1210,12 @@ mod tests { Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::infinite_loop( Node::new( - BlockExpression::Sync(VecDeque::from([Statement::ExpressionNullified( - Node::new(Expression::r#break(None, (7, 12)), (7, 13)) - )])), + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::ExpressionNullified(Node::new( + Expression::r#break(None, (7, 12)), + (7, 13) + )) + ])), (5, 15) ), (0, 15) @@ -1238,8 +1250,8 @@ mod tests { assert_eq!( parse(source), - Ok(AbstractSyntaxTree { - statements: [Statement::Expression(Expression::map( + Ok(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::map( vec![ ( Node::new(Identifier::new("x"), (6, 7)), @@ -1255,9 +1267,8 @@ mod tests { ), ], (0, 31), - ))] - .into(), - }) + )) + ])) ); } @@ -1267,42 +1278,39 @@ mod tests { assert_eq!( parse(source), - Ok(AbstractSyntaxTree { - statements: [ - Statement::Let(Node::new( - LetStatement::LetMut { - identifier: Node::new(Identifier::new("x"), (8, 9)), - value: Expression::literal(0, (12, 13)), - }, - (0, 14), - )), - Statement::ExpressionNullified(Node::new( - Expression::while_loop( - Expression::comparison( - Expression::identifier(Identifier::new("x"), (21, 22)), - Node::new(ComparisonOperator::LessThan, (23, 24)), - Expression::literal(10, (25, 27)), - (21, 27), - ), - Node::new( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::compound_assignment( - Expression::identifier(Identifier::new("x"), (30, 31)), - Node::new(MathOperator::Add, (32, 34)), - Expression::literal(1, (35, 36)), - (30, 36), - ), - )])), - (28, 38), - ), - (15, 38), + Ok(AbstractSyntaxTree::with_statements([ + Statement::Let(Node::new( + LetStatement::LetMut { + identifier: Node::new(Identifier::new("x"), (8, 9)), + value: Expression::literal(0, (12, 13)), + }, + (0, 14), + )), + Statement::ExpressionNullified(Node::new( + Expression::while_loop( + Expression::comparison( + Expression::identifier(Identifier::new("x"), (21, 22)), + Node::new(ComparisonOperator::LessThan, (23, 24)), + Expression::literal(10, (25, 27)), + (21, 27), ), - (15, 39) - )), - Statement::Expression(Expression::identifier(Identifier::new("x"), (40, 41)),), - ] - .into() - }) + Node::new( + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::compound_assignment( + Expression::identifier(Identifier::new("x"), (30, 31)), + Node::new(MathOperator::Add, (32, 34)), + Expression::literal(1, (35, 36)), + (30, 36), + ),) + ])), + (28, 38), + ), + (15, 38), + ), + (15, 39) + )), + Statement::Expression(Expression::identifier(Identifier::new("x"), (40, 41)),), + ])) ); } @@ -1330,16 +1338,15 @@ mod tests { assert_eq!( parse(source), - Ok(AbstractSyntaxTree { - statements: [Statement::Let(Node::new( + Ok(AbstractSyntaxTree::with_statements([Statement::Let( + Node::new( LetStatement::LetMut { identifier: Node::new(Identifier::new("x"), (8, 9)), value: Expression::literal(false, (12, 17)), }, (0, 18), - ))] - .into() - }) + ) + )])) ); } @@ -1349,9 +1356,9 @@ mod tests { assert_eq!( parse(source), - Ok(AbstractSyntaxTree { - statements: [Statement::Expression(Expression::block( - BlockExpression::Async(VecDeque::from([ + Ok(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::block( + BlockExpression::Async(AbstractSyntaxTree::with_statements([ Statement::ExpressionNullified(Node::new( Expression::operator( OperatorExpression::Assignment { @@ -1371,9 +1378,8 @@ mod tests { )) ])), (0, 25) - ))] - .into() - }) + )) + ])) ); } @@ -1668,9 +1674,12 @@ mod tests { IfExpression::If { condition: Expression::identifier(Identifier::new("x"), (3, 4)), if_block: Node::new( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::identifier(Identifier::new("y"), (7, 8)) - )])), + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::identifier( + Identifier::new("y"), + (7, 8) + )) + ])), (5, 10) ) }, @@ -1691,15 +1700,21 @@ mod tests { IfExpression::IfElse { condition: Expression::identifier(Identifier::new("x"), (3, 4)), if_block: Node::new( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::identifier(Identifier::new("y"), (7, 8)) - )])), + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::identifier( + Identifier::new("y"), + (7, 8) + )) + ])), (5, 10) ), r#else: ElseExpression::Block(Node::new( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::identifier(Identifier::new("z"), (18, 19)) - )])), + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::identifier( + Identifier::new("z"), + (18, 19) + )) + ])), (16, 21) )) }, @@ -1720,24 +1735,33 @@ mod tests { IfExpression::IfElse { condition: Expression::identifier(Identifier::new("x"), (3, 4)), if_block: Node::new( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::identifier(Identifier::new("y"), (7, 8)) - )])), + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::identifier( + Identifier::new("y"), + (7, 8) + )) + ])), (5, 10) ), r#else: ElseExpression::If(Node::new( Box::new(IfExpression::IfElse { condition: Expression::identifier(Identifier::new("z"), (19, 20)), if_block: Node::new( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::identifier(Identifier::new("a"), (23, 24)) - )])), + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::identifier( + Identifier::new("a"), + (23, 24) + )) + ])), (21, 26) ), r#else: ElseExpression::Block(Node::new( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::identifier(Identifier::new("b"), (34, 35)) - )])), + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::identifier( + Identifier::new("b"), + (34, 35) + )) + ])), (32, 37) )), }), @@ -1767,8 +1791,8 @@ mod tests { (6, 12) ), Node::new( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::operator( + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::operator( OperatorExpression::CompoundAssignment { assignee: Expression::identifier( Identifier::new("x"), @@ -1778,8 +1802,8 @@ mod tests { modifier: Expression::literal(1, (20, 21)), }, (15, 21) - ) - )])), + )) + ])), (13, 23) ), (0, 23) @@ -1834,16 +1858,16 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::block( - BlockExpression::Sync(VecDeque::from([Statement::Expression( - Expression::operator( + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ + Statement::Expression(Expression::operator( OperatorExpression::Math { left: Expression::literal(40, (2, 4)), operator: Node::new(MathOperator::Add, (5, 6)), right: Expression::literal(2, (7, 8)), }, (2, 8) - ) - )])), + )) + ])), (0, 10) )) ])) @@ -1858,7 +1882,7 @@ mod tests { parse(source), Ok(AbstractSyntaxTree::with_statements([ Statement::Expression(Expression::block( - BlockExpression::Sync(VecDeque::from([ + BlockExpression::Sync(AbstractSyntaxTree::with_statements([ Statement::ExpressionNullified(Node::new( Expression::assignment( Expression::identifier("foo", (2, 5)), diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index c6827cb..767928b 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -1418,9 +1418,7 @@ impl Function { } } - let vm = Vm::new(new_context); - - vm.run(body) + Vm.run(body) .map_err(|error| FunctionCallError::Runtime(Box::new(error))) } } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 375aaeb..723c7d9 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -37,28 +37,8 @@ use crate::{ /// assert_eq!(result, Ok(Some(Value::integer(42)))); /// ``` pub fn run(source: &str) -> Result, DustError> { - let context = core_library().create_child(); - - 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, DustError> { let abstract_syntax_tree = parse(source)?; - let mut analyzer = Analyzer::new(&abstract_syntax_tree, context.clone()); + let mut analyzer = Analyzer::new(&abstract_syntax_tree); analyzer.analyze(); @@ -69,9 +49,7 @@ pub fn run_with_context(source: &str, context: Context) -> Result, }); } - let vm = Vm::new(context); - - vm.run(abstract_syntax_tree) + Vm.run(abstract_syntax_tree) .map_err(|runtime_error| DustError::Runtime { runtime_error, source, @@ -85,20 +63,14 @@ pub fn run_with_context(source: &str, context: Context) -> Result, /// before running it. /// /// See the `run_with_context` function for an example of how to use the Analyzer and the VM. -pub struct Vm { - context: Context, -} +pub struct Vm; impl Vm { - pub fn new(context: Context) -> Self { - Self { context } - } - pub fn run(&self, mut tree: AbstractSyntaxTree) -> Result, RuntimeError> { let mut previous_evaluation = Evaluation::Return(None); while let Some(statement) = tree.statements.pop_front() { - previous_evaluation = self.run_statement(statement, true)?; + previous_evaluation = self.run_statement(statement, &tree.context, true)?; } match previous_evaluation { @@ -117,7 +89,7 @@ impl Vm { .into_par_iter() .enumerate() .find_map_any(|(i, statement)| { - let evaluation_result = self.run_statement(statement, false); + let evaluation_result = self.run_statement(statement, &tree.context, false); match evaluation_result { Ok(evaluation_option) => { @@ -134,21 +106,22 @@ impl Vm { }); if let Some(error) = error_option { - Err(error) - } else { - let final_result = final_result.lock().unwrap(); + return Err(error); + } - match &*final_result { - Evaluation::Break(value_option) => Ok(value_option.clone()), - Evaluation::Return(value_option) => Ok(value_option.clone()), - _ => Ok(None), - } + let final_result = final_result.lock().unwrap(); + + match &*final_result { + Evaluation::Break(value_option) => Ok(value_option.clone()), + Evaluation::Return(value_option) => Ok(value_option.clone()), + _ => Ok(None), } } fn run_statement( &self, statement: Statement, + context: &Context, collect_garbage: bool, ) -> Result { log::trace!( @@ -160,10 +133,10 @@ impl Vm { let position = statement.position(); let result = match statement { Statement::Expression(expression) => { - Ok(self.run_expression(expression, collect_garbage)?) + Ok(self.run_expression(expression, context, collect_garbage)?) } Statement::ExpressionNullified(expression) => { - let evaluation = self.run_expression(expression.inner, collect_garbage)?; + let evaluation = self.run_expression(expression.inner, context, collect_garbage)?; if let Evaluation::Break(_) = evaluation { Ok(evaluation) @@ -172,7 +145,7 @@ impl Vm { } } Statement::Let(let_statement) => { - self.run_let_statement(let_statement.inner, collect_garbage)?; + self.run_let_statement(let_statement.inner, context, collect_garbage)?; Ok(Evaluation::Return(None)) } @@ -209,7 +182,7 @@ impl Vm { }; let constructor = struct_type.constructor(); - self.context + context .set_constructor(name, constructor) .map_err(|error| RuntimeError::ContextError { error, @@ -221,7 +194,7 @@ impl Vm { }; if collect_garbage { - self.context + context .collect_garbage(position.1) .map_err(|error| RuntimeError::ContextError { error, position })?; } @@ -235,13 +208,14 @@ impl Vm { fn run_let_statement( &self, let_statement: LetStatement, + context: &Context, collect_garbage: bool, ) -> Result<(), RuntimeError> { match let_statement { LetStatement::Let { identifier, value } => { let position = value.position(); let value = self - .run_expression(value, collect_garbage)? + .run_expression(value, context, collect_garbage)? .expect_value(position)?; let new_value = match value { Value::Mutable(_) => { @@ -250,7 +224,7 @@ impl Vm { _ => value, }; - self.context + context .set_variable_value(identifier.inner, new_value) .map_err(|error| RuntimeError::ContextError { error, position })?; @@ -259,11 +233,11 @@ impl Vm { LetStatement::LetMut { identifier, value } => { let position = value.position(); let mutable_value = self - .run_expression(value, collect_garbage)? + .run_expression(value, context, collect_garbage)? .expect_value(position)? .into_mutable(); - self.context + context .set_variable_value(identifier.inner, mutable_value) .map_err(|error| RuntimeError::ContextError { error, position })?; @@ -277,6 +251,7 @@ impl Vm { fn run_expression( &self, expression: Expression, + context: &Context, collect_garbage: bool, ) -> Result { log::trace!( @@ -287,14 +262,16 @@ impl Vm { let position = expression.position(); let evaluation_result = match expression { - Expression::Block(Node { inner, .. }) => self.run_block(*inner, collect_garbage), + Expression::Block(Node { inner, .. }) => { + self.run_block(*inner, context, collect_garbage) + } Expression::Break(Node { inner, .. }) => { let break_expression = if let Some(expression) = inner { *expression } else { return Ok(Evaluation::Break(None)); }; - let run_break = self.run_expression(break_expression, collect_garbage)?; + let run_break = self.run_expression(break_expression, context, collect_garbage)?; let evaluation = match run_break { Evaluation::Break(value_option) => Evaluation::Break(value_option), Evaluation::Return(value_option) => Evaluation::Break(value_option), @@ -305,9 +282,9 @@ impl Vm { Ok(evaluation) } - Expression::Call(call) => self.run_call(*call.inner, collect_garbage), + Expression::Call(call) => self.run_call(*call.inner, context, collect_garbage), Expression::Dereference(Node { inner, .. }) => { - let run_expression = self.run_expression(*inner, collect_garbage)?; + let run_expression = self.run_expression(*inner, context, collect_garbage)?; let evaluation = match run_expression { Evaluation::Constructor(_) => { return Err(RuntimeError::ExpectedValue { position }) @@ -323,30 +300,34 @@ impl Vm { Ok(evaluation) } Expression::FieldAccess(field_access) => { - self.run_field_access(*field_access.inner, collect_garbage) + self.run_field_access(*field_access.inner, context, collect_garbage) } Expression::Grouped(expression) => { - self.run_expression(*expression.inner, collect_garbage) + self.run_expression(*expression.inner, context, collect_garbage) + } + Expression::Identifier(identifier) => self.run_identifier(identifier, context), + Expression::If(if_expression) => { + self.run_if(*if_expression.inner, context, collect_garbage) } - Expression::Identifier(identifier) => self.run_identifier(identifier), - Expression::If(if_expression) => self.run_if(*if_expression.inner, collect_garbage), Expression::List(list_expression) => { - self.run_list(*list_expression.inner, collect_garbage) + self.run_list(*list_expression.inner, context, collect_garbage) } Expression::ListIndex(list_index) => { - self.run_list_index(*list_index.inner, collect_garbage) + self.run_list_index(*list_index.inner, context, collect_garbage) } Expression::Literal(literal) => self.run_literal(*literal.inner), - Expression::Loop(loop_expression) => self.run_loop(*loop_expression.inner), - Expression::Map(map_expression) => self.run_map(*map_expression.inner, collect_garbage), + Expression::Loop(loop_expression) => self.run_loop(*loop_expression.inner, context), + Expression::Map(map_expression) => { + self.run_map(*map_expression.inner, context, collect_garbage) + } Expression::Operator(operator_expression) => { - self.run_operator(*operator_expression.inner, collect_garbage) + self.run_operator(*operator_expression.inner, context, collect_garbage) } Expression::Range(range_expression) => { - self.run_range(*range_expression.inner, collect_garbage) + self.run_range(*range_expression.inner, context, collect_garbage) } Expression::Struct(struct_expression) => { - self.run_struct(*struct_expression.inner, collect_garbage) + self.run_struct(*struct_expression.inner, context, collect_garbage) } Expression::TupleAccess(_) => todo!(), }; @@ -363,13 +344,18 @@ impl Vm { }) } - fn run_identifier(&self, identifier: Node) -> Result { - let get_data = self.context.get_data(&identifier.inner).map_err(|error| { - RuntimeError::ContextError { - error, - position: identifier.position, - } - })?; + fn run_identifier( + &self, + identifier: Node, + context: &Context, + ) -> Result { + let get_data = + context + .get_data(&identifier.inner) + .map_err(|error| RuntimeError::ContextError { + error, + position: identifier.position, + })?; if let Some(ContextData::VariableValue(value)) = get_data { return Ok(Evaluation::Return(Some(value))); @@ -397,13 +383,13 @@ impl Vm { fn run_struct( &self, struct_expression: StructExpression, + context: &Context, collect_garbage: bool, ) -> Result { let StructExpression::Fields { name, fields } = struct_expression; let position = name.position; - let constructor = self - .context + let constructor = context .get_constructor(&name.inner) .map_err(|error| RuntimeError::ContextError { error, position })?; @@ -413,7 +399,7 @@ impl Vm { for (identifier, expression) in fields { let position = expression.position(); let value = self - .run_expression(expression, collect_garbage)? + .run_expression(expression, context, collect_garbage)? .expect_value(position)?; arguments.insert(identifier.inner, value); @@ -432,13 +418,14 @@ impl Vm { fn run_range( &self, range: RangeExpression, + context: &Context, collect_garbage: bool, ) -> Result { match range { RangeExpression::Exclusive { start, end } => { let start_position = start.position(); let start = self - .run_expression(start, collect_garbage)? + .run_expression(start, context, collect_garbage)? .expect_value(start_position)?; let start_data = match start { @@ -448,7 +435,7 @@ impl Vm { }; let end_position = end.position(); let end = self - .run_expression(end, collect_garbage)? + .run_expression(end, context, collect_garbage)? .expect_value(end_position)?; let end_data = match end { Value::Raw(data) => data, @@ -478,7 +465,7 @@ impl Vm { RangeExpression::Inclusive { start, end } => { let start_position = start.position(); let start = self - .run_expression(start, collect_garbage)? + .run_expression(start, context, collect_garbage)? .expect_value(start_position)?; let start_data = match start { @@ -488,7 +475,7 @@ impl Vm { }; let end_position = end.position(); let end = self - .run_expression(end, collect_garbage)? + .run_expression(end, context, collect_garbage)? .expect_value(end_position)?; let end_data = match end { Value::Raw(data) => data, @@ -521,6 +508,7 @@ impl Vm { fn run_map( &self, map: MapExpression, + context: &Context, collect_garbage: bool, ) -> Result { let MapExpression { pairs } = map; @@ -530,7 +518,7 @@ impl Vm { for (identifier, expression) in pairs { let expression_position = expression.position(); let value = self - .run_expression(expression, collect_garbage)? + .run_expression(expression, context, collect_garbage)? .expect_value(expression_position)?; map.insert(identifier.inner, value); @@ -542,17 +530,18 @@ impl Vm { fn run_operator( &self, operator: OperatorExpression, + context: &Context, collect_garbage: bool, ) -> Result { match operator { OperatorExpression::Assignment { assignee, value } => { let assignee_position = assignee.position(); let assignee = self - .run_expression(assignee, collect_garbage)? + .run_expression(assignee, context, collect_garbage)? .expect_value(assignee_position)?; let value_position = value.position(); let value = self - .run_expression(value, collect_garbage)? + .run_expression(value, context, collect_garbage)? .expect_value(value_position)?; assignee @@ -572,11 +561,11 @@ impl Vm { } => { let left_position = left.position(); let left_value = self - .run_expression(left, collect_garbage)? + .run_expression(left, context, collect_garbage)? .expect_value(left_position)?; let right_position = right.position(); let right_value = self - .run_expression(right, collect_garbage)? + .run_expression(right, context, collect_garbage)? .expect_value(right_position)?; let result = match operator.inner { ComparisonOperator::Equal => left_value.equal(&right_value), @@ -605,11 +594,11 @@ impl Vm { } => { let assignee_position = assignee.position(); let assignee = self - .run_expression(assignee, collect_garbage)? + .run_expression(assignee, context, collect_garbage)? .expect_value(assignee_position)?; let modifier_position = modifier.position(); let modifier = self - .run_expression(modifier, collect_garbage)? + .run_expression(modifier, context, collect_garbage)? .expect_value(modifier_position)?; match operator.inner { @@ -631,7 +620,7 @@ impl Vm { OperatorExpression::Negation(expression) => { let position = expression.position(); let value = self - .run_expression(expression, collect_garbage)? + .run_expression(expression, context, collect_garbage)? .expect_value(position)?; let negated = value.negate().map_err(|error| RuntimeError::ValueError { error, @@ -644,7 +633,7 @@ impl Vm { OperatorExpression::Not(expression) => { let position = expression.position(); let value = self - .run_expression(expression, collect_garbage)? + .run_expression(expression, context, collect_garbage)? .expect_value(position)?; let not = value.not().map_err(|error| RuntimeError::ValueError { error, @@ -661,11 +650,11 @@ impl Vm { } => { let left_position = left.position(); let left_value = self - .run_expression(left, collect_garbage)? + .run_expression(left, context, collect_garbage)? .expect_value(left_position)?; let right_position = right.position(); let right_value = self - .run_expression(right, collect_garbage)? + .run_expression(right, context, collect_garbage)? .expect_value(right_position)?; let outcome = match operator.inner { MathOperator::Add => left_value.add(&right_value), @@ -689,11 +678,11 @@ impl Vm { } => { let left_position = left.position(); let left_value = self - .run_expression(left, collect_garbage)? + .run_expression(left, context, collect_garbage)? .expect_value(left_position)?; let right_position = right.position(); let right_value = self - .run_expression(right, collect_garbage)? + .run_expression(right, context, collect_garbage)? .expect_value(right_position)?; let outcome = match operator.inner { LogicOperator::And => left_value.and(&right_value), @@ -710,14 +699,18 @@ impl Vm { } } - fn run_loop(&self, loop_expression: LoopExpression) -> Result { + fn run_loop( + &self, + loop_expression: LoopExpression, + context: &Context, + ) -> Result { match loop_expression { LoopExpression::Infinite { block: Node { inner, .. }, } => match inner { - BlockExpression::Sync(statements) => 'outer: loop { - for statement in statements.clone() { - let evaluation = self.run_statement(statement, false)?; + BlockExpression::Sync(ast) => 'outer: loop { + for statement in ast.statements.clone() { + let evaluation = self.run_statement(statement, &ast.context, false)?; if let Evaluation::Break(value_option) = evaluation { break 'outer Ok(Evaluation::Return(value_option)); @@ -728,14 +721,14 @@ impl Vm { }, LoopExpression::While { condition, block } => { while self - .run_expression(condition.clone(), false)? + .run_expression(condition.clone(), context, false)? .expect_value(condition.position())? .as_boolean() .ok_or_else(|| RuntimeError::ExpectedBoolean { position: condition.position(), })? { - self.run_block(block.inner.clone(), false)?; + self.run_block(block.inner.clone(), context, false)?; } Ok(Evaluation::Return(None)) @@ -764,18 +757,19 @@ impl Vm { fn run_list_index( &self, list_index: ListIndexExpression, + context: &Context, collect_garbage: bool, ) -> Result { let ListIndexExpression { list, index } = list_index; let list_position = list.position(); let list_value = self - .run_expression(list, collect_garbage)? + .run_expression(list, context, collect_garbage)? .expect_value(list_position)?; let index_position = index.position(); let index_value = self - .run_expression(index, collect_garbage)? + .run_expression(index, context, collect_garbage)? .expect_value(index_position)?; let get_index = @@ -793,6 +787,7 @@ impl Vm { fn run_call( &self, call_expression: CallExpression, + context: &Context, collect_garbage: bool, ) -> Result { let CallExpression { invoker, arguments } = call_expression; @@ -803,7 +798,7 @@ impl Vm { let container_position = container.position(); let container_value = self - .run_expression(container, collect_garbage)? + .run_expression(container, context, collect_garbage)? .expect_value(container_position)?; let function = if let Some(value) = container_value.get_field(&field.inner) { @@ -848,7 +843,7 @@ impl Vm { for argument in arguments { let position = argument.position(); let value = self - .run_expression(argument, collect_garbage)? + .run_expression(argument, context, collect_garbage)? .expect_value(position)?; value_arguments.push(value); @@ -866,7 +861,7 @@ impl Vm { } let invoker_position = invoker.position(); - let run_invoker = self.run_expression(invoker, collect_garbage)?; + let run_invoker = self.run_expression(invoker, context, collect_garbage)?; match run_invoker { Evaluation::Constructor(constructor) => { @@ -875,7 +870,10 @@ impl Vm { for argument in arguments { let position = argument.position(); - if let Some(value) = self.run_expression(argument, collect_garbage)?.value() { + if let Some(value) = self + .run_expression(argument, context, collect_garbage)? + .value() + { fields.push(value); } else { return Err(RuntimeError::ExpectedValue { position }); @@ -925,7 +923,7 @@ impl Vm { for argument in arguments { let position = argument.position(); let value = self - .run_expression(argument, collect_garbage)? + .run_expression(argument, context, collect_garbage)? .expect_value(position)?; if let Some(value_arguments) = &mut value_arguments { @@ -954,19 +952,22 @@ impl Vm { fn run_field_access( &self, field_access: FieldAccessExpression, + context: &Context, collect_garbage: bool, ) -> Result { let FieldAccessExpression { container, field } = field_access; let container_position = container.position(); - let container_value = - if let Some(value) = self.run_expression(container, collect_garbage)?.value() { - value - } else { - return Err(RuntimeError::ExpectedValue { - position: container_position, - }); - }; + let container_value = if let Some(value) = self + .run_expression(container, context, collect_garbage)? + .value() + { + value + } else { + return Err(RuntimeError::ExpectedValue { + position: container_position, + }); + }; Ok(Evaluation::Return(container_value.get_field(&field.inner))) } @@ -974,6 +975,7 @@ impl Vm { fn run_list( &self, list_expression: ListExpression, + context: &Context, collect_garbage: bool, ) -> Result { match list_expression { @@ -983,14 +985,14 @@ impl Vm { } => { let position = length_operand.position(); let length = self - .run_expression(length_operand, collect_garbage)? + .run_expression(length_operand, context, collect_garbage)? .expect_value(position)? .as_integer() .ok_or(RuntimeError::ExpectedInteger { position })?; let position = repeat_operand.position(); let value = self - .run_expression(repeat_operand, collect_garbage)? + .run_expression(repeat_operand, context, collect_garbage)? .expect_value(position)?; Ok(Evaluation::Return(Some(Value::list(vec![ @@ -1004,7 +1006,7 @@ impl Vm { for expression in expressions { let position = expression.position(); let value = self - .run_expression(expression, collect_garbage)? + .run_expression(expression, context, collect_garbage)? .expect_value(position)?; values.push(value); @@ -1018,20 +1020,16 @@ impl Vm { fn run_block( &self, block: BlockExpression, + context: &Context, collect_garbage: bool, ) -> Result { - let block_context = self.context.create_child(); - let vm = Vm::new(block_context); - match block { - BlockExpression::Async(statements) => vm - .run_async(AbstractSyntaxTree::with_statements(statements)) - .map(Evaluation::Return), - BlockExpression::Sync(statements) => { + BlockExpression::Async(ast) => Vm.run_async(ast).map(Evaluation::Return), + BlockExpression::Sync(ast) => { let mut evaluation = Evaluation::Return(None); - for statement in statements { - evaluation = vm.run_statement(statement, collect_garbage)?; + for statement in ast.statements { + evaluation = Vm.run_statement(statement, &ast.context, collect_garbage)?; if let Evaluation::Break(_) = evaluation { return Ok(evaluation); @@ -1046,6 +1044,7 @@ impl Vm { fn run_if( &self, if_expression: IfExpression, + context: &Context, collect_garbage: bool, ) -> Result { match if_expression { @@ -1055,13 +1054,13 @@ impl Vm { } => { let position = condition.position(); let boolean = self - .run_expression(condition, collect_garbage)? + .run_expression(condition, context, collect_garbage)? .expect_value(position)? .as_boolean() .ok_or(RuntimeError::ExpectedBoolean { position })?; if boolean { - let evaluation = self.run_block(if_block.inner, collect_garbage)?; + let evaluation = self.run_block(if_block.inner, context, collect_garbage)?; if let Evaluation::Break(_) = evaluation { return Ok(evaluation); @@ -1077,20 +1076,20 @@ impl Vm { } => { let position = condition.position(); let boolean = self - .run_expression(condition, collect_garbage)? + .run_expression(condition, context, collect_garbage)? .expect_value(position)? .as_boolean() .ok_or(RuntimeError::ExpectedBoolean { position })?; if boolean { - self.run_block(if_block.inner, collect_garbage) + self.run_block(if_block.inner, context, collect_garbage) } else { match r#else { ElseExpression::If(if_expression) => { - self.run_if(*if_expression.inner, collect_garbage) + self.run_if(*if_expression.inner, context, collect_garbage) } ElseExpression::Block(block) => { - self.run_block(block.inner, collect_garbage) + self.run_block(block.inner, context, collect_garbage) } } }