Remove RefCell from streams (#227)

This commit is contained in:
Mike Voronov 2022-03-03 19:09:48 +03:00 committed by GitHub
parent 9ae79f44ff
commit c00b453a48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 50 additions and 48 deletions

4
Cargo.lock generated
View File

@ -13,7 +13,7 @@ dependencies = [
[[package]] [[package]]
name = "air" name = "air"
version = "0.20.0" version = "0.21.0"
dependencies = [ dependencies = [
"air-execution-info-collector", "air-execution-info-collector",
"air-interpreter-data", "air-interpreter-data",
@ -51,7 +51,7 @@ version = "0.1.0"
[[package]] [[package]]
name = "air-interpreter" name = "air-interpreter"
version = "0.20.0" version = "0.21.0"
dependencies = [ dependencies = [
"air", "air",
"air-log-targets", "air-log-targets",

View File

@ -81,7 +81,7 @@ fn variable_to_generations(variable: &ast::Variable<'_>, exec_ctx: &ExecutionCtx
// unwrap here is safe because this function will be called only // unwrap here is safe because this function will be called only
// when this stream's been created // when this stream's been created
let stream = exec_ctx.streams.get(stream.name, stream.position).unwrap(); let stream = exec_ctx.streams.get(stream.name, stream.position).unwrap();
let generation = match stream.borrow().generations_count() { let generation = match stream.generations_count() {
0 => 0, 0 => 0,
n => n - 1, n => n - 1,
}; };

View File

@ -42,7 +42,7 @@ pub(crate) fn set_local_result<'i>(
// TODO: refactor this generation handling // TODO: refactor this generation handling
let generation = match exec_ctx.streams.get(stream.name, stream.position) { let generation = match exec_ctx.streams.get(stream.name, stream.position) {
Some(stream) => { Some(stream) => {
let generation = match stream.borrow().generations_count() { let generation = match stream.generations_count() {
0 => 0, 0 => 0,
n => n - 1, n => n - 1,
}; };

View File

@ -22,7 +22,6 @@ use crate::SecurityTetraplet;
use air_parser::ast; use air_parser::ast;
use std::cell::RefCell;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
@ -48,11 +47,10 @@ pub(crate) fn construct_scalar_iterable_value<'ctx>(
/// Constructs iterable value for given stream iterable. /// Constructs iterable value for given stream iterable.
pub(crate) fn construct_stream_iterable_values( pub(crate) fn construct_stream_iterable_values(
stream: &RefCell<Stream>, stream: &Stream,
start: Generation, start: Generation,
end: Generation, end: Generation,
) -> Vec<IterableValue> { ) -> Vec<IterableValue> {
let stream = stream.borrow();
let stream_iter = match stream.slice_iter(start, end) { let stream_iter = match stream.slice_iter(start, end) {
Some(stream_iter) => stream_iter, Some(stream_iter) => stream_iter,
None => return vec![], None => return vec![],

View File

@ -25,13 +25,11 @@ use super::TraceHandler;
use crate::execution_step::boxed_value::Stream; use crate::execution_step::boxed_value::Stream;
use crate::log_instruction; use crate::log_instruction;
use crate::trace_to_exec_err; use crate::trace_to_exec_err;
use air_parser::ast;
use stream_cursor::StreamCursor; use stream_cursor::StreamCursor;
use air_parser::ast;
use air_parser::ast::FoldStream; use air_parser::ast::FoldStream;
use std::cell::RefCell;
impl<'i> ExecutableInstruction<'i> for FoldStream<'i> { impl<'i> ExecutableInstruction<'i> for FoldStream<'i> {
fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> { fn execute(&self, exec_ctx: &mut ExecutionCtx<'i>, trace_ctx: &mut TraceHandler) -> ExecutionResult<()> {
log_instruction!(fold, exec_ctx, trace_ctx); log_instruction!(fold, exec_ctx, trace_ctx);
@ -118,16 +116,16 @@ fn should_stop_iteration(iteration_result: &ExecutionResult<bool>) -> bool {
/// Safety: this function should be called iff stream is present in context /// Safety: this function should be called iff stream is present in context
fn add_new_generation_if_non_empty(stream: &ast::Stream<'_>, exec_ctx: &mut ExecutionCtx<'_>) { fn add_new_generation_if_non_empty(stream: &ast::Stream<'_>, exec_ctx: &mut ExecutionCtx<'_>) {
let stream = exec_ctx.streams.get(stream.name, stream.position).unwrap(); let stream = exec_ctx.streams.get_mut(stream.name, stream.position).unwrap();
stream.borrow_mut().add_new_generation_if_non_empty(); stream.add_new_generation_if_non_empty();
} }
/// Safety: this function should be called iff stream is present in context /// Safety: this function should be called iff stream is present in context
fn remove_new_generation_if_non_empty<'ctx>( fn remove_new_generation_if_non_empty<'ctx>(
stream: &ast::Stream<'_>, stream: &ast::Stream<'_>,
exec_ctx: &'ctx mut ExecutionCtx<'_>, exec_ctx: &'ctx mut ExecutionCtx<'_>,
) -> &'ctx RefCell<Stream> { ) -> &'ctx Stream {
let stream = exec_ctx.streams.get(stream.name, stream.position).unwrap(); let stream = exec_ctx.streams.get_mut(stream.name, stream.position).unwrap();
stream.borrow_mut().remove_last_generation_if_empty(); stream.remove_last_generation_if_empty();
stream stream
} }

View File

@ -19,8 +19,6 @@ use crate::execution_step::air::fold::IterableValue;
use crate::execution_step::boxed_value::Generation; use crate::execution_step::boxed_value::Generation;
use crate::execution_step::boxed_value::Stream; use crate::execution_step::boxed_value::Stream;
use std::cell::RefCell;
pub(super) struct StreamCursor { pub(super) struct StreamCursor {
last_seen_generation: u32, last_seen_generation: u32,
} }
@ -32,10 +30,10 @@ impl StreamCursor {
} }
} }
pub(super) fn construct_iterables(&mut self, stream: &RefCell<Stream>) -> Vec<IterableValue> { pub(super) fn construct_iterables(&mut self, stream: &Stream) -> Vec<IterableValue> {
let iterables = let iterables =
construct_stream_iterable_values(stream, Generation::Nth(self.last_seen_generation), Generation::Last); construct_stream_iterable_values(stream, Generation::Nth(self.last_seen_generation), Generation::Last);
self.last_seen_generation = stream.borrow().non_empty_generations_count() as u32; self.last_seen_generation = stream.non_empty_generations_count() as u32;
iterables iterables
} }

View File

@ -32,7 +32,7 @@ use std::ops::Deref;
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct StreamJvaluableIngredients<'stream> { pub(crate) struct StreamJvaluableIngredients<'stream> {
pub(crate) stream: std::cell::Ref<'stream, Stream>, pub(crate) stream: &'stream Stream,
pub(crate) generation: Generation, pub(crate) generation: Generation,
} }
@ -63,7 +63,7 @@ impl JValuable for StreamJvaluableIngredients<'_> {
} }
fn as_jvalue(&self) -> Cow<'_, JValue> { fn as_jvalue(&self) -> Cow<'_, JValue> {
let jvalue = self.stream.deref().clone().as_jvalue(self.generation).unwrap(); let jvalue = self.stream.as_jvalue(self.generation).unwrap();
Cow::Owned(jvalue) Cow::Owned(jvalue)
} }
@ -83,7 +83,7 @@ impl JValuable for StreamJvaluableIngredients<'_> {
use crate::execution_step::boxed_value::StreamIter; use crate::execution_step::boxed_value::StreamIter;
impl<'stream> StreamJvaluableIngredients<'stream> { impl<'stream> StreamJvaluableIngredients<'stream> {
pub(crate) fn new(stream: std::cell::Ref<'stream, Stream>, generation: Generation) -> Self { pub(crate) fn new(stream: &'stream Stream, generation: Generation) -> Self {
Self { stream, generation } Self { stream, generation }
} }
@ -98,7 +98,7 @@ impl<'stream> StreamJvaluableIngredients<'stream> {
Generation::Last => unreachable!(), Generation::Last => unreachable!(),
}; };
Err(StreamDontHaveSuchGeneration(self.stream.deref().clone(), generation as usize).into()) Err(StreamDontHaveSuchGeneration(self.stream.clone(), generation as usize).into())
} }
} }
} }

View File

@ -22,7 +22,6 @@ use crate::execution_step::ValueAggregate;
use air_interpreter_data::GlobalStreamGens; use air_interpreter_data::GlobalStreamGens;
use air_interpreter_data::RestrictedStreamGens; use air_interpreter_data::RestrictedStreamGens;
use std::cell::RefCell;
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap; use std::collections::HashMap;
@ -43,17 +42,22 @@ pub(crate) struct Streams {
struct StreamDescriptor { struct StreamDescriptor {
pub(self) span: Span, pub(self) span: Span,
// TODO: get rid of RefCell in a separate PR pub(self) stream: Stream,
pub(self) stream: RefCell<Stream>,
} }
impl Streams { impl Streams {
pub(crate) fn get(&self, name: &str, position: usize) -> Option<&RefCell<Stream>> { pub(crate) fn get(&self, name: &str, position: usize) -> Option<&Stream> {
self.streams self.streams
.get(name) .get(name)
.and_then(|descriptors| find_closest(descriptors.iter(), position)) .and_then(|descriptors| find_closest(descriptors.iter(), position))
} }
pub(crate) fn get_mut(&mut self, name: &str, position: usize) -> Option<&mut Stream> {
self.streams
.get_mut(name)
.and_then(|descriptors| find_closest_mut(descriptors.iter_mut(), position))
}
pub(crate) fn add_stream_value( pub(crate) fn add_stream_value(
&mut self, &mut self,
value: ValueAggregate, value: ValueAggregate,
@ -61,8 +65,8 @@ impl Streams {
stream_name: &str, stream_name: &str,
position: usize, position: usize,
) -> ExecutionResult<u32> { ) -> ExecutionResult<u32> {
match self.get(stream_name, position) { match self.get_mut(stream_name, position) {
Some(stream) => stream.borrow_mut().add_value(value, generation), Some(stream) => stream.add_value(value, generation),
None => { None => {
// streams could be created in three ways: // streams could be created in three ways:
// - after met new instruction with stream name that isn't present in streams // - after met new instruction with stream name that isn't present in streams
@ -80,7 +84,7 @@ impl Streams {
} }
pub(crate) fn add_global_stream(&mut self, name: String, stream: Stream) { pub(crate) fn add_global_stream(&mut self, name: String, stream: Stream) {
let descriptor = StreamDescriptor::global(RefCell::new(stream)); let descriptor = StreamDescriptor::global(stream);
self.streams.insert(name, vec![descriptor]); self.streams.insert(name, vec![descriptor]);
} }
@ -90,7 +94,7 @@ impl Streams {
.stream_generation_from_data(&name, span.left as u32, iteration as usize) .stream_generation_from_data(&name, span.left as u32, iteration as usize)
.unwrap_or_default(); .unwrap_or_default();
let new_stream = RefCell::new(Stream::from_generations_count(generations_count as usize)); let new_stream = Stream::from_generations_count(generations_count as usize);
let new_descriptor = StreamDescriptor::restricted(new_stream, span); let new_descriptor = StreamDescriptor::restricted(new_stream, span);
match self.streams.entry(name) { match self.streams.entry(name) {
Occupied(mut entry) => { Occupied(mut entry) => {
@ -112,11 +116,7 @@ impl Streams {
self.streams.remove(&name); self.streams.remove(&name);
} }
self.collect_stream_generation( self.collect_stream_generation(name, position, last_descriptor.stream.generations_count() as u32);
name,
position,
last_descriptor.stream.borrow().generations_count() as u32,
);
} }
/// This method must be called at the end of execution, because it contains logic to collect /// This method must be called at the end of execution, because it contains logic to collect
@ -131,7 +131,7 @@ impl Streams {
// unwrap is safe here because of invariant that streams contains non-empty vectors, // unwrap is safe here because of invariant that streams contains non-empty vectors,
// moreover it must contain only one value, because this method is called at the end // moreover it must contain only one value, because this method is called at the end
// of the execution // of the execution
let generation = descriptors.pop().unwrap().stream.borrow().generations_count(); let generation = descriptors.pop().unwrap().stream.generations_count();
(name, generation as u32) (name, generation as u32)
}) })
.collect::<GlobalStreamGens>(); .collect::<GlobalStreamGens>();
@ -165,14 +165,14 @@ impl Streams {
} }
impl StreamDescriptor { impl StreamDescriptor {
pub(self) fn global(stream: RefCell<Stream>) -> Self { pub(self) fn global(stream: Stream) -> Self {
Self { Self {
span: Span::new(0, usize::MAX), span: Span::new(0, usize::MAX),
stream, stream,
} }
} }
pub(self) fn restricted(stream: RefCell<Stream>, span: Span) -> Self { pub(self) fn restricted(stream: Stream, span: Span) -> Self {
Self { span, stream } Self { span, stream }
} }
} }
@ -180,7 +180,7 @@ impl StreamDescriptor {
fn find_closest<'d>( fn find_closest<'d>(
descriptors: impl DoubleEndedIterator<Item = &'d StreamDescriptor>, descriptors: impl DoubleEndedIterator<Item = &'d StreamDescriptor>,
position: usize, position: usize,
) -> Option<&'d RefCell<Stream>> { ) -> Option<&'d Stream> {
// descriptors are placed in a order of decreasing scopes, so it's enough to get the latest suitable // descriptors are placed in a order of decreasing scopes, so it's enough to get the latest suitable
for descriptor in descriptors.rev() { for descriptor in descriptors.rev() {
if descriptor.span.contains_position(position) { if descriptor.span.contains_position(position) {
@ -191,6 +191,20 @@ fn find_closest<'d>(
None None
} }
fn find_closest_mut<'d>(
descriptors: impl DoubleEndedIterator<Item = &'d mut StreamDescriptor>,
position: usize,
) -> Option<&'d mut Stream> {
// descriptors are placed in a order of decreasing scopes, so it's enough to get the latest suitable
for descriptor in descriptors.rev() {
if descriptor.span.contains_position(position) {
return Some(&mut descriptor.stream);
}
}
None
}
use air_parser::ast::Span; use air_parser::ast::Span;
use std::fmt; use std::fmt;
@ -207,12 +221,6 @@ impl fmt::Display for Streams {
impl fmt::Display for StreamDescriptor { impl fmt::Display for StreamDescriptor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(f, " <{}> - <{}>: {}", self.span.left, self.span.right, self.stream)
f,
" <{}> - <{}>: {}",
self.span.left,
self.span.right,
self.stream.borrow()
)
} }
} }

View File

@ -100,7 +100,7 @@ pub(crate) fn resolve_variable<'ctx, 'i>(
} => { } => {
match ctx.streams.get(name, position) { match ctx.streams.get(name, position) {
Some(stream) => { Some(stream) => {
let ingredients = StreamJvaluableIngredients::new(stream.borrow(), generation); let ingredients = StreamJvaluableIngredients::new(stream, generation);
Ok(Box::new(ingredients)) Ok(Box::new(ingredients))
} }
// return an empty stream for not found stream // return an empty stream for not found stream