Add TypeCmpCache

This commit is contained in:
Shunsuke Shibayama 2022-08-26 14:37:39 +09:00
parent 592671af96
commit 8e73b9b6b7
9 changed files with 105 additions and 39 deletions

View file

@ -7,33 +7,33 @@ use crate::set::Set;
use crate::{RcArray, Str}; use crate::{RcArray, Str};
#[derive(Debug)] #[derive(Debug)]
pub struct Cache<T: ?Sized>(RefCell<Set<Rc<T>>>); pub struct CacheSet<T: ?Sized>(RefCell<Set<Rc<T>>>);
impl<T: ?Sized> Default for Cache<T> { impl<T: ?Sized> Default for CacheSet<T> {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }
} }
impl<T: ?Sized> Cache<T> { impl<T: ?Sized> CacheSet<T> {
pub fn new() -> Self { pub fn new() -> Self {
Self(RefCell::new(Set::new())) Self(RefCell::new(Set::new()))
} }
} }
impl Clone for Cache<str> { impl Clone for CacheSet<str> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self(self.0.clone()) Self(self.0.clone())
} }
} }
impl<T: Hash + Eq> Clone for Cache<T> { impl<T: Hash + Eq> Clone for CacheSet<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self(self.0.clone()) Self(self.0.clone())
} }
} }
impl Cache<str> { impl CacheSet<str> {
pub fn get(&self, s: &str) -> Str { pub fn get(&self, s: &str) -> Str {
if let Some(cached) = self.0.borrow().get(s) { if let Some(cached) = self.0.borrow().get(s) {
return cached.clone().into(); return cached.clone().into();
@ -44,7 +44,7 @@ impl Cache<str> {
} }
} }
impl<T: Hash + Eq + Clone> Cache<[T]> { impl<T: Hash + Eq + Clone> CacheSet<[T]> {
pub fn get(&self, q: &[T]) -> Rc<[T]> { pub fn get(&self, q: &[T]) -> Rc<[T]> {
if let Some(cached) = self.0.borrow().get(q) { if let Some(cached) = self.0.borrow().get(q) {
return cached.clone(); return cached.clone();
@ -55,7 +55,7 @@ impl<T: Hash + Eq + Clone> Cache<[T]> {
} }
} }
impl<T: Hash + Eq> Cache<T> { impl<T: Hash + Eq> CacheSet<T> {
pub fn get<Q: ?Sized + Hash + Eq>(&self, q: &Q) -> Rc<T> pub fn get<Q: ?Sized + Hash + Eq>(&self, q: &Q) -> Rc<T>
where where
Rc<T>: Borrow<Q>, Rc<T>: Borrow<Q>,
@ -69,3 +69,5 @@ impl<T: Hash + Eq> Cache<T> {
s s
} }
} }
pub struct CacheDict<T: ?Sized>(RefCell<Set<Rc<T>>>);

View file

@ -2,13 +2,11 @@
//! //!
//! コマンドオプション(パーサー)を定義する //! コマンドオプション(パーサー)を定義する
use std::env; use std::env;
// use std::env::consts::{ARCH, OS};
use std::fs::File; use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read}; use std::io::{stdin, BufRead, BufReader, Read};
use std::process; use std::process;
// use crate::lazy::Lazy; use crate::stdin::GLOBAL_STDIN;
use crate::stdin;
use crate::Str; use crate::Str;
use crate::{power_assert, read_file}; use crate::{power_assert, read_file};
@ -76,7 +74,7 @@ impl Input {
Str::from(src) Str::from(src)
} }
Self::Pipe(s) | Self::Str(s) => s.clone(), Self::Pipe(s) | Self::Str(s) => s.clone(),
Self::REPL => stdin::read(), Self::REPL => GLOBAL_STDIN.read(),
Self::Dummy => panic!("cannot read from a dummy file"), Self::Dummy => panic!("cannot read from a dummy file"),
} }
} }
@ -100,7 +98,7 @@ impl Input {
.iter() .iter()
.map(|s| Str::rc(*s)) .map(|s| Str::rc(*s))
.collect(), .collect(),
Self::REPL => stdin::reread_lines(ln_begin, ln_end), Self::REPL => GLOBAL_STDIN.reread_lines(ln_begin, ln_end),
Self::Dummy => panic!("cannot read lines from a dummy file"), Self::Dummy => panic!("cannot read lines from a dummy file"),
} }
} }
@ -109,7 +107,7 @@ impl Input {
match self { match self {
Self::File(_filename) => todo!(), Self::File(_filename) => todo!(),
Self::Pipe(s) | Self::Str(s) => s.clone(), Self::Pipe(s) | Self::Str(s) => s.clone(),
Self::REPL => stdin::reread(), Self::REPL => GLOBAL_STDIN.reread(),
Self::Dummy => panic!("cannot read from a dummy file"), Self::Dummy => panic!("cannot read from a dummy file"),
} }
} }

View file

@ -1,5 +1,6 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::io::{stdin, BufRead, BufReader}; use std::io::{stdin, BufRead, BufReader};
use std::thread::LocalKey;
use crate::Str; use crate::Str;
@ -29,17 +30,25 @@ impl StdinReader {
} }
thread_local! { thread_local! {
pub static READER: RefCell<StdinReader> = RefCell::new(StdinReader{ lineno: 0, buf: vec![] }); static READER: RefCell<StdinReader> = RefCell::new(StdinReader{ lineno: 0, buf: vec![] });
} }
pub fn read() -> Str { #[derive(Debug)]
READER.with(|s| s.borrow_mut().read()) pub struct GlobalStdin(LocalKey<RefCell<StdinReader>>);
pub static GLOBAL_STDIN: GlobalStdin = GlobalStdin(READER);
impl GlobalStdin {
pub fn read(&'static self) -> Str {
self.0.with(|s| s.borrow_mut().read())
} }
pub fn reread() -> Str { pub fn reread(&'static self) -> Str {
READER.with(|s| s.borrow().reread()) self.0.with(|s| s.borrow().reread())
} }
pub fn reread_lines(ln_begin: usize, ln_end: usize) -> Vec<Str> { pub fn reread_lines(&'static self, ln_begin: usize, ln_end: usize) -> Vec<Str> {
READER.with(|s| s.borrow_mut().reread_lines(ln_begin, ln_end)) self.0
.with(|s| s.borrow_mut().reread_lines(ln_begin, ln_end))
}
} }

View file

@ -4,7 +4,7 @@
use std::fmt; use std::fmt;
use std::process; use std::process;
use erg_common::cache::Cache; use erg_common::cache::CacheSet;
use erg_common::color::{GREEN, RESET}; use erg_common::color::{GREEN, RESET};
use erg_common::config::{ErgConfig, Input}; use erg_common::config::{ErgConfig, Input};
use erg_common::error::{Location, MultiErrorDisplay}; use erg_common::error::{Location, MultiErrorDisplay};
@ -298,7 +298,7 @@ impl_stream_for_wrapper!(CodeGenStack, CodeGenUnit);
#[derive(Debug)] #[derive(Debug)]
pub struct CodeGenerator { pub struct CodeGenerator {
cfg: ErgConfig, cfg: ErgConfig,
str_cache: Cache<str>, str_cache: CacheSet<str>,
unit_size: usize, unit_size: usize,
units: CodeGenStack, units: CodeGenStack,
pub(crate) errs: CompileErrors, pub(crate) errs: CompileErrors,
@ -308,7 +308,7 @@ impl CodeGenerator {
pub fn new(cfg: ErgConfig) -> Self { pub fn new(cfg: ErgConfig) -> Self {
Self { Self {
cfg, cfg,
str_cache: Cache::new(), str_cache: CacheSet::new(),
unit_size: 0, unit_size: 0,
units: CodeGenStack::empty(), units: CodeGenStack::empty(),
errs: CompileErrors::empty(), errs: CompileErrors::empty(),

View file

@ -0,0 +1,56 @@
use std::cell::RefCell;
use std::thread::LocalKey;
use erg_common::dict::Dict;
use erg_type::Type;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TypePair {
pub sub: Type,
pub sup: Type,
}
impl TypePair {
pub const fn new(sub: Type, sup: Type) -> Self {
Self { sub, sup }
}
}
#[derive(Debug, Default)]
pub struct TypeCmpCache {
cache: Dict<TypePair, bool>,
}
impl TypeCmpCache {
pub fn new() -> Self {
Self::default()
}
pub fn get(&self, pair: &TypePair) -> Option<bool> {
self.cache.get(pair).map(|b| *b)
}
pub fn register(&mut self, pair: &TypePair, b: bool) {
self.cache.insert(pair.clone(), b);
}
}
thread_local! {
static TYPE_CACHE: RefCell<TypeCmpCache> = RefCell::new(TypeCmpCache::default());
}
#[derive(Debug)]
pub struct GlobalTypeCmpCache(LocalKey<RefCell<TypeCmpCache>>);
pub static GLOBAL_TYPE_CACHE: GlobalTypeCmpCache = GlobalTypeCmpCache(TYPE_CACHE);
impl GlobalTypeCmpCache {
pub fn get(&'static self, pair: &TypePair) -> Option<bool> {
self.0.with(|s| s.borrow().get(pair))
}
pub fn register(&'static self, pair: &TypePair, b: bool) {
self.0.with(|s| s.borrow_mut().register(pair, b));
}
}

View file

@ -84,8 +84,8 @@ impl Context {
let traits: Vec<_> = self let traits: Vec<_> = self
.trait_impls .trait_impls
.iter() .iter()
.map(|(_, sub_and_sup)| { .map(|(_, pair)| {
sub_and_sup.iter().filter_map(|pair| { pair.iter().filter_map(|pair| {
let t_name = pair.sub_type.name(); let t_name = pair.sub_type.name();
let sub_ctx = self.rec_type_ctx_by_name(&t_name).unwrap(); let sub_ctx = self.rec_type_ctx_by_name(&t_name).unwrap();
let bounds = sub_ctx.type_params_bounds(); let bounds = sub_ctx.type_params_bounds();

View file

@ -1,5 +1,6 @@
//! Defines `Context`. //! Defines `Context`.
//! `Context` is used for type inference and type checking. //! `Context` is used for type inference and type checking.
pub mod cache;
pub mod compare; pub mod compare;
pub mod inquire; pub mod inquire;
pub mod instantiate; pub mod instantiate;

View file

@ -1,7 +1,7 @@
//! defines and implements `Lexer` (Tokenizer). //! defines and implements `Lexer` (Tokenizer).
use std::cmp::Ordering; use std::cmp::Ordering;
use erg_common::cache::Cache; use erg_common::cache::CacheSet;
use erg_common::config::ErgConfig; use erg_common::config::ErgConfig;
use erg_common::config::Input; use erg_common::config::Input;
use erg_common::traits::{Locational, Runnable, Stream}; use erg_common::traits::{Locational, Runnable, Stream};
@ -64,7 +64,7 @@ impl Runnable for LexerRunner {
/// This can be used as an iterator or to generate a `TokenStream`. /// This can be used as an iterator or to generate a `TokenStream`.
#[derive(Debug)] #[derive(Debug)]
pub struct Lexer /*<'a>*/ { pub struct Lexer /*<'a>*/ {
str_cache: Cache<str>, str_cache: CacheSet<str>,
chars: Vec<char>, chars: Vec<char>,
indent_stack: Vec<usize>, indent_stack: Vec<usize>,
/// indicates the position in the entire source code /// indicates the position in the entire source code
@ -81,7 +81,7 @@ impl Lexer /*<'a>*/ {
pub fn new(input: Input) -> Self { pub fn new(input: Input) -> Self {
let normed = normalize_newline(&input.read()); let normed = normalize_newline(&input.read());
Lexer { Lexer {
str_cache: Cache::new(), str_cache: CacheSet::new(),
chars: normed.chars().collect::<Vec<char>>(), chars: normed.chars().collect::<Vec<char>>(),
indent_stack: vec![], indent_stack: vec![],
cursor: 0, cursor: 0,
@ -94,7 +94,7 @@ impl Lexer /*<'a>*/ {
pub fn from_str(src: Str) -> Self { pub fn from_str(src: Str) -> Self {
let escaped = normalize_newline(&src); let escaped = normalize_newline(&src);
Lexer { Lexer {
str_cache: Cache::new(), str_cache: CacheSet::new(),
chars: escaped.chars().collect::<Vec<char>>(), chars: escaped.chars().collect::<Vec<char>>(),
indent_stack: vec![], indent_stack: vec![],
cursor: 0, cursor: 0,

View file

@ -2,7 +2,7 @@
use std::process; use std::process;
use std::string::FromUtf8Error; use std::string::FromUtf8Error;
use erg_common::cache::Cache; use erg_common::cache::CacheSet;
use erg_common::config::{ErgConfig, Input}; use erg_common::config::{ErgConfig, Input};
use erg_common::error::{ErrorCore, ErrorKind, Location}; use erg_common::error::{ErrorCore, ErrorKind, Location};
use erg_common::serialize::DataTypePrefix; use erg_common::serialize::DataTypePrefix;
@ -98,17 +98,17 @@ pub type DeserializeResult<T> = Result<T, DeserializeError>;
#[derive(Default)] #[derive(Default)]
pub struct Deserializer { pub struct Deserializer {
str_cache: Cache<str>, str_cache: CacheSet<str>,
arr_cache: Cache<[ValueObj]>, arr_cache: CacheSet<[ValueObj]>,
dict_cache: Cache<[(ValueObj, ValueObj)]>, dict_cache: CacheSet<[(ValueObj, ValueObj)]>,
} }
impl Deserializer { impl Deserializer {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
str_cache: Cache::new(), str_cache: CacheSet::new(),
arr_cache: Cache::new(), arr_cache: CacheSet::new(),
dict_cache: Cache::new(), dict_cache: CacheSet::new(),
} }
} }