Apply trivial clippy fixes

This commit is contained in:
Félix Saparelli 2022-08-15 17:37:20 +12:00
parent 6d3dda8129
commit 7d3116f546
No known key found for this signature in database
GPG key ID: B948C4BAE44FC474
26 changed files with 360 additions and 384 deletions

View file

@ -58,33 +58,33 @@ pub enum CodeObjFlags {
Illegal = 0x0000,
}
impl Into<CodeObjFlags> for u32 {
fn into(self) -> CodeObjFlags {
match self {
0x0001 => CodeObjFlags::Optimized,
0x0002 => CodeObjFlags::NewLocals,
0x0004 => CodeObjFlags::VarArgs,
0x0008 => CodeObjFlags::VarKeywords,
0x0010 => CodeObjFlags::Nested,
0x0020 => CodeObjFlags::Generator,
0x0040 => CodeObjFlags::NoFree,
0x0080 => CodeObjFlags::Coroutine,
0x0100 => CodeObjFlags::IterableCoroutine,
0x0200 => CodeObjFlags::AsyncGenerator,
impl From<u32> for CodeObjFlags {
fn from(flags: u32) -> Self {
match flags {
0x0001 => Self::Optimized,
0x0002 => Self::NewLocals,
0x0004 => Self::VarArgs,
0x0008 => Self::VarKeywords,
0x0010 => Self::Nested,
0x0020 => Self::Generator,
0x0040 => Self::NoFree,
0x0080 => Self::Coroutine,
0x0100 => Self::IterableCoroutine,
0x0200 => Self::AsyncGenerator,
// CO_GENERATOR_ALLOWED,
0x2000 => CodeObjFlags::FutureDivision,
0x4000 => CodeObjFlags::FutureAbsoluteImport,
0x8000 => CodeObjFlags::FutureWithStatement,
0x1_0000 => CodeObjFlags::FuturePrintFunction,
0x2_0000 => CodeObjFlags::FutureUnicodeLiterals,
0x4_0000 => CodeObjFlags::FutureBarryAsBDFL,
0x8_0000 => CodeObjFlags::FutureGeneratorStop,
0x10_0000 => CodeObjFlags::FutureAnnotations,
0x2000 => Self::FutureDivision,
0x4000 => Self::FutureAbsoluteImport,
0x8000 => Self::FutureWithStatement,
0x1_0000 => Self::FuturePrintFunction,
0x2_0000 => Self::FutureUnicodeLiterals,
0x4_0000 => Self::FutureBarryAsBDFL,
0x8_0000 => Self::FutureGeneratorStop,
0x10_0000 => Self::FutureAnnotations,
// EVM flags
0x1000_0000 => CodeObjFlags::EvmDynParam,
0x2000_0000 => CodeObjFlags::EvmDynamic,
0x4000_0000 => CodeObjFlags::EvmNoGC,
_ => CodeObjFlags::Illegal,
0x1000_0000 => Self::EvmDynParam,
0x2000_0000 => Self::EvmDynamic,
0x4000_0000 => Self::EvmNoGC,
_ => Self::Illegal,
}
}
}
@ -330,31 +330,31 @@ impl CodeObj {
fn tables_info(&self) -> String {
let mut tables = "".to_string();
if !self.consts.is_empty() {
tables += &format!("Constants:\n");
tables += "Constants:\n";
}
for (i, obj) in self.consts.iter().enumerate() {
tables += &format!(" {}: {}\n", i, obj);
}
if !self.names.is_empty() {
tables += &format!("Names:\n");
tables += "Names:\n";
}
for (i, name) in self.names.iter().enumerate() {
tables += &format!(" {}: {}\n", i, name);
}
if !self.varnames.is_empty() {
tables += &format!("Varnames:\n");
tables += "Varnames:\n";
}
for (i, varname) in self.varnames.iter().enumerate() {
tables += &format!(" {}: {}\n", i, varname);
}
if !self.cellvars.is_empty() {
tables += &format!("Cellvars:\n");
tables += "Cellvars:\n";
}
for (i, cellvar) in self.cellvars.iter().enumerate() {
tables += &format!(" {}: {}\n", i, cellvar);
}
if !self.freevars.is_empty() {
tables += &format!("Freevars:\n");
tables += "Freevars:\n";
}
for (i, freevar) in self.freevars.iter().enumerate() {
tables += &format!(" {}: {}\n", i, freevar);

View file

@ -1,6 +1,6 @@
use std::borrow::Borrow;
use std::collections::hash_map::{IntoIter, IntoValues, Iter, IterMut, Keys, Values, ValuesMut};
use std::fmt;
use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
@ -42,7 +42,7 @@ impl<K: fmt::Display, V: fmt::Display> fmt::Display for Dict<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = "".to_string();
for (k, v) in self.dict.iter() {
s += &format!("{k}: {v}, ");
write!(s, "{k}: {v}, ")?;
}
s.pop();
s.pop();

View file

@ -328,8 +328,8 @@ impl ErrorCore {
}
}
pub const VBAR_UNICODE: &'static str = "";
pub const VBAR_BREAK_UNICODE: &'static str = "·";
pub const VBAR_UNICODE: &str = "";
pub const VBAR_BREAK_UNICODE: &str = "·";
/// format:
/// ```console
@ -399,9 +399,9 @@ pub trait ErrorDisplay {
let kind = self.core().kind as u8;
let (color, err_or_warn) = if kind < 100 {
(RED, "Error")
} else if 100 <= kind && kind < 150 {
} else if (100..150).contains(&kind) {
(YELLOW, "Warning")
} else if 150 <= kind && kind < 200 {
} else if (150..200).contains(&kind) {
(DEEP_RED, "Error")
} else {
("", "Exception")

View file

@ -52,6 +52,7 @@ pub type FxHashSet<T> = HashSet<T, BuildHasherDefault<FxHasher>>;
/// out-performs an FNV-based hash within rustc itself -- the collision rate is
/// similar or slightly worse than FNV, but the speed of the hash function
/// itself is much higher because it works on up to 8 bytes at a time.
#[derive(Default)]
pub struct FxHasher {
hash: usize,
}
@ -61,13 +62,6 @@ const K: usize = 0x9e3779b9;
#[cfg(target_pointer_width = "64")]
const K: usize = 0x517cc1b727220a95;
impl Default for FxHasher {
#[inline]
fn default() -> FxHasher {
FxHasher { hash: 0 }
}
}
impl FxHasher {
#[inline]
fn add_to_hash(&mut self, i: usize) {
@ -97,7 +91,7 @@ impl Hasher for FxHasher {
hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize);
bytes = &bytes[2..];
}
if (size_of::<usize>() > 1) && bytes.len() >= 1 {
if (size_of::<usize>() > 1) && !bytes.is_empty() {
hash.add_to_hash(bytes[0] as usize);
}
self.hash = hash.hash;

View file

@ -27,6 +27,10 @@ where
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;

View file

@ -43,7 +43,7 @@ pub fn read_file(mut f: std::fs::File) -> std::io::Result<String> {
Ok(s)
}
pub fn fmt_vec<T: fmt::Display>(v: &Vec<T>) -> String {
pub fn fmt_vec<T: fmt::Display>(v: &[T]) -> String {
fmt_iter(v.iter())
}
@ -51,7 +51,7 @@ pub fn fmt_slice<T: fmt::Display>(v: &[T]) -> String {
fmt_iter(v.iter())
}
pub fn fmt_vec_split_with<T: fmt::Display>(v: &Vec<T>, splitter: &str) -> String {
pub fn fmt_vec_split_with<T: fmt::Display>(v: &[T], splitter: &str) -> String {
fmt_iter_split_with(v.iter(), splitter)
}
@ -102,13 +102,13 @@ pub fn get_hash<T: std::hash::Hash>(t: &T) -> usize {
/// \r\n (Windows), \r (old MacOS) -> \n (Unix)
#[inline]
pub fn normalize_newline(src: &str) -> String {
src.replace("\r\n", "\n").replace("\r", "\n")
src.replace("\r\n", "\n").replace('\r', "\n")
}
/// cut \n
#[inline]
pub fn chomp(src: &str) -> String {
normalize_newline(src).replace("\n", "")
normalize_newline(src).replace('\n', "")
}
pub fn try_map<T, U, E, F, I>(i: I, f: F) -> Result<Vec<U>, E>

View file

@ -20,7 +20,7 @@ pub fn which_python() -> String {
if res.is_empty() {
panic!("python not found");
}
res.to_string()
res
}
pub fn detect_magic_number() -> u32 {

View file

@ -37,30 +37,30 @@ pub fn get_timestamp_bytes() -> [u8; 4] {
pub enum DataTypePrefix {
/* sized objects */
Illegal = 0,
Int32 = 'i' as u8, // 0x69
Int64 = 'I' as u8, // 0x49
Float = 'f' as u8, // 0x66 (float32, not generated anymore?)
BinFloat = 'g' as u8, // 0x67 (float64)
Complex = 'x' as u8, // 0x78
BinComplex = 'y' as u8, // 0x79
True = 'T' as u8, // 0x54
False = 'F' as u8, // 0x46
None = 'N' as u8, // 0x4E
StopIter = 'S' as u8, // 0x53
Ref = 'r' as u8,
Int32 = b'i', // 0x69
Int64 = b'I', // 0x49
Float = b'f', // 0x66 (float32, not generated anymore?)
BinFloat = b'g', // 0x67 (float64)
Complex = b'x', // 0x78
BinComplex = b'y', // 0x79
True = b'T', // 0x54
False = b'F', // 0x46
None = b'N', // 0x4E
StopIter = b'S', // 0x53
Ref = b'r',
/* unsized objects (ref counted) */
Long = 'l' as u8, // 0x6C + len: u32 + payload: 2*len+3byte (~ -2^31-1 && 2^31 ~)
Str = 's' as u8, // 0x73 + len: u32 + payload
ShortAscii = 'z' as u8, // 0x7A + len: u8 + payload
ShortAsciiInterned = 'Z' as u8, // 0x5A + len: u8 + payload
Unicode = 'u' as u8, // 0x75 + len: u32 + payload
Interned = 't' as u8, // 0x74 + len + payload
SmallTuple = ')' as u8, // 0x29 + len: u8 + payload
Tuple = '(' as u8, // 0x28 + len: u32 + payload
Code = 'c' as u8, // 0x63
Long = b'l', // 0x6C + len: u32 + payload: 2*len+3byte (~ -2^31-1 && 2^31 ~)
Str = b's', // 0x73 + len: u32 + payload
ShortAscii = b'z', // 0x7A + len: u8 + payload
ShortAsciiInterned = b'Z', // 0x5A + len: u8 + payload
Unicode = b'u', // 0x75 + len: u32 + payload
Interned = b't', // 0x74 + len + payload
SmallTuple = b')', // 0x29 + len: u8 + payload
Tuple = b'(', // 0x28 + len: u32 + payload
Code = b'c', // 0x63
/* Erg specific prefix */
Builtin = 'b' as u8, // 0x62 + str
Nat = 'n' as u8,
Builtin = b'b', // 0x62 + str
Nat = b'n',
}
impl_display_from_debug!(DataTypePrefix);
@ -103,7 +103,7 @@ impl From<u8> for DataTypePrefix {
impl DataTypePrefix {
pub const fn is_sized(&self) -> bool {
match self {
matches!(self,
Self::Long
| Self::Str
| Self::ShortAscii
@ -113,9 +113,7 @@ impl DataTypePrefix {
| Self::SmallTuple
| Self::Tuple
| Self::Code
| Self::Builtin => false,
_ => true,
}
| Self::Builtin)
}
}

View file

@ -168,7 +168,7 @@ impl<T: Hash + Eq + Clone> Set<T> {
pub fn union(&self, other: &Set<T>) -> Set<T> {
let u = self.elems.union(&other.elems);
Self {
elems: u.into_iter().map(|x| x.clone()).collect(),
elems: u.into_iter().cloned().collect(),
}
}
@ -176,7 +176,7 @@ impl<T: Hash + Eq + Clone> Set<T> {
pub fn intersection(&self, other: &Set<T>) -> Set<T> {
let u = self.elems.intersection(&other.elems);
Self {
elems: u.into_iter().map(|x| x.clone()).collect(),
elems: u.into_iter().cloned().collect(),
}
}
}

View file

@ -32,7 +32,7 @@ impl Add<&str> for Str {
impl Hash for Str {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Str::Rc(s) => (&s[..]).hash(state),
Str::Rc(s) => (s[..]).hash(state),
Str::Static(s) => s.hash(state),
}
}
@ -59,14 +59,14 @@ impl From<&'static str> for Str {
impl From<&String> for Str {
#[inline]
fn from(s: &String) -> Self {
Str::Rc((&s[..]).into())
Str::Rc((s[..]).into())
}
}
impl From<String> for Str {
#[inline]
fn from(s: String) -> Self {
Str::Rc((&s[..]).into())
Str::Rc((s[..]).into())
}
}

View file

@ -44,7 +44,7 @@ fn reorder_by_key<T: Eq, U>(mut g: Graph<T, U>, idx: Vec<T>) -> Graph<T, U> {
fn dfs<T: Eq + Hash + Clone, U>(g: &Graph<T, U>, v: T, used: &mut Set<T>, idx: &mut Vec<T>) {
used.insert(v.clone());
for node_id in g.iter().find(|n| &n.id == &v).unwrap().depends_on.iter() {
for node_id in g.iter().find(|n| n.id == v).unwrap().depends_on.iter() {
if !used.contains(node_id) {
dfs(g, node_id.clone(), used, idx);
}

View file

@ -67,7 +67,7 @@ thread_local! {
pub fn fresh_varname() -> String {
REFINEMENT_VAR_ID.with(|id| {
*id.borrow_mut() += 1;
let i = id.borrow().clone();
let i = *id.borrow();
format!("%v{i}")
})
}
@ -75,7 +75,7 @@ pub fn fresh_varname() -> String {
pub fn fresh_param_name() -> String {
REFINEMENT_VAR_ID.with(|id| {
*id.borrow_mut() += 1;
let i = id.borrow().clone();
let i = *id.borrow();
format!("%p{i}")
})
}
@ -1472,9 +1472,9 @@ impl HasLevel for SubrKind {
Self::FuncMethod(t) => t.update_level(level),
Self::ProcMethod { before, after } => {
before.update_level(level);
after.as_ref().map(|t| {
if let Some(t) = after.as_ref() {
t.update_level(level);
});
}
}
_ => {}
}
@ -1485,9 +1485,9 @@ impl HasLevel for SubrKind {
Self::FuncMethod(t) => t.lift(),
Self::ProcMethod { before, after } => {
before.lift();
after.as_ref().map(|t| {
if let Some(t) = after.as_ref() {
t.lift();
});
}
}
_ => {}
}
@ -1546,13 +1546,11 @@ impl SubrKind {
}
pub fn same_kind_as(&self, other: &Self) -> bool {
match (self, other) {
matches!((self, other),
(Self::Func, Self::Func)
| (Self::Proc, Self::Proc)
| (Self::FuncMethod(_), Self::FuncMethod(_))
| (Self::ProcMethod { .. }, Self::ProcMethod { .. }) => true,
_ => false,
}
| (Self::ProcMethod { .. }, Self::ProcMethod { .. }))
}
pub fn self_t(&self) -> Option<&SelfType> {
@ -2029,7 +2027,7 @@ impl Type {
Predicate::le(name.clone(), r),
),
IntervalOp::Open if l == TyParam::value(NegInf) && r == TyParam::value(Inf) => {
return Type::refinement(name.clone(), Type::Int, set! {})
return Type::refinement(name, Type::Int, set! {})
}
// l<..<r => {I: classof(l) | I >= l+ε and I <= r-ε}
IntervalOp::Open => Predicate::and(
@ -2037,7 +2035,7 @@ impl Type {
Predicate::le(name.clone(), TyParam::pred(r)),
),
};
Type::refinement(name.clone(), Type::Int, set! {pred})
Type::refinement(name, Type::Int, set! {pred})
}
pub fn iter(t: Type) -> Self {
@ -2333,7 +2331,7 @@ impl Type {
if fv.is_linked() {
fv.crack().is_mut()
} else {
fv.unbound_name().unwrap().ends_with("!")
fv.unbound_name().unwrap().ends_with('!')
}
}
Self::IntMut
@ -2346,7 +2344,7 @@ impl Type {
| Self::MonoQVar(name)
| Self::Poly { name, .. }
| Self::PolyQVar { name, .. }
| Self::MonoProj { rhs: name, .. } => name.ends_with("!"),
| Self::MonoProj { rhs: name, .. } => name.ends_with('!'),
_ => false,
}
}
@ -2460,9 +2458,9 @@ impl Type {
},
) => todo!(),
(Self::Record(_l), Self::Record(_r)) => todo!(),
(Self::Refinement(l), Self::Refinement(r)) => l.t.rec_eq(&r.t) && &l.preds == &r.preds,
(Self::Refinement(l), Self::Refinement(r)) => l.t.rec_eq(&r.t) && l.preds == r.preds,
(Self::Quantified(l), Self::Quantified(r)) => {
l.unbound_callable.rec_eq(&r.unbound_callable) && &l.bounds == &r.bounds
l.unbound_callable.rec_eq(&r.unbound_callable) && l.bounds == r.bounds
}
(Self::And(l), Self::And(r))
| (Self::Not(l), Self::Not(r))
@ -2567,7 +2565,7 @@ impl Type {
Self::Callable { .. } => "Callable",
Self::Record(_) => "Record",
Self::VarArgs(_) => "VarArgs",
Self::Poly { name, .. } | Self::PolyQVar { name, .. } => &*name,
Self::Poly { name, .. } | Self::PolyQVar { name, .. } => name,
// NOTE: compiler/codegen/convert_to_python_methodでクラス名を使うため、こうすると都合が良い
Self::Refinement(refine) => refine.t.name(),
Self::Quantified(_) => "Quantified",
@ -3038,7 +3036,7 @@ impl From<u8> for TypePair {
62 => Self::ProcArray,
63 => Self::ProcProc,
64 => Self::Others,
65 | _ => Self::Illegals,
_ => Self::Illegals,
}
}
}

View file

@ -2,7 +2,7 @@
//!
//! コンパイラ、VM等で使われる(データも保持した)値オブジェクトを定義する
use std::cmp::Ordering;
use std::fmt;
use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
use std::ops::Neg;
use std::rc::Rc;
@ -56,7 +56,7 @@ impl fmt::Debug for ValueObj {
Self::Dict(dict) => {
let mut s = "".to_string();
for (k, v) in dict.iter() {
s += &format!("{k}: {v}, ");
write!(s, "{k}: {v}, ")?;
}
s.pop();
s.pop();
@ -255,11 +255,11 @@ impl ValueObj {
pub fn from_str(t: Type, content: Str) -> Self {
match t {
Type::Int => Self::Int(content.replace("_", "").parse::<i32>().unwrap()),
Type::Nat => Self::Nat(content.replace("_", "").parse::<u64>().unwrap()),
Type::Float => Self::Float(content.replace("_", "").parse::<f64>().unwrap()),
Type::Int => Self::Int(content.replace('_', "").parse::<i32>().unwrap()),
Type::Nat => Self::Nat(content.replace('_', "").parse::<u64>().unwrap()),
Type::Float => Self::Float(content.replace('_', "").parse::<f64>().unwrap()),
// TODO:
Type::Ratio => Self::Float(content.replace("_", "").parse::<f64>().unwrap()),
Type::Ratio => Self::Float(content.replace('_', "").parse::<f64>().unwrap()),
Type::Str => {
if &content[..] == "\"\"" {
Self::Str(Str::from(""))
@ -288,18 +288,18 @@ impl ValueObj {
match self {
Self::Int(i) => [
vec![DataTypePrefix::Int32 as u8],
i32::from(i).to_le_bytes().to_vec(),
i.to_le_bytes().to_vec(),
]
.concat(),
// TODO: Natとしてシリアライズ
Self::Nat(n) => [
vec![DataTypePrefix::Int32 as u8],
i32::from(n as i32).to_le_bytes().to_vec(),
(n as i32).to_le_bytes().to_vec(),
]
.concat(),
Self::Float(f) => [
vec![DataTypePrefix::BinFloat as u8],
f64::from(f).to_le_bytes().to_vec(),
f.to_le_bytes().to_vec(),
]
.concat(),
Self::Str(s) => str_into_bytes(s, false),
@ -310,7 +310,7 @@ impl ValueObj {
let mut bytes = Vec::with_capacity(arr.len());
bytes.push(DataTypePrefix::Tuple as u8);
bytes.append(&mut (arr.len() as u32).to_le_bytes().to_vec());
for obj in arr.to_vec().into_iter() {
for obj in arr.iter().cloned() {
bytes.append(&mut obj.into_bytes());
}
bytes

View file

@ -51,8 +51,8 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -
fn escape_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -> Str {
let mut name = convert_to_python_attr(class, uniq_obj_name, name).to_string();
name = name.replace("!", "__erg_proc__");
name = name.replace("$", "__erg_shared__");
name = name.replace('!', "__erg_proc__");
name = name.replace('$', "__erg_shared__");
Str::rc(&name)
}
@ -78,8 +78,8 @@ fn convert_to_python_name(name: Str) -> Str {
fn escape_name(name: Str) -> Str {
let mut name = convert_to_python_name(name).to_string();
name = name.replace("!", "__erg_proc__");
name = name.replace("$", "__erg_shared__");
name = name.replace('!', "__erg_proc__");
name = name.replace('$', "__erg_shared__");
Str::rc(&name)
}
@ -290,15 +290,12 @@ impl CodeGenerator {
} else {
Some(Name::fast(idx))
}
} else if let Some(idx) = self
} else { self
.cur_block_codeobj()
.freevars
.iter()
.position(|f| &**f == name)
{
Some(Name::deref(idx))
} else {
None
.map(Name::deref)
}
}
@ -307,7 +304,7 @@ impl CodeGenerator {
// search_name()を実行した後なのでcur_blockはskipする
for (nth_from_toplevel, block) in self.units.iter_mut().enumerate().rev().skip(1) {
let block_is_toplevel = nth_from_toplevel == 0;
if let Some(_) = block.codeobj.cellvars.iter().position(|c| &**c == name) {
if block.codeobj.cellvars.iter().any(|c| &**c == name) {
return Some(StoreLoadKind::Deref);
} else if let Some(idx) = block.codeobj.varnames.iter().position(|v| &**v == name) {
if block_is_toplevel {
@ -319,10 +316,8 @@ impl CodeGenerator {
return Some(StoreLoadKind::Deref);
}
}
if block_is_toplevel {
if let Some(_) = block.codeobj.names.iter().position(|n| &**n == name) {
return Some(StoreLoadKind::Global);
}
if block_is_toplevel && block.codeobj.names.iter().any(|n| &**n == name) {
return Some(StoreLoadKind::Global);
}
}
// 見つからなかった変数(前方参照変数など)はグローバル
@ -363,14 +358,14 @@ impl CodeGenerator {
}
fn register_attr(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name {
let name = Str::rc(name.split(".").last().unwrap());
let name = Str::rc(name.split('.').last().unwrap());
let name = escape_attr(class, uniq_obj_name, name);
self.mut_cur_block_codeobj().names.push(name);
Name::local(self.cur_block_codeobj().names.len() - 1)
}
fn register_method(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name {
let name = Str::rc(name.split(".").last().unwrap());
let name = Str::rc(name.split('.').last().unwrap());
let name = escape_attr(class, uniq_obj_name, name);
self.mut_cur_block_codeobj().names.push(name);
Name::local(self.cur_block_codeobj().names.len() - 1)
@ -493,7 +488,7 @@ impl CodeGenerator {
.iter()
.map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")),
)
.map(|s| self.get_cached(&s))
.map(|s| self.get_cached(s))
.collect()
}
@ -590,7 +585,7 @@ impl CodeGenerator {
let idx_pop_jump_if_false = self.cur_block().lasti;
self.write_instr(POP_JUMP_IF_FALSE);
// cannot detect where to jump to at this moment, so put as 0
self.write_arg(0 as u8);
self.write_arg(0_u8);
match args.remove(0) {
// then block
Expr::Lambda(lambda) => {
@ -603,7 +598,7 @@ impl CodeGenerator {
}
if args.get(0).is_some() {
self.write_instr(JUMP_FORWARD); // jump to end
self.write_arg(0 as u8);
self.write_arg(0_u8);
// else block
let idx_else_begin = self.cur_block().lasti;
self.edit_code(idx_pop_jump_if_false + 1, idx_else_begin / 2);
@ -659,7 +654,7 @@ impl CodeGenerator {
let mut absolute_jump_points = vec![];
while let Some(expr) = args.try_remove(0) {
// パターンが複数ある場合引数を複製する、ただし最後はしない
if len > 1 && args.len() > 0 {
if len > 1 && !args.is_empty() {
self.write_instr(Opcode::DUP_TOP);
self.write_arg(0);
self.stack_inc();
@ -1145,9 +1140,9 @@ impl CodeGenerator {
if !self.units.is_empty() {
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
if ld != 0 {
self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| {
if let Some(l) = self.mut_cur_block_codeobj().lnotab.last_mut() {
*l += ld as u8;
});
}
self.mut_cur_block().prev_lineno += ld;
}
}
@ -1204,9 +1199,9 @@ impl CodeGenerator {
if !self.units.is_empty() {
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
if ld != 0 {
self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| {
if let Some(l) = self.mut_cur_block_codeobj().lnotab.last_mut() {
*l += ld as u8;
});
}
self.mut_cur_block().prev_lineno += ld;
}
}
@ -1242,7 +1237,7 @@ impl CodeGenerator {
self.edit_code(print_point, Opcode::NOP as usize);
} else {
self.write_instr(CALL_FUNCTION);
self.write_arg(1 as u8);
self.write_arg(1_u8);
}
self.stack_dec();
}
@ -1271,9 +1266,9 @@ impl CodeGenerator {
if !self.units.is_empty() {
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
if ld != 0 {
self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| {
if let Some(l) = self.mut_cur_block_codeobj().lnotab.last_mut() {
*l += ld as u8;
});
}
self.mut_cur_block().prev_lineno += ld;
}
}

View file

@ -176,7 +176,7 @@ impl TyVarContext {
Type::Poly { params, .. } => params.iter().fold(dep, |acc, arg| {
[acc, Self::rec_tp_inner_qvars(arg, vec![])].concat()
}),
Type::VarArgs(t) => Self::rec_t_inner_qvars(&t, dep),
Type::VarArgs(t) => Self::rec_t_inner_qvars(t, dep),
Type::Subr(_subr) => todo!(),
Type::Callable { param_ts: _, return_t: _ } => todo!(),
Type::And(_) | Type::Or(_) | Type::Not(_) => todo!(),
@ -210,11 +210,10 @@ impl TyVarContext {
TyBound::Subtype { sub, sup } => {
let sup = match sup {
Type::Poly { name, params } => {
let sup = Type::poly(
Type::poly(
name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
);
sup
)
}
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
sup => sup,
@ -226,11 +225,10 @@ impl TyVarContext {
TyBound::Supertype { sup, sub } => {
let sub = match sub {
Type::Poly { name, params } => {
let sub = Type::poly(
Type::poly(
name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
);
sub
)
}
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
sub => sub,
@ -242,22 +240,20 @@ impl TyVarContext {
TyBound::Sandwiched { sub, mid, sup } => {
let sub = match sub {
Type::Poly { name, params } => {
let sub = Type::poly(
Type::poly(
name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
);
sub
)
}
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
sub => sub,
};
let sup = match sup {
Type::Poly { name, params } => {
let sup = Type::poly(
Type::poly(
name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
);
sup
)
}
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
sup => sup,
@ -269,16 +265,15 @@ impl TyVarContext {
TyBound::Instance { name, t } => {
let t = match t {
Type::Poly { name, params } => {
let t = Type::poly(
Type::poly(
name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
);
t
)
}
t => t,
};
// TODO: type-like types
if &t == &Type {
if t == Type {
let constraint = Constraint::TypeOf(t);
self.push_tyvar(
name.clone(),
@ -299,10 +294,10 @@ impl TyVarContext {
match quantified {
Type::MonoQVar(n) => {
if let Some(t) = self.get_tyvar(&n) {
return t.clone();
t.clone()
} else if let Some(t) = self.get_typaram(&n) {
if let TyParam::Type(t) = t {
return *t.clone();
*t.clone()
} else {
todo!()
}
@ -318,9 +313,9 @@ impl TyVarContext {
match quantified {
TyParam::MonoQVar(n) => {
if let Some(t) = self.get_typaram(&n) {
return t.clone();
t.clone()
} else if let Some(t) = self.get_tyvar(&n) {
return TyParam::t(t.clone());
TyParam::t(t.clone())
} else {
panic!("Type parameter {n} is not found. This is a bug.")
}
@ -328,9 +323,9 @@ impl TyVarContext {
TyParam::Type(t) => {
if let Type::MonoQVar(n) = *t {
if let Some(t) = self.get_typaram(&n) {
return t.clone();
t.clone()
} else if let Some(t) = self.get_tyvar(&n) {
return TyParam::t(t.clone());
TyParam::t(t.clone())
} else {
panic!("Type variable {n} is not found. This is a bug.")
}
@ -710,9 +705,7 @@ impl Context {
v.inspect(),
));
}
let kind = id
.map(|id| VarKind::Defined(id))
.unwrap_or(VarKind::Declared);
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?;
self.decls
.insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind));
@ -743,9 +736,7 @@ impl Context {
) -> TyCheckResult<()> {
let name = sig.name.inspect();
let muty = Mutability::from(&name[..]);
let kind = id
.map(|id| VarKind::Defined(id))
.unwrap_or(VarKind::Declared);
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
if self.registered(name, name.is_uppercase()) {
return Err(TyCheckError::duplicate_decl_error(
sig.loc(),
@ -805,7 +796,7 @@ impl Context {
v.inspect(),
))
} else {
if let Some(_) = self.decls.remove(v.inspect()) {
if self.decls.remove(v.inspect()).is_some() {
// something to do?
}
let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id));
@ -957,7 +948,7 @@ impl Context {
let name = &sig.name;
// FIXME: constでない関数
let t = self
.get_current_scope_var(&name.inspect())
.get_current_scope_var(name.inspect())
.map(|v| &v.t)
.unwrap();
let non_default_params = t.non_default_params().unwrap();
@ -1490,7 +1481,7 @@ impl Context {
)
.map_err(|e| {
// REVIEW:
let name = callee.var_full_name().unwrap_or("".to_string());
let name = callee.var_full_name().unwrap_or_else(|| "".to_string());
let name =
name + "::" + param_ty.name.as_ref().map(|s| &s[..]).unwrap_or("");
TyCheckError::type_mismatch_error(
@ -1649,18 +1640,12 @@ impl Context {
/// 可変依存型の変更を伝搬させる
fn propagate(&self, t: &Type, callee: &hir::Expr) -> TyCheckResult<()> {
match t {
Type::Subr(subr) => match &subr.kind {
SubrKind::ProcMethod {
before: _,
after: Some(after),
} => {
let receiver_t = callee.receiver_t().unwrap();
self.reunify(receiver_t, after, Some(callee.loc()), None)?;
}
_ => {}
},
_ => {}
if let Type::Subr(SubrType {
kind: SubrKind::ProcMethod { after: Some(after), .. },
..
}) = t {
let receiver_t = callee.receiver_t().unwrap();
self.reunify(receiver_t, after, Some(callee.loc()), None)?;
}
Ok(())
}
@ -1682,7 +1667,7 @@ impl Context {
return Ok(());
}
match (l, r) {
(TyParam::Type(l), TyParam::Type(r)) => self.unify(&l, &r, None, None),
(TyParam::Type(l), TyParam::Type(r)) => self.unify(l, r, None, None),
(ltp @ TyParam::FreeVar(lfv), rtp @ TyParam::FreeVar(rfv))
if lfv.is_unbound() && rfv.is_unbound() =>
{
@ -1701,11 +1686,11 @@ impl Context {
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {}
} // &fv is dropped
let fv_t = fv.borrow().constraint().unwrap().typ().unwrap().clone(); // fvを参照しないよいにcloneする(あとでborrow_mutするため)
let tp_t = self.eval.get_tp_t(tp, bounds, &self)?;
let tp_t = self.eval.get_tp_t(tp, bounds, self)?;
if self.rec_full_supertype_of(&fv_t, &tp_t) {
// 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md)
if fv.level() < Some(self.level) {
let new_constraint = Constraint::SubtypeOf(tp_t.clone());
let new_constraint = Constraint::SubtypeOf(tp_t);
if self.is_sub_constraint_of(
fv.borrow().constraint().unwrap(),
&new_constraint,
@ -1717,17 +1702,15 @@ impl Context {
fv.link(tp);
}
Ok(())
} else if allow_divergence
&& (self.eq_tp(tp, &TyParam::value(Inf), None, None)
|| self.eq_tp(tp, &TyParam::value(NegInf), None, None))
&& self.rec_full_subtype_of(&fv_t, &Type::mono("Num"))
{
fv.link(tp);
Ok(())
} else {
if allow_divergence
&& (self.eq_tp(&tp, &TyParam::value(Inf), None, None)
|| self.eq_tp(&tp, &TyParam::value(NegInf), None, None))
&& self.rec_full_subtype_of(&fv_t, &Type::mono("Num"))
{
fv.link(tp);
Ok(())
} else {
Err(TyCheckError::unreachable(fn_name!(), line!()))
}
Err(TyCheckError::unreachable(fn_name!(), line!()))
}
}
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval })
@ -1769,7 +1752,7 @@ impl Context {
*l.borrow_mut() = r.borrow().clone();
Ok(())
}
(TyParam::Type(l), TyParam::Type(r)) => self.reunify(&l, &r, None, None),
(TyParam::Type(l), TyParam::Type(r)) => self.reunify(l, r, None, None),
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval })
if lop == rop =>
{
@ -2333,7 +2316,7 @@ impl Context {
self.instantiate_typespec(spec, mode)?
} else {
match &sig.pat {
ast::ParamPattern::Lit(lit) => Type::enum_t(set![self.eval.eval_const_lit(&lit)]),
ast::ParamPattern::Lit(lit) => Type::enum_t(set![self.eval.eval_const_lit(lit)]),
// TODO: Array<Lit>
_ => {
let level = if mode == PreRegister {
@ -2607,7 +2590,7 @@ impl Context {
self.caused_by(),
"match",
&Type::mono("LambdaFunc"),
&t,
t,
));
}
}
@ -2633,13 +2616,13 @@ impl Context {
// NG: expr_t: Nat, union_pat_t: {1, 2}
// OK: expr_t: Int, union_pat_t: {1} | 'T
if expr_t.has_no_unbound_var()
&& self.formal_supertype_of(&expr_t, &union_pat_t, None, None)
&& !self.formal_supertype_of(&union_pat_t, &expr_t, None, None)
&& self.formal_supertype_of(expr_t, &union_pat_t, None, None)
&& !self.formal_supertype_of(&union_pat_t, expr_t, None, None)
{
return Err(TyCheckError::match_error(
pos_args[0].loc(),
self.caused_by(),
&expr_t,
expr_t,
));
}
let branch_ts = pos_args
@ -2658,7 +2641,7 @@ impl Context {
};
let param_ts = [
vec![ParamTy::anonymous(expr_t)],
branch_ts.iter().map(|pt| pt.clone()).collect(),
branch_ts.to_vec(),
]
.concat();
let t = Type::func(param_ts, vec![], return_t);
@ -2749,8 +2732,8 @@ impl Context {
) -> TyCheckResult<Type> {
erg_common::debug_power_assert!(args.len() == 2);
let symbol = Token::symbol(binop_to_dname(op.inspect()));
let mut op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
self.get_call_t(&mut op, args, &[], namespace).map_err(|e| {
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
self.get_call_t(&op, args, &[], namespace).map_err(|e| {
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
let core = ErrorCore::new(
e.core.errno,
@ -2771,8 +2754,8 @@ impl Context {
) -> TyCheckResult<Type> {
erg_common::debug_power_assert!(args.len() == 1);
let symbol = Token::symbol(unaryop_to_dname(op.inspect()));
let mut op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
self.get_call_t(&mut op, args, &[], namespace).map_err(|e| {
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
self.get_call_t(&op, args, &[], namespace).map_err(|e| {
let core = ErrorCore::new(
e.core.errno,
e.core.kind,
@ -2809,7 +2792,7 @@ impl Context {
log!("Substituted:\ninstance: {instance}");
let res = self.deref_tyvar(instance)?;
log!("Eliminated:\nres: {res}\n");
let res = self.eval.eval_t_params(res, &self, self.level)?;
let res = self.eval.eval_t_params(res, self, self.level)?;
log!("Params Evaluated:\nres: {res}\n");
let res = self.deref_tyvar(res)?;
log!("Eliminated (2):\nres: {res}\n");
@ -2873,13 +2856,13 @@ impl Context {
| FreeKind::NamedUnbound { constraint, .. } => {
let t = constraint.typ().unwrap();
let other_t = self.type_of(other, bounds);
return self.formal_supertype_of(&t, &other_t, bounds, lhs_variance);
return self.formal_supertype_of(t, &other_t, bounds, lhs_variance);
}
},
(l, r) if l == r => return true,
_ => {}
}
self.eval.shallow_eq_tp(lhs, rhs, &self)
self.eval.shallow_eq_tp(lhs, rhs, self)
}
/// e.g.
@ -3292,7 +3275,7 @@ impl Context {
// try_cmp((n: 2.._), 1) -> Some(Greater)
// try_cmp((n: -1.._), 1) -> Some(Any)
(l @ (TyParam::Erased(_) | TyParam::FreeVar(_) | TyParam::MonoQVar(_)), p) => {
let t = self.eval.get_tp_t(l, bounds, &self).unwrap();
let t = self.eval.get_tp_t(l, bounds, self).unwrap();
let inf = self.inf(&t);
let sup = self.sup(&t);
if let (Some(inf), Some(sup)) = (inf, sup) {
@ -3355,7 +3338,7 @@ impl Context {
Refinement(r) => r,
t => {
let var = Str::from(fresh_varname());
RefinementType::new(var.clone(), t, set! {})
RefinementType::new(var, t, set! {})
}
}
}
@ -3486,7 +3469,7 @@ impl Context {
#[inline]
fn type_of(&self, p: &TyParam, bounds: Option<&Set<TyBound>>) -> Type {
self.eval.get_tp_t(p, bounds, &self).unwrap()
self.eval.get_tp_t(p, bounds, self).unwrap()
}
// sup/inf({±∞}) = ±∞ではあるが、Inf/NegInfにはOrdを実装しない
@ -3501,7 +3484,7 @@ impl Context {
if lhs == &refine.var =>
{
if let Some(max) = &maybe_max {
if self.try_cmp(rhs, &max, None).unwrap() == Greater {
if self.try_cmp(rhs, max, None).unwrap() == Greater {
maybe_max = Some(rhs.clone());
}
} else {
@ -3529,7 +3512,7 @@ impl Context {
if lhs == &refine.var =>
{
if let Some(min) = &maybe_min {
if self.try_cmp(rhs, &min, None).unwrap() == Less {
if self.try_cmp(rhs, min, None).unwrap() == Less {
maybe_min = Some(rhs.clone());
}
} else {
@ -3753,24 +3736,22 @@ impl Context {
fn rec_get_patch(&self, name: &VarName) -> Option<&Context> {
if let Some(patch) = self.patches.get(name) {
return Some(patch);
Some(patch)
} else if let Some(outer) = &self.outer {
outer.rec_get_patch(name)
} else {
if let Some(outer) = &self.outer {
return outer.rec_get_patch(name);
}
None
}
None
}
fn rec_get_mod(&self, name: &str) -> Option<&Context> {
if let Some(mod_) = self.mods.get(name) {
return Some(mod_);
Some(mod_)
} else if let Some(outer) = &self.outer {
outer.rec_get_mod(name)
} else {
if let Some(outer) = &self.outer {
return outer.rec_get_mod(name);
}
None
}
None
}
fn rec_get_trait_impls(&self, name: &Str) -> Vec<Type> {
@ -3785,37 +3766,34 @@ impl Context {
}
// 再帰サブルーチン/型の推論を可能にするため、予め登録しておく
pub(crate) fn preregister(&mut self, block: &Vec<ast::Expr>) -> TyCheckResult<()> {
pub(crate) fn preregister(&mut self, block: &[ast::Expr]) -> TyCheckResult<()> {
for expr in block.iter() {
match expr {
ast::Expr::Def(def) => {
let id = Some(def.body.id);
let eval_body_t = || {
self.eval
.eval_const_block(&def.body.block, &self)
.map(|c| Type::enum_t(set![c]))
};
match &def.sig {
ast::Signature::Subr(sig) => {
let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() {
Some(self.instantiate_typespec(spec, PreRegister)?)
} else {
eval_body_t()
};
self.declare_sub(&sig, opt_ret_t, id)?;
}
ast::Signature::Var(sig) if sig.is_const() => {
let t = if let Some(spec) = sig.t_spec.as_ref() {
Some(self.instantiate_typespec(spec, PreRegister)?)
} else {
eval_body_t()
};
self.declare_var(&sig, t, id)?;
}
_ => {}
if let ast::Expr::Def(def) = expr {
let id = Some(def.body.id);
let eval_body_t = || {
self.eval
.eval_const_block(&def.body.block, self)
.map(|c| Type::enum_t(set![c]))
};
match &def.sig {
ast::Signature::Subr(sig) => {
let opt_ret_t = if let Some(spec) = sig.return_t_spec.as_ref() {
Some(self.instantiate_typespec(spec, PreRegister)?)
} else {
eval_body_t()
};
self.declare_sub(sig, opt_ret_t, id)?;
}
ast::Signature::Var(sig) if sig.is_const() => {
let t = if let Some(spec) = sig.t_spec.as_ref() {
Some(self.instantiate_typespec(spec, PreRegister)?)
} else {
eval_body_t()
};
self.declare_var(sig, t, id)?;
}
_ => {}
}
_ => {}
}
}
Ok(())

View file

@ -219,3 +219,9 @@ impl SideEffectChecker {
}
}
}
impl Default for SideEffectChecker {
fn default() -> Self {
Self::new()
}
}

View file

@ -28,17 +28,14 @@ impl SubstContext {
let param_names = ty_ctx.params.iter().map(|(opt_name, _)| {
opt_name
.as_ref()
.map(|n| n.inspect().clone())
.unwrap_or(Str::ever("_"))
.clone()
.map_or_else(|| Str::ever("_"), |n| n.inspect().clone())
});
let self_ = SubstContext {
// REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は?
SubstContext {
params: param_names
.zip(substituted.typarams().into_iter())
.collect(),
};
// REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は?
self_
}
}
fn substitute(&self, quant_t: Type, ty_ctx: &Context, level: usize) -> TyCheckResult<Type> {
@ -58,10 +55,8 @@ impl SubstContext {
if let Some(v) = self.params.get(&name) {
ty_ctx.unify_tp(param, v, None, None, false)?;
}
} else {
if fv.is_unbound() {
panic!()
}
} else if fv.is_unbound() {
panic!()
}
}
TyParam::BinOp { lhs, rhs, .. } => {
@ -192,28 +187,28 @@ impl Evaluator {
match op {
Add => lhs
.try_add(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Sub => lhs
.try_sub(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Mul => lhs
.try_mul(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Div => lhs
.try_div(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Gt => lhs
.try_gt(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Ge => lhs
.try_ge(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Eq => lhs
.try_eq(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Ne => lhs
.try_ne(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
other => todo!("{other}"),
}
}
@ -227,7 +222,7 @@ impl Evaluator {
match (lhs, rhs) {
(TyParam::ConstObj(ConstObj::Value(lhs)), TyParam::ConstObj(ConstObj::Value(rhs))) => {
self.eval_bin_lit(op, lhs.clone(), rhs.clone())
.map(|v| TyParam::value(v))
.map(TyParam::value)
}
(
TyParam::ConstObj(ConstObj::MutValue(lhs)),
@ -272,14 +267,14 @@ impl Evaluator {
fn eval_unary_tp(&self, op: OpKind, val: &TyParam) -> EvalResult<TyParam> {
match val {
TyParam::ConstObj(c) => self.eval_unary_lit(op, c.clone()).map(|c| TyParam::cons(c)),
TyParam::ConstObj(c) => self.eval_unary_lit(op, c.clone()).map(TyParam::cons),
TyParam::FreeVar(fv) if fv.is_linked() => self.eval_unary_tp(op, &*fv.crack()),
e @ TyParam::Erased(_) => Ok(e.clone()),
other => todo!("{op} {other}"),
}
}
fn eval_app(&self, _name: &Str, _args: &Vec<TyParam>) -> EvalResult<TyParam> {
fn eval_app(&self, _name: &Str, _args: &[TyParam]) -> EvalResult<TyParam> {
todo!()
}
@ -294,7 +289,7 @@ impl Evaluator {
ConstObj::Value(v) => Some(TyParam::value(v.clone())),
_ => None,
})
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
TyParam::BinOp { op, lhs, rhs } => self.eval_bin_tp(*op, lhs, rhs),
TyParam::UnaryOp { op, val } => self.eval_unary_tp(*op, val),
TyParam::App { name, args } => self.eval_app(name, args),
@ -443,7 +438,7 @@ impl Evaluator {
match p {
TyParam::ConstObj(ConstObj::Value(v)) => Ok(Type::enum_t(set![v])),
TyParam::ConstObj(ConstObj::MutValue(v)) => Ok(v.borrow().class().mutate()),
TyParam::Erased(t) => Ok((&*t).clone()),
TyParam::Erased(t) => Ok((*t).clone()),
TyParam::FreeVar(fv) => {
if let Some(t) = fv.type_of() {
Ok(t)
@ -459,7 +454,7 @@ impl Evaluator {
ConstObj::Value(v) => Some(Type::enum_t(set![v.clone()])),
_ => None,
})
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
TyParam::MonoQVar(name) => {
if let Some(bs) = bounds {
if let Some(bound) = bs.iter().find(|b| b.mentions_as_instance(&name)) {
@ -483,7 +478,7 @@ impl Evaluator {
let p = self.eval_tp(p, ctx)?;
match p {
TyParam::ConstObj(ConstObj::Value(v)) => Ok(v.class()),
TyParam::Erased(t) => Ok((&*t).clone()),
TyParam::Erased(t) => Ok((*t).clone()),
TyParam::FreeVar(fv) => {
if let Some(t) = fv.type_of() {
Ok(t)
@ -499,7 +494,7 @@ impl Evaluator {
ConstObj::Value(v) => Some(v.class()),
_ => None,
})
.ok_or(EvalError::unreachable(fn_name!(), line!())),
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
other => todo!("{other}"),
}
}

View file

@ -108,7 +108,7 @@ pub struct KwArg {
impl NestedDisplay for KwArg {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
write!(f, "{}:\n", self.keyword)?;
writeln!(f, "{}:", self.keyword)?;
self.expr.fmt_nest(f, level + 1)
}
}
@ -189,6 +189,11 @@ impl Args {
self.pos_args.len() + self.kw_args.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.pos_args.is_empty() && self.kw_args.is_empty()
}
#[inline]
pub fn kw_len(&self) -> usize {
self.kw_args.len()
@ -563,9 +568,9 @@ pub struct BinOp {
impl NestedDisplay for BinOp {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
write!(f, "`{}`:\n", self.op.content)?;
writeln!(f, "`{}`:", self.op.content)?;
self.lhs.fmt_nest(f, level + 1)?;
write!(f, "\n")?;
writeln!(f)?;
self.rhs.fmt_nest(f, level + 1)
}
}
@ -573,15 +578,15 @@ impl NestedDisplay for BinOp {
impl HasType for BinOp {
#[inline]
fn ref_t(&self) -> &Type {
&self.sig_t.return_t().unwrap()
self.sig_t.return_t().unwrap()
}
#[inline]
fn lhs_t(&self) -> &Type {
&self.sig_t.lhs_t()
self.sig_t.lhs_t()
}
#[inline]
fn rhs_t(&self) -> &Type {
&self.sig_t.rhs_t()
self.sig_t.rhs_t()
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
@ -613,7 +618,7 @@ pub struct UnaryOp {
impl HasType for UnaryOp {
#[inline]
fn ref_t(&self) -> &Type {
&self.sig_t.return_t().unwrap()
self.sig_t.return_t().unwrap()
}
#[inline]
fn lhs_t(&self) -> &Type {
@ -631,7 +636,7 @@ impl HasType for UnaryOp {
impl NestedDisplay for UnaryOp {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
write!(f, "`{}`: {}:\n", self.op, self.sig_t)?;
writeln!(f, "`{}`: {}:", self.op, self.sig_t)?;
self.expr.fmt_nest(f, level + 1)
}
}
@ -660,7 +665,7 @@ pub struct Call {
impl NestedDisplay for Call {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
write!(f, "({}): {}:\n", self.obj, self.sig_t)?;
writeln!(f, "({}): {}:", self.obj, self.sig_t)?;
self.args.fmt_nest(f, level + 1)
}
}
@ -670,7 +675,7 @@ impl_display_from_nested!(Call);
impl HasType for Call {
#[inline]
fn ref_t(&self) -> &Type {
&self.sig_t.return_t().unwrap()
self.sig_t.return_t().unwrap()
}
#[inline]
fn lhs_t(&self) -> &Type {
@ -821,7 +826,7 @@ impl HasType for Lambda {
impl NestedDisplay for Lambda {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
write!(f, "{} {}\n", self.params, self.op.content)?;
writeln!(f, "{} {}", self.params, self.op.content)?;
self.body.fmt_nest(f, level + 1)
}
}
@ -943,7 +948,7 @@ pub struct Def {
impl NestedDisplay for Def {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
write!(f, "{} {}\n", self.sig, self.body.op.content)?;
writeln!(f, "{} {}", self.sig, self.body.op.content)?;
self.body.block.fmt_nest(f, level + 1)
}
}

View file

@ -111,7 +111,7 @@ impl Context {
op_t,
set! {subtype(mono_q("Self"), mono("Eq")), subtype(mono_q("R"), poly("Eq", vec![]))},
);
eq.register_decl("__eq__", op_t.clone(), Public);
eq.register_decl("__eq__", op_t, Public);
let mut ord = Self::poly_trait(
"Ord",
vec![PS::t("R", WithDefault)],
@ -123,7 +123,7 @@ impl Context {
op_t,
set! {subtype(mono_q("Self"), mono("Ord")), subtype(mono_q("R"), poly("Ord", vec![]))},
);
ord.register_decl("__lt__", op_t.clone(), Public);
ord.register_decl("__lt__", op_t, Public);
let mut seq = Self::poly_trait(
"Seq",
vec![PS::t("T", NonDefault)],
@ -142,7 +142,7 @@ impl Context {
seq.register_decl("get", t, Public);
let params = vec![PS::t("T", NonDefault)];
let input = Self::poly_trait("Input", params.clone(), vec![], Self::TOP_LEVEL);
let output = Self::poly_trait("Output", params.clone(), vec![], Self::TOP_LEVEL);
let output = Self::poly_trait("Output", params, vec![], Self::TOP_LEVEL);
let (r, o) = (mono_q("R"), mono_q("O"));
let (r_bound, o_bound) = (static_instance("R", Type), static_instance("O", Type));
let params = vec![PS::t("R", WithDefault), PS::t("O", WithDefault)];
@ -167,7 +167,7 @@ impl Context {
poly("Sub", ty_params.clone()),
);
let op_t = fn1_met(poly_q("Self", ty_params.clone()), r.clone(), o.clone());
let op_t = quant(op_t, set! {r_bound.clone(), o_bound.clone(), self_bound});
let op_t = quant(op_t, set! {r_bound, o_bound, self_bound});
sub.register_decl("__sub__", op_t, Public);
let mut mul = Self::poly_trait("Mul", params.clone(), vec![
poly("Output", vec![ty_tp(mono_q("R"))]),
@ -175,7 +175,7 @@ impl Context {
], Self::TOP_LEVEL);
let op_t = fn1_met(poly("Mul", ty_params.clone()), r.clone(), o.clone());
mul.register_decl("__mul__", op_t, Public);
let mut div = Self::poly_trait("Div", params.clone(), vec![
let mut div = Self::poly_trait("Div", params, vec![
poly("Output", vec![ty_tp(mono_q("R"))]),
poly("Output", vec![ty_tp(mono_q("O"))]),
], Self::TOP_LEVEL);
@ -618,8 +618,8 @@ impl Context {
let op_t = Type::func2(l.clone(), r.clone(), o.clone());
let op_t = quant(op_t, set! {subtype(l.clone(), poly("Mul", params.clone()))});
self.register_impl("__mul__", op_t, Const, Private);
let op_t = Type::func2(l.clone(), r.clone(), o.clone());
let op_t = quant(op_t, set! {subtype(l, poly("Mul", params.clone()))});
let op_t = Type::func2(l.clone(), r, o);
let op_t = quant(op_t, set! {subtype(l, poly("Mul", params))});
self.register_impl("__div__", op_t, Const, Private);
let m = mono_q("M");
let op_t = Type::func2(m.clone(), m.clone(), m.clone());

View file

@ -50,14 +50,14 @@ impl ASTLowerer {
expect: &Type,
found: &Type,
) -> LowerResult<()> {
self.ctx.unify(expect, found, Some(loc), None).or_else(|_| {
Err(LowerError::type_mismatch_error(
self.ctx.unify(expect, found, Some(loc), None).map_err(|_| {
LowerError::type_mismatch_error(
loc,
self.ctx.caused_by(),
name,
expect,
found,
))
)
})
}
@ -176,9 +176,9 @@ impl ASTLowerer {
self.lower_expr(arg.expr, true)?,
));
}
let mut obj = self.lower_expr(*call.obj, false)?;
let obj = self.lower_expr(*call.obj, false)?;
let t = self.ctx.get_call_t(
&mut obj,
&obj,
hir_args.pos_args(),
hir_args.kw_args(),
&self.ctx.name,
@ -283,7 +283,7 @@ impl ASTLowerer {
.map(|vi| vi.t.clone());
let name = sig.pat.inspect().unwrap();
if let Some(expect_body_t) = opt_expect_body_t {
if let Err(e) = self.return_t_check(sig.loc(), name, &expect_body_t, &found_body_t) {
if let Err(e) = self.return_t_check(sig.loc(), name, &expect_body_t, found_body_t) {
self.errs.push(e);
}
}
@ -416,3 +416,9 @@ impl ASTLowerer {
}
}
}
impl Default for ASTLowerer {
fn default() -> Self {
Self::new()
}
}

View file

@ -83,7 +83,7 @@ impl OwnershipChecker {
fn check_expr(&mut self, expr: &Expr, ownership: Ownership) {
match expr {
Expr::Def(def) => {
self.define(&def);
self.define(def);
let name_and_vis = match &def.sig {
Signature::Var(var) =>
// TODO: visibility
@ -249,3 +249,9 @@ impl OwnershipChecker {
panic!("variable not found: {name}");
}
}
impl Default for OwnershipChecker {
fn default() -> Self {
Self::new()
}
}

View file

@ -25,7 +25,7 @@ pub fn fmt_lines<'a, T: NestedDisplay + 'a>(
line.fmt_nest(f, level)?;
}
for arg in iter {
write!(f, "\n")?;
writeln!(f)?;
arg.fmt_nest(f, level)?;
}
Ok(())
@ -107,7 +107,7 @@ pub struct KwArg {
impl NestedDisplay for KwArg {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
write!(f, "{}:\n", self.keyword)?;
writeln!(f, "{}:", self.keyword)?;
self.expr.fmt_nest(f, level + 1)
}
}
@ -453,9 +453,9 @@ pub struct BinOp {
impl NestedDisplay for BinOp {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
write!(f, "`{}`:\n", self.op.content)?;
writeln!(f, "`{}`:", self.op.content)?;
self.args[0].fmt_nest(f, level + 1)?;
write!(f, "\n")?;
writeln!(f)?;
self.args[1].fmt_nest(f, level + 1)
}
}
@ -485,7 +485,7 @@ pub struct UnaryOp {
impl NestedDisplay for UnaryOp {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
write!(f, "`{}`:\n", self.op.content)?;
writeln!(f, "`{}`:", self.op.content)?;
self.args[0].fmt_nest(f, level + 1)
}
}
@ -515,7 +515,7 @@ pub struct Call {
impl NestedDisplay for Call {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
write!(f, "({}):\n", self.obj)?;
writeln!(f, "({}):", self.obj)?;
self.args.fmt_nest(f, level + 1)
}
}
@ -1186,7 +1186,7 @@ impl fmt::Display for TypeSpec {
Self::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"),
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
Self::Array { t, len } => write!(f, "[{t}; {len}]"),
Self::Tuple(tys) => write!(f, "({})", fmt_vec(&tys)),
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
Self::Enum(elems) => write!(f, "{{{elems}}}"),
Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()),
Self::Subr(s) => write!(f, "{s}"),
@ -1537,7 +1537,7 @@ impl VarPattern {
Self::Array(VarArrayPattern { elems, .. })
| Self::Tuple(VarTuplePattern { elems, .. })
| Self::Record(VarRecordPattern { elems, .. }) => {
elems.iter().map(|s| s.pat.inspects()).flatten().collect()
elems.iter().flat_map(|s| s.pat.inspects()).collect()
}
_ => vec![],
}
@ -1992,7 +1992,7 @@ pub struct Lambda {
impl NestedDisplay for Lambda {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
write!(f, "{} {}\n", self.sig, self.op.content)?;
writeln!(f, "{} {}", self.sig, self.op.content)?;
self.body.fmt_nest(f, level + 1)
}
}
@ -2026,7 +2026,7 @@ impl Signature {
pub fn name_as_str(&self) -> &Str {
match self {
Self::Var(v) => v.pat.inspect().unwrap(),
Self::Subr(s) => &s.name.inspect(),
Self::Subr(s) => s.name.inspect(),
}
}
@ -2083,7 +2083,7 @@ pub struct Def {
impl NestedDisplay for Def {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
write!(f, "{} {}\n", self.sig, self.body.op.content)?;
writeln!(f, "{} {}", self.sig, self.body.op.content)?;
self.body.block.fmt_nest(f, level + 1)
}
}

View file

@ -193,3 +193,9 @@ impl Desugarer {
todo!()
}
}
impl Default for Desugarer {
fn default() -> Self {
Self::new()
}
}

View file

@ -1,4 +1,6 @@
//! defines and implements `Lexer` (Tokenizer).
use std::cmp::Ordering;
use erg_common::cache::Cache;
use erg_common::config::ErgConfig;
use erg_common::config::Input;
@ -105,7 +107,7 @@ impl Lexer /*<'a>*/ {
pub fn lex(self) -> Result<TokenStream, LexErrors> {
let mut result = TokenStream::empty();
let mut errs = LexErrors::empty();
for i in self.into_iter() {
for i in self {
match i {
Ok(token) => result.push(token),
Err(err) => {
@ -172,19 +174,14 @@ impl Lexer /*<'a>*/ {
/// Detect `c` is a bidirectional overriding character.
/// [CVE-2021-42574: homoglyph atack](https://blog.rust-lang.org/2021/11/01/cve-2021-42574.html) countermeasures.
pub fn is_bidi(c: char) -> bool {
match c {
'\u{200F}' | '\u{202B}' | '\u{202E}' | '\u{2067}' => true,
_ => false,
}
matches!(c, '\u{200F}' | '\u{202B}' | '\u{202E}' | '\u{2067}')
}
#[inline]
fn is_definable_operator(s: &str) -> bool {
match s {
matches!(s,
"+" | "-" | "*" | "/" | "//" | "**" | "%" | ".." | "..=" | "~" | "&&" | "||" | "^^"
| ">>" | "<<" | "==" | "!=" | ">" | "<" | ">=" | "<=" | "dot" | "cross" => true,
_ => false,
}
| ">>" | "<<" | "==" | "!=" | ">" | "<" | ">=" | "<=" | "dot" | "cross")
}
// +, -, * etc. may be pre/bin
@ -209,32 +206,32 @@ impl Lexer /*<'a>*/ {
}
fn is_zero(s: &str) -> bool {
s.replace("-0", "").replace("0", "").is_empty()
s.replace("-0", "").replace('0', "").is_empty()
}
/// emit_tokenで一気にcol_token_startsを移動させるのでここでは移動させない
fn consume(&mut self) -> Option<char> {
let now = self.cursor;
self.cursor += 1;
self.chars.get(now).map(|x| *x)
self.chars.get(now).copied()
}
fn peek_prev_ch(&self) -> Option<char> {
if self.cursor == 0 {
None
} else {
self.chars.get(self.cursor - 1).map(|x| *x)
self.chars.get(self.cursor - 1).copied()
}
}
#[inline]
fn peek_cur_ch(&self) -> Option<char> {
self.chars.get(self.cursor).map(|x| *x)
self.chars.get(self.cursor).copied()
}
#[inline]
fn peek_next_ch(&self) -> Option<char> {
self.chars.get(self.cursor + 1).map(|x| *x)
self.chars.get(self.cursor + 1).copied()
}
fn lex_comment(&mut self) -> LexResult<()> {
@ -322,31 +319,33 @@ impl Lexer /*<'a>*/ {
sum + *x
};
let sum_indent = self.indent_stack.iter().fold(0, calc_indent_and_validate);
if sum_indent < spaces.len() {
let indent_len = spaces.len() - sum_indent;
self.col_token_starts += sum_indent;
let indent = self.emit_token(Indent, &" ".repeat(indent_len));
self.indent_stack.push(indent_len);
Some(Ok(indent))
} else if sum_indent > spaces.len() {
if is_valid_dedent {
let dedent = self.emit_token(Dedent, "");
self.indent_stack.pop();
Some(Ok(dedent))
} else {
let invalid_dedent = self.emit_token(Dedent, "");
Some(Err(LexError::syntax_error(
0,
invalid_dedent.loc(),
switch_lang!("invalid indent", "インデントが不正です"),
None,
)))
match sum_indent.cmp(&spaces.len()) {
Ordering::Less => {
let indent_len = spaces.len() - sum_indent;
self.col_token_starts += sum_indent;
let indent = self.emit_token(Indent, &" ".repeat(indent_len));
self.indent_stack.push(indent_len);
Some(Ok(indent))
}
Ordering::Greater => {
if is_valid_dedent {
let dedent = self.emit_token(Dedent, "");
self.indent_stack.pop();
Some(Ok(dedent))
} else {
let invalid_dedent = self.emit_token(Dedent, "");
Some(Err(LexError::syntax_error(
0,
invalid_dedent.loc(),
switch_lang!("invalid indent", "インデントが不正です"),
None,
)))
}
}
Ordering::Equal /* if indent_sum == space.len() */ => {
self.col_token_starts += spaces.len();
None
}
} else
/* if indent_sum == space.len() */
{
self.col_token_starts += spaces.len();
None
}
}
@ -495,7 +494,7 @@ impl Lexer /*<'a>*/ {
fn lex_str(&mut self) -> LexResult<Token> {
let mut s = "\"".to_string();
while let Some(c) = self.peek_cur_ch() {
if c == '\"' && s.chars().last() != Some('\\') {
if c == '\"' && !s.ends_with('\\') {
s.push(self.consume().unwrap());
let token = self.emit_token(StrLit, &s);
return Ok(token);
@ -805,7 +804,7 @@ impl Iterator for Lexer /*<'a>*/ {
)))
}
None => {
if self.indent_stack.len() == 0 {
if self.indent_stack.is_empty() {
self.accept(EOF, "")
} else {
self.indent_stack.pop();

View file

@ -158,12 +158,10 @@ impl Parser {
Side::LhsAssign
}
// (cur) -> ... ; ... =
else {
if self.arrow_distance(0, 0) == 1 {
Side::LhsLambda
} else {
Side::Rhs
}
else if self.arrow_distance(0, 0) == 1 {
Side::LhsLambda
} else {
Side::Rhs
}
}
}
@ -454,15 +452,8 @@ impl Parser {
#[inline]
fn opt_reduce_decorators(&mut self) -> ParseResult<Set<Decorator>> {
let mut decs = set![];
loop {
match self.opt_reduce_decorator()? {
Some(deco) => {
decs.insert(deco);
}
None => {
break;
}
}
while let Some(deco) = self.opt_reduce_decorator()? {
decs.insert(deco);
}
Ok(decs)
}
@ -521,14 +512,13 @@ impl Parser {
}
None
}
} else if self.cur_is(Colon) {
self.skip();
Some(self.try_reduce_type_spec()?)
} else {
if self.cur_is(Colon) {
self.skip();
Some(self.try_reduce_type_spec()?)
} else {
None
}
None
};
Ok(Signature::Var(VarSignature::new(
VarPattern::VarName(name),
t_spec,
@ -1236,7 +1226,7 @@ impl Parser {
};
Ok(KwArg::new(keyword, self.try_reduce_expr()?))
} else {
return Err(ParseError::simple_syntax_error(0, t.loc()));
Err(ParseError::simple_syntax_error(0, t.loc()))
}
}
Some(other) => Err(ParseError::simple_syntax_error(0, other.loc())),

View file

@ -293,11 +293,7 @@ impl TokenKind {
}
pub const fn is_right_associative(&self) -> bool {
match self {
FuncArrow | ProcArrow | Equal => true,
// PreDollar | PreAt => true,
_ => false,
}
matches!(self, FuncArrow | ProcArrow | Equal /* | PreDollar | PreAt */)
}
}
@ -337,7 +333,7 @@ impl fmt::Debug for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Token")
.field("kind", &self.kind)
.field("content", &self.content.replace("\n", "\\n"))
.field("content", &self.content.replace('\n', "\\n"))
.field("lineno", &self.lineno)
.field("col_begin", &self.col_begin)
.finish()
@ -346,7 +342,7 @@ impl fmt::Debug for Token {
impl fmt::Display for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?} {}", self.kind, self.content.replace("\n", "\\n"))
write!(f, "{:?} {}", self.kind, self.content.replace('\n', "\\n"))
}
}
@ -451,7 +447,7 @@ impl Token {
}
pub fn is_procedural(&self) -> bool {
self.inspect().ends_with("!")
self.inspect().ends_with('!')
}
}