mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 13:11:11 +00:00
Delete unnecessary deps
This commit is contained in:
parent
d45919028d
commit
974bfc0b86
11 changed files with 15 additions and 702 deletions
|
@ -1,5 +1,4 @@
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
// use std::io::Write;
|
|
||||||
|
|
||||||
mod datetime;
|
mod datetime;
|
||||||
|
|
||||||
|
|
|
@ -1,220 +0,0 @@
|
||||||
// Copied and modified from https://github.com/rust-itertools/itertools/blob/master/src/combinations.rs
|
|
||||||
// and https://github.com/rust-itertools/itertools/blob/master/src/impl_macros.rs
|
|
||||||
// MIT license | Apache 2.0 license
|
|
||||||
// License files are placed at the root.
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use std::iter::FusedIterator;
|
|
||||||
|
|
||||||
use super::lazy_buffer::LazyBuffer;
|
|
||||||
|
|
||||||
pub struct TotalCombinations<I: Iterator> {
|
|
||||||
combinations: Combinations<I>,
|
|
||||||
len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ```
|
|
||||||
/// let it = total_combinations(0..2);
|
|
||||||
/// itertools::assert_equal(it, vec![
|
|
||||||
/// vec![0],
|
|
||||||
/// vec![1],
|
|
||||||
/// vec![2],
|
|
||||||
/// vec![0, 1],
|
|
||||||
/// vec![0, 2],
|
|
||||||
/// vec![1, 2],
|
|
||||||
/// vec![0, 1, 2],
|
|
||||||
/// ]);
|
|
||||||
///
|
|
||||||
pub fn total_combinations<I>(iter: I) -> TotalCombinations<I>
|
|
||||||
where
|
|
||||||
I: Iterator + ExactSizeIterator,
|
|
||||||
I::Item: Clone,
|
|
||||||
{
|
|
||||||
TotalCombinations {
|
|
||||||
len: iter.len(),
|
|
||||||
combinations: combinations(iter, 1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> Iterator for TotalCombinations<I>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
I::Item: Clone,
|
|
||||||
{
|
|
||||||
type Item = Vec<I::Item>;
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if let Some(i) = self.combinations.next() {
|
|
||||||
Some(i)
|
|
||||||
} else {
|
|
||||||
self.combinations.reset(self.combinations.k() + 1);
|
|
||||||
self.len -= 1;
|
|
||||||
if self.len == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
self.combinations.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> FusedIterator for TotalCombinations<I>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
I::Item: Clone,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! debug_fmt_fields {
|
|
||||||
($tyname:ident, $($($field:tt/*TODO ideally we would accept ident or tuple element here*/).+),*) => {
|
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
|
||||||
f.debug_struct(stringify!($tyname))
|
|
||||||
$(
|
|
||||||
.field(stringify!($($field).+), &self.$($field).+)
|
|
||||||
)*
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! clone_fields {
|
|
||||||
($($field:ident),*) => {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Self {
|
|
||||||
$($field: self.$field.clone(),)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An iterator to iterate through all the `k`-length combinations in an iterator.
|
|
||||||
///
|
|
||||||
/// See [`.combinations()`](crate::Itertools::combinations) for more information.
|
|
||||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
|
||||||
pub struct Combinations<I: Iterator> {
|
|
||||||
indices: Vec<usize>,
|
|
||||||
pool: LazyBuffer<I>,
|
|
||||||
first: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> Clone for Combinations<I>
|
|
||||||
where
|
|
||||||
I: Clone + Iterator,
|
|
||||||
I::Item: Clone,
|
|
||||||
{
|
|
||||||
clone_fields!(indices, pool, first);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> fmt::Debug for Combinations<I>
|
|
||||||
where
|
|
||||||
I: Iterator + fmt::Debug,
|
|
||||||
I::Item: fmt::Debug,
|
|
||||||
{
|
|
||||||
debug_fmt_fields!(Combinations, indices, pool, first);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new `Combinations` from a clonable iterator.
|
|
||||||
pub fn combinations<I>(iter: I, k: usize) -> Combinations<I>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
{
|
|
||||||
let mut pool = LazyBuffer::new(iter);
|
|
||||||
pool.prefill(k);
|
|
||||||
|
|
||||||
Combinations {
|
|
||||||
indices: (0..k).collect(),
|
|
||||||
pool,
|
|
||||||
first: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I: Iterator> Combinations<I> {
|
|
||||||
/// Returns the length of a combination produced by this iterator.
|
|
||||||
#[inline]
|
|
||||||
pub fn k(&self) -> usize {
|
|
||||||
self.indices.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the (current) length of the pool from which combination elements are
|
|
||||||
/// selected. This value can change between invocations of [`next`](Combinations::next).
|
|
||||||
#[inline]
|
|
||||||
pub fn n(&self) -> usize {
|
|
||||||
self.pool.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a reference to the source iterator.
|
|
||||||
#[inline]
|
|
||||||
pub fn src(&self) -> &I {
|
|
||||||
&self.pool.it
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resets this `Combinations` back to an initial state for combinations of length
|
|
||||||
/// `k` over the same pool data source. If `k` is larger than the current length
|
|
||||||
/// of the data pool an attempt is made to prefill the pool so that it holds `k`
|
|
||||||
/// elements.
|
|
||||||
pub fn reset(&mut self, k: usize) {
|
|
||||||
self.first = true;
|
|
||||||
|
|
||||||
if k < self.indices.len() {
|
|
||||||
self.indices.truncate(k);
|
|
||||||
for i in 0..k {
|
|
||||||
self.indices[i] = i;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i in 0..self.indices.len() {
|
|
||||||
self.indices[i] = i;
|
|
||||||
}
|
|
||||||
self.indices.extend(self.indices.len()..k);
|
|
||||||
self.pool.prefill(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> Iterator for Combinations<I>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
I::Item: Clone,
|
|
||||||
{
|
|
||||||
type Item = Vec<I::Item>;
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if self.first {
|
|
||||||
if self.k() > self.n() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
self.first = false;
|
|
||||||
} else if self.indices.is_empty() {
|
|
||||||
return None;
|
|
||||||
} else {
|
|
||||||
// Scan from the end, looking for an index to increment
|
|
||||||
let mut i: usize = self.indices.len() - 1;
|
|
||||||
|
|
||||||
// Check if we need to consume more from the iterator
|
|
||||||
if self.indices[i] == self.pool.len() - 1 {
|
|
||||||
self.pool.get_next(); // may change pool size
|
|
||||||
}
|
|
||||||
|
|
||||||
while self.indices[i] == i + self.pool.len() - self.indices.len() {
|
|
||||||
if i > 0 {
|
|
||||||
i -= 1;
|
|
||||||
} else {
|
|
||||||
// Reached the last combination
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment index, and reset the ones to its right
|
|
||||||
self.indices[i] += 1;
|
|
||||||
for j in i + 1..self.indices.len() {
|
|
||||||
self.indices[j] = self.indices[j - 1] + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create result vector based on the indices
|
|
||||||
Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> FusedIterator for Combinations<I>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
I::Item: Clone,
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -2,12 +2,12 @@
|
||||||
//!
|
//!
|
||||||
//! コマンドオプション(パーサー)を定義する
|
//! コマンドオプション(パーサー)を定義する
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::env::consts::{ARCH, OS};
|
// use std::env::consts::{ARCH, OS};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufRead, BufReader, Read, stdin};
|
use std::io::{BufRead, BufReader, Read, stdin};
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use crate::lazy::Lazy;
|
// use crate::lazy::Lazy;
|
||||||
use crate::stdin;
|
use crate::stdin;
|
||||||
use crate::Str;
|
use crate::Str;
|
||||||
use crate::{power_assert, read_file};
|
use crate::{power_assert, read_file};
|
||||||
|
@ -15,9 +15,6 @@ use crate::{power_assert, read_file};
|
||||||
pub const SEMVER: &str = env!("CARGO_PKG_VERSION");
|
pub const SEMVER: &str = env!("CARGO_PKG_VERSION");
|
||||||
pub const GIT_HASH_SHORT: &str = env!("GIT_HASH_SHORT");
|
pub const GIT_HASH_SHORT: &str = env!("GIT_HASH_SHORT");
|
||||||
pub const BUILD_DATE: &str = env!("BUILD_DATE");
|
pub const BUILD_DATE: &str = env!("BUILD_DATE");
|
||||||
/// TODO: タグを含める
|
|
||||||
pub const BUILD_INFO: Lazy<String> =
|
|
||||||
Lazy::new(|| format!("(tags/?:{GIT_HASH_SHORT}, {BUILD_DATE}) on {ARCH}/{OS}"));
|
|
||||||
|
|
||||||
/// 入力はファイルからだけとは限らないので
|
/// 入力はファイルからだけとは限らないので
|
||||||
/// Inputで操作を一本化する
|
/// Inputで操作を一本化する
|
||||||
|
|
|
@ -1,374 +0,0 @@
|
||||||
// Copied and modified from https://github.com/rust-lang/rust/blob/master/library/core/src/lazy.rs
|
|
||||||
// and https://github.com/rust-lang/rust/blob/master/library/core/src/mem/maybe_uninit.rs
|
|
||||||
// MIT license | Apache 2.0 license
|
|
||||||
// License files are placed at the root.
|
|
||||||
|
|
||||||
//! Lazy values and one-time initialization of static data.
|
|
||||||
|
|
||||||
use std::cell::{Cell, UnsafeCell};
|
|
||||||
use std::fmt;
|
|
||||||
use std::mem;
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
/// A cell which can be written to only once.
|
|
||||||
///
|
|
||||||
/// Unlike `RefCell`, a `OnceCell` only provides shared `&T` references to its value.
|
|
||||||
/// Unlike `Cell`, a `OnceCell` doesn't require copying or replacing the value to access it.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// use std::lazy::OnceCell;
|
|
||||||
///
|
|
||||||
/// let cell = OnceCell::new();
|
|
||||||
/// assert!(cell.get().is_none());
|
|
||||||
///
|
|
||||||
/// let value: &String = cell.get_or_init(|| {
|
|
||||||
/// "Hello, World!".to_string()
|
|
||||||
/// });
|
|
||||||
/// assert_eq!(value, "Hello, World!");
|
|
||||||
/// assert!(cell.get().is_some());
|
|
||||||
/// ```
|
|
||||||
pub struct OnceCell<T> {
|
|
||||||
// Invariant: written to at most once.
|
|
||||||
inner: UnsafeCell<Option<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Default for OnceCell<T> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self.get() {
|
|
||||||
Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
|
|
||||||
None => f.write_str("OnceCell(Uninit)"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone> Clone for OnceCell<T> {
|
|
||||||
fn clone(&self) -> OnceCell<T> {
|
|
||||||
let res = OnceCell::new();
|
|
||||||
if let Some(value) = self.get() {
|
|
||||||
match res.set(value.clone()) {
|
|
||||||
Ok(()) => (),
|
|
||||||
Err(_) => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq> PartialEq for OnceCell<T> {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.get() == other.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Eq> Eq for OnceCell<T> {}
|
|
||||||
|
|
||||||
impl<T> From<T> for OnceCell<T> {
|
|
||||||
fn from(value: T) -> Self {
|
|
||||||
OnceCell {
|
|
||||||
inner: UnsafeCell::new(Some(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> OnceCell<T> {
|
|
||||||
/// Creates a new empty cell.
|
|
||||||
pub const fn new() -> OnceCell<T> {
|
|
||||||
OnceCell {
|
|
||||||
inner: UnsafeCell::new(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the reference to the underlying value.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the cell is empty.
|
|
||||||
pub fn get(&self) -> Option<&T> {
|
|
||||||
// SAFETY: Safe due to `inner`'s invariant
|
|
||||||
unsafe { &*self.inner.get() }.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the mutable reference to the underlying value.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the cell is empty.
|
|
||||||
pub fn get_mut(&mut self) -> Option<&mut T> {
|
|
||||||
// SAFETY: Safe because we have unique access
|
|
||||||
unsafe { &mut *self.inner.get() }.as_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the contents of the cell to `value`.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// This method returns `Ok(())` if the cell was empty and `Err(value)` if
|
|
||||||
/// it was full.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// use std::lazy::OnceCell;
|
|
||||||
///
|
|
||||||
/// let cell = OnceCell::new();
|
|
||||||
/// assert!(cell.get().is_none());
|
|
||||||
///
|
|
||||||
/// assert_eq!(cell.set(92), Ok(()));
|
|
||||||
/// assert_eq!(cell.set(62), Err(62));
|
|
||||||
///
|
|
||||||
/// assert!(cell.get().is_some());
|
|
||||||
/// ```
|
|
||||||
pub fn set(&self, value: T) -> Result<(), T> {
|
|
||||||
// SAFETY: Safe because we cannot have overlapping mutable borrows
|
|
||||||
let slot = unsafe { &*self.inner.get() };
|
|
||||||
if slot.is_some() {
|
|
||||||
return Err(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: This is the only place where we set the slot, no races
|
|
||||||
// due to reentrancy/concurrency are possible, and we've
|
|
||||||
// checked that slot is currently `None`, so this write
|
|
||||||
// maintains the `inner`'s invariant.
|
|
||||||
let slot = unsafe { &mut *self.inner.get() };
|
|
||||||
*slot = Some(value);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the contents of the cell, initializing it with `f`
|
|
||||||
/// if the cell was empty.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// If `f` panics, the panic is propagated to the caller, and the cell
|
|
||||||
/// remains uninitialized.
|
|
||||||
///
|
|
||||||
/// It is an error to reentrantly initialize the cell from `f`. Doing
|
|
||||||
/// so results in a panic.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// use std::lazy::OnceCell;
|
|
||||||
///
|
|
||||||
/// let cell = OnceCell::new();
|
|
||||||
/// let value = cell.get_or_init(|| 92);
|
|
||||||
/// assert_eq!(value, &92);
|
|
||||||
/// let value = cell.get_or_init(|| unreachable!());
|
|
||||||
/// assert_eq!(value, &92);
|
|
||||||
/// ```
|
|
||||||
pub fn get_or_init<F>(&self, f: F) -> &T
|
|
||||||
where
|
|
||||||
F: FnOnce() -> T,
|
|
||||||
{
|
|
||||||
match self.get_or_try_init(|| Ok::<T, ()>(f())) {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(()) => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the contents of the cell, initializing it with `f` if
|
|
||||||
/// the cell was empty. If the cell was empty and `f` failed, an
|
|
||||||
/// error is returned.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// If `f` panics, the panic is propagated to the caller, and the cell
|
|
||||||
/// remains uninitialized.
|
|
||||||
///
|
|
||||||
/// It is an error to reentrantly initialize the cell from `f`. Doing
|
|
||||||
/// so results in a panic.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// use std::lazy::OnceCell;
|
|
||||||
///
|
|
||||||
/// let cell = OnceCell::new();
|
|
||||||
/// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
|
|
||||||
/// assert!(cell.get().is_none());
|
|
||||||
/// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
|
|
||||||
/// Ok(92)
|
|
||||||
/// });
|
|
||||||
/// assert_eq!(value, Ok(&92));
|
|
||||||
/// assert_eq!(cell.get(), Some(&92))
|
|
||||||
/// ```
|
|
||||||
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Result<T, E>,
|
|
||||||
{
|
|
||||||
if let Some(val) = self.get() {
|
|
||||||
return Ok(val);
|
|
||||||
}
|
|
||||||
let val = f()?;
|
|
||||||
// Note that *some* forms of reentrant initialization might lead to
|
|
||||||
// UB (see `reentrant_init` test). I believe that just removing this
|
|
||||||
// `assert`, while keeping `set/get` would be sound, but it seems
|
|
||||||
// better to panic, rather than to silently use an old value.
|
|
||||||
assert!(self.set(val).is_ok(), "reentrant init");
|
|
||||||
Ok(self.get().unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consumes the cell, returning the wrapped value.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the cell was empty.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// use std::lazy::OnceCell;
|
|
||||||
///
|
|
||||||
/// let cell: OnceCell<String> = OnceCell::new();
|
|
||||||
/// assert_eq!(cell.into_inner(), None);
|
|
||||||
///
|
|
||||||
/// let cell = OnceCell::new();
|
|
||||||
/// cell.set("hello".to_string()).unwrap();
|
|
||||||
/// assert_eq!(cell.into_inner(), Some("hello".to_string()));
|
|
||||||
/// ```
|
|
||||||
pub fn into_inner(self) -> Option<T> {
|
|
||||||
// Because `into_inner` takes `self` by value, the compiler statically verifies
|
|
||||||
// that it is not currently borrowed. So it is safe to move out `Option<T>`.
|
|
||||||
self.inner.into_inner()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
|
|
||||||
///
|
|
||||||
/// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
|
|
||||||
///
|
|
||||||
/// Safety is guaranteed by requiring a mutable reference.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// use std::lazy::OnceCell;
|
|
||||||
///
|
|
||||||
/// let mut cell: OnceCell<String> = OnceCell::new();
|
|
||||||
/// assert_eq!(cell.take(), None);
|
|
||||||
///
|
|
||||||
/// let mut cell = OnceCell::new();
|
|
||||||
/// cell.set("hello".to_string()).unwrap();
|
|
||||||
/// assert_eq!(cell.take(), Some("hello".to_string()));
|
|
||||||
/// assert_eq!(cell.get(), None);
|
|
||||||
/// ```
|
|
||||||
pub fn take(&mut self) -> Option<T> {
|
|
||||||
mem::take(self).into_inner()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A value which is initialized on the first access.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// use std::lazy::Lazy;
|
|
||||||
///
|
|
||||||
/// let lazy: Lazy<i32> = Lazy::new(|| {
|
|
||||||
/// println!("initializing");
|
|
||||||
/// 92
|
|
||||||
/// });
|
|
||||||
/// println!("ready");
|
|
||||||
/// println!("{}", *lazy);
|
|
||||||
/// println!("{}", *lazy);
|
|
||||||
///
|
|
||||||
/// // Prints:
|
|
||||||
/// // ready
|
|
||||||
/// // initializing
|
|
||||||
/// // 92
|
|
||||||
/// // 92
|
|
||||||
/// ```
|
|
||||||
pub struct Lazy<T, F = fn() -> T> {
|
|
||||||
cell: OnceCell<T>,
|
|
||||||
init: Cell<Option<F>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.debug_struct("Lazy")
|
|
||||||
.field("cell", &self.cell)
|
|
||||||
.field("init", &"..")
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F> Lazy<T, F> {
|
|
||||||
/// Creates a new lazy value with the given initializing function.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// # fn main() {
|
|
||||||
/// use std::lazy::Lazy;
|
|
||||||
///
|
|
||||||
/// let hello = "Hello, World!".to_string();
|
|
||||||
///
|
|
||||||
/// let lazy = Lazy::new(|| hello.to_uppercase());
|
|
||||||
///
|
|
||||||
/// assert_eq!(&*lazy, "HELLO, WORLD!");
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub const fn new(init: F) -> Lazy<T, F> {
|
|
||||||
Lazy {
|
|
||||||
cell: OnceCell::new(),
|
|
||||||
init: Cell::new(Some(init)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F: FnOnce() -> T> Lazy<T, F> {
|
|
||||||
/// Forces the evaluation of this lazy value and returns a reference to
|
|
||||||
/// the result.
|
|
||||||
///
|
|
||||||
/// This is equivalent to the `Deref` impl, but is explicit.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(once_cell)]
|
|
||||||
///
|
|
||||||
/// use std::lazy::Lazy;
|
|
||||||
///
|
|
||||||
/// let lazy = Lazy::new(|| 92);
|
|
||||||
///
|
|
||||||
/// assert_eq!(Lazy::force(&lazy), &92);
|
|
||||||
/// assert_eq!(&*lazy, &92);
|
|
||||||
/// ```
|
|
||||||
pub fn force(this: &Lazy<T, F>) -> &T {
|
|
||||||
this.cell.get_or_init(|| match this.init.take() {
|
|
||||||
Some(f) => f(),
|
|
||||||
None => panic!("`Lazy` instance has previously been poisoned"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
|
|
||||||
type Target = T;
|
|
||||||
fn deref(&self) -> &T {
|
|
||||||
Lazy::force(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default> Default for Lazy<T> {
|
|
||||||
/// Creates a new lazy value using `Default` as the initializing function.
|
|
||||||
fn default() -> Lazy<T> {
|
|
||||||
Lazy::new(T::default)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
// Copied and modified from https://github.com/rust-itertools/itertools/blob/master/src/lazy_buffer.rs
|
|
||||||
// MIT license | Apache 2.0 license
|
|
||||||
// License files are placed at the root.
|
|
||||||
|
|
||||||
use std::ops::Index;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct LazyBuffer<I: Iterator> {
|
|
||||||
pub it: I,
|
|
||||||
done: bool,
|
|
||||||
buffer: Vec<I::Item>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> LazyBuffer<I>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
{
|
|
||||||
pub fn new(it: I) -> LazyBuffer<I> {
|
|
||||||
LazyBuffer {
|
|
||||||
it,
|
|
||||||
done: false,
|
|
||||||
buffer: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.buffer.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.buffer.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_next(&mut self) -> bool {
|
|
||||||
if self.done {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let next_item = self.it.next();
|
|
||||||
match next_item {
|
|
||||||
Some(x) => {
|
|
||||||
self.buffer.push(x);
|
|
||||||
true
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.done = true;
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prefill(&mut self, len: usize) {
|
|
||||||
let buffer_len = self.buffer.len();
|
|
||||||
|
|
||||||
if !self.done && len > buffer_len {
|
|
||||||
let delta = len - buffer_len;
|
|
||||||
|
|
||||||
self.buffer.extend(self.it.by_ref().take(delta));
|
|
||||||
self.done = self.buffer.len() < len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, J> Index<J> for LazyBuffer<I>
|
|
||||||
where
|
|
||||||
I: Iterator,
|
|
||||||
I::Item: Sized,
|
|
||||||
Vec<I::Item>: Index<J>,
|
|
||||||
{
|
|
||||||
type Output = <Vec<I::Item> as Index<J>>::Output;
|
|
||||||
|
|
||||||
fn index(&self, _index: J) -> &Self::Output {
|
|
||||||
self.buffer.index(_index)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,15 +4,12 @@ use std::fmt;
|
||||||
pub mod cache;
|
pub mod cache;
|
||||||
pub mod codeobj;
|
pub mod codeobj;
|
||||||
pub mod color;
|
pub mod color;
|
||||||
pub mod combinations;
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod datetime;
|
pub mod datetime;
|
||||||
pub mod deserialize;
|
pub mod deserialize;
|
||||||
pub mod dict;
|
pub mod dict;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod fxhash;
|
pub mod fxhash;
|
||||||
pub mod lazy;
|
|
||||||
pub mod lazy_buffer;
|
|
||||||
pub mod levenshtein;
|
pub mod levenshtein;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
pub mod opcode;
|
pub mod opcode;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! defines common traits used in the compiler.
|
//! defines common traits used in the compiler.
|
||||||
//!
|
//!
|
||||||
//! コンパイラ等で汎用的に使われるトレイトを定義する
|
//! コンパイラ等で汎用的に使われるトレイトを定義する
|
||||||
|
use std::env::consts::{ARCH, OS};
|
||||||
use std::io::{stdout, BufWriter, Write};
|
use std::io::{stdout, BufWriter, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
@ -8,7 +9,7 @@ use std::slice::{Iter, IterMut};
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
use crate::color::{GREEN, RESET};
|
use crate::color::{GREEN, RESET};
|
||||||
use crate::config::{ErgConfig, Input};
|
use crate::config::{ErgConfig, Input, SEMVER, GIT_HASH_SHORT, BUILD_DATE};
|
||||||
use crate::error::{ErrorDisplay, Location, MultiErrorDisplay};
|
use crate::error::{ErrorDisplay, Location, MultiErrorDisplay};
|
||||||
use crate::ty::Type;
|
use crate::ty::Type;
|
||||||
use crate::Str;
|
use crate::Str;
|
||||||
|
@ -308,9 +309,12 @@ fn expect_block(src: &str) -> bool {
|
||||||
pub trait Runnable: Sized {
|
pub trait Runnable: Sized {
|
||||||
type Err: ErrorDisplay;
|
type Err: ErrorDisplay;
|
||||||
type Errs: MultiErrorDisplay<Self::Err>;
|
type Errs: MultiErrorDisplay<Self::Err>;
|
||||||
|
const NAME: &'static str;
|
||||||
fn new(cfg: ErgConfig) -> Self;
|
fn new(cfg: ErgConfig) -> Self;
|
||||||
fn input(&self) -> &Input;
|
fn input(&self) -> &Input;
|
||||||
fn start_message(&self) -> String;
|
fn start_message(&self) -> String {
|
||||||
|
format!("{} {SEMVER} tags/?:{GIT_HASH_SHORT}, {BUILD_DATE}) on {ARCH}/{OS}\n", Self::NAME)
|
||||||
|
}
|
||||||
fn finish(&mut self); // called when the :exit command is received.
|
fn finish(&mut self); // called when the :exit command is received.
|
||||||
fn clear(&mut self);
|
fn clear(&mut self);
|
||||||
fn eval(&mut self, src: Str) -> Result<String, Self::Errs>;
|
fn eval(&mut self, src: Str) -> Result<String, Self::Errs>;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use erg_common::codeobj::{CodeObj, CodeObjFlags};
|
use erg_common::codeobj::{CodeObj, CodeObjFlags};
|
||||||
use erg_common::color::{GREEN, RESET};
|
use erg_common::color::{GREEN, RESET};
|
||||||
use erg_common::config::{ErgConfig, Input, BUILD_INFO, SEMVER};
|
use erg_common::config::{ErgConfig, Input};
|
||||||
use erg_common::error::MultiErrorDisplay;
|
use erg_common::error::MultiErrorDisplay;
|
||||||
use erg_common::log;
|
use erg_common::log;
|
||||||
use erg_common::traits::{Runnable, Stream};
|
use erg_common::traits::{Runnable, Stream};
|
||||||
|
@ -104,6 +104,7 @@ pub struct Compiler {
|
||||||
impl Runnable for Compiler {
|
impl Runnable for Compiler {
|
||||||
type Err = CompileError;
|
type Err = CompileError;
|
||||||
type Errs = CompileErrors;
|
type Errs = CompileErrors;
|
||||||
|
const NAME: &'static str = "Erg compiler";
|
||||||
|
|
||||||
fn new(cfg: ErgConfig) -> Self {
|
fn new(cfg: ErgConfig) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -118,11 +119,6 @@ impl Runnable for Compiler {
|
||||||
&self.cfg.input
|
&self.cfg.input
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn start_message(&self) -> String {
|
|
||||||
format!("Erg compiler {} {}\n", SEMVER, &*BUILD_INFO)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn finish(&mut self) {}
|
fn finish(&mut self) {}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub struct LexerRunner {
|
||||||
impl Runnable for LexerRunner {
|
impl Runnable for LexerRunner {
|
||||||
type Err = LexerRunnerError;
|
type Err = LexerRunnerError;
|
||||||
type Errs = LexerRunnerErrors;
|
type Errs = LexerRunnerErrors;
|
||||||
|
const NAME: &'static str = "Erg lexer";
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(cfg: ErgConfig) -> Self {
|
fn new(cfg: ErgConfig) -> Self {
|
||||||
|
@ -31,11 +32,6 @@ impl Runnable for LexerRunner {
|
||||||
&self.cfg.input
|
&self.cfg.input
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn start_message(&self) -> String {
|
|
||||||
"Erg lexer\n".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn finish(&mut self) {}
|
fn finish(&mut self) {}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::mem;
|
||||||
|
|
||||||
use erg_common::color::{GREEN, RED, RESET};
|
use erg_common::color::{GREEN, RED, RESET};
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
use erg_common::config::{Input, BUILD_INFO, SEMVER};
|
use erg_common::config::{Input};
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
use erg_common::traits::Runnable;
|
use erg_common::traits::Runnable;
|
||||||
|
@ -272,6 +272,7 @@ pub struct ParserRunner {
|
||||||
impl Runnable for ParserRunner {
|
impl Runnable for ParserRunner {
|
||||||
type Err = ParserRunnerError;
|
type Err = ParserRunnerError;
|
||||||
type Errs = ParserRunnerErrors;
|
type Errs = ParserRunnerErrors;
|
||||||
|
const NAME: &'static str = "Erg parser";
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(cfg: ErgConfig) -> Self {
|
fn new(cfg: ErgConfig) -> Self {
|
||||||
|
@ -283,11 +284,6 @@ impl Runnable for ParserRunner {
|
||||||
&self.cfg.input
|
&self.cfg.input
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn start_message(&self) -> String {
|
|
||||||
format!("Erg parser {} {}\n", SEMVER, &*BUILD_INFO)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn finish(&mut self) {}
|
fn finish(&mut self) {}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::net::TcpStream;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use erg_common::config::{ErgConfig, Input, BUILD_INFO, SEMVER};
|
use erg_common::config::{ErgConfig, Input};
|
||||||
use erg_common::python_util::{exec_py, exec_pyc};
|
use erg_common::python_util::{exec_py, exec_pyc};
|
||||||
use erg_common::str::Str;
|
use erg_common::str::Str;
|
||||||
use erg_common::traits::Runnable;
|
use erg_common::traits::Runnable;
|
||||||
|
@ -23,6 +23,7 @@ pub struct DummyVM {
|
||||||
impl Runnable for DummyVM {
|
impl Runnable for DummyVM {
|
||||||
type Err = CompileError;
|
type Err = CompileError;
|
||||||
type Errs = CompileErrors;
|
type Errs = CompileErrors;
|
||||||
|
const NAME: &'static str = "Erg interpreter";
|
||||||
|
|
||||||
fn new(cfg: ErgConfig) -> Self {
|
fn new(cfg: ErgConfig) -> Self {
|
||||||
let stream = if cfg.input.is_repl() {
|
let stream = if cfg.input.is_repl() {
|
||||||
|
@ -59,11 +60,6 @@ impl Runnable for DummyVM {
|
||||||
&self.cfg.input
|
&self.cfg.input
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn start_message(&self) -> String {
|
|
||||||
format!("Erg interpreter {} {}\n", SEMVER, &*BUILD_INFO)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finish(&mut self) {
|
fn finish(&mut self) {
|
||||||
if let Some(stream) = &mut self.stream {
|
if let Some(stream) = &mut self.stream {
|
||||||
stream.write_all("exit".as_bytes()).unwrap();
|
stream.write_all("exit".as_bytes()).unwrap();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue