1
0

Move reference counted rw lock for list values

This commit is contained in:
Jeff 2024-01-03 14:11:19 -05:00
parent 7f7772e654
commit ee30ae55a8
7 changed files with 68 additions and 53 deletions

View File

@ -1,3 +1,5 @@
use std::sync::RwLock;
use rayon::prelude::*; use rayon::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
@ -54,21 +56,26 @@ impl AbstractTree for For {
let key = self.item_id.inner(); let key = self.item_id.inner();
if self.is_async { if self.is_async {
let context = RwLock::new(context);
values.par_iter().try_for_each(|value| { values.par_iter().try_for_each(|value| {
let mut iter_context = Map::clone_from(context)?; let mut context = match context.write() {
Ok(map) => map,
Err(error) => return Err(error.into()),
};
iter_context.set(key.clone(), value.clone(), None); context.set(key.clone(), value.clone(), None);
self.block.run(source, &mut context).map(|_value| ())
self.block.run(source, &mut iter_context).map(|_value| ())
})?; })?;
context.write()?.set(key.clone(), Value::none(), None);
} else { } else {
let mut loop_context = Map::clone_from(context)?;
for value in values.iter() { for value in values.iter() {
loop_context.set(key.clone(), value.clone(), None); context.set(key.clone(), value.clone(), None);
self.block.run(source, context)?;
self.block.run(source, &mut loop_context)?;
} }
context.set(key.clone(), Value::none(), None);
} }
Ok(Value::none()) Ok(Value::none())

View File

@ -35,6 +35,10 @@ impl AbstractTree for Identifier {
Ok(Identifier(text.to_string())) Ok(Identifier(text.to_string()))
} }
fn check_type(&self, _source: &str, _context: &Map) -> Result<()> {
Ok(())
}
fn run(&self, _source: &str, context: &mut Map) -> Result<Value> { fn run(&self, _source: &str, context: &mut Map) -> Result<Value> {
if let Some((value, _)) = context.variables().get(&self.0) { if let Some((value, _)) = context.variables().get(&self.0) {
Ok(value.clone()) Ok(value.clone())
@ -43,10 +47,6 @@ impl AbstractTree for Identifier {
} }
} }
fn check_type(&self, _source: &str, _context: &Map) -> Result<()> {
Ok(())
}
fn expected_type(&self, context: &Map) -> Result<Type> { fn expected_type(&self, context: &Map) -> Result<Type> {
if let Some((_value, r#type)) = context.variables().get(&self.0) { if let Some((_value, r#type)) = context.variables().get(&self.0) {
Ok(r#type.clone()) Ok(r#type.clone())

View File

@ -6,21 +6,21 @@ use egui_extras::{Column, TableBuilder};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct App { pub struct App<'c> {
path: String, path: String,
source: String, source: String,
context: Map, context: Map,
#[serde(skip)] #[serde(skip)]
interpreter: Interpreter, interpreter: Interpreter<'c>,
output: Result<Value>, output: Result<Value>,
error: Option<String>, error: Option<String>,
} }
impl App { impl<'c> App<'c> {
pub fn new(cc: &eframe::CreationContext<'_>, path: PathBuf) -> Self { pub fn new(cc: &eframe::CreationContext<'_>, path: PathBuf) -> Self {
fn create_app(path: PathBuf) -> App { fn create_app<'c>(path: PathBuf) -> App<'c> {
let context = Map::new(); let context = Map::new();
let mut interpreter = Interpreter::new(context.clone()); let mut interpreter = Interpreter::new(&mut context);
let read_source = read_to_string(&path); let read_source = read_to_string(&path);
let source = if let Ok(source) = read_source { let source = if let Ok(source) = read_source {
source source
@ -54,7 +54,7 @@ impl App {
} }
} }
impl eframe::App for App { impl<'c> eframe::App for App<'c> {
/// Called by the frame work to save state before shutdown. /// Called by the frame work to save state before shutdown.
fn save(&mut self, storage: &mut dyn eframe::Storage) { fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, eframe::APP_KEY, self); eframe::set_value(storage, eframe::APP_KEY, self);

View File

@ -18,7 +18,7 @@ use crate::{language, AbstractTree, Error, Map, Result, Root, Value};
/// assert_eq!(interpret("1 + 2 + 3"), Ok(Value::Integer(6))); /// assert_eq!(interpret("1 + 2 + 3"), Ok(Value::Integer(6)));
/// ``` /// ```
pub fn interpret(source: &str) -> Result<Value> { pub fn interpret(source: &str) -> Result<Value> {
interpret_with_context(source, Map::new()) interpret_with_context(source, &mut Map::new())
} }
/// Interpret the given source code with the given context. /// Interpret the given source code with the given context.
@ -40,7 +40,7 @@ pub fn interpret(source: &str) -> Result<Value> {
/// Ok(Value::Integer(10)) /// Ok(Value::Integer(10))
/// ); /// );
/// ``` /// ```
pub fn interpret_with_context(source: &str, context: Map) -> Result<Value> { pub fn interpret_with_context(source: &str, context: &mut Map) -> Result<Value> {
let mut interpreter = Interpreter::new(context); let mut interpreter = Interpreter::new(context);
let value = interpreter.run(source)?; let value = interpreter.run(source)?;
@ -48,15 +48,15 @@ pub fn interpret_with_context(source: &str, context: Map) -> Result<Value> {
} }
/// A source code interpreter for the Dust language. /// A source code interpreter for the Dust language.
pub struct Interpreter { pub struct Interpreter<'c> {
parser: Parser, parser: Parser,
context: Map, context: &'c mut Map,
syntax_tree: Option<TSTree>, syntax_tree: Option<TSTree>,
abstract_tree: Option<Root>, abstract_tree: Option<Root>,
} }
impl Interpreter { impl<'c> Interpreter<'c> {
pub fn new(context: Map) -> Self { pub fn new(context: &'c mut Map) -> Self {
let mut parser = Parser::new(); let mut parser = Parser::new();
parser parser
@ -71,6 +71,14 @@ impl Interpreter {
} }
} }
pub fn context(&self) -> &Map {
&self.context
}
pub fn context_mut(&mut self) -> &mut Map {
&mut self.context
}
pub fn parse(&mut self, source: &str) -> Result<()> { pub fn parse(&mut self, source: &str) -> Result<()> {
fn check_for_error(source: &str, node: Node, cursor: &mut TreeCursor) -> Result<()> { fn check_for_error(source: &str, node: Node, cursor: &mut TreeCursor) -> Result<()> {
if node.is_error() { if node.is_error() {
@ -101,14 +109,14 @@ impl Interpreter {
Ok(()) Ok(())
} }
pub fn run(&mut self, source: &str) -> Result<Value> { pub fn run(&'c mut self, source: &str) -> Result<Value> {
self.parse(source)?; self.parse(source)?;
self.abstract_tree = if let Some(syntax_tree) = &self.syntax_tree { self.abstract_tree = if let Some(syntax_tree) = &self.syntax_tree {
Some(Root::from_syntax_node( Some(Root::from_syntax_node(
source, source,
syntax_tree.root_node(), syntax_tree.root_node(),
&mut self.context, self.context,
)?) )?)
} else { } else {
return Err(Error::ParserCancelled); return Err(Error::ParserCancelled);
@ -130,9 +138,3 @@ impl Interpreter {
} }
} }
} }
impl Default for Interpreter {
fn default() -> Self {
Interpreter::new(Map::new())
}
}

View File

@ -72,7 +72,7 @@ fn main() {
let mut parser = TSParser::new(); let mut parser = TSParser::new();
parser.set_language(language()).unwrap(); parser.set_language(language()).unwrap();
let mut interpreter = Interpreter::new(context); let mut interpreter = Interpreter::new(&mut context);
if args.show_syntax_tree { if args.show_syntax_tree {
interpreter.parse(&source).unwrap(); interpreter.parse(&source).unwrap();
@ -168,7 +168,7 @@ impl Highlighter for DustReadline {
} }
fn run_cli_shell() { fn run_cli_shell() {
let context = Map::new(); let mut context = Map::new();
let mut rl: Editor<DustReadline, DefaultHistory> = Editor::new().unwrap(); let mut rl: Editor<DustReadline, DefaultHistory> = Editor::new().unwrap();
rl.set_helper(Some(DustReadline::new())); rl.set_helper(Some(DustReadline::new()));
@ -185,7 +185,7 @@ fn run_cli_shell() {
rl.add_history_entry(line).unwrap(); rl.add_history_entry(line).unwrap();
let eval_result = interpret_with_context(line, context.clone()); let eval_result = interpret_with_context(line, &mut context);
match eval_result { match eval_result {
Ok(value) => println!("{value}"), Ok(value) => println!("{value}"),

View File

@ -1,13 +1,12 @@
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
}; };
use crate::Value; use crate::Value;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct List(Arc<RwLock<Vec<Value>>>); pub struct List(Vec<Value>);
impl Default for List { impl Default for List {
fn default() -> Self { fn default() -> Self {
@ -17,23 +16,23 @@ impl Default for List {
impl List { impl List {
pub fn new() -> Self { pub fn new() -> Self {
List(Arc::new(RwLock::new(Vec::new()))) List(Vec::new())
} }
pub fn with_capacity(capacity: usize) -> Self { pub fn with_capacity(capacity: usize) -> Self {
List(Arc::new(RwLock::new(Vec::with_capacity(capacity)))) List(Vec::with_capacity(capacity))
} }
pub fn with_items(items: Vec<Value>) -> Self { pub fn with_items(items: Vec<Value>) -> Self {
List(Arc::new(RwLock::new(items))) List(items)
} }
pub fn items(&self) -> RwLockReadGuard<'_, Vec<Value>> { pub fn items(&self) -> &Vec<Value> {
self.0.read().unwrap() &self.0
} }
pub fn items_mut(&self) -> RwLockWriteGuard<'_, Vec<Value>> { pub fn items_mut(&mut self) -> &mut Vec<Value> {
self.0.write().unwrap() &mut self.0
} }
} }
@ -41,19 +40,13 @@ impl Eq for List {}
impl PartialEq for List { impl PartialEq for List {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
let left = self.0.read().unwrap().clone().into_iter(); self.0.eq(&other.0)
let right = other.0.read().unwrap().clone().into_iter();
left.eq(right)
} }
} }
impl Ord for List { impl Ord for List {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
let left = self.0.read().unwrap().clone().into_iter(); self.0.cmp(&other.0)
let right = other.0.read().unwrap().clone().into_iter();
left.cmp(right)
} }
} }

View File

@ -76,6 +76,19 @@ mod for_loop {
result result
); );
} }
#[test]
fn async_modify_value() {
let result = interpret(
"
list = []
async for i in [1 2 3] { list += i }
length(list)
",
);
assert_eq!(Ok(Value::Integer(3)), result);
}
} }
mod logic { mod logic {