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

View file

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

View file

@ -328,8 +328,8 @@ impl ErrorCore {
} }
} }
pub const VBAR_UNICODE: &'static str = ""; pub const VBAR_UNICODE: &str = "";
pub const VBAR_BREAK_UNICODE: &'static str = "·"; pub const VBAR_BREAK_UNICODE: &str = "·";
/// format: /// format:
/// ```console /// ```console
@ -399,9 +399,9 @@ pub trait ErrorDisplay {
let kind = self.core().kind as u8; let kind = self.core().kind as u8;
let (color, err_or_warn) = if kind < 100 { let (color, err_or_warn) = if kind < 100 {
(RED, "Error") (RED, "Error")
} else if 100 <= kind && kind < 150 { } else if (100..150).contains(&kind) {
(YELLOW, "Warning") (YELLOW, "Warning")
} else if 150 <= kind && kind < 200 { } else if (150..200).contains(&kind) {
(DEEP_RED, "Error") (DEEP_RED, "Error")
} else { } else {
("", "Exception") ("", "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 /// 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 /// 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. /// itself is much higher because it works on up to 8 bytes at a time.
#[derive(Default)]
pub struct FxHasher { pub struct FxHasher {
hash: usize, hash: usize,
} }
@ -61,13 +62,6 @@ const K: usize = 0x9e3779b9;
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
const K: usize = 0x517cc1b727220a95; const K: usize = 0x517cc1b727220a95;
impl Default for FxHasher {
#[inline]
fn default() -> FxHasher {
FxHasher { hash: 0 }
}
}
impl FxHasher { impl FxHasher {
#[inline] #[inline]
fn add_to_hash(&mut self, i: usize) { 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); hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize);
bytes = &bytes[2..]; 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); hash.add_to_hash(bytes[0] as usize);
} }
self.hash = hash.hash; self.hash = hash.hash;

View file

@ -27,6 +27,10 @@ where
self.buffer.len() self.buffer.len()
} }
pub fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
pub fn get_next(&mut self) -> bool { pub fn get_next(&mut self) -> bool {
if self.done { if self.done {
return false; return false;

View file

@ -43,7 +43,7 @@ pub fn read_file(mut f: std::fs::File) -> std::io::Result<String> {
Ok(s) 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()) fmt_iter(v.iter())
} }
@ -51,7 +51,7 @@ pub fn fmt_slice<T: fmt::Display>(v: &[T]) -> String {
fmt_iter(v.iter()) 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) 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) /// \r\n (Windows), \r (old MacOS) -> \n (Unix)
#[inline] #[inline]
pub fn normalize_newline(src: &str) -> String { 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 /// cut \n
#[inline] #[inline]
pub fn chomp(src: &str) -> String { 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> 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() { if res.is_empty() {
panic!("python not found"); panic!("python not found");
} }
res.to_string() res
} }
pub fn detect_magic_number() -> u32 { pub fn detect_magic_number() -> u32 {

View file

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

View file

@ -168,7 +168,7 @@ impl<T: Hash + Eq + Clone> Set<T> {
pub fn union(&self, other: &Set<T>) -> Set<T> { pub fn union(&self, other: &Set<T>) -> Set<T> {
let u = self.elems.union(&other.elems); let u = self.elems.union(&other.elems);
Self { 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> { pub fn intersection(&self, other: &Set<T>) -> Set<T> {
let u = self.elems.intersection(&other.elems); let u = self.elems.intersection(&other.elems);
Self { 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 { impl Hash for Str {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
match self { match self {
Str::Rc(s) => (&s[..]).hash(state), Str::Rc(s) => (s[..]).hash(state),
Str::Static(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 { impl From<&String> for Str {
#[inline] #[inline]
fn from(s: &String) -> Self { fn from(s: &String) -> Self {
Str::Rc((&s[..]).into()) Str::Rc((s[..]).into())
} }
} }
impl From<String> for Str { impl From<String> for Str {
#[inline] #[inline]
fn from(s: String) -> Self { 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>) { 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()); 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) { if !used.contains(node_id) {
dfs(g, node_id.clone(), used, idx); dfs(g, node_id.clone(), used, idx);
} }

View file

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

View file

@ -2,7 +2,7 @@
//! //!
//! コンパイラ、VM等で使われる(データも保持した)値オブジェクトを定義する //! コンパイラ、VM等で使われる(データも保持した)値オブジェクトを定義する
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fmt; use std::fmt::{self, Write};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::Neg; use std::ops::Neg;
use std::rc::Rc; use std::rc::Rc;
@ -56,7 +56,7 @@ impl fmt::Debug for ValueObj {
Self::Dict(dict) => { Self::Dict(dict) => {
let mut s = "".to_string(); let mut s = "".to_string();
for (k, v) in dict.iter() { for (k, v) in dict.iter() {
s += &format!("{k}: {v}, "); write!(s, "{k}: {v}, ")?;
} }
s.pop(); s.pop();
s.pop(); s.pop();
@ -255,11 +255,11 @@ impl ValueObj {
pub fn from_str(t: Type, content: Str) -> Self { pub fn from_str(t: Type, content: Str) -> Self {
match t { match t {
Type::Int => Self::Int(content.replace("_", "").parse::<i32>().unwrap()), Type::Int => Self::Int(content.replace('_', "").parse::<i32>().unwrap()),
Type::Nat => Self::Nat(content.replace("_", "").parse::<u64>().unwrap()), Type::Nat => Self::Nat(content.replace('_', "").parse::<u64>().unwrap()),
Type::Float => Self::Float(content.replace("_", "").parse::<f64>().unwrap()), Type::Float => Self::Float(content.replace('_', "").parse::<f64>().unwrap()),
// TODO: // TODO:
Type::Ratio => Self::Float(content.replace("_", "").parse::<f64>().unwrap()), Type::Ratio => Self::Float(content.replace('_', "").parse::<f64>().unwrap()),
Type::Str => { Type::Str => {
if &content[..] == "\"\"" { if &content[..] == "\"\"" {
Self::Str(Str::from("")) Self::Str(Str::from(""))
@ -288,18 +288,18 @@ impl ValueObj {
match self { match self {
Self::Int(i) => [ Self::Int(i) => [
vec![DataTypePrefix::Int32 as u8], vec![DataTypePrefix::Int32 as u8],
i32::from(i).to_le_bytes().to_vec(), i.to_le_bytes().to_vec(),
] ]
.concat(), .concat(),
// TODO: Natとしてシリアライズ // TODO: Natとしてシリアライズ
Self::Nat(n) => [ Self::Nat(n) => [
vec![DataTypePrefix::Int32 as u8], vec![DataTypePrefix::Int32 as u8],
i32::from(n as i32).to_le_bytes().to_vec(), (n as i32).to_le_bytes().to_vec(),
] ]
.concat(), .concat(),
Self::Float(f) => [ Self::Float(f) => [
vec![DataTypePrefix::BinFloat as u8], vec![DataTypePrefix::BinFloat as u8],
f64::from(f).to_le_bytes().to_vec(), f.to_le_bytes().to_vec(),
] ]
.concat(), .concat(),
Self::Str(s) => str_into_bytes(s, false), Self::Str(s) => str_into_bytes(s, false),
@ -310,7 +310,7 @@ impl ValueObj {
let mut bytes = Vec::with_capacity(arr.len()); let mut bytes = Vec::with_capacity(arr.len());
bytes.push(DataTypePrefix::Tuple as u8); bytes.push(DataTypePrefix::Tuple as u8);
bytes.append(&mut (arr.len() as u32).to_le_bytes().to_vec()); 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.append(&mut obj.into_bytes());
} }
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 { 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(); let mut name = convert_to_python_attr(class, uniq_obj_name, name).to_string();
name = name.replace("!", "__erg_proc__"); name = name.replace('!', "__erg_proc__");
name = name.replace("$", "__erg_shared__"); name = name.replace('$', "__erg_shared__");
Str::rc(&name) Str::rc(&name)
} }
@ -78,8 +78,8 @@ fn convert_to_python_name(name: Str) -> Str {
fn escape_name(name: Str) -> Str { fn escape_name(name: Str) -> Str {
let mut name = convert_to_python_name(name).to_string(); let mut name = convert_to_python_name(name).to_string();
name = name.replace("!", "__erg_proc__"); name = name.replace('!', "__erg_proc__");
name = name.replace("$", "__erg_shared__"); name = name.replace('$', "__erg_shared__");
Str::rc(&name) Str::rc(&name)
} }
@ -290,15 +290,12 @@ impl CodeGenerator {
} else { } else {
Some(Name::fast(idx)) Some(Name::fast(idx))
} }
} else if let Some(idx) = self } else { self
.cur_block_codeobj() .cur_block_codeobj()
.freevars .freevars
.iter() .iter()
.position(|f| &**f == name) .position(|f| &**f == name)
{ .map(Name::deref)
Some(Name::deref(idx))
} else {
None
} }
} }
@ -307,7 +304,7 @@ impl CodeGenerator {
// search_name()を実行した後なのでcur_blockはskipする // search_name()を実行した後なのでcur_blockはskipする
for (nth_from_toplevel, block) in self.units.iter_mut().enumerate().rev().skip(1) { for (nth_from_toplevel, block) in self.units.iter_mut().enumerate().rev().skip(1) {
let block_is_toplevel = nth_from_toplevel == 0; 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); return Some(StoreLoadKind::Deref);
} else if let Some(idx) = block.codeobj.varnames.iter().position(|v| &**v == name) { } else if let Some(idx) = block.codeobj.varnames.iter().position(|v| &**v == name) {
if block_is_toplevel { if block_is_toplevel {
@ -319,12 +316,10 @@ impl CodeGenerator {
return Some(StoreLoadKind::Deref); return Some(StoreLoadKind::Deref);
} }
} }
if block_is_toplevel { if block_is_toplevel && block.codeobj.names.iter().any(|n| &**n == name) {
if let Some(_) = block.codeobj.names.iter().position(|n| &**n == name) {
return Some(StoreLoadKind::Global); return Some(StoreLoadKind::Global);
} }
} }
}
// 見つからなかった変数(前方参照変数など)はグローバル // 見つからなかった変数(前方参照変数など)はグローバル
Some(StoreLoadKind::Global) Some(StoreLoadKind::Global)
} }
@ -363,14 +358,14 @@ impl CodeGenerator {
} }
fn register_attr(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name { 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); let name = escape_attr(class, uniq_obj_name, name);
self.mut_cur_block_codeobj().names.push(name); self.mut_cur_block_codeobj().names.push(name);
Name::local(self.cur_block_codeobj().names.len() - 1) Name::local(self.cur_block_codeobj().names.len() - 1)
} }
fn register_method(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name { 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); let name = escape_attr(class, uniq_obj_name, name);
self.mut_cur_block_codeobj().names.push(name); self.mut_cur_block_codeobj().names.push(name);
Name::local(self.cur_block_codeobj().names.len() - 1) Name::local(self.cur_block_codeobj().names.len() - 1)
@ -493,7 +488,7 @@ impl CodeGenerator {
.iter() .iter()
.map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")), .map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")),
) )
.map(|s| self.get_cached(&s)) .map(|s| self.get_cached(s))
.collect() .collect()
} }
@ -590,7 +585,7 @@ impl CodeGenerator {
let idx_pop_jump_if_false = self.cur_block().lasti; let idx_pop_jump_if_false = self.cur_block().lasti;
self.write_instr(POP_JUMP_IF_FALSE); self.write_instr(POP_JUMP_IF_FALSE);
// cannot detect where to jump to at this moment, so put as 0 // 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) { match args.remove(0) {
// then block // then block
Expr::Lambda(lambda) => { Expr::Lambda(lambda) => {
@ -603,7 +598,7 @@ impl CodeGenerator {
} }
if args.get(0).is_some() { if args.get(0).is_some() {
self.write_instr(JUMP_FORWARD); // jump to end self.write_instr(JUMP_FORWARD); // jump to end
self.write_arg(0 as u8); self.write_arg(0_u8);
// else block // else block
let idx_else_begin = self.cur_block().lasti; let idx_else_begin = self.cur_block().lasti;
self.edit_code(idx_pop_jump_if_false + 1, idx_else_begin / 2); 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![]; let mut absolute_jump_points = vec![];
while let Some(expr) = args.try_remove(0) { 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_instr(Opcode::DUP_TOP);
self.write_arg(0); self.write_arg(0);
self.stack_inc(); self.stack_inc();
@ -1145,9 +1140,9 @@ impl CodeGenerator {
if !self.units.is_empty() { if !self.units.is_empty() {
let ld = unit.prev_lineno - self.cur_block().prev_lineno; let ld = unit.prev_lineno - self.cur_block().prev_lineno;
if ld != 0 { 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; *l += ld as u8;
}); }
self.mut_cur_block().prev_lineno += ld; self.mut_cur_block().prev_lineno += ld;
} }
} }
@ -1204,9 +1199,9 @@ impl CodeGenerator {
if !self.units.is_empty() { if !self.units.is_empty() {
let ld = unit.prev_lineno - self.cur_block().prev_lineno; let ld = unit.prev_lineno - self.cur_block().prev_lineno;
if ld != 0 { 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; *l += ld as u8;
}); }
self.mut_cur_block().prev_lineno += ld; self.mut_cur_block().prev_lineno += ld;
} }
} }
@ -1242,7 +1237,7 @@ impl CodeGenerator {
self.edit_code(print_point, Opcode::NOP as usize); self.edit_code(print_point, Opcode::NOP as usize);
} else { } else {
self.write_instr(CALL_FUNCTION); self.write_instr(CALL_FUNCTION);
self.write_arg(1 as u8); self.write_arg(1_u8);
} }
self.stack_dec(); self.stack_dec();
} }
@ -1271,9 +1266,9 @@ impl CodeGenerator {
if !self.units.is_empty() { if !self.units.is_empty() {
let ld = unit.prev_lineno - self.cur_block().prev_lineno; let ld = unit.prev_lineno - self.cur_block().prev_lineno;
if ld != 0 { 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; *l += ld as u8;
}); }
self.mut_cur_block().prev_lineno += ld; self.mut_cur_block().prev_lineno += ld;
} }
} }

View file

@ -176,7 +176,7 @@ impl TyVarContext {
Type::Poly { params, .. } => params.iter().fold(dep, |acc, arg| { Type::Poly { params, .. } => params.iter().fold(dep, |acc, arg| {
[acc, Self::rec_tp_inner_qvars(arg, vec![])].concat() [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::Subr(_subr) => todo!(),
Type::Callable { param_ts: _, return_t: _ } => todo!(), Type::Callable { param_ts: _, return_t: _ } => todo!(),
Type::And(_) | Type::Or(_) | Type::Not(_) => todo!(), Type::And(_) | Type::Or(_) | Type::Not(_) => todo!(),
@ -210,11 +210,10 @@ impl TyVarContext {
TyBound::Subtype { sub, sup } => { TyBound::Subtype { sub, sup } => {
let sup = match sup { let sup = match sup {
Type::Poly { name, params } => { Type::Poly { name, params } => {
let sup = Type::poly( Type::poly(
name, name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(), params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
); )
sup
} }
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs), Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
sup => sup, sup => sup,
@ -226,11 +225,10 @@ impl TyVarContext {
TyBound::Supertype { sup, sub } => { TyBound::Supertype { sup, sub } => {
let sub = match sub { let sub = match sub {
Type::Poly { name, params } => { Type::Poly { name, params } => {
let sub = Type::poly( Type::poly(
name, name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(), params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
); )
sub
} }
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs), Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
sub => sub, sub => sub,
@ -242,22 +240,20 @@ impl TyVarContext {
TyBound::Sandwiched { sub, mid, sup } => { TyBound::Sandwiched { sub, mid, sup } => {
let sub = match sub { let sub = match sub {
Type::Poly { name, params } => { Type::Poly { name, params } => {
let sub = Type::poly( Type::poly(
name, name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(), params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
); )
sub
} }
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs), Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
sub => sub, sub => sub,
}; };
let sup = match sup { let sup = match sup {
Type::Poly { name, params } => { Type::Poly { name, params } => {
let sup = Type::poly( Type::poly(
name, name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(), params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
); )
sup
} }
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs), Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
sup => sup, sup => sup,
@ -269,16 +265,15 @@ impl TyVarContext {
TyBound::Instance { name, t } => { TyBound::Instance { name, t } => {
let t = match t { let t = match t {
Type::Poly { name, params } => { Type::Poly { name, params } => {
let t = Type::poly( Type::poly(
name, name,
params.into_iter().map(|p| self.instantiate_tp(p)).collect(), params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
); )
t
} }
t => t, t => t,
}; };
// TODO: type-like types // TODO: type-like types
if &t == &Type { if t == Type {
let constraint = Constraint::TypeOf(t); let constraint = Constraint::TypeOf(t);
self.push_tyvar( self.push_tyvar(
name.clone(), name.clone(),
@ -299,10 +294,10 @@ impl TyVarContext {
match quantified { match quantified {
Type::MonoQVar(n) => { Type::MonoQVar(n) => {
if let Some(t) = self.get_tyvar(&n) { if let Some(t) = self.get_tyvar(&n) {
return t.clone(); t.clone()
} else if let Some(t) = self.get_typaram(&n) { } else if let Some(t) = self.get_typaram(&n) {
if let TyParam::Type(t) = t { if let TyParam::Type(t) = t {
return *t.clone(); *t.clone()
} else { } else {
todo!() todo!()
} }
@ -318,9 +313,9 @@ impl TyVarContext {
match quantified { match quantified {
TyParam::MonoQVar(n) => { TyParam::MonoQVar(n) => {
if let Some(t) = self.get_typaram(&n) { if let Some(t) = self.get_typaram(&n) {
return t.clone(); t.clone()
} else if let Some(t) = self.get_tyvar(&n) { } else if let Some(t) = self.get_tyvar(&n) {
return TyParam::t(t.clone()); TyParam::t(t.clone())
} else { } else {
panic!("Type parameter {n} is not found. This is a bug.") panic!("Type parameter {n} is not found. This is a bug.")
} }
@ -328,9 +323,9 @@ impl TyVarContext {
TyParam::Type(t) => { TyParam::Type(t) => {
if let Type::MonoQVar(n) = *t { if let Type::MonoQVar(n) = *t {
if let Some(t) = self.get_typaram(&n) { if let Some(t) = self.get_typaram(&n) {
return t.clone(); t.clone()
} else if let Some(t) = self.get_tyvar(&n) { } else if let Some(t) = self.get_tyvar(&n) {
return TyParam::t(t.clone()); TyParam::t(t.clone())
} else { } else {
panic!("Type variable {n} is not found. This is a bug.") panic!("Type variable {n} is not found. This is a bug.")
} }
@ -710,9 +705,7 @@ impl Context {
v.inspect(), v.inspect(),
)); ));
} }
let kind = id let kind = id.map_or(VarKind::Declared, VarKind::Defined);
.map(|id| VarKind::Defined(id))
.unwrap_or(VarKind::Declared);
let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?; let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?;
self.decls self.decls
.insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind)); .insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind));
@ -743,9 +736,7 @@ impl Context {
) -> TyCheckResult<()> { ) -> TyCheckResult<()> {
let name = sig.name.inspect(); let name = sig.name.inspect();
let muty = Mutability::from(&name[..]); let muty = Mutability::from(&name[..]);
let kind = id let kind = id.map_or(VarKind::Declared, VarKind::Defined);
.map(|id| VarKind::Defined(id))
.unwrap_or(VarKind::Declared);
if self.registered(name, name.is_uppercase()) { if self.registered(name, name.is_uppercase()) {
return Err(TyCheckError::duplicate_decl_error( return Err(TyCheckError::duplicate_decl_error(
sig.loc(), sig.loc(),
@ -805,7 +796,7 @@ impl Context {
v.inspect(), v.inspect(),
)) ))
} else { } else {
if let Some(_) = self.decls.remove(v.inspect()) { if self.decls.remove(v.inspect()).is_some() {
// something to do? // something to do?
} }
let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id)); let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id));
@ -957,7 +948,7 @@ impl Context {
let name = &sig.name; let name = &sig.name;
// FIXME: constでない関数 // FIXME: constでない関数
let t = self let t = self
.get_current_scope_var(&name.inspect()) .get_current_scope_var(name.inspect())
.map(|v| &v.t) .map(|v| &v.t)
.unwrap(); .unwrap();
let non_default_params = t.non_default_params().unwrap(); let non_default_params = t.non_default_params().unwrap();
@ -1490,7 +1481,7 @@ impl Context {
) )
.map_err(|e| { .map_err(|e| {
// REVIEW: // REVIEW:
let name = callee.var_full_name().unwrap_or("".to_string()); let name = callee.var_full_name().unwrap_or_else(|| "".to_string());
let name = let name =
name + "::" + param_ty.name.as_ref().map(|s| &s[..]).unwrap_or(""); name + "::" + param_ty.name.as_ref().map(|s| &s[..]).unwrap_or("");
TyCheckError::type_mismatch_error( TyCheckError::type_mismatch_error(
@ -1649,19 +1640,13 @@ impl Context {
/// 可変依存型の変更を伝搬させる /// 可変依存型の変更を伝搬させる
fn propagate(&self, t: &Type, callee: &hir::Expr) -> TyCheckResult<()> { fn propagate(&self, t: &Type, callee: &hir::Expr) -> TyCheckResult<()> {
match t { if let Type::Subr(SubrType {
Type::Subr(subr) => match &subr.kind { kind: SubrKind::ProcMethod { after: Some(after), .. },
SubrKind::ProcMethod { ..
before: _, }) = t {
after: Some(after),
} => {
let receiver_t = callee.receiver_t().unwrap(); let receiver_t = callee.receiver_t().unwrap();
self.reunify(receiver_t, after, Some(callee.loc()), None)?; self.reunify(receiver_t, after, Some(callee.loc()), None)?;
} }
_ => {}
},
_ => {}
}
Ok(()) Ok(())
} }
@ -1682,7 +1667,7 @@ impl Context {
return Ok(()); return Ok(());
} }
match (l, r) { 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)) (ltp @ TyParam::FreeVar(lfv), rtp @ TyParam::FreeVar(rfv))
if lfv.is_unbound() && rfv.is_unbound() => if lfv.is_unbound() && rfv.is_unbound() =>
{ {
@ -1701,11 +1686,11 @@ impl Context {
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {} FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {}
} // &fv is dropped } // &fv is dropped
let fv_t = fv.borrow().constraint().unwrap().typ().unwrap().clone(); // fvを参照しないよいにcloneする(あとでborrow_mutするため) 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) { if self.rec_full_supertype_of(&fv_t, &tp_t) {
// 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md) // 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md)
if fv.level() < Some(self.level) { 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( if self.is_sub_constraint_of(
fv.borrow().constraint().unwrap(), fv.borrow().constraint().unwrap(),
&new_constraint, &new_constraint,
@ -1717,10 +1702,9 @@ impl Context {
fv.link(tp); fv.link(tp);
} }
Ok(()) Ok(())
} else { } else if allow_divergence
if allow_divergence && (self.eq_tp(tp, &TyParam::value(Inf), None, None)
&& (self.eq_tp(&tp, &TyParam::value(Inf), None, None) || self.eq_tp(tp, &TyParam::value(NegInf), None, None))
|| self.eq_tp(&tp, &TyParam::value(NegInf), None, None))
&& self.rec_full_subtype_of(&fv_t, &Type::mono("Num")) && self.rec_full_subtype_of(&fv_t, &Type::mono("Num"))
{ {
fv.link(tp); fv.link(tp);
@ -1729,7 +1713,6 @@ impl Context {
Err(TyCheckError::unreachable(fn_name!(), line!())) Err(TyCheckError::unreachable(fn_name!(), line!()))
} }
} }
}
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval }) (TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval })
if lop == rop => if lop == rop =>
{ {
@ -1769,7 +1752,7 @@ impl Context {
*l.borrow_mut() = r.borrow().clone(); *l.borrow_mut() = r.borrow().clone();
Ok(()) 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 }) (TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval })
if lop == rop => if lop == rop =>
{ {
@ -2333,7 +2316,7 @@ impl Context {
self.instantiate_typespec(spec, mode)? self.instantiate_typespec(spec, mode)?
} else { } else {
match &sig.pat { 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> // TODO: Array<Lit>
_ => { _ => {
let level = if mode == PreRegister { let level = if mode == PreRegister {
@ -2607,7 +2590,7 @@ impl Context {
self.caused_by(), self.caused_by(),
"match", "match",
&Type::mono("LambdaFunc"), &Type::mono("LambdaFunc"),
&t, t,
)); ));
} }
} }
@ -2633,13 +2616,13 @@ impl Context {
// NG: expr_t: Nat, union_pat_t: {1, 2} // NG: expr_t: Nat, union_pat_t: {1, 2}
// OK: expr_t: Int, union_pat_t: {1} | 'T // OK: expr_t: Int, union_pat_t: {1} | 'T
if expr_t.has_no_unbound_var() if expr_t.has_no_unbound_var()
&& self.formal_supertype_of(&expr_t, &union_pat_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) && !self.formal_supertype_of(&union_pat_t, expr_t, None, None)
{ {
return Err(TyCheckError::match_error( return Err(TyCheckError::match_error(
pos_args[0].loc(), pos_args[0].loc(),
self.caused_by(), self.caused_by(),
&expr_t, expr_t,
)); ));
} }
let branch_ts = pos_args let branch_ts = pos_args
@ -2658,7 +2641,7 @@ impl Context {
}; };
let param_ts = [ let param_ts = [
vec![ParamTy::anonymous(expr_t)], vec![ParamTy::anonymous(expr_t)],
branch_ts.iter().map(|pt| pt.clone()).collect(), branch_ts.to_vec(),
] ]
.concat(); .concat();
let t = Type::func(param_ts, vec![], return_t); let t = Type::func(param_ts, vec![], return_t);
@ -2749,8 +2732,8 @@ impl Context {
) -> TyCheckResult<Type> { ) -> TyCheckResult<Type> {
erg_common::debug_power_assert!(args.len() == 2); erg_common::debug_power_assert!(args.len() == 2);
let symbol = Token::symbol(binop_to_dname(op.inspect())); let symbol = Token::symbol(binop_to_dname(op.inspect()));
let mut op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted)); let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
self.get_call_t(&mut op, args, &[], namespace).map_err(|e| { self.get_call_t(&op, args, &[], namespace).map_err(|e| {
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする // HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
let core = ErrorCore::new( let core = ErrorCore::new(
e.core.errno, e.core.errno,
@ -2771,8 +2754,8 @@ impl Context {
) -> TyCheckResult<Type> { ) -> TyCheckResult<Type> {
erg_common::debug_power_assert!(args.len() == 1); erg_common::debug_power_assert!(args.len() == 1);
let symbol = Token::symbol(unaryop_to_dname(op.inspect())); let symbol = Token::symbol(unaryop_to_dname(op.inspect()));
let mut op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted)); let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
self.get_call_t(&mut op, args, &[], namespace).map_err(|e| { self.get_call_t(&op, args, &[], namespace).map_err(|e| {
let core = ErrorCore::new( let core = ErrorCore::new(
e.core.errno, e.core.errno,
e.core.kind, e.core.kind,
@ -2809,7 +2792,7 @@ impl Context {
log!("Substituted:\ninstance: {instance}"); log!("Substituted:\ninstance: {instance}");
let res = self.deref_tyvar(instance)?; let res = self.deref_tyvar(instance)?;
log!("Eliminated:\nres: {res}\n"); 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"); log!("Params Evaluated:\nres: {res}\n");
let res = self.deref_tyvar(res)?; let res = self.deref_tyvar(res)?;
log!("Eliminated (2):\nres: {res}\n"); log!("Eliminated (2):\nres: {res}\n");
@ -2873,13 +2856,13 @@ impl Context {
| FreeKind::NamedUnbound { constraint, .. } => { | FreeKind::NamedUnbound { constraint, .. } => {
let t = constraint.typ().unwrap(); let t = constraint.typ().unwrap();
let other_t = self.type_of(other, bounds); 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, (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. /// e.g.
@ -3292,7 +3275,7 @@ impl Context {
// try_cmp((n: 2.._), 1) -> Some(Greater) // try_cmp((n: 2.._), 1) -> Some(Greater)
// try_cmp((n: -1.._), 1) -> Some(Any) // try_cmp((n: -1.._), 1) -> Some(Any)
(l @ (TyParam::Erased(_) | TyParam::FreeVar(_) | TyParam::MonoQVar(_)), p) => { (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 inf = self.inf(&t);
let sup = self.sup(&t); let sup = self.sup(&t);
if let (Some(inf), Some(sup)) = (inf, sup) { if let (Some(inf), Some(sup)) = (inf, sup) {
@ -3355,7 +3338,7 @@ impl Context {
Refinement(r) => r, Refinement(r) => r,
t => { t => {
let var = Str::from(fresh_varname()); let var = Str::from(fresh_varname());
RefinementType::new(var.clone(), t, set! {}) RefinementType::new(var, t, set! {})
} }
} }
} }
@ -3486,7 +3469,7 @@ impl Context {
#[inline] #[inline]
fn type_of(&self, p: &TyParam, bounds: Option<&Set<TyBound>>) -> Type { 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を実装しない // sup/inf({±∞}) = ±∞ではあるが、Inf/NegInfにはOrdを実装しない
@ -3501,7 +3484,7 @@ impl Context {
if lhs == &refine.var => if lhs == &refine.var =>
{ {
if let Some(max) = &maybe_max { 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()); maybe_max = Some(rhs.clone());
} }
} else { } else {
@ -3529,7 +3512,7 @@ impl Context {
if lhs == &refine.var => if lhs == &refine.var =>
{ {
if let Some(min) = &maybe_min { 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()); maybe_min = Some(rhs.clone());
} }
} else { } else {
@ -3753,25 +3736,23 @@ impl Context {
fn rec_get_patch(&self, name: &VarName) -> Option<&Context> { fn rec_get_patch(&self, name: &VarName) -> Option<&Context> {
if let Some(patch) = self.patches.get(name) { 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 { } else {
if let Some(outer) = &self.outer {
return outer.rec_get_patch(name);
}
}
None None
} }
}
fn rec_get_mod(&self, name: &str) -> Option<&Context> { fn rec_get_mod(&self, name: &str) -> Option<&Context> {
if let Some(mod_) = self.mods.get(name) { 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 { } 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> { fn rec_get_trait_impls(&self, name: &Str) -> Vec<Type> {
let impls = if let Some(impls) = self.poly_trait_impls.get(name) { let impls = if let Some(impls) = self.poly_trait_impls.get(name) {
@ -3785,14 +3766,13 @@ 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() { for expr in block.iter() {
match expr { if let ast::Expr::Def(def) = expr {
ast::Expr::Def(def) => {
let id = Some(def.body.id); let id = Some(def.body.id);
let eval_body_t = || { let eval_body_t = || {
self.eval self.eval
.eval_const_block(&def.body.block, &self) .eval_const_block(&def.body.block, self)
.map(|c| Type::enum_t(set![c])) .map(|c| Type::enum_t(set![c]))
}; };
match &def.sig { match &def.sig {
@ -3802,7 +3782,7 @@ impl Context {
} else { } else {
eval_body_t() eval_body_t()
}; };
self.declare_sub(&sig, opt_ret_t, id)?; self.declare_sub(sig, opt_ret_t, id)?;
} }
ast::Signature::Var(sig) if sig.is_const() => { ast::Signature::Var(sig) if sig.is_const() => {
let t = if let Some(spec) = sig.t_spec.as_ref() { let t = if let Some(spec) = sig.t_spec.as_ref() {
@ -3810,13 +3790,11 @@ impl Context {
} else { } else {
eval_body_t() eval_body_t()
}; };
self.declare_var(&sig, t, id)?; self.declare_var(sig, t, id)?;
} }
_ => {} _ => {}
} }
} }
_ => {}
}
} }
Ok(()) 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, _)| { let param_names = ty_ctx.params.iter().map(|(opt_name, _)| {
opt_name opt_name
.as_ref() .as_ref()
.map(|n| n.inspect().clone()) .map_or_else(|| Str::ever("_"), |n| n.inspect().clone())
.unwrap_or(Str::ever("_"))
.clone()
}); });
let self_ = SubstContext { // REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は?
SubstContext {
params: param_names params: param_names
.zip(substituted.typarams().into_iter()) .zip(substituted.typarams().into_iter())
.collect(), .collect(),
}; }
// REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は?
self_
} }
fn substitute(&self, quant_t: Type, ty_ctx: &Context, level: usize) -> TyCheckResult<Type> { fn substitute(&self, quant_t: Type, ty_ctx: &Context, level: usize) -> TyCheckResult<Type> {
@ -58,12 +55,10 @@ impl SubstContext {
if let Some(v) = self.params.get(&name) { if let Some(v) = self.params.get(&name) {
ty_ctx.unify_tp(param, v, None, None, false)?; ty_ctx.unify_tp(param, v, None, None, false)?;
} }
} else { } else if fv.is_unbound() {
if fv.is_unbound() {
panic!() panic!()
} }
} }
}
TyParam::BinOp { lhs, rhs, .. } => { TyParam::BinOp { lhs, rhs, .. } => {
self.substitute_tp(lhs, ty_ctx)?; self.substitute_tp(lhs, ty_ctx)?;
self.substitute_tp(rhs, ty_ctx)?; self.substitute_tp(rhs, ty_ctx)?;
@ -192,28 +187,28 @@ impl Evaluator {
match op { match op {
Add => lhs Add => lhs
.try_add(rhs) .try_add(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Sub => lhs Sub => lhs
.try_sub(rhs) .try_sub(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Mul => lhs Mul => lhs
.try_mul(rhs) .try_mul(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Div => lhs Div => lhs
.try_div(rhs) .try_div(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Gt => lhs Gt => lhs
.try_gt(rhs) .try_gt(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Ge => lhs Ge => lhs
.try_ge(rhs) .try_ge(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Eq => lhs Eq => lhs
.try_eq(rhs) .try_eq(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
Ne => lhs Ne => lhs
.try_ne(rhs) .try_ne(rhs)
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
other => todo!("{other}"), other => todo!("{other}"),
} }
} }
@ -227,7 +222,7 @@ impl Evaluator {
match (lhs, rhs) { match (lhs, rhs) {
(TyParam::ConstObj(ConstObj::Value(lhs)), TyParam::ConstObj(ConstObj::Value(rhs))) => { (TyParam::ConstObj(ConstObj::Value(lhs)), TyParam::ConstObj(ConstObj::Value(rhs))) => {
self.eval_bin_lit(op, lhs.clone(), rhs.clone()) self.eval_bin_lit(op, lhs.clone(), rhs.clone())
.map(|v| TyParam::value(v)) .map(TyParam::value)
} }
( (
TyParam::ConstObj(ConstObj::MutValue(lhs)), TyParam::ConstObj(ConstObj::MutValue(lhs)),
@ -272,14 +267,14 @@ impl Evaluator {
fn eval_unary_tp(&self, op: OpKind, val: &TyParam) -> EvalResult<TyParam> { fn eval_unary_tp(&self, op: OpKind, val: &TyParam) -> EvalResult<TyParam> {
match val { 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()), TyParam::FreeVar(fv) if fv.is_linked() => self.eval_unary_tp(op, &*fv.crack()),
e @ TyParam::Erased(_) => Ok(e.clone()), e @ TyParam::Erased(_) => Ok(e.clone()),
other => todo!("{op} {other}"), 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!() todo!()
} }
@ -294,7 +289,7 @@ impl Evaluator {
ConstObj::Value(v) => Some(TyParam::value(v.clone())), ConstObj::Value(v) => Some(TyParam::value(v.clone())),
_ => None, _ => 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::BinOp { op, lhs, rhs } => self.eval_bin_tp(*op, lhs, rhs),
TyParam::UnaryOp { op, val } => self.eval_unary_tp(*op, val), TyParam::UnaryOp { op, val } => self.eval_unary_tp(*op, val),
TyParam::App { name, args } => self.eval_app(name, args), TyParam::App { name, args } => self.eval_app(name, args),
@ -443,7 +438,7 @@ impl Evaluator {
match p { match p {
TyParam::ConstObj(ConstObj::Value(v)) => Ok(Type::enum_t(set![v])), TyParam::ConstObj(ConstObj::Value(v)) => Ok(Type::enum_t(set![v])),
TyParam::ConstObj(ConstObj::MutValue(v)) => Ok(v.borrow().class().mutate()), 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) => { TyParam::FreeVar(fv) => {
if let Some(t) = fv.type_of() { if let Some(t) = fv.type_of() {
Ok(t) Ok(t)
@ -459,7 +454,7 @@ impl Evaluator {
ConstObj::Value(v) => Some(Type::enum_t(set![v.clone()])), ConstObj::Value(v) => Some(Type::enum_t(set![v.clone()])),
_ => None, _ => None,
}) })
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
TyParam::MonoQVar(name) => { TyParam::MonoQVar(name) => {
if let Some(bs) = bounds { if let Some(bs) = bounds {
if let Some(bound) = bs.iter().find(|b| b.mentions_as_instance(&name)) { 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)?; let p = self.eval_tp(p, ctx)?;
match p { match p {
TyParam::ConstObj(ConstObj::Value(v)) => Ok(v.class()), TyParam::ConstObj(ConstObj::Value(v)) => Ok(v.class()),
TyParam::Erased(t) => Ok((&*t).clone()), TyParam::Erased(t) => Ok((*t).clone()),
TyParam::FreeVar(fv) => { TyParam::FreeVar(fv) => {
if let Some(t) = fv.type_of() { if let Some(t) = fv.type_of() {
Ok(t) Ok(t)
@ -499,7 +494,7 @@ impl Evaluator {
ConstObj::Value(v) => Some(v.class()), ConstObj::Value(v) => Some(v.class()),
_ => None, _ => None,
}) })
.ok_or(EvalError::unreachable(fn_name!(), line!())), .ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
other => todo!("{other}"), other => todo!("{other}"),
} }
} }

View file

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

View file

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

View file

@ -50,14 +50,14 @@ impl ASTLowerer {
expect: &Type, expect: &Type,
found: &Type, found: &Type,
) -> LowerResult<()> { ) -> LowerResult<()> {
self.ctx.unify(expect, found, Some(loc), None).or_else(|_| { self.ctx.unify(expect, found, Some(loc), None).map_err(|_| {
Err(LowerError::type_mismatch_error( LowerError::type_mismatch_error(
loc, loc,
self.ctx.caused_by(), self.ctx.caused_by(),
name, name,
expect, expect,
found, found,
)) )
}) })
} }
@ -176,9 +176,9 @@ impl ASTLowerer {
self.lower_expr(arg.expr, true)?, 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( let t = self.ctx.get_call_t(
&mut obj, &obj,
hir_args.pos_args(), hir_args.pos_args(),
hir_args.kw_args(), hir_args.kw_args(),
&self.ctx.name, &self.ctx.name,
@ -283,7 +283,7 @@ impl ASTLowerer {
.map(|vi| vi.t.clone()); .map(|vi| vi.t.clone());
let name = sig.pat.inspect().unwrap(); let name = sig.pat.inspect().unwrap();
if let Some(expect_body_t) = opt_expect_body_t { 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); 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) { fn check_expr(&mut self, expr: &Expr, ownership: Ownership) {
match expr { match expr {
Expr::Def(def) => { Expr::Def(def) => {
self.define(&def); self.define(def);
let name_and_vis = match &def.sig { let name_and_vis = match &def.sig {
Signature::Var(var) => Signature::Var(var) =>
// TODO: visibility // TODO: visibility
@ -249,3 +249,9 @@ impl OwnershipChecker {
panic!("variable not found: {name}"); 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)?; line.fmt_nest(f, level)?;
} }
for arg in iter { for arg in iter {
write!(f, "\n")?; writeln!(f)?;
arg.fmt_nest(f, level)?; arg.fmt_nest(f, level)?;
} }
Ok(()) Ok(())
@ -107,7 +107,7 @@ pub struct KwArg {
impl NestedDisplay for KwArg { impl NestedDisplay for KwArg {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { 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) self.expr.fmt_nest(f, level + 1)
} }
} }
@ -453,9 +453,9 @@ pub struct BinOp {
impl NestedDisplay for BinOp { impl NestedDisplay for BinOp {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { 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)?; self.args[0].fmt_nest(f, level + 1)?;
write!(f, "\n")?; writeln!(f)?;
self.args[1].fmt_nest(f, level + 1) self.args[1].fmt_nest(f, level + 1)
} }
} }
@ -485,7 +485,7 @@ pub struct UnaryOp {
impl NestedDisplay for UnaryOp { impl NestedDisplay for UnaryOp {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { 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) self.args[0].fmt_nest(f, level + 1)
} }
} }
@ -515,7 +515,7 @@ pub struct Call {
impl NestedDisplay for Call { impl NestedDisplay for Call {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { 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) 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::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"),
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"), Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
Self::Array { t, len } => write!(f, "[{t}; {len}]"), 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::Enum(elems) => write!(f, "{{{elems}}}"),
Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()), Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()),
Self::Subr(s) => write!(f, "{s}"), Self::Subr(s) => write!(f, "{s}"),
@ -1537,7 +1537,7 @@ impl VarPattern {
Self::Array(VarArrayPattern { elems, .. }) Self::Array(VarArrayPattern { elems, .. })
| Self::Tuple(VarTuplePattern { elems, .. }) | Self::Tuple(VarTuplePattern { elems, .. })
| Self::Record(VarRecordPattern { elems, .. }) => { | Self::Record(VarRecordPattern { elems, .. }) => {
elems.iter().map(|s| s.pat.inspects()).flatten().collect() elems.iter().flat_map(|s| s.pat.inspects()).collect()
} }
_ => vec![], _ => vec![],
} }
@ -1992,7 +1992,7 @@ pub struct Lambda {
impl NestedDisplay for Lambda { impl NestedDisplay for Lambda {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { 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) self.body.fmt_nest(f, level + 1)
} }
} }
@ -2026,7 +2026,7 @@ impl Signature {
pub fn name_as_str(&self) -> &Str { pub fn name_as_str(&self) -> &Str {
match self { match self {
Self::Var(v) => v.pat.inspect().unwrap(), 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 { impl NestedDisplay for Def {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { 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) self.body.block.fmt_nest(f, level + 1)
} }
} }

View file

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

View file

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

View file

@ -158,15 +158,13 @@ impl Parser {
Side::LhsAssign Side::LhsAssign
} }
// (cur) -> ... ; ... = // (cur) -> ... ; ... =
else { else if self.arrow_distance(0, 0) == 1 {
if self.arrow_distance(0, 0) == 1 {
Side::LhsLambda Side::LhsLambda
} else { } else {
Side::Rhs Side::Rhs
} }
} }
} }
}
// (cur) = ... -> ... // (cur) = ... -> ...
// (cur) -> ... = ... // (cur) -> ... = ...
(Some(_eq), Some(_arrow), None) => Side::LhsAssign, (Some(_eq), Some(_arrow), None) => Side::LhsAssign,
@ -454,16 +452,9 @@ impl Parser {
#[inline] #[inline]
fn opt_reduce_decorators(&mut self) -> ParseResult<Set<Decorator>> { fn opt_reduce_decorators(&mut self) -> ParseResult<Set<Decorator>> {
let mut decs = set![]; let mut decs = set![];
loop { while let Some(deco) = self.opt_reduce_decorator()? {
match self.opt_reduce_decorator()? {
Some(deco) => {
decs.insert(deco); decs.insert(deco);
} }
None => {
break;
}
}
}
Ok(decs) Ok(decs)
} }
@ -521,14 +512,13 @@ impl Parser {
} }
None None
} }
} else { } else if self.cur_is(Colon) {
if self.cur_is(Colon) {
self.skip(); self.skip();
Some(self.try_reduce_type_spec()?) Some(self.try_reduce_type_spec()?)
} else { } else {
None None
}
}; };
Ok(Signature::Var(VarSignature::new( Ok(Signature::Var(VarSignature::new(
VarPattern::VarName(name), VarPattern::VarName(name),
t_spec, t_spec,
@ -1236,7 +1226,7 @@ impl Parser {
}; };
Ok(KwArg::new(keyword, self.try_reduce_expr()?)) Ok(KwArg::new(keyword, self.try_reduce_expr()?))
} else { } 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())), 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 { pub const fn is_right_associative(&self) -> bool {
match self { matches!(self, FuncArrow | ProcArrow | Equal /* | PreDollar | PreAt */)
FuncArrow | ProcArrow | Equal => true,
// PreDollar | PreAt => true,
_ => false,
}
} }
} }
@ -337,7 +333,7 @@ impl fmt::Debug for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Token") f.debug_struct("Token")
.field("kind", &self.kind) .field("kind", &self.kind)
.field("content", &self.content.replace("\n", "\\n")) .field("content", &self.content.replace('\n', "\\n"))
.field("lineno", &self.lineno) .field("lineno", &self.lineno)
.field("col_begin", &self.col_begin) .field("col_begin", &self.col_begin)
.finish() .finish()
@ -346,7 +342,7 @@ impl fmt::Debug for Token {
impl fmt::Display for Token { impl fmt::Display for Token {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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 { pub fn is_procedural(&self) -> bool {
self.inspect().ends_with("!") self.inspect().ends_with('!')
} }
} }