mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 14:04:33 +00:00
Add TypeCmpCache
This commit is contained in:
parent
592671af96
commit
8e73b9b6b7
9 changed files with 105 additions and 39 deletions
|
@ -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>>>);
|
||||||
|
|
|
@ -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"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
56
compiler/erg_compiler/context/cache.rs
Normal file
56
compiler/erg_compiler/context/cache.rs
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue