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 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())
|
||||||
|
@ -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())
|
||||||
|
@ -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);
|
||||||
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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}"),
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user