Move reference counted rw lock for list values
This commit is contained in:
parent
7f7772e654
commit
ee30ae55a8
@ -1,3 +1,5 @@
|
||||
use std::sync::RwLock;
|
||||
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tree_sitter::Node;
|
||||
@ -54,21 +56,26 @@ impl AbstractTree for For {
|
||||
let key = self.item_id.inner();
|
||||
|
||||
if self.is_async {
|
||||
let context = RwLock::new(context);
|
||||
|
||||
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);
|
||||
|
||||
self.block.run(source, &mut iter_context).map(|_value| ())
|
||||
context.set(key.clone(), value.clone(), None);
|
||||
self.block.run(source, &mut context).map(|_value| ())
|
||||
})?;
|
||||
|
||||
context.write()?.set(key.clone(), Value::none(), None);
|
||||
} else {
|
||||
let mut loop_context = Map::clone_from(context)?;
|
||||
|
||||
for value in values.iter() {
|
||||
loop_context.set(key.clone(), value.clone(), None);
|
||||
|
||||
self.block.run(source, &mut loop_context)?;
|
||||
context.set(key.clone(), value.clone(), None);
|
||||
self.block.run(source, context)?;
|
||||
}
|
||||
|
||||
context.set(key.clone(), Value::none(), None);
|
||||
}
|
||||
|
||||
Ok(Value::none())
|
||||
|
@ -35,6 +35,10 @@ impl AbstractTree for Identifier {
|
||||
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> {
|
||||
if let Some((value, _)) = context.variables().get(&self.0) {
|
||||
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> {
|
||||
if let Some((_value, r#type)) = context.variables().get(&self.0) {
|
||||
Ok(r#type.clone())
|
||||
|
@ -6,21 +6,21 @@ use egui_extras::{Column, TableBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct App {
|
||||
pub struct App<'c> {
|
||||
path: String,
|
||||
source: String,
|
||||
context: Map,
|
||||
#[serde(skip)]
|
||||
interpreter: Interpreter,
|
||||
interpreter: Interpreter<'c>,
|
||||
output: Result<Value>,
|
||||
error: Option<String>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
impl<'c> App<'c> {
|
||||
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 mut interpreter = Interpreter::new(context.clone());
|
||||
let mut interpreter = Interpreter::new(&mut context);
|
||||
let read_source = read_to_string(&path);
|
||||
let source = if let Ok(source) = read_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.
|
||||
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
||||
eframe::set_value(storage, eframe::APP_KEY, self);
|
||||
|
@ -18,7 +18,7 @@ use crate::{language, AbstractTree, Error, Map, Result, Root, Value};
|
||||
/// assert_eq!(interpret("1 + 2 + 3"), Ok(Value::Integer(6)));
|
||||
/// ```
|
||||
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.
|
||||
@ -40,7 +40,7 @@ pub fn interpret(source: &str) -> Result<Value> {
|
||||
/// 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 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.
|
||||
pub struct Interpreter {
|
||||
pub struct Interpreter<'c> {
|
||||
parser: Parser,
|
||||
context: Map,
|
||||
context: &'c mut Map,
|
||||
syntax_tree: Option<TSTree>,
|
||||
abstract_tree: Option<Root>,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub fn new(context: Map) -> Self {
|
||||
impl<'c> Interpreter<'c> {
|
||||
pub fn new(context: &'c mut Map) -> Self {
|
||||
let mut parser = Parser::new();
|
||||
|
||||
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<()> {
|
||||
fn check_for_error(source: &str, node: Node, cursor: &mut TreeCursor) -> Result<()> {
|
||||
if node.is_error() {
|
||||
@ -101,14 +109,14 @@ impl Interpreter {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(&mut self, source: &str) -> Result<Value> {
|
||||
pub fn run(&'c mut self, source: &str) -> Result<Value> {
|
||||
self.parse(source)?;
|
||||
|
||||
self.abstract_tree = if let Some(syntax_tree) = &self.syntax_tree {
|
||||
Some(Root::from_syntax_node(
|
||||
source,
|
||||
syntax_tree.root_node(),
|
||||
&mut self.context,
|
||||
self.context,
|
||||
)?)
|
||||
} else {
|
||||
return Err(Error::ParserCancelled);
|
||||
@ -130,9 +138,3 @@ impl Interpreter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Interpreter {
|
||||
fn default() -> Self {
|
||||
Interpreter::new(Map::new())
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ fn main() {
|
||||
let mut parser = TSParser::new();
|
||||
parser.set_language(language()).unwrap();
|
||||
|
||||
let mut interpreter = Interpreter::new(context);
|
||||
let mut interpreter = Interpreter::new(&mut context);
|
||||
|
||||
if args.show_syntax_tree {
|
||||
interpreter.parse(&source).unwrap();
|
||||
@ -168,7 +168,7 @@ impl Highlighter for DustReadline {
|
||||
}
|
||||
|
||||
fn run_cli_shell() {
|
||||
let context = Map::new();
|
||||
let mut context = Map::new();
|
||||
let mut rl: Editor<DustReadline, DefaultHistory> = Editor::new().unwrap();
|
||||
|
||||
rl.set_helper(Some(DustReadline::new()));
|
||||
@ -185,7 +185,7 @@ fn run_cli_shell() {
|
||||
|
||||
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 {
|
||||
Ok(value) => println!("{value}"),
|
||||
|
@ -1,13 +1,12 @@
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
fmt::{self, Display, Formatter},
|
||||
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
};
|
||||
|
||||
use crate::Value;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct List(Arc<RwLock<Vec<Value>>>);
|
||||
pub struct List(Vec<Value>);
|
||||
|
||||
impl Default for List {
|
||||
fn default() -> Self {
|
||||
@ -17,23 +16,23 @@ impl Default for List {
|
||||
|
||||
impl List {
|
||||
pub fn new() -> Self {
|
||||
List(Arc::new(RwLock::new(Vec::new())))
|
||||
List(Vec::new())
|
||||
}
|
||||
|
||||
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 {
|
||||
List(Arc::new(RwLock::new(items)))
|
||||
List(items)
|
||||
}
|
||||
|
||||
pub fn items(&self) -> RwLockReadGuard<'_, Vec<Value>> {
|
||||
self.0.read().unwrap()
|
||||
pub fn items(&self) -> &Vec<Value> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn items_mut(&self) -> RwLockWriteGuard<'_, Vec<Value>> {
|
||||
self.0.write().unwrap()
|
||||
pub fn items_mut(&mut self) -> &mut Vec<Value> {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,19 +40,13 @@ impl Eq for List {}
|
||||
|
||||
impl PartialEq for List {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let left = self.0.read().unwrap().clone().into_iter();
|
||||
let right = other.0.read().unwrap().clone().into_iter();
|
||||
|
||||
left.eq(right)
|
||||
self.0.eq(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for List {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
let left = self.0.read().unwrap().clone().into_iter();
|
||||
let right = other.0.read().unwrap().clone().into_iter();
|
||||
|
||||
left.cmp(right)
|
||||
self.0.cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,19 @@ mod for_loop {
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user