mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Apply trivial clippy fixes
This commit is contained in:
parent
6d3dda8129
commit
7d3116f546
26 changed files with 360 additions and 384 deletions
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -219,3 +219,9 @@ impl SideEffectChecker {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SideEffectChecker {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,3 +193,9 @@ impl Desugarer {
|
|||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Desugarer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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())),
|
||||
|
|
|
@ -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('!')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue