diff --git a/compiler/erg_common/cache.rs b/compiler/erg_common/cache.rs index c701da9b..8ffe4aa9 100644 --- a/compiler/erg_common/cache.rs +++ b/compiler/erg_common/cache.rs @@ -1,20 +1,24 @@ -use std::rc::Rc; -use std::cell::RefCell; use std::borrow::{Borrow, ToOwned}; +use std::cell::RefCell; use std::hash::Hash; +use std::rc::Rc; use crate::set::Set; -use crate::{Str, RcArray}; +use crate::{RcArray, Str}; #[derive(Debug)] pub struct Cache(RefCell>>); impl Default for Cache { - fn default() -> Self { Self::new() } + fn default() -> Self { + Self::new() + } } impl Cache { - pub fn new() -> Self { Self(RefCell::new(Set::new())) } + pub fn new() -> Self { + Self(RefCell::new(Set::new())) + } } impl Clone for Cache { @@ -32,7 +36,7 @@ impl Clone for Cache { impl Cache { pub fn get(&self, s: &str) -> Str { if let Some(cached) = self.0.borrow().get(s) { - return cached.clone().into() + return cached.clone().into(); } // &self.0 is dropped let s = Str::rc(s); self.0.borrow_mut().insert(s.clone().into_rc()); @@ -43,7 +47,7 @@ impl Cache { impl Cache<[T]> { pub fn get(&self, q: &[T]) -> Rc<[T]> { if let Some(cached) = self.0.borrow().get(q) { - return cached.clone() + return cached.clone(); } // &self.0 is dropped let s = RcArray::from(q); self.0.borrow_mut().insert(s.clone()); @@ -53,9 +57,12 @@ impl Cache<[T]> { impl Cache { pub fn get(&self, q: &Q) -> Rc - where Rc: Borrow, Q: ToOwned { + where + Rc: Borrow, + Q: ToOwned, + { if let Some(cached) = self.0.borrow().get(q) { - return cached.clone() + return cached.clone(); } // &self.0 is dropped let s = Rc::from(q.to_owned()); self.0.borrow_mut().insert(s.clone()); diff --git a/compiler/erg_common/codeobj.rs b/compiler/erg_common/codeobj.rs index b71b5a17..8e8b3e64 100644 --- a/compiler/erg_common/codeobj.rs +++ b/compiler/erg_common/codeobj.rs @@ -3,15 +3,15 @@ use std::fs::File; use std::io::{BufReader, Read, Write}; use std::path::Path; -use crate::{Str}; +use crate::deserialize::{DeserializeResult, Deserializer}; use crate::impl_display_from_debug; -use crate::value::ValueObj; use crate::opcode::Opcode; use crate::python_util::detect_magic_number; use crate::serialize::*; use crate::traits::HasType; -use crate::ty::{TypePair, Type}; -use crate::deserialize::{Deserializer, DeserializeResult}; +use crate::ty::{Type, TypePair}; +use crate::value::ValueObj; +use crate::Str; pub fn consts_into_bytes(consts: Vec) -> Vec { let mut tuple = vec![]; @@ -32,30 +32,30 @@ pub fn consts_into_bytes(consts: Vec) -> Vec { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u32)] pub enum CodeObjFlags { - Optimized = 0x0001, - NewLocals = 0x0002, - VarArgs = 0x0004, - VarKeywords = 0x0008, - Nested = 0x0010, - Generator = 0x0020, - NoFree = 0x0040, - Coroutine = 0x0080, - IterableCoroutine = 0x0100, - AsyncGenerator = 0x0200, + Optimized = 0x0001, + NewLocals = 0x0002, + VarArgs = 0x0004, + VarKeywords = 0x0008, + Nested = 0x0010, + Generator = 0x0020, + NoFree = 0x0040, + Coroutine = 0x0080, + IterableCoroutine = 0x0100, + AsyncGenerator = 0x0200, // CO_GENERATOR_ALLOWED = 0x0400, - FutureDivision = 0x2000, - FutureAbsoluteImport = 0x4000, - FutureWithStatement = 0x8000, - FuturePrintFunction = 0x1_0000, - FutureUnicodeLiterals = 0x2_0000, - FutureBarryAsBDFL = 0x4_0000, - FutureGeneratorStop = 0x8_0000, - FutureAnnotations = 0x10_0000, + FutureDivision = 0x2000, + FutureAbsoluteImport = 0x4000, + FutureWithStatement = 0x8000, + FuturePrintFunction = 0x1_0000, + FutureUnicodeLiterals = 0x2_0000, + FutureBarryAsBDFL = 0x4_0000, + FutureGeneratorStop = 0x8_0000, + FutureAnnotations = 0x10_0000, // Erg-specific flags - EvmDynParam = 0x1000_0000, - EvmDynamic = 0x2000_0000, - EvmNoGC = 0x4000_0000, - Illegal = 0x0000, + EvmDynParam = 0x1000_0000, + EvmDynamic = 0x2000_0000, + EvmNoGC = 0x4000_0000, + Illegal = 0x0000, } impl Into for u32 { @@ -108,10 +108,10 @@ pub struct CodeObj { pub flags: u32, pub code: Vec, pub consts: Vec, // objects used in the code (literal) - pub names: Vec, // names used in the code object - pub varnames: Vec, // names defined in the code object - pub freevars: Vec, // names captured from the outer scope - pub cellvars: Vec, // names used in the inner function (closure) + pub names: Vec, // names used in the code object + pub varnames: Vec, // names defined in the code object + pub freevars: Vec, // names captured from the outer scope + pub cellvars: Vec, // names used in the inner function (closure) pub filename: Str, pub name: Str, pub firstlineno: u32, @@ -123,8 +123,12 @@ pub struct CodeObj { } impl HasType for CodeObj { - fn ref_t(&self) -> &Type { &Type::Code } - fn signature_t(&self) -> Option<&Type> { None } + fn ref_t(&self) -> &Type { + &Type::Code + } + fn signature_t(&self) -> Option<&Type> { + None + } } impl fmt::Debug for CodeObj { @@ -201,7 +205,12 @@ impl CodeObj { } } - pub fn empty, T: Into>(params: Vec, filename: S, name: T, firstlineno: u32) -> Self { + pub fn empty, T: Into>( + params: Vec, + filename: S, + name: T, + firstlineno: u32, + ) -> Self { Self { argcount: params.len() as u32, posonlyargcount: 0, @@ -226,8 +235,7 @@ impl CodeObj { let mut f = BufReader::new(File::open(path)?); let v = &mut Vec::with_capacity(16); f.read_to_end(v)?; - let python_ver = - get_magic_num_from_bytes(&Deserializer::consume::<4>(v)); + let python_ver = get_magic_num_from_bytes(&Deserializer::consume::<4>(v)); let _padding = Deserializer::deserialize_u32(v); let _timestamp = Deserializer::deserialize_u32(v); let _padding = Deserializer::deserialize_u32(v); @@ -238,16 +246,20 @@ impl CodeObj { pub fn from_bytes(v: &mut Vec, python_ver: u32) -> DeserializeResult { let mut des = Deserializer::new(); let argcount = Deserializer::deserialize_u32(v); - let posonlyargcount = if python_ver >= 3413 { Deserializer::deserialize_u32(v)} else { 0 }; + let posonlyargcount = if python_ver >= 3413 { + Deserializer::deserialize_u32(v) + } else { + 0 + }; let kwonlyargcount = Deserializer::deserialize_u32(v); let nlocals = Deserializer::deserialize_u32(v); - let stacksize = Deserializer::deserialize_u32(v); - let flags = Deserializer::deserialize_u32(v); + let stacksize = Deserializer::deserialize_u32(v); + let flags = Deserializer::deserialize_u32(v); let code = des.deserialize_bytes(v)?; let consts = des.deserialize_const_vec(v, python_ver)?; let names = des.deserialize_str_vec(v, python_ver)?; let varnames = des.deserialize_str_vec(v, python_ver)?; - let freevars =des.deserialize_str_vec(v, python_ver)?; + let freevars = des.deserialize_str_vec(v, python_ver)?; let cellvars = des.deserialize_str_vec(v, python_ver)?; let filename = des.deserialize_str(v, python_ver)?; let name = des.deserialize_str(v, python_ver)?; @@ -269,7 +281,7 @@ impl CodeObj { filename, name, firstlineno, - lnotab + lnotab, )) } @@ -298,7 +310,11 @@ impl CodeObj { bytes } - pub fn dump_as_pyc>(self, path: P, python_ver: Option) -> std::io::Result<()> { + pub fn dump_as_pyc>( + self, + path: P, + python_ver: Option, + ) -> std::io::Result<()> { let mut file = File::create(path)?; let mut bytes = Vec::with_capacity(16); let python_ver = python_ver.unwrap_or_else(|| detect_magic_number()); @@ -406,9 +422,12 @@ impl CodeObj { }; instrs += &format!("{} ({})", arg, op); } - Opcode::STORE_NAME | Opcode::LOAD_NAME - | Opcode::STORE_GLOBAL | Opcode::LOAD_GLOBAL - | Opcode::STORE_ATTR | Opcode::LOAD_ATTR + Opcode::STORE_NAME + | Opcode::LOAD_NAME + | Opcode::STORE_GLOBAL + | Opcode::LOAD_GLOBAL + | Opcode::STORE_ATTR + | Opcode::LOAD_ATTR | Opcode::LOAD_METHOD => { instrs += &format!("{} ({})", arg, self.names.get(*arg as usize).unwrap()); } @@ -422,18 +441,18 @@ impl CodeObj { } Opcode::LOAD_CONST => { instrs += &format!("{} ({})", arg, self.consts.get(*arg as usize).unwrap()); - }, + } Opcode::FOR_ITER => { - instrs += &format!("{} (to {})", arg, idx + arg*2 + 2); + instrs += &format!("{} (to {})", arg, idx + arg * 2 + 2); } Opcode::JUMP_FORWARD => { - instrs += &format!("{} (to {})", arg, idx + arg*2 + 2); + instrs += &format!("{} (to {})", arg, idx + arg * 2 + 2); } Opcode::JUMP_ABSOLUTE => { - instrs += &format!("{} (to {})", arg, arg*2); + instrs += &format!("{} (to {})", arg, arg * 2); } Opcode::POP_JUMP_IF_FALSE | Opcode::POP_JUMP_IF_TRUE => { - instrs += &format!("{} (to {})", arg, arg*2); + instrs += &format!("{} (to {})", arg, arg * 2); } Opcode::MAKE_FUNCTION => { let flag = match arg { @@ -444,8 +463,10 @@ impl CodeObj { instrs += &format!("{} {}", arg, flag); } // Ergでは引数で型キャストする - Opcode::BINARY_ADD | Opcode::BINARY_SUBTRACT - | Opcode::BINARY_MULTIPLY | Opcode::BINARY_TRUE_DIVIDE => { + Opcode::BINARY_ADD + | Opcode::BINARY_SUBTRACT + | Opcode::BINARY_MULTIPLY + | Opcode::BINARY_TRUE_DIVIDE => { instrs += &format!("{} ({:?})", arg, TypePair::from(*arg)); } other if other.take_arg() => { diff --git a/compiler/erg_common/combinations.rs b/compiler/erg_common/combinations.rs index 6f14faa8..6dc55cdd 100644 --- a/compiler/erg_common/combinations.rs +++ b/compiler/erg_common/combinations.rs @@ -26,32 +26,42 @@ pub struct TotalCombinations { /// ]); /// pub fn total_combinations(iter: I) -> TotalCombinations - where I: Iterator + ExactSizeIterator, - I::Item: Clone +where + I: Iterator + ExactSizeIterator, + I::Item: Clone, { - TotalCombinations { len: iter.len(), combinations: combinations(iter, 1) } + TotalCombinations { + len: iter.len(), + combinations: combinations(iter, 1), + } } impl Iterator for TotalCombinations - where I: Iterator, - I::Item: Clone +where + I: Iterator, + I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option { - if let Some(i) = self.combinations.next() { return Some(i) } - else { + if let Some(i) = self.combinations.next() { + return Some(i); + } else { self.combinations.reset(self.combinations.k() + 1); self.len -= 1; - if self.len == 0 { return None } + if self.len == 0 { + return None; + } self.combinations.next() } } } impl FusedIterator for TotalCombinations - where I: Iterator, - I::Item: Clone -{} +where + I: Iterator, + I::Item: Clone, +{ +} macro_rules! debug_fmt_fields { ($tyname:ident, $($($field:tt/*TODO ideally we would accept ident or tuple element here*/).+),*) => { @@ -86,22 +96,25 @@ pub struct Combinations { } impl Clone for Combinations - where I: Clone + Iterator, - I::Item: Clone, +where + I: Clone + Iterator, + I::Item: Clone, { clone_fields!(indices, pool, first); } impl fmt::Debug for Combinations - where I: Iterator + fmt::Debug, - I::Item: fmt::Debug, +where + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, { debug_fmt_fields!(Combinations, indices, pool, first); } /// Create a new `Combinations` from a clonable iterator. pub fn combinations(iter: I, k: usize) -> Combinations - where I: Iterator +where + I: Iterator, { let mut pool = LazyBuffer::new(iter); pool.prefill(k); @@ -116,16 +129,22 @@ pub fn combinations(iter: I, k: usize) -> Combinations impl Combinations { /// Returns the length of a combination produced by this iterator. #[inline] - pub fn k(&self) -> usize { self.indices.len() } + pub fn k(&self) -> usize { + self.indices.len() + } /// Returns the (current) length of the pool from which combination elements are /// selected. This value can change between invocations of [`next`](Combinations::next). #[inline] - pub fn n(&self) -> usize { self.pool.len() } + pub fn n(&self) -> usize { + self.pool.len() + } /// Returns a reference to the source iterator. #[inline] - pub fn src(&self) -> &I { &self.pool.it } + pub fn src(&self) -> &I { + &self.pool.it + } /// Resets this `Combinations` back to an initial state for combinations of length /// `k` over the same pool data source. If `k` is larger than the current length @@ -139,7 +158,6 @@ impl Combinations { for i in 0..k { self.indices[i] = i; } - } else { for i in 0..self.indices.len() { self.indices[i] = i; @@ -151,8 +169,9 @@ impl Combinations { } impl Iterator for Combinations - where I: Iterator, - I::Item: Clone +where + I: Iterator, + I::Item: Clone, { type Item = Vec; fn next(&mut self) -> Option { @@ -183,7 +202,7 @@ impl Iterator for Combinations // Increment index, and reset the ones to its right self.indices[i] += 1; - for j in i+1..self.indices.len() { + for j in i + 1..self.indices.len() { self.indices[j] = self.indices[j - 1] + 1; } } @@ -194,6 +213,8 @@ impl Iterator for Combinations } impl FusedIterator for Combinations - where I: Iterator, - I::Item: Clone -{} +where + I: Iterator, + I::Item: Clone, +{ +} diff --git a/compiler/erg_common/config.rs b/compiler/erg_common/config.rs index 7d891f79..8ac6238b 100644 --- a/compiler/erg_common/config.rs +++ b/compiler/erg_common/config.rs @@ -3,20 +3,21 @@ //! コマンドオプション(パーサー)を定義する use std::env; use std::env::consts::{ARCH, OS}; -use std::process; use std::fs::File; -use std::io::{BufReader, BufRead}; +use std::io::{BufRead, BufReader}; +use std::process; +use crate::lazy::Lazy; use crate::stdin; use crate::Str; use crate::{power_assert, read_file}; -use crate::lazy::Lazy; pub const SEMVER: &str = env!("CARGO_PKG_VERSION"); pub const GIT_HASH_SHORT: &str = env!("GIT_HASH_SHORT"); pub const BUILD_DATE: &str = env!("BUILD_DATE"); /// TODO: タグを含める -pub const BUILD_INFO: Lazy = Lazy::new(|| format!("(tags/?:{GIT_HASH_SHORT}, {BUILD_DATE}) on {ARCH}/{OS}")); +pub const BUILD_INFO: Lazy = + Lazy::new(|| format!("(tags/?:{GIT_HASH_SHORT}, {BUILD_DATE}) on {ARCH}/{OS}")); /// 入力はファイルからだけとは限らないので /// Inputで操作を一本化する @@ -36,7 +37,7 @@ impl Input { pub fn enclosed_name(&self) -> &str { match self { Self::File(filename) => &filename[..], - Self::REPL | Self::Pipe(_) => "", + Self::REPL | Self::Pipe(_) => "", Self::Str(_) => "", Self::Dummy => "", } @@ -46,7 +47,7 @@ impl Input { pub fn filename(&self) -> &str { match self { Self::File(filename) => &filename[..], - Self::REPL | Self::Pipe(_) => "stdin", + Self::REPL | Self::Pipe(_) => "stdin", Self::Str(_) => "string", Self::Dummy => "dummy", } @@ -82,24 +83,22 @@ impl Input { pub fn reread_lines(&self, ln_begin: usize, ln_end: usize) -> Vec { power_assert!(ln_begin, >=, 1); match self { - Self::File(filename) => { - match File::open(&filename[..]) { - Ok(file) => { - let mut codes = vec![]; - let mut lines = BufReader::new(file).lines().skip(ln_begin - 1); - for _ in ln_begin..=ln_end { - codes.push(Str::from(lines.next().unwrap().unwrap())); - } - codes + Self::File(filename) => match File::open(&filename[..]) { + Ok(file) => { + let mut codes = vec![]; + let mut lines = BufReader::new(file).lines().skip(ln_begin - 1); + for _ in ln_begin..=ln_end { + codes.push(Str::from(lines.next().unwrap().unwrap())); } - Err(_) => vec!["".into()], + codes } - } - Self::Pipe(s) | Self::Str(s) => { - s.split('\n') - .collect::>()[ln_begin-1..=ln_end-1] - .into_iter().map(|s| Str::rc(*s)).collect() - } + Err(_) => vec!["".into()], + }, + Self::Pipe(s) | Self::Str(s) => s.split('\n').collect::>() + [ln_begin - 1..=ln_end - 1] + .into_iter() + .map(|s| Str::rc(*s)) + .collect(), Self::REPL => stdin::reread_lines(ln_begin, ln_end), Self::Dummy => panic!("cannot read lines from a dummy file"), } @@ -166,7 +165,9 @@ impl ErgConfig { /// cloneのエイリアス(実際のcloneコストは低いので) #[inline] - pub fn copy(&self) -> Self { self.clone() } + pub fn copy(&self) -> Self { + self.clone() + } pub fn parse() -> Self { let mut args = env::args(); diff --git a/compiler/erg_common/deserialize.rs b/compiler/erg_common/deserialize.rs index dc993f08..6d42aede 100644 --- a/compiler/erg_common/deserialize.rs +++ b/compiler/erg_common/deserialize.rs @@ -1,17 +1,17 @@ //! バイトコードからオブジェクトを復元する -use std::string::FromUtf8Error; use std::process; +use std::string::FromUtf8Error; -use crate::{Str, RcArray}; use crate::cache::Cache; -use crate::{fn_name, switch_lang}; -use crate::serialize::DataTypePrefix; use crate::codeobj::CodeObj; use crate::config::{ErgConfig, Input}; -use crate::value::ValueObj; -use crate::error::{ErrorCore, Location, ErrorKind}; +use crate::error::{ErrorCore, ErrorKind, Location}; +use crate::serialize::DataTypePrefix; use crate::traits::HasType; -use crate::ty::{Type, TyParam}; +use crate::ty::{TyParam, Type}; +use crate::value::ValueObj; +use crate::{fn_name, switch_lang}; +use crate::{RcArray, Str}; #[derive(Debug)] pub struct DeserializeError { @@ -34,24 +34,51 @@ impl From for DeserializeError { impl From for ErrorCore { fn from(err: DeserializeError) -> Self { - ErrorCore::new(err.errno, ErrorKind::ImportError, Location::Unknown, err.desc, Option::::None) + ErrorCore::new( + err.errno, + ErrorKind::ImportError, + Location::Unknown, + err.desc, + Option::::None, + ) } } impl DeserializeError { pub fn new, T: Into>(errno: usize, caused_by: S, desc: T) -> Self { - Self { errno, caused_by: caused_by.into(), desc: desc.into() } + Self { + errno, + caused_by: caused_by.into(), + desc: desc.into(), + } } pub fn file_broken_error() -> Self { - Self::new(0, fn_name!(), switch_lang!("the loaded .pyc file is broken", "読み込んだ.pycファイルは破損しています")) + Self::new( + 0, + fn_name!(), + switch_lang!( + "the loaded .pyc file is broken", + "読み込んだ.pycファイルは破損しています" + ), + ) } pub fn type_error(expect: &Type, found: &Type) -> Self { - Self::new(0, fn_name!(), switch_lang!( - format!("expect a {} object, but the deserialized object is {}", expect, found), - format!("{}型オブジェクトを予期しましたが、 読み込んだオブジェクトは{}型です", expect, found) - )) + Self::new( + 0, + fn_name!(), + switch_lang!( + format!( + "expect a {} object, but the deserialized object is {}", + expect, found + ), + format!( + "{}型オブジェクトを予期しましたが、 読み込んだオブジェクトは{}型です", + expect, found + ) + ), + ) } } @@ -73,12 +100,14 @@ impl Deserializer { } pub fn run(cfg: ErgConfig) { - let filename = if let Input::File(f) = cfg.input { f } else { + let filename = if let Input::File(f) = cfg.input { + f + } else { eprintln!("{:?} is not a filename", cfg.input); process::exit(1); }; - let codeobj = CodeObj::from_pyc(&filename[..]) - .expect(&format!("failed to deserialize {filename}")); + let codeobj = + CodeObj::from_pyc(&filename[..]).expect(&format!("failed to deserialize {filename}")); println!("{}", codeobj.code_info()); } @@ -111,26 +140,30 @@ impl Deserializer { u32::from_le_bytes(Self::consume::<4>(v)) } - pub fn deserialize_const(&mut self, v: &mut Vec, python_ver: u32) -> DeserializeResult { + pub fn deserialize_const( + &mut self, + v: &mut Vec, + python_ver: u32, + ) -> DeserializeResult { match DataTypePrefix::from(v.remove(0)) { DataTypePrefix::Int32 => { let bytes = Self::consume::<4>(v); Ok(ValueObj::Int(i32::from_le_bytes(bytes))) - }, + } DataTypePrefix::BinFloat => { let bytes = Self::consume::<8>(v); Ok(ValueObj::Float(f64::from_le_bytes(bytes))) - }, + } DataTypePrefix::ShortAscii | DataTypePrefix::ShortAsciiInterned => { let len = v.remove(0); let bytes = v.drain(..len as usize).collect(); Ok(self.get_cached_str(&String::from_utf8(bytes)?)) - }, - DataTypePrefix::Str | DataTypePrefix::Unicode => { + } + DataTypePrefix::Str | DataTypePrefix::Unicode => { let len = Self::deserialize_u32(v); let bytes = v.drain(..len as usize).collect(); Ok(self.get_cached_str(&String::from_utf8(bytes)?)) - }, + } DataTypePrefix::True => Ok(ValueObj::True), DataTypePrefix::False => Ok(ValueObj::False), DataTypePrefix::SmallTuple => { @@ -140,7 +173,7 @@ impl Deserializer { arr.push(self.deserialize_const(v, python_ver)?); } Ok(self.get_cached_arr(&arr)) - }, + } DataTypePrefix::Tuple => { let len = Self::deserialize_u32(v); let mut arr = Vec::with_capacity(len as usize); @@ -148,15 +181,18 @@ impl Deserializer { arr.push(self.deserialize_const(v, python_ver)?); } Ok(self.get_cached_arr(&arr)) - }, + } DataTypePrefix::Code => { let argcount = Self::deserialize_u32(v); - let posonlyargcount = - if python_ver >= 3413 { Self::deserialize_u32(v) } else { 0 }; + let posonlyargcount = if python_ver >= 3413 { + Self::deserialize_u32(v) + } else { + 0 + }; let kwonlyargcount = Self::deserialize_u32(v); let nlocals = Self::deserialize_u32(v); - let stacksize = Self::deserialize_u32(v); - let flags = Self::deserialize_u32(v); + let stacksize = Self::deserialize_u32(v); + let flags = Self::deserialize_u32(v); let code = self.deserialize_bytes(v)?; let consts = self.deserialize_const_vec(v, python_ver)?; let names = self.deserialize_str_vec(v, python_ver)?; @@ -183,30 +219,40 @@ impl Deserializer { filename, name, firstlineno, - lnotab + lnotab, ))) - }, + } DataTypePrefix::None => Ok(ValueObj::None), - other => { - Err(DeserializeError::new(0, fn_name!(), switch_lang!( + other => Err(DeserializeError::new( + 0, + fn_name!(), + switch_lang!( format!("cannot deserialize this object: {}", other), format!("このオブジェクトは復元できません: {}", other) - ))) - }, + ), + )), } } - pub fn deserialize_const_vec(&mut self, v: &mut Vec, python_ver: u32) -> DeserializeResult> { + pub fn deserialize_const_vec( + &mut self, + v: &mut Vec, + python_ver: u32, + ) -> DeserializeResult> { match self.deserialize_const(v, python_ver)? { ValueObj::Array(arr) => Ok(arr.to_vec()), - other => Err(DeserializeError::type_error(&Type::Str, &other.ref_t())) + other => Err(DeserializeError::type_error(&Type::Str, &other.ref_t())), } } - pub fn deserialize_const_array(&mut self, v: &mut Vec, python_ver: u32) -> DeserializeResult> { + pub fn deserialize_const_array( + &mut self, + v: &mut Vec, + python_ver: u32, + ) -> DeserializeResult> { match self.deserialize_const(v, python_ver)? { ValueObj::Array(arr) => Ok(arr), - other => Err(DeserializeError::type_error(&Type::Str, &other.ref_t())) + other => Err(DeserializeError::type_error(&Type::Str, &other.ref_t())), } } @@ -217,11 +263,15 @@ impl Deserializer { pub fn try_into_str(&mut self, c: ValueObj) -> DeserializeResult { match c { ValueObj::Str(s) => Ok(s), - other => Err(DeserializeError::type_error(&Type::Str, &other.ref_t())) + other => Err(DeserializeError::type_error(&Type::Str, &other.ref_t())), } } - pub fn deserialize_str_vec(&mut self, v: &mut Vec, python_ver: u32) -> DeserializeResult> { + pub fn deserialize_str_vec( + &mut self, + v: &mut Vec, + python_ver: u32, + ) -> DeserializeResult> { match self.deserialize_const(v, python_ver)? { ValueObj::Array(arr) => { let mut strs = Vec::with_capacity(arr.len()); @@ -230,14 +280,17 @@ impl Deserializer { } Ok(strs) } - other => Err(DeserializeError::type_error(&Type::array(Type::Str, TyParam::erased(Type::Nat)), &other.ref_t())) + other => Err(DeserializeError::type_error( + &Type::array(Type::Str, TyParam::erased(Type::Nat)), + &other.ref_t(), + )), } } pub fn deserialize_str(&mut self, v: &mut Vec, python_ver: u32) -> DeserializeResult { match self.deserialize_const(v, python_ver)? { ValueObj::Str(s) => Ok(s), - other => Err(DeserializeError::type_error(&Type::Str, &other.ref_t())) + other => Err(DeserializeError::type_error(&Type::Str, &other.ref_t())), } } @@ -247,7 +300,7 @@ impl Deserializer { 0, fn_name!(), switch_lang!("failed to load bytes", "バイト列の読み込みに失敗しました"), - )) + )); } let len = Self::deserialize_u32(v); Ok(v.drain(0..len as usize).collect()) diff --git a/compiler/erg_common/dict.rs b/compiler/erg_common/dict.rs index fb8522bb..d0acb8fb 100644 --- a/compiler/erg_common/dict.rs +++ b/compiler/erg_common/dict.rs @@ -1,8 +1,8 @@ -use std::collections::hash_map::{Keys, Values, ValuesMut, IntoValues, Iter, IntoIter, IterMut}; +use std::borrow::Borrow; +use std::collections::hash_map::{IntoIter, IntoValues, Iter, IterMut, Keys, Values, ValuesMut}; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; -use std::borrow::Borrow; use crate::fxhash::FxHashMap; @@ -18,11 +18,13 @@ macro_rules! dict { #[derive(Debug, Clone)] pub struct Dict { - dict: FxHashMap + dict: FxHashMap, } impl PartialEq for Dict { - fn eq(&self, other: &Dict) -> bool { self.dict == other.dict } + fn eq(&self, other: &Dict) -> bool { + self.dict == other.dict + } } impl Eq for Dict {} @@ -58,47 +60,73 @@ impl FromIterator<(K, V)> for Dict { } impl Default for Dict { - fn default() -> Dict { Dict::new() } + fn default() -> Dict { + Dict::new() + } } impl Dict { #[inline] pub fn new() -> Self { - Self{ dict: FxHashMap::default() } + Self { + dict: FxHashMap::default(), + } } pub fn with_capacity(capacity: usize) -> Self { - Self{ dict: FxHashMap::with_capacity_and_hasher(capacity, Default::default()) } + Self { + dict: FxHashMap::with_capacity_and_hasher(capacity, Default::default()), + } } #[inline] - pub fn len(&self) -> usize { self.dict.len() } + pub fn len(&self) -> usize { + self.dict.len() + } #[inline] - pub fn capacity(&self) -> usize { self.dict.capacity() } + pub fn capacity(&self) -> usize { + self.dict.capacity() + } #[inline] - pub fn keys(&self) -> Keys { self.dict.keys() } + pub fn keys(&self) -> Keys { + self.dict.keys() + } #[inline] - pub fn values(&self) -> Values { self.dict.values() } + pub fn values(&self) -> Values { + self.dict.values() + } #[inline] - pub fn values_mut(&mut self) -> ValuesMut { self.dict.values_mut() } + pub fn values_mut(&mut self) -> ValuesMut { + self.dict.values_mut() + } #[inline] - pub fn into_values(self) -> IntoValues { self.dict.into_values() } + pub fn into_values(self) -> IntoValues { + self.dict.into_values() + } #[inline] - pub fn iter(&self) -> Iter { self.dict.iter() } + pub fn iter(&self) -> Iter { + self.dict.iter() + } #[inline] - pub fn into_iter(self) -> IntoIter { self.dict.into_iter() } + pub fn into_iter(self) -> IntoIter { + self.dict.into_iter() + } #[inline] - pub fn iter_mut(&mut self) -> IterMut { self.dict.iter_mut() } + pub fn iter_mut(&mut self) -> IterMut { + self.dict.iter_mut() + } - pub fn clear(&mut self) { self.dict.clear(); } + pub fn clear(&mut self) { + self.dict.clear(); + } } impl Dict { @@ -106,7 +134,8 @@ impl Dict { pub fn get(&self, k: &Q) -> Option<&V> where K: Borrow, - Q: Hash + Eq { + Q: Hash + Eq, + { self.dict.get(k) } @@ -114,7 +143,8 @@ impl Dict { pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> where K: Borrow, - Q: Hash + Eq { + Q: Hash + Eq, + { self.dict.get_mut(k) } @@ -122,23 +152,29 @@ impl Dict { pub fn contains_key(&self, k: &Q) -> bool where K: Borrow, - Q: Hash + Eq { + Q: Hash + Eq, + { self.dict.contains_key(k) } #[inline] - pub fn insert(&mut self, k: K, v: V) { self.dict.insert(k, v); } + pub fn insert(&mut self, k: K, v: V) { + self.dict.insert(k, v); + } #[inline] pub fn remove(&mut self, k: &Q) -> Option where K: Borrow, - Q: Hash + Eq { + Q: Hash + Eq, + { self.dict.remove(k) } #[inline] - pub fn extend>(&mut self, iter: I) { self.dict.extend(iter); } + pub fn extend>(&mut self, iter: I) { + self.dict.extend(iter); + } #[inline] pub fn merge(&mut self, other: Self) { diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index 54188c1a..20760019 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -3,13 +3,13 @@ //! エラー処理に関する汎用的なコンポーネントを提供する use std::cmp; use std::fmt; -use std::io::{Write, BufWriter, stderr}; +use std::io::{stderr, BufWriter, Write}; -use crate::Str; -use crate::{fmt_option, switch_lang, impl_display_from_debug}; -use crate::config::Input; -use crate::traits::{Stream, Locational}; use crate::color::*; +use crate::config::Input; +use crate::traits::{Locational, Stream}; +use crate::Str; +use crate::{fmt_option, impl_display_from_debug, switch_lang}; /// ErrorKindと言っているが、ErrorだけでなくWarning, Exceptionも含まれる /// Numbering of this is not specifically related to ErrFmt.errno(). @@ -17,7 +17,7 @@ use crate::color::*; #[repr(u8)] pub enum ErrorKind { /* compile errors */ - AssignError = 0, + AssignError = 0, AttributeError, BytecodeError, CompilerSystemError, @@ -36,7 +36,7 @@ pub enum ErrorKind { HasEffect, MoveError, /* compile warnings */ - AttributeWarning = 60, + AttributeWarning = 60, CastWarning, DeprecationWarning, FutureWarning, @@ -48,7 +48,7 @@ pub enum ErrorKind { UnusedWarning, Warning, /* runtime errors */ - ArithmeticError = 100, + ArithmeticError = 100, AssertionError, BlockingIOError, BrokenPipeError, @@ -88,13 +88,13 @@ pub enum ErrorKind { WindowsError, ZeroDivisionError, /* runtime warnings */ - BytesWarning = 180, + BytesWarning = 180, ResourceWarning, RuntimeWarning, UnicodeWarning, UserWarning, /* exceptions */ - BaseException = 200, + BaseException = 200, Exception, GeneratorExit, KeyboardInterrupt, @@ -200,8 +200,18 @@ impl From<&str> for ErrorKind { /// points the location (of an error) in a code #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Location { - RangePair{ ln_begin: usize, col_first: (usize, usize), ln_end: usize, col_second: (usize, usize), }, - Range{ ln_begin: usize, col_begin: usize, ln_end: usize, col_end: usize }, + RangePair { + ln_begin: usize, + col_first: (usize, usize), + ln_end: usize, + col_second: (usize, usize), + }, + Range { + ln_begin: usize, + col_begin: usize, + ln_end: usize, + col_end: usize, + }, LineRange(usize, usize), Line(usize), Unknown, @@ -210,8 +220,7 @@ pub enum Location { impl Location { pub fn concat(l: &L, r: &R) -> Self { match (l.ln_begin(), l.col_begin(), r.ln_end(), r.col_end()) { - (Some(lb), Some(cb), Some(le), Some(ce)) => - Self::range(lb, cb, le, ce), + (Some(lb), Some(cb), Some(le), Some(ce)) => Self::range(lb, cb, le, ce), (Some(lb), _, Some(le), _) => Self::LineRange(lb, le), (Some(l), _, _, _) | (_, _, Some(l), _) => Self::Line(l), _ => Self::Unknown, @@ -219,11 +228,16 @@ impl Location { } pub const fn range(ln_begin: usize, col_begin: usize, ln_end: usize, col_end: usize) -> Self { - Self::Range{ ln_begin, col_begin, ln_end, col_end } + Self::Range { + ln_begin, + col_begin, + ln_end, + col_end, + } } pub fn pair(lhs: Self, rhs: Self) -> Self { - Self::RangePair{ + Self::RangePair { ln_begin: lhs.ln_begin().unwrap(), col_first: (lhs.col_begin().unwrap(), lhs.col_end().unwrap()), ln_end: rhs.ln_end().unwrap(), @@ -233,8 +247,8 @@ impl Location { pub const fn ln_begin(&self) -> Option { match self { - Self::RangePair{ ln_begin, .. } - | Self::Range{ ln_begin, .. } + Self::RangePair { ln_begin, .. } + | Self::Range { ln_begin, .. } | Self::LineRange(ln_begin, _) | Self::Line(ln_begin) => Some(*ln_begin), Self::Unknown => None, @@ -243,8 +257,8 @@ impl Location { pub const fn ln_end(&self) -> Option { match self { - Self::RangePair{ ln_end, .. } - | Self::Range{ ln_end, .. } + Self::RangePair { ln_end, .. } + | Self::Range { ln_end, .. } | Self::LineRange(ln_end, _) | Self::Line(ln_end) => Some(*ln_end), Self::Unknown => None, @@ -253,16 +267,22 @@ impl Location { pub const fn col_begin(&self) -> Option { match self { - Self::RangePair{ col_first: (col_begin, _), .. } - | Self::Range{ col_begin, .. } => Some(*col_begin), + Self::RangePair { + col_first: (col_begin, _), + .. + } + | Self::Range { col_begin, .. } => Some(*col_begin), _ => None, } } pub const fn col_end(&self) -> Option { match self { - Self::RangePair{ col_second: (_, col_end), .. } - | Self::Range{ col_end, .. } => Some(*col_end), + Self::RangePair { + col_second: (_, col_end), + .. + } + | Self::Range { col_end, .. } => Some(*col_end), _ => None, } } @@ -280,11 +300,25 @@ pub struct ErrorCore { } impl ErrorCore { - pub fn new>(errno: usize, kind: ErrorKind, loc: Location, desc: S, hint: Option) -> Self { - Self { errno, kind, loc, desc: desc.into(), hint } + pub fn new>( + errno: usize, + kind: ErrorKind, + loc: Location, + desc: S, + hint: Option, + ) -> Self { + Self { + errno, + kind, + loc, + desc: desc.into(), + hint, + } } - pub fn unreachable(fn_name: &str, line: u32) -> Self { Self::bug(0, Location::Unknown, fn_name, line) } + pub fn unreachable(fn_name: &str, line: u32) -> Self { + Self::bug(0, Location::Unknown, fn_name, line) + } pub fn bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self { Self::new(errno, CompilerSystemError, loc, switch_lang!( @@ -324,14 +358,19 @@ pub trait ErrorDisplay { fn write_to_stderr(&self) { let mut writer = BufWriter::new(stderr()); - writer.write(format!( - "{}{}{}: {}{}\n", - self.format_header(), - self.format_code_and_pointer(), - self.core().kind, - self.core().desc, - fmt_option!(pre format!("\n{GREEN}hint{RESET}: "), &self.core().hint), - ).as_bytes()).unwrap(); + writer + .write( + format!( + "{}{}{}: {}{}\n", + self.format_header(), + self.format_code_and_pointer(), + self.core().kind, + self.core().desc, + fmt_option!(pre format!("\n{GREEN}hint{RESET}: "), &self.core().hint), + ) + .as_bytes(), + ) + .unwrap(); writer.flush().unwrap(); if let Some(inner) = self.ref_inner() { inner.write_to_stderr() @@ -351,27 +390,41 @@ pub trait ErrorDisplay { )?; if let Some(inner) = self.ref_inner() { inner.format(f) - } else { Ok(()) } + } else { + Ok(()) + } } fn format_header(&self) -> String { let kind = self.core().kind as u8; - let (color, err_or_warn) = - if kind < 100 { (RED, "Error") } - else if 100 <= kind && kind < 150 { (YELLOW, "Warning") } - else if 150 <= kind && kind < 200 { (DEEP_RED, "Error") } - else { ("", "Exception") }; + let (color, err_or_warn) = if kind < 100 { + (RED, "Error") + } else if 100 <= kind && kind < 150 { + (YELLOW, "Warning") + } else if 150 <= kind && kind < 200 { + (DEEP_RED, "Error") + } else { + ("", "Exception") + }; let loc = match self.core().loc { - Location::Range{ ln_begin, ln_end, .. } if ln_begin == ln_end => format!(", line {ln_begin}"), - Location::RangePair{ ln_begin, ln_end, .. } - | Location::Range{ ln_begin, ln_end, .. } + Location::Range { + ln_begin, ln_end, .. + } if ln_begin == ln_end => format!(", line {ln_begin}"), + Location::RangePair { + ln_begin, ln_end, .. + } + | Location::Range { + ln_begin, ln_end, .. + } | Location::LineRange(ln_begin, ln_end) => format!(", line {ln_begin}..{ln_end}"), Location::Line(lineno) => format!(", line {lineno}"), Location::Unknown => "".to_string(), }; let caused_by = if self.caused_by() != "" { format!(", in {}", self.caused_by()) - } else { "".to_string() }; + } else { + "".to_string() + }; format!( "{color}{err_or_warn}[#{errno:>04}]{RESET}: File {input}{loc}{caused_by}\n", errno = self.core().errno, @@ -381,8 +434,13 @@ pub trait ErrorDisplay { fn format_code_and_pointer(&self) -> String { match self.core().loc { - Location::RangePair{ .. } => todo!(), - Location::Range { ln_begin, col_begin, ln_end, col_end } => { + Location::RangePair { .. } => todo!(), + Location::Range { + ln_begin, + col_begin, + ln_end, + col_end, + } => { let codes = if self.input() == &Input::REPL { vec![self.input().reread()] } else { @@ -403,13 +461,16 @@ pub trait ErrorDisplay { } else { pointer += &"^".repeat(cmp::max(1, codes[i].len())); } - res += &format!("{lineno}{VBAR_UNICODE} {code}\n{pointer}\n", code = codes[i]); + res += &format!( + "{lineno}{VBAR_UNICODE} {code}\n{pointer}\n", + code = codes[i] + ); } res + RESET - }, + } Location::LineRange(_begin, _end) => { todo!() - }, + } Location::Line(lineno) => { let code = if self.input() == &Input::REPL { self.input().reread() @@ -417,12 +478,13 @@ pub trait ErrorDisplay { self.input().reread_lines(lineno, lineno).remove(0) }; format!("{CYAN}{lineno}{VBAR_UNICODE} {code}\n{RESET}") - }, - Location::Unknown => { - match self.input() { - Input::File(_) => "\n".to_string(), - other => format!("{CYAN}?{VBAR_UNICODE} {code}\n{RESET}", code = other.reread()), - } + } + Location::Unknown => match self.input() { + Input::File(_) => "\n".to_string(), + other => format!( + "{CYAN}?{VBAR_UNICODE} {code}\n{RESET}", + code = other.reread() + ), }, } } diff --git a/compiler/erg_common/lazy.rs b/compiler/erg_common/lazy.rs index 52da737e..26c213c1 100644 --- a/compiler/erg_common/lazy.rs +++ b/compiler/erg_common/lazy.rs @@ -74,20 +74,24 @@ impl Eq for OnceCell {} impl From for OnceCell { fn from(value: T) -> Self { - OnceCell { inner: UnsafeCell::new(Some(value)) } + OnceCell { + inner: UnsafeCell::new(Some(value)), + } } } impl OnceCell { /// Creates a new empty cell. - pub const fn new() -> OnceCell { - OnceCell { inner: UnsafeCell::new(None) } + pub const fn new() -> OnceCell { + OnceCell { + inner: UnsafeCell::new(None), + } } /// Gets the reference to the underlying value. /// /// Returns `None` if the cell is empty. - pub fn get(&self) -> Option<&T> { + pub fn get(&self) -> Option<&T> { // SAFETY: Safe due to `inner`'s invariant unsafe { &*self.inner.get() }.as_ref() } @@ -95,7 +99,7 @@ impl OnceCell { /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. - pub fn get_mut(&mut self) -> Option<&mut T> { + pub fn get_mut(&mut self) -> Option<&mut T> { // SAFETY: Safe because we have unique access unsafe { &mut *self.inner.get() }.as_mut() } @@ -122,7 +126,7 @@ impl OnceCell { /// /// assert!(cell.get().is_some()); /// ``` - pub fn set(&self, value: T) -> Result<(), T> { + pub fn set(&self, value: T) -> Result<(), T> { // SAFETY: Safe because we cannot have overlapping mutable borrows let slot = unsafe { &*self.inner.get() }; if slot.is_some() { @@ -162,7 +166,7 @@ impl OnceCell { /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` - pub fn get_or_init(&self, f: F) -> &T + pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, { @@ -200,7 +204,7 @@ impl OnceCell { /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` - pub fn get_or_try_init(&self, f: F) -> Result<&T, E> + pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { @@ -234,7 +238,7 @@ impl OnceCell { /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` - pub fn into_inner(self) -> Option { + pub fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies // that it is not currently borrowed. So it is safe to move out `Option`. self.inner.into_inner() @@ -261,7 +265,7 @@ impl OnceCell { /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` - pub fn take(&mut self) -> Option { + pub fn take(&mut self) -> Option { mem::take(self).into_inner() } } @@ -296,7 +300,10 @@ pub struct Lazy T> { impl fmt::Debug for Lazy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() + f.debug_struct("Lazy") + .field("cell", &self.cell) + .field("init", &"..") + .finish() } } @@ -319,7 +326,10 @@ impl Lazy { /// # } /// ``` pub const fn new(init: F) -> Lazy { - Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) } + Lazy { + cell: OnceCell::new(), + init: Cell::new(Some(init)), + } } } diff --git a/compiler/erg_common/lazy_buffer.rs b/compiler/erg_common/lazy_buffer.rs index 696cb53d..abd8a765 100644 --- a/compiler/erg_common/lazy_buffer.rs +++ b/compiler/erg_common/lazy_buffer.rs @@ -60,7 +60,7 @@ impl Index for LazyBuffer where I: Iterator, I::Item: Sized, - Vec: Index + Vec: Index, { type Output = as Index>::Output; diff --git a/compiler/erg_common/levenshtein.rs b/compiler/erg_common/levenshtein.rs index 5c40707f..0ef1b671 100644 --- a/compiler/erg_common/levenshtein.rs +++ b/compiler/erg_common/levenshtein.rs @@ -26,5 +26,5 @@ pub fn levenshtein(lhs: &str, rhs: &str) -> usize { .unwrap(); } } - return table[l_len][r_len] + return table[l_len][r_len]; } diff --git a/compiler/erg_common/lib.rs b/compiler/erg_common/lib.rs index 1ee4b588..8b3132f6 100644 --- a/compiler/erg_common/lib.rs +++ b/compiler/erg_common/lib.rs @@ -2,33 +2,33 @@ use std::fmt; pub mod cache; +pub mod codeobj; +pub mod color; +pub mod combinations; pub mod config; pub mod datetime; +pub mod deserialize; +pub mod dict; pub mod error; +pub mod fxhash; +pub mod lazy; pub mod lazy_buffer; pub mod levenshtein; -pub mod codeobj; -pub mod combinations; -pub mod value; -pub mod color; pub mod macros; pub mod opcode; pub mod python_util; +pub mod rccell; pub mod serialize; -pub mod deserialize; +pub mod set; +pub mod stdin; +pub mod str; pub mod traits; pub mod tsort; pub mod ty; -pub mod lazy; -pub mod rccell; -pub mod stdin; -pub mod str; -pub mod fxhash; -pub mod set; -pub mod dict; +pub mod value; -pub use crate::str::Str; use crate::set::Set; +pub use crate::str::Str; pub type RcArray = std::rc::Rc<[T]>; @@ -59,21 +59,21 @@ pub fn fmt_set_split_with(s: &Set, splitte fmt_iter_split_with(s.iter(), splitter) } -pub fn debug_fmt_iter>(iter: I) -> String { +pub fn debug_fmt_iter>(iter: I) -> String { let mut s = iter.fold("".to_string(), |sum, elem| format!("{sum}{elem:?}, ")); s.pop(); s.pop(); s } -pub fn fmt_iter>(iter: I) -> String { +pub fn fmt_iter>(iter: I) -> String { let mut s = iter.fold("".to_string(), |sum, elem| sum + &elem.to_string() + ", "); s.pop(); s.pop(); s } -pub fn fmt_iter_split_with>(i: I, splitter: &str) -> String { +pub fn fmt_iter_split_with>(i: I, splitter: &str) -> String { let mut s = i.fold("".to_string(), |sum, elem| { sum + &elem.to_string() + splitter }); @@ -92,8 +92,11 @@ pub fn get_hash(t: &T) -> usize { let mut s = fxhash::FxHasher::default(); t.hash(&mut s); let res = std::hash::Hasher::finish(&s); - if cfg!(target_pointer_width = "64") { res as usize } - else { (res % usize::MAX as u64) as usize } + if cfg!(target_pointer_width = "64") { + res as usize + } else { + (res % usize::MAX as u64) as usize + } } /// \r\n (Windows), \r (old MacOS) -> \n (Unix) @@ -111,11 +114,12 @@ pub fn chomp(src: &str) -> String { pub fn try_map(i: I, f: F) -> Result, E> where F: Fn(T) -> Result, - I: Iterator { - let mut v = vec![]; - for x in i { - let y = f(x)?; - v.push(y); - } - Ok(v) + I: Iterator, +{ + let mut v = vec![]; + for x in i { + let y = f(x)?; + v.push(y); + } + Ok(v) } diff --git a/compiler/erg_common/macros.rs b/compiler/erg_common/macros.rs index 84a3d14b..317281f0 100644 --- a/compiler/erg_common/macros.rs +++ b/compiler/erg_common/macros.rs @@ -21,9 +21,11 @@ macro_rules! impl_display_from_debug { ($Name: ident) => { impl std::fmt::Display for $Name { #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{self:#?}") } + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{self:#?}") + } } - } + }; } #[macro_export] @@ -57,8 +59,12 @@ macro_rules! impl_display_for_enum_with_variant { #[macro_export] macro_rules! switch_lang { ($en: expr, $jp: expr $(,)*) => {{ - if cfg!(feature = "japanese") { $jp } else { $en } - }} + if cfg!(feature = "japanese") { + $jp + } else { + $en + } + }}; } /// 2重のunwrapまでサポート @@ -91,33 +97,58 @@ macro_rules! enum_unwrap { #[macro_export] macro_rules! fmt_option { ($ex: expr $(,)*) => { - if let Some(x) = $ex { format!("{}", x) } else { "".to_string() } + if let Some(x) = $ex { + format!("{}", x) + } else { + "".to_string() + } }; ($ex: expr $(,)*, else $els: expr $(,)*) => { - if let Some(x) = $ex { format!("{}", x) } else { $els.to_string() } + if let Some(x) = $ex { + format!("{}", x) + } else { + $els.to_string() + } }; (pre $prefix: expr, $ex: expr $(,)*) => { - if let Some(x) = $ex { format!("{}{}", $prefix, x) } else { "".to_string() } + if let Some(x) = $ex { + format!("{}{}", $prefix, x) + } else { + "".to_string() + } }; ($ex: expr, post $postfix: expr $(,)*) => { - if let Some(x) = $ex { format!("{}{}", x, $postfix) } else { "".to_string() } + if let Some(x) = $ex { + format!("{}{}", x, $postfix) + } else { + "".to_string() + } }; ($prefix: expr, $ex: expr, $postfix: expr $(,)*) => { - if let Some(x) = $ex { format!("{}{}{}", $prefix, x, $postfix) } else { "".to_string() } + if let Some(x) = $ex { + format!("{}{}{}", $prefix, x, $postfix) + } else { + "".to_string() + } }; } #[macro_export] macro_rules! switch_unreachable { () => {{ - if cfg!(debug_assertions) { unreachable!() } - else { unsafe { std::hint::unreachable_unchecked() } } - }} + if cfg!(debug_assertions) { + unreachable!() + } else { + unsafe { std::hint::unreachable_unchecked() } + } + }}; } #[macro_export] macro_rules! assume_unreachable { - () => {{ unsafe { std::hint::unreachable_unchecked() } }} + () => {{ + unsafe { std::hint::unreachable_unchecked() } + }}; } /// indicates the current invoked function. @@ -125,26 +156,33 @@ macro_rules! assume_unreachable { macro_rules! fn_name_full { () => {{ const fn dummy() {} - fn type_name_of(_: T) -> &'static str { std::any::type_name::() } + fn type_name_of(_: T) -> &'static str { + std::any::type_name::() + } let name = type_name_of(dummy); // "~::dummy" &name[..name.len() - 7] // remove "::dummy" - }} + }}; } #[macro_export] macro_rules! fn_name { () => {{ const fn dummy() {} - fn type_name_of(_: T) -> &'static str { std::any::type_name::() } + fn type_name_of(_: T) -> &'static str { + std::any::type_name::() + } let name = type_name_of(dummy).rsplit("::").nth(1).unwrap(); &name[..] - }} + }}; } // do not break lines (line!() is used) #[macro_export] macro_rules! caused_by { - () => {{ let fn_name = $crate::fn_name!(); &format!("{fn_name} at line {}", line!()) }} + () => {{ + let fn_name = $crate::fn_name!(); + &format!("{fn_name} at line {}", line!()) + }}; } /// 一度文字列をパースするので @@ -155,12 +193,14 @@ macro_rules! addr { let s = format!("{:p}", &$obj); let s = s.trim_start_matches("0x"); u64::from_str_radix(&s, 16).unwrap() - }} + }}; } #[macro_export] macro_rules! addr_eq { - ($l: expr, $r: expr $(,)*) => {{ &$l as *const _ == &$r as *const _ }} + ($l: expr, $r: expr $(,)*) => {{ + &$l as *const _ == &$r as *const _ + }}; } #[macro_export] @@ -187,10 +227,14 @@ macro_rules! power_assert { #[macro_export] macro_rules! debug_power_assert { ($l: expr, $op: tt, $r: expr) => { - if cfg!(debug_assertions) { erg_common::power_assert!($l, $op, $r) } + if cfg!(debug_assertions) { + erg_common::power_assert!($l, $op, $r) + } }; ($ex: expr) => { - if cfg!(debug_assertions) { erg_common::power_assert!($ex) } + if cfg!(debug_assertions) { + erg_common::power_assert!($ex) + } }; } @@ -204,7 +248,7 @@ macro_rules! debug_enum_assert { }}; ($ex: expr, $TupleCons: ident, $Enum: ident :: $Variant: ident $(,)*) => {{ debug_assert!(common::enum_is!($ex, $TupleCons, $Enum::$Variant)); - }} + }}; } #[macro_export] diff --git a/compiler/erg_common/opcode.rs b/compiler/erg_common/opcode.rs index 18980467..53fdcbfc 100644 --- a/compiler/erg_common/opcode.rs +++ b/compiler/erg_common/opcode.rs @@ -14,142 +14,142 @@ use crate::impl_display_from_debug; #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq)] #[repr(u8)] pub enum Opcode { - POP_TOP = 1, - ROT_TWO = 2, - ROT_THREE = 3, - DUP_TOP = 4, - DUP_TOP2 = 5, - ROT_FOUR = 6, - NOP = 9, - UNARY_POSITIVE = 10, - UNARY_NEGATIVE = 11, - UNARY_NOT = 12, - UNARY_INVERT = 15, - BINARY_MATRIX_MULTIPLY = 16, + POP_TOP = 1, + ROT_TWO = 2, + ROT_THREE = 3, + DUP_TOP = 4, + DUP_TOP2 = 5, + ROT_FOUR = 6, + NOP = 9, + UNARY_POSITIVE = 10, + UNARY_NEGATIVE = 11, + UNARY_NOT = 12, + UNARY_INVERT = 15, + BINARY_MATRIX_MULTIPLY = 16, INPLACE_MATRIX_MULTIPLY = 17, - BINARY_POWER = 19, - BINARY_MULTIPLY = 20, - BINARY_MODULO = 22, - BINARY_ADD = 23, - BINARY_SUBTRACT = 24, - BINARY_SUBSCR = 25, - BINARY_TRUE_DIVIDE = 27, - INPLACE_FLOOR_DIVIDE = 28, - INPLACE_TRUE_DIVIDE = 29, - GET_LEN = 30, - MATCH_MAPPING = 31, - MATCH_SEQUENCE = 32, - MATCH_KEYS = 33, - PUSH_EXC_INFO = 35, - CHECK_EXC_MATCH = 36, - CHECK_EG_MATCH = 37, - WITH_EXCEPT_START = 49, - GET_AITER = 50, - GET_ANEXT = 51, - BEFORE_ASYNC_WITH = 52, - BEFORE_WITH = 53, - END_ASYNC_FOR = 54, + BINARY_POWER = 19, + BINARY_MULTIPLY = 20, + BINARY_MODULO = 22, + BINARY_ADD = 23, + BINARY_SUBTRACT = 24, + BINARY_SUBSCR = 25, + BINARY_TRUE_DIVIDE = 27, + INPLACE_FLOOR_DIVIDE = 28, + INPLACE_TRUE_DIVIDE = 29, + GET_LEN = 30, + MATCH_MAPPING = 31, + MATCH_SEQUENCE = 32, + MATCH_KEYS = 33, + PUSH_EXC_INFO = 35, + CHECK_EXC_MATCH = 36, + CHECK_EG_MATCH = 37, + WITH_EXCEPT_START = 49, + GET_AITER = 50, + GET_ANEXT = 51, + BEFORE_ASYNC_WITH = 52, + BEFORE_WITH = 53, + END_ASYNC_FOR = 54, // TODO: - INPLACE_ADD = 55, - INPLACE_SUBTRACT = 56, - INPLACE_MULTIPLY = 57, - INPLACE_MODULO = 59, - STORE_SUBSCR = 60, - BINARY_AND = 64, - BINARY_XOR = 65, - BINARY_OR = 66, - GET_ITER = 68, - GET_YIELD_FROM_ITER = 69, - PRINT_EXPR = 70, - LOAD_BUILD_CLASS = 71, - LOAD_ASSERTION_ERROR = 74, - RETURN_VALUE = 83, + INPLACE_ADD = 55, + INPLACE_SUBTRACT = 56, + INPLACE_MULTIPLY = 57, + INPLACE_MODULO = 59, + STORE_SUBSCR = 60, + BINARY_AND = 64, + BINARY_XOR = 65, + BINARY_OR = 66, + GET_ITER = 68, + GET_YIELD_FROM_ITER = 69, + PRINT_EXPR = 70, + LOAD_BUILD_CLASS = 71, + LOAD_ASSERTION_ERROR = 74, + RETURN_VALUE = 83, /* ↓ These opcodes take an arg */ - STORE_NAME = 90, - DELETE_NAME = 91, - UNPACK_SEQUENCE = 92, - FOR_ITER = 93, - UNPACK_EX = 94, - STORE_ATTR = 95, - STORE_GLOBAL = 97, - LOAD_CONST = 100, - LOAD_NAME = 101, - BUILD_TUPLE = 102, - BUILD_LIST = 103, - BUILD_SET = 104, - BUILD_MAP = 105, // build a Dict object - LOAD_ATTR = 106, - COMPARE_OP = 107, - IMPORT_NAME = 108, - IMPORT_FROM = 109, - JUMP_FORWARD = 110, - JUMP_IF_FALSE_OR_POP = 111, - JUMP_IF_TRUE_OR_POP = 112, - JUMP_ABSOLUTE = 113, - POP_JUMP_IF_FALSE = 114, - POP_JUMP_IF_TRUE = 115, - LOAD_GLOBAL = 116, - IS_OP = 117, - CONTAINS_OP = 118, - LOAD_FAST = 124, - STORE_FAST = 125, - DELETE_FAST = 126, - RAISE_VARARGS = 130, - CALL_FUNCTION = 131, - MAKE_FUNCTION = 132, - LOAD_CLOSURE = 135, - LOAD_DEREF = 136, - STORE_DEREF = 137, - CALL_FUNCTION_KW = 141, - LOAD_METHOD = 160, - CALL_METHOD = 161, + STORE_NAME = 90, + DELETE_NAME = 91, + UNPACK_SEQUENCE = 92, + FOR_ITER = 93, + UNPACK_EX = 94, + STORE_ATTR = 95, + STORE_GLOBAL = 97, + LOAD_CONST = 100, + LOAD_NAME = 101, + BUILD_TUPLE = 102, + BUILD_LIST = 103, + BUILD_SET = 104, + BUILD_MAP = 105, // build a Dict object + LOAD_ATTR = 106, + COMPARE_OP = 107, + IMPORT_NAME = 108, + IMPORT_FROM = 109, + JUMP_FORWARD = 110, + JUMP_IF_FALSE_OR_POP = 111, + JUMP_IF_TRUE_OR_POP = 112, + JUMP_ABSOLUTE = 113, + POP_JUMP_IF_FALSE = 114, + POP_JUMP_IF_TRUE = 115, + LOAD_GLOBAL = 116, + IS_OP = 117, + CONTAINS_OP = 118, + LOAD_FAST = 124, + STORE_FAST = 125, + DELETE_FAST = 126, + RAISE_VARARGS = 130, + CALL_FUNCTION = 131, + MAKE_FUNCTION = 132, + LOAD_CLOSURE = 135, + LOAD_DEREF = 136, + STORE_DEREF = 137, + CALL_FUNCTION_KW = 141, + LOAD_METHOD = 160, + CALL_METHOD = 161, // Erg-specific opcodes (must have a unary `ERG_`) // Define in descending order from 219, 255 - ERG_POP_NTH = 196, - ERG_PEEK_NTH = 197, // get ref to the arg-th element from TOS - ERG_INC = 198, // name += 1; arg: typecode - ERG_DEC = 199, // name -= 1 - ERG_LOAD_FAST_IMMUT = 200, - ERG_STORE_FAST_IMMUT = 201, - ERG_MOVE_FAST = 202, - ERG_CLONE_FAST = 203, - ERG_COPY_FAST = 204, - ERG_REF_FAST = 205, - ERG_REF_MUT_FAST = 206, - ERG_MOVE_OUTER = 207, - ERG_CLONE_OUTER = 208, - ERG_COPY_OUTER = 209, - ERG_REF_OUTER = 210, - ERG_REF_MUT_OUTER = 211, - ERG_LESS_THAN = 212, - ERG_LESS_EQUAL = 213, - ERG_EQUAL = 214, - ERG_NOT_EQUAL = 215, - ERG_MAKE_SLOT = 216, - ERG_MAKE_TYPE = 217, - ERG_MAKE_PURE_FUNCTION = 218, - ERG_CALL_PURE_FUNCTION = 219, + ERG_POP_NTH = 196, + ERG_PEEK_NTH = 197, // get ref to the arg-th element from TOS + ERG_INC = 198, // name += 1; arg: typecode + ERG_DEC = 199, // name -= 1 + ERG_LOAD_FAST_IMMUT = 200, + ERG_STORE_FAST_IMMUT = 201, + ERG_MOVE_FAST = 202, + ERG_CLONE_FAST = 203, + ERG_COPY_FAST = 204, + ERG_REF_FAST = 205, + ERG_REF_MUT_FAST = 206, + ERG_MOVE_OUTER = 207, + ERG_CLONE_OUTER = 208, + ERG_COPY_OUTER = 209, + ERG_REF_OUTER = 210, + ERG_REF_MUT_OUTER = 211, + ERG_LESS_THAN = 212, + ERG_LESS_EQUAL = 213, + ERG_EQUAL = 214, + ERG_NOT_EQUAL = 215, + ERG_MAKE_SLOT = 216, + ERG_MAKE_TYPE = 217, + ERG_MAKE_PURE_FUNCTION = 218, + ERG_CALL_PURE_FUNCTION = 219, /* ↑ These opcodes take an arg ↑ */ /* ↓ These opcodes take no arg ↓ */ // ... = 220, - ERG_LOAD_EMPTY_SLOT = 242, - ERG_LOAD_EMPTY_STR = 243, - ERG_LOAD_1_NAT = 244, - ERG_LOAD_1_INT = 245, - ERG_LOAD_1_REAL = 246, - ERG_LOAD_NONE = 247, - ERG_MUTATE = 248, // !x + ERG_LOAD_EMPTY_SLOT = 242, + ERG_LOAD_EMPTY_STR = 243, + ERG_LOAD_1_NAT = 244, + ERG_LOAD_1_INT = 245, + ERG_LOAD_1_REAL = 246, + ERG_LOAD_NONE = 247, + ERG_MUTATE = 248, // !x /// `[] =` (it doesn't cause any exceptions) - ERG_STORE_SUBSCR = 249, + ERG_STORE_SUBSCR = 249, // ... = 250, /// `= []` (it doesn't cause any exceptions) - ERG_BINARY_SUBSCR = 251, - ERG_BINARY_RANGE = 252, + ERG_BINARY_SUBSCR = 251, + ERG_BINARY_RANGE = 252, /// `/?` (rhs may be 0, it may cause a runtime panic) - ERG_TRY_BINARY_DIVIDE = 253, + ERG_TRY_BINARY_DIVIDE = 253, /// `/` (rhs could not be 0, it doesn't cause any exceptions) - ERG_BINARY_TRUE_DIVIDE = 254, - NOT_IMPLEMENTED = 255, + ERG_BINARY_TRUE_DIVIDE = 254, + NOT_IMPLEMENTED = 255, } use Opcode::*; @@ -159,61 +159,61 @@ impl_display_from_debug!(Opcode); impl From for Opcode { fn from(byte: u8) -> Self { match byte { - 1 => POP_TOP, - 2 => ROT_TWO, - 3 => ROT_THREE, - 4 => DUP_TOP, - 5 => DUP_TOP2, - 6 => ROT_FOUR, - 9 => NOP, - 10 => UNARY_POSITIVE, - 11 => UNARY_NEGATIVE, - 12 => UNARY_NOT, - 15 => UNARY_INVERT, - 19 => BINARY_POWER, - 20 => BINARY_MULTIPLY, - 22 => BINARY_MODULO, - 23 => BINARY_ADD, - 24 => BINARY_SUBTRACT, - 25 => BINARY_SUBSCR, - 27 => BINARY_TRUE_DIVIDE, - 28 => INPLACE_FLOOR_DIVIDE, - 29 => INPLACE_TRUE_DIVIDE, - 30 => GET_LEN, - 31 => MATCH_MAPPING, - 32 => MATCH_SEQUENCE, - 33 => MATCH_KEYS, - 35 => PUSH_EXC_INFO, - 36 => CHECK_EXC_MATCH, - 37 => CHECK_EG_MATCH, - 49 => WITH_EXCEPT_START, - 50 => GET_AITER, - 51 => GET_ANEXT, - 52 => BEFORE_ASYNC_WITH, - 53 => BEFORE_WITH, - 54 => END_ASYNC_FOR, - 55 => INPLACE_ADD, - 56 => INPLACE_SUBTRACT, - 57 => INPLACE_MULTIPLY, - 59 => INPLACE_MODULO, - 60 => STORE_SUBSCR, - 64 => BINARY_AND, - 65 => BINARY_XOR, - 66 => BINARY_OR, - 68 => GET_ITER, - 69 => GET_YIELD_FROM_ITER, - 70 => PRINT_EXPR, - 71 => LOAD_BUILD_CLASS, - 74 => LOAD_ASSERTION_ERROR, - 83 => RETURN_VALUE, + 1 => POP_TOP, + 2 => ROT_TWO, + 3 => ROT_THREE, + 4 => DUP_TOP, + 5 => DUP_TOP2, + 6 => ROT_FOUR, + 9 => NOP, + 10 => UNARY_POSITIVE, + 11 => UNARY_NEGATIVE, + 12 => UNARY_NOT, + 15 => UNARY_INVERT, + 19 => BINARY_POWER, + 20 => BINARY_MULTIPLY, + 22 => BINARY_MODULO, + 23 => BINARY_ADD, + 24 => BINARY_SUBTRACT, + 25 => BINARY_SUBSCR, + 27 => BINARY_TRUE_DIVIDE, + 28 => INPLACE_FLOOR_DIVIDE, + 29 => INPLACE_TRUE_DIVIDE, + 30 => GET_LEN, + 31 => MATCH_MAPPING, + 32 => MATCH_SEQUENCE, + 33 => MATCH_KEYS, + 35 => PUSH_EXC_INFO, + 36 => CHECK_EXC_MATCH, + 37 => CHECK_EG_MATCH, + 49 => WITH_EXCEPT_START, + 50 => GET_AITER, + 51 => GET_ANEXT, + 52 => BEFORE_ASYNC_WITH, + 53 => BEFORE_WITH, + 54 => END_ASYNC_FOR, + 55 => INPLACE_ADD, + 56 => INPLACE_SUBTRACT, + 57 => INPLACE_MULTIPLY, + 59 => INPLACE_MODULO, + 60 => STORE_SUBSCR, + 64 => BINARY_AND, + 65 => BINARY_XOR, + 66 => BINARY_OR, + 68 => GET_ITER, + 69 => GET_YIELD_FROM_ITER, + 70 => PRINT_EXPR, + 71 => LOAD_BUILD_CLASS, + 74 => LOAD_ASSERTION_ERROR, + 83 => RETURN_VALUE, /* ↓ These opcodes take an arg */ - 90 => STORE_NAME, - 91 => DELETE_NAME, - 92 => UNPACK_SEQUENCE, - 93 => FOR_ITER, - 94 => UNPACK_EX, - 95 => STORE_ATTR, - 97 => STORE_GLOBAL, + 90 => STORE_NAME, + 91 => DELETE_NAME, + 92 => UNPACK_SEQUENCE, + 93 => FOR_ITER, + 94 => UNPACK_EX, + 95 => STORE_ATTR, + 97 => STORE_GLOBAL, 100 => LOAD_CONST, 101 => LOAD_NAME, 102 => BUILD_TUPLE, @@ -294,5 +294,7 @@ impl From for Opcode { } impl Opcode { - pub const fn take_arg(&self) -> bool { 90 <= (*self as u8) && (*self as u8) < 220 } + pub const fn take_arg(&self) -> bool { + 90 <= (*self as u8) && (*self as u8) < 220 + } } diff --git a/compiler/erg_common/python_util.rs b/compiler/erg_common/python_util.rs index 936b8ec6..3e964ea8 100644 --- a/compiler/erg_common/python_util.rs +++ b/compiler/erg_common/python_util.rs @@ -31,7 +31,10 @@ pub fn detect_magic_number() -> u32 { .output() .expect("cannot get the magic number from python") } else { - let python_command = format!("{} -c 'import importlib.util as util;print(util.MAGIC_NUMBER.hex())'", which_python()); + let python_command = format!( + "{} -c 'import importlib.util as util;print(util.MAGIC_NUMBER.hex())'", + which_python() + ); Command::new("sh") .arg("-c") .arg(python_command) diff --git a/compiler/erg_common/rccell.rs b/compiler/erg_common/rccell.rs index c66a9ca4..7b73cf1a 100644 --- a/compiler/erg_common/rccell.rs +++ b/compiler/erg_common/rccell.rs @@ -1,7 +1,7 @@ +use std::cell::{Ref, RefCell, RefMut}; use std::fmt; -use std::rc::Rc; -use std::cell::{RefCell, Ref, RefMut}; use std::hash::{Hash, Hasher}; +use std::rc::Rc; #[derive(Debug)] pub struct RcCell(Rc>); @@ -28,7 +28,9 @@ impl Hash for RcCell { } impl Default for RcCell { - fn default() -> Self { Self::new(Default::default()) } + fn default() -> Self { + Self::new(Default::default()) + } } impl fmt::Display for RcCell { @@ -38,7 +40,9 @@ impl fmt::Display for RcCell { } impl RcCell { - pub fn new(t: T) -> Self { Self(Rc::new(RefCell::new(t))) } + pub fn new(t: T) -> Self { + Self(Rc::new(RefCell::new(t))) + } #[inline] pub fn into_inner(self) -> T { @@ -52,7 +56,9 @@ impl RcCell { impl RcCell { #[inline] - pub fn copy(&self) -> Self { Self(self.0.clone()) } + pub fn copy(&self) -> Self { + Self(self.0.clone()) + } #[inline] pub fn borrow(&self) -> Ref<'_, T> { @@ -67,5 +73,7 @@ impl RcCell { impl RcCell { #[inline] - pub fn clone_inner(&self) -> T { self.borrow().clone() } + pub fn clone_inner(&self) -> T { + self.borrow().clone() + } } diff --git a/compiler/erg_common/serialize.rs b/compiler/erg_common/serialize.rs index 70409753..ff71b657 100644 --- a/compiler/erg_common/serialize.rs +++ b/compiler/erg_common/serialize.rs @@ -49,17 +49,17 @@ pub enum DataTypePrefix { StopIter = 'S' as u8, // 0x53 Ref = 'r' as u8, /* 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 + 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 + 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 + Tuple = '(' as u8, // 0x28 + len: u32 + payload + Code = 'c' as u8, // 0x63 /* Erg specific prefix */ - Builtin = 'b' as u8, // 0x62 + str + Builtin = 'b' as u8, // 0x62 + str Nat = 'n' as u8, } diff --git a/compiler/erg_common/set.rs b/compiler/erg_common/set.rs index 3e3af035..2aec7319 100644 --- a/compiler/erg_common/set.rs +++ b/compiler/erg_common/set.rs @@ -1,13 +1,13 @@ use std::borrow::Borrow; +use std::collections::hash_set::{IntoIter, Iter}; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; -use std::collections::hash_set::{Iter, IntoIter}; -use crate::{fmt_iter, debug_fmt_iter}; use crate::fxhash::FxHashSet; -use crate::value::ValueObj; use crate::ty::Type; +use crate::value::ValueObj; +use crate::{debug_fmt_iter, fmt_iter}; #[macro_export] macro_rules! set { @@ -21,18 +21,19 @@ macro_rules! set { #[derive(Clone)] pub struct Set { - elems: FxHashSet + elems: FxHashSet, } impl PartialEq for Set { fn eq(&self, other: &Set) -> bool { - self.len() == other.len() - && self.iter().all(|key| other.contains(key)) + self.len() == other.len() && self.iter().all(|key| other.contains(key)) } } impl Default for Set { - fn default() -> Self { Self::new() } + fn default() -> Self { + Self::new() + } } impl Eq for Set {} @@ -44,7 +45,9 @@ impl Hash for Set { } impl From> for Set { - fn from(vec: Vec) -> Self { vec.into_iter().collect() } + fn from(vec: Vec) -> Self { + vec.into_iter().collect() + } } impl fmt::Debug for Set { @@ -70,45 +73,78 @@ impl FromIterator for Set { impl Set { #[inline] - pub fn new() -> Self { Self{ elems: FxHashSet::default() } } + pub fn new() -> Self { + Self { + elems: FxHashSet::default(), + } + } } impl Set { pub fn with_capacity(capacity: usize) -> Self { - Self{ elems: FxHashSet::with_capacity_and_hasher(capacity, Default::default()) } + Self { + elems: FxHashSet::with_capacity_and_hasher(capacity, Default::default()), + } } #[inline] - pub fn len(&self) -> usize { self.elems.len() } + pub fn len(&self) -> usize { + self.elems.len() + } #[inline] - pub fn is_empty(&self) -> bool { self.elems.is_empty() } + pub fn is_empty(&self) -> bool { + self.elems.is_empty() + } #[inline] - pub fn iter(&self) -> Iter<'_, T> { self.elems.iter() } + pub fn iter(&self) -> Iter<'_, T> { + self.elems.iter() + } #[inline] - pub fn into_iter(self) -> IntoIter { self.elems.into_iter() } + pub fn into_iter(self) -> IntoIter { + self.elems.into_iter() + } } impl Set { #[inline] pub fn get(&self, value: &Q) -> Option<&T> - where T: Borrow, Q: ?Sized + Hash + Eq { self.elems.get(value) } + where + T: Borrow, + Q: ?Sized + Hash + Eq, + { + self.elems.get(value) + } #[inline] pub fn contains(&self, value: &Q) -> bool - where T: Borrow, Q: ?Sized + Hash + Eq { self.elems.contains(value) } + where + T: Borrow, + Q: ?Sized + Hash + Eq, + { + self.elems.contains(value) + } #[inline] - pub fn insert(&mut self, value: T) { self.elems.insert(value); } + pub fn insert(&mut self, value: T) { + self.elems.insert(value); + } #[inline] pub fn remove(&mut self, value: &Q) -> bool - where T: Borrow, Q: ?Sized + Hash + Eq { self.elems.remove(value) } + where + T: Borrow, + Q: ?Sized + Hash + Eq, + { + self.elems.remove(value) + } #[inline] - pub fn extend>(&mut self, iter: I) { self.elems.extend(iter); } + pub fn extend>(&mut self, iter: I) { + self.elems.extend(iter); + } #[inline] pub fn is_superset(&self, other: &Set) -> bool { @@ -131,13 +167,17 @@ impl Set { #[inline] pub fn union(&self, other: &Set) -> Set { let u = self.elems.union(&other.elems); - Self{ elems: u.into_iter().map(|x| x.clone()).collect() } + Self { + elems: u.into_iter().map(|x| x.clone()).collect(), + } } #[inline] pub fn intersection(&self, other: &Set) -> Set { let u = self.elems.intersection(&other.elems); - Self{ elems: u.into_iter().map(|x| x.clone()).collect() } + Self { + elems: u.into_iter().map(|x| x.clone()).collect(), + } } } @@ -163,14 +203,18 @@ impl Set { } pub fn max(&self) -> Option { - if !self.is_homogeneous() { return None } + if !self.is_homogeneous() { + return None; + } self.iter() .max_by(|x, y| x.try_cmp(y).unwrap()) .map(Clone::clone) } pub fn min(&self) -> Option { - if !self.is_homogeneous() { return None } + if !self.is_homogeneous() { + return None; + } self.iter() .min_by(|x, y| x.try_cmp(y).unwrap()) .map(Clone::clone) diff --git a/compiler/erg_common/stdin.rs b/compiler/erg_common/stdin.rs index c394dbfe..d7da0ef0 100644 --- a/compiler/erg_common/stdin.rs +++ b/compiler/erg_common/stdin.rs @@ -1,5 +1,5 @@ -use std::io::{stdin, BufReader, BufRead}; use std::cell::RefCell; +use std::io::{stdin, BufRead, BufReader}; use crate::Str; @@ -24,7 +24,7 @@ impl StdinReader { } pub fn reread_lines(&self, ln_begin: usize, ln_end: usize) -> Vec { - self.buf[ln_begin-1..=ln_end-1].to_vec() + self.buf[ln_begin - 1..=ln_end - 1].to_vec() } } diff --git a/compiler/erg_common/str.rs b/compiler/erg_common/str.rs index cfc85dc4..872ba230 100644 --- a/compiler/erg_common/str.rs +++ b/compiler/erg_common/str.rs @@ -1,6 +1,6 @@ -use std::hash::{Hash, Hasher}; -use std::fmt; use std::borrow::Borrow; +use std::fmt; +use std::hash::{Hash, Hasher}; use std::ops::{Add, Deref}; pub type RcStr = std::rc::Rc; @@ -16,7 +16,9 @@ pub enum Str { impl PartialEq for Str { #[inline] - fn eq(&self, other: &Str) -> bool { &self[..] == &other[..] } + fn eq(&self, other: &Str) -> bool { + &self[..] == &other[..] + } } impl Add<&str> for Str { @@ -49,27 +51,37 @@ impl fmt::Display for Str { // あえて`impl> From for Str { ... }`はしない impl From<&'static str> for Str { #[inline] - fn from(s: &'static str) -> Self { Str::ever(s) } + fn from(s: &'static str) -> Self { + Str::ever(s) + } } impl From<&String> for Str { #[inline] - fn from(s: &String) -> Self { Str::Rc((&s[..]).into()) } + fn from(s: &String) -> Self { + Str::Rc((&s[..]).into()) + } } impl From for Str { #[inline] - fn from(s: String) -> Self { Str::Rc((&s[..]).into()) } + fn from(s: String) -> Self { + Str::Rc((&s[..]).into()) + } } impl From<&RcStr> for Str { #[inline] - fn from(s: &RcStr) -> Self { Str::Rc(s.clone()) } + fn from(s: &RcStr) -> Self { + Str::Rc(s.clone()) + } } impl From for Str { #[inline] - fn from(s: RcStr) -> Self { Str::Rc(s) } + fn from(s: RcStr) -> Self { + Str::Rc(s) + } } impl From<&Str> for Str { @@ -84,7 +96,9 @@ impl From<&Str> for Str { impl Deref for Str { type Target = str; - fn deref(&self) -> &Self::Target { self.borrow() } + fn deref(&self) -> &Self::Target { + self.borrow() + } } impl Borrow for Str { @@ -98,11 +112,17 @@ impl Borrow for Str { } impl Str { - pub const fn ever(s: &'static str) -> Self { Str::Static(s) } + pub const fn ever(s: &'static str) -> Self { + Str::Static(s) + } - pub fn rc(s: &str) -> Self { Str::Rc(s.into()) } + pub fn rc(s: &str) -> Self { + Str::Rc(s.into()) + } - pub fn as_ref(&self) -> &str { self.borrow() } + pub fn as_ref(&self) -> &str { + self.borrow() + } pub fn into_rc(self) -> RcStr { match self { @@ -112,6 +132,9 @@ impl Str { } pub fn is_uppercase(&self) -> bool { - self.chars().next().map(|c| c.is_uppercase()).unwrap_or(false) + self.chars() + .next() + .map(|c| c.is_uppercase()) + .unwrap_or(false) } } diff --git a/compiler/erg_common/traits.rs b/compiler/erg_common/traits.rs index 408cc42b..a3150a4a 100644 --- a/compiler/erg_common/traits.rs +++ b/compiler/erg_common/traits.rs @@ -1,18 +1,18 @@ //! defines common traits used in the compiler. //! //! コンパイラ等で汎用的に使われるトレイトを定義する +use std::io::{stdout, BufWriter, Write}; +use std::mem; +use std::process; use std::slice::{Iter, IterMut}; use std::vec::IntoIter; -use std::io::{BufWriter, Write, stdout}; -use std::process; -use std::mem; -use crate::Str; -use crate::{addr_eq, switch_unreachable, chomp, log}; use crate::color::{GREEN, RESET}; use crate::config::{ErgConfig, Input}; -use crate::error::{Location, ErrorDisplay, MultiErrorDisplay}; +use crate::error::{ErrorDisplay, Location, MultiErrorDisplay}; use crate::ty::Type; +use crate::Str; +use crate::{addr_eq, chomp, log, switch_unreachable}; pub trait Stream: Sized { fn payload(self) -> Vec; @@ -20,17 +20,23 @@ pub trait Stream: Sized { fn ref_mut_payload(&mut self) -> &mut Vec; #[inline] - fn clear(&mut self) { self.ref_mut_payload().clear(); } + fn clear(&mut self) { + self.ref_mut_payload().clear(); + } #[inline] - fn len(&self) -> usize { self.ref_payload().len() } + fn len(&self) -> usize { + self.ref_payload().len() + } fn size(&self) -> usize { std::mem::size_of::>() + std::mem::size_of::() * self.ref_payload().capacity() } #[inline] - fn is_empty(&self) -> bool { self.ref_payload().is_empty() } + fn is_empty(&self) -> bool { + self.ref_payload().is_empty() + } #[inline] fn insert(&mut self, idx: usize, elem: T) { @@ -38,89 +44,141 @@ pub trait Stream: Sized { } #[inline] - fn remove(&mut self, idx: usize) -> T { self.ref_mut_payload().remove(idx) } - - #[inline] - fn push(&mut self, elem: T) { self.ref_mut_payload().push(elem); } - - fn append>(&mut self, s: &mut S) { self.ref_mut_payload().append(s.ref_mut_payload()); } - - #[inline] - fn pop(&mut self) -> Option { self.ref_mut_payload().pop() } - - fn lpop(&mut self) -> Option { - let len = self.len(); - if len == 0 { None } else { Some(self.ref_mut_payload().remove(0)) } + fn remove(&mut self, idx: usize) -> T { + self.ref_mut_payload().remove(idx) } #[inline] - fn get(&self, idx: usize) -> Option<&T> { self.ref_payload().get(idx) } + fn push(&mut self, elem: T) { + self.ref_mut_payload().push(elem); + } + + fn append>(&mut self, s: &mut S) { + self.ref_mut_payload().append(s.ref_mut_payload()); + } #[inline] - fn get_mut(&mut self, idx: usize) -> Option<&mut T> { self.ref_mut_payload().get_mut(idx) } + fn pop(&mut self) -> Option { + self.ref_mut_payload().pop() + } + + fn lpop(&mut self) -> Option { + let len = self.len(); + if len == 0 { + None + } else { + Some(self.ref_mut_payload().remove(0)) + } + } #[inline] - fn first(&self) -> Option<&T> { self.ref_payload().first() } + fn get(&self, idx: usize) -> Option<&T> { + self.ref_payload().get(idx) + } #[inline] - fn first_mut(&mut self) -> Option<&mut T> { self.ref_mut_payload().first_mut() } + fn get_mut(&mut self, idx: usize) -> Option<&mut T> { + self.ref_mut_payload().get_mut(idx) + } #[inline] - fn last(&self) -> Option<&T> { self.ref_payload().last() } + fn first(&self) -> Option<&T> { + self.ref_payload().first() + } #[inline] - fn last_mut(&mut self) -> Option<&mut T> { self.ref_mut_payload().last_mut() } + fn first_mut(&mut self) -> Option<&mut T> { + self.ref_mut_payload().first_mut() + } #[inline] - fn iter(&self) -> Iter<'_, T> { self.ref_payload().iter() } + fn last(&self) -> Option<&T> { + self.ref_payload().last() + } #[inline] - fn iter_mut(&mut self) -> IterMut<'_, T> { self.ref_mut_payload().iter_mut() } + fn last_mut(&mut self) -> Option<&mut T> { + self.ref_mut_payload().last_mut() + } #[inline] - fn into_iter(self) -> IntoIter { self.payload().into_iter() } + fn iter(&self) -> Iter<'_, T> { + self.ref_payload().iter() + } #[inline] - fn take_all(&mut self) -> Vec { self.ref_mut_payload().drain(..).collect() } + fn iter_mut(&mut self) -> IterMut<'_, T> { + self.ref_mut_payload().iter_mut() + } + + #[inline] + fn into_iter(self) -> IntoIter { + self.payload().into_iter() + } + + #[inline] + fn take_all(&mut self) -> Vec { + self.ref_mut_payload().drain(..).collect() + } } #[macro_export] macro_rules! impl_displayable_stream_for_wrapper { ($Strc: ident, $Inner: ident) => { impl $Strc { - pub const fn new(v: Vec<$Inner>) -> $Strc { $Strc(v) } + pub const fn new(v: Vec<$Inner>) -> $Strc { + $Strc(v) + } #[inline] - pub fn empty() -> $Strc { $Strc(Vec::with_capacity(20)) } + pub fn empty() -> $Strc { + $Strc(Vec::with_capacity(20)) + } } impl From> for $Strc { #[inline] - fn from(errs: Vec<$Inner>) -> Self { Self(errs) } + fn from(errs: Vec<$Inner>) -> Self { + Self(errs) + } } impl std::fmt::Display for $Strc { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result { - write!(f, "[{}]", erg_common::fmt_iter(self.iter()).replace("\n", "\\n")) + write!( + f, + "[{}]", + erg_common::fmt_iter(self.iter()).replace("\n", "\\n") + ) } } impl Default for $Strc { #[inline] - fn default() -> Self { Self::empty() } + fn default() -> Self { + Self::empty() + } } impl std::ops::Index for $Strc { type Output = $Inner; - fn index(&self, idx: usize) -> &Self::Output { erg_common::traits::Stream::get(self, idx).unwrap() } + fn index(&self, idx: usize) -> &Self::Output { + erg_common::traits::Stream::get(self, idx).unwrap() + } } impl erg_common::traits::Stream<$Inner> for $Strc { #[inline] - fn payload(self) -> Vec<$Inner> { self.0 } + fn payload(self) -> Vec<$Inner> { + self.0 + } #[inline] - fn ref_payload(&self) -> &Vec<$Inner> { &self.0 } + fn ref_payload(&self) -> &Vec<$Inner> { + &self.0 + } #[inline] - fn ref_mut_payload(&mut self) -> &mut Vec<$Inner> { &mut self.0 } + fn ref_mut_payload(&mut self) -> &mut Vec<$Inner> { + &mut self.0 + } } }; } @@ -129,31 +187,47 @@ macro_rules! impl_displayable_stream_for_wrapper { macro_rules! impl_stream_for_wrapper { ($Strc: ident, $Inner: ident) => { impl $Strc { - pub const fn new(v: Vec<$Inner>) -> $Strc { $Strc(v) } - pub const fn empty() -> $Strc { $Strc(Vec::new()) } + pub const fn new(v: Vec<$Inner>) -> $Strc { + $Strc(v) + } + pub const fn empty() -> $Strc { + $Strc(Vec::new()) + } #[inline] - pub fn with_capacity(capacity: usize) -> $Strc { $Strc(Vec::with_capacity(capacity)) } + pub fn with_capacity(capacity: usize) -> $Strc { + $Strc(Vec::with_capacity(capacity)) + } } impl Default for $Strc { #[inline] - fn default() -> $Strc { $Strc::with_capacity(0) } + fn default() -> $Strc { + $Strc::with_capacity(0) + } } impl std::ops::Index for $Strc { type Output = $Inner; - fn index(&self, idx: usize) -> &Self::Output { erg_common::traits::Stream::get(self, idx).unwrap() } + fn index(&self, idx: usize) -> &Self::Output { + erg_common::traits::Stream::get(self, idx).unwrap() + } } impl erg_common::traits::Stream<$Inner> for $Strc { #[inline] - fn payload(self) -> Vec<$Inner> { self.0 } + fn payload(self) -> Vec<$Inner> { + self.0 + } #[inline] - fn ref_payload(&self) -> &Vec<$Inner> { &self.0 } + fn ref_payload(&self) -> &Vec<$Inner> { + &self.0 + } #[inline] - fn ref_mut_payload(&mut self) -> &mut Vec<$Inner> { &mut self.0 } + fn ref_mut_payload(&mut self) -> &mut Vec<$Inner> { + &mut self.0 + } } - } + }; } #[macro_export] @@ -161,18 +235,26 @@ macro_rules! impl_stream { ($Strc: ident, $Inner: ident, $field: ident) => { impl erg_common::traits::Stream<$Inner> for $Strc { #[inline] - fn payload(self) -> Vec<$Inner> { self.$field } + fn payload(self) -> Vec<$Inner> { + self.$field + } #[inline] - fn ref_payload(&self) -> &Vec<$Inner> { &self.$field } + fn ref_payload(&self) -> &Vec<$Inner> { + &self.$field + } #[inline] - fn ref_mut_payload(&mut self) -> &mut Vec<$Inner> { &mut self.$field } + fn ref_mut_payload(&mut self) -> &mut Vec<$Inner> { + &mut self.$field + } } impl std::ops::Index for $Strc { type Output = $Inner; - fn index(&self, idx: usize) -> &Self::Output { erg_common::traits::Stream::get(self, idx).unwrap() } + fn index(&self, idx: usize) -> &Self::Output { + erg_common::traits::Stream::get(self, idx).unwrap() + } } - } + }; } pub trait ImmutableStream: Sized { @@ -180,33 +262,48 @@ pub trait ImmutableStream: Sized { fn capacity(&self) -> usize; #[inline] - fn len(&self) -> usize { self.ref_payload().len() } + fn len(&self) -> usize { + self.ref_payload().len() + } fn size(&self) -> usize { std::mem::size_of::>() + std::mem::size_of::() * self.capacity() } #[inline] - fn is_empty(&self) -> bool { self.ref_payload().is_empty() } + fn is_empty(&self) -> bool { + self.ref_payload().is_empty() + } #[inline] - fn get(&self, idx: usize) -> Option<&T> { self.ref_payload().get(idx) } + fn get(&self, idx: usize) -> Option<&T> { + self.ref_payload().get(idx) + } #[inline] - fn first(&self) -> Option<&T> { self.ref_payload().first() } + fn first(&self) -> Option<&T> { + self.ref_payload().first() + } #[inline] - fn last(&self) -> Option<&T> { self.ref_payload().last() } + fn last(&self) -> Option<&T> { + self.ref_payload().last() + } #[inline] - fn iter(&self) -> Iter<'_, T> { self.ref_payload().iter() } + fn iter(&self) -> Iter<'_, T> { + self.ref_payload().iter() + } } // for Runnable::run fn expect_block(src: &str) -> bool { - src.ends_with(&['=', ':']) || src.ends_with(":=") - || src.ends_with("->") || src.ends_with("=>") - || src.ends_with("do") || src.ends_with("do!") + src.ends_with(&['=', ':']) + || src.ends_with(":=") + || src.ends_with("->") + || src.ends_with("=>") + || src.ends_with("do") + || src.ends_with("do!") } /// this trait implements REPL (Read-Eval-Print-Loop) automatically @@ -220,11 +317,17 @@ pub trait Runnable: Sized { fn clear(&mut self); fn eval(&mut self, src: Str) -> Result; - fn ps1(&self) -> String { ">>> ".to_string() } // TODO: &str (VMのせいで参照をとれない) - fn ps2(&self) -> String { "... ".to_string() } + fn ps1(&self) -> String { + ">>> ".to_string() + } // TODO: &str (VMのせいで参照をとれない) + fn ps2(&self) -> String { + "... ".to_string() + } #[inline] - fn quit(&self, code: i32) { process::exit(code); } + fn quit(&self, code: i32) { + process::exit(code); + } fn run(cfg: ErgConfig) { let mut instance = Self::new(cfg); @@ -264,14 +367,16 @@ pub trait Runnable: Sized { Ok(out) => { output.write((out + "\n").as_bytes()).unwrap(); output.flush().unwrap(); - }, - Err(e) => { e.fmt_all_stderr(); } + } + Err(e) => { + e.fmt_all_stderr(); + } } output.write(instance.ps1().as_bytes()).unwrap(); output.flush().unwrap(); instance.clear(); } - }, + } Input::Dummy => switch_unreachable!(), }; if let Err(e) = res { @@ -286,8 +391,8 @@ pub trait Locational { fn ln_begin(&self) -> Option { match self.loc() { - Location::RangePair{ ln_begin, .. } - | Location::Range{ ln_begin, .. } + Location::RangePair { ln_begin, .. } + | Location::Range { ln_begin, .. } | Location::LineRange(ln_begin, _) => Some(ln_begin), Location::Line(lineno) => Some(lineno), Location::Unknown => None, @@ -296,8 +401,8 @@ pub trait Locational { fn ln_end(&self) -> Option { match self.loc() { - Location::RangePair{ ln_end, .. } - | Location::Range{ ln_end, .. } + Location::RangePair { ln_end, .. } + | Location::Range { ln_end, .. } | Location::LineRange(_, ln_end) => Some(ln_end), Location::Line(lineno) => Some(lineno), Location::Unknown => None, @@ -306,14 +411,14 @@ pub trait Locational { fn col_begin(&self) -> Option { match self.loc() { - Location::Range{ col_begin, .. } => Some(col_begin), + Location::Range { col_begin, .. } => Some(col_begin), _ => None, } } fn col_end(&self) -> Option { match self.loc() { - Location::Range{ col_end, .. } => Some(col_end), + Location::Range { col_end, .. } => Some(col_end), _ => None, } } @@ -337,7 +442,12 @@ macro_rules! impl_locational { ($T: ty, $begin: ident, $end: ident) => { impl Locational for $T { fn loc(&self) -> Location { - match (self.$begin.ln_begin(), self.$begin.col_begin(), self.$end.ln_end(), self.$end.col_end()) { + match ( + self.$begin.ln_begin(), + self.$begin.col_begin(), + self.$end.ln_end(), + self.$end.col_end(), + ) { (Some(lb), Some(cb), Some(le), Some(ce)) => Location::range(lb, cb, le, ce), (Some(lb), _, Some(le), _) => Location::LineRange(lb, le), (Some(l), _, _, _) | (_, _, Some(l), _) => Location::Line(l), @@ -386,13 +496,21 @@ pub trait HasType { // 関数呼び出しの場合、.ref_t()は戻り値を返し、signature_t()は関数全体の型を返す fn signature_t(&self) -> Option<&Type>; #[inline] - fn t(&self) -> Type { self.ref_t().clone() } + fn t(&self) -> Type { + self.ref_t().clone() + } #[inline] - fn inner_ts(&self) -> Vec { self.ref_t().inner_ts() } + fn inner_ts(&self) -> Vec { + self.ref_t().inner_ts() + } #[inline] - fn lhs_t(&self) -> &Type { &self.ref_t().non_default_params().unwrap()[0].ty } + fn lhs_t(&self) -> &Type { + &self.ref_t().non_default_params().unwrap()[0].ty + } #[inline] - fn rhs_t(&self) -> &Type { &self.ref_t().non_default_params().unwrap()[1].ty } + fn rhs_t(&self) -> &Type { + &self.ref_t().non_default_params().unwrap()[1].ty + } } #[macro_export] @@ -400,7 +518,9 @@ macro_rules! impl_t { ($T: ty, $t: ident) => { impl erg_common::traits::HasType for $T { #[inline] - fn ref_t(&self) -> &common::ty::Type { &common::ty::Type::$t } + fn ref_t(&self) -> &common::ty::Type { + &common::ty::Type::$t + } } }; } @@ -408,7 +528,9 @@ macro_rules! impl_t { /// Pythonではis演算子に相当 pub trait AddrEq { #[inline] - fn addr_eq(&self, other: &Self) -> bool { addr_eq!(self, other) } + fn addr_eq(&self, other: &Self) -> bool { + addr_eq!(self, other) + } } pub trait __Str__ { diff --git a/compiler/erg_common/tsort.rs b/compiler/erg_common/tsort.rs index e476e1d9..9b687381 100644 --- a/compiler/erg_common/tsort.rs +++ b/compiler/erg_common/tsort.rs @@ -10,7 +10,10 @@ pub struct Node { impl Node { pub const fn new(id: T, depends_on: Vec) -> Self { - Node { _id: id, depends_on,} + Node { + _id: id, + depends_on, + } } } @@ -19,7 +22,9 @@ pub type Graph = Vec>; fn reorder_by_idx(mut v: Vec, idx: Vec) -> Vec { let mut swap_table = Dict::new(); for (node_id, mut sort_i) in idx.into_iter().enumerate() { - if node_id == sort_i { continue; } + if node_id == sort_i { + continue; + } while let Some(moved_to) = swap_table.get(&sort_i) { sort_i = *moved_to; } @@ -32,7 +37,9 @@ fn reorder_by_idx(mut v: Vec, idx: Vec) -> Vec { fn dfs(g: &Graph, v: NodeIdx, used: &mut Vec, idx: &mut Vec) { used[v] = true; for &node_id in g[v].depends_on.iter() { - if !used[node_id] { dfs(g, node_id, used, idx); } + if !used[node_id] { + dfs(g, node_id, used, idx); + } } idx.push(v); } @@ -43,7 +50,9 @@ pub fn tsort(g: Graph) -> Graph { let mut idx = Vec::with_capacity(n); let mut used = vec![false; n]; for v in 0..n { - if !used[v] { dfs(&g, v, &mut used, &mut idx); } + if !used[v] { + dfs(&g, v, &mut used, &mut idx); + } } reorder_by_idx(g, idx) } @@ -58,7 +67,13 @@ fn _test() { let on_2 = Node::new("odd n", vec![3, 0]); let e0_3 = Node::new("even 0", vec![]); let ond_4 = Node::new("odd n (decl)", vec![]); - let sorted = vec![ond_4.clone(), o0_1.clone(), en_0.clone(), e0_3.clone(), on_2.clone()]; + let sorted = vec![ + ond_4.clone(), + o0_1.clone(), + en_0.clone(), + e0_3.clone(), + on_2.clone(), + ]; let dag = vec![en_0, o0_1, on_2, e0_3, ond_4]; assert_eq!(sorted, tsort(dag)); } diff --git a/compiler/erg_common/ty.rs b/compiler/erg_common/ty.rs index 85a22e3b..9faf64ea 100644 --- a/compiler/erg_common/ty.rs +++ b/compiler/erg_common/ty.rs @@ -5,16 +5,16 @@ use std::cell::{Ref, RefMut}; use std::cmp::Ordering; use std::fmt; use std::mem; -use std::ops::{Add, Sub, Mul, Div, Neg, Range, RangeInclusive}; +use std::ops::{Add, Div, Mul, Neg, Range, RangeInclusive, Sub}; -use crate::{Str, fmt_vec, fmt_vec_split_with, fmt_set_split_with, set}; use crate::codeobj::CodeObj; -use crate::value::ValueObj; use crate::dict::Dict; use crate::rccell::RcCell; use crate::set::Set; use crate::traits::HasType; -use crate::ty::ValueObj::{NegInf, Inf}; +use crate::ty::ValueObj::{Inf, NegInf}; +use crate::value::ValueObj; +use crate::{fmt_set_split_with, fmt_vec, fmt_vec_split_with, set, Str}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(u8)] @@ -91,7 +91,7 @@ pub trait HasLevel { pub enum Constraint { SupertypeOf(Type), SubtypeOf(Type), - Sandwiched{ sub: Type, sup: Type }, + Sandwiched { sub: Type, sup: Type }, TypeOf(Type), } @@ -100,7 +100,7 @@ impl fmt::Display for Constraint { match self { Self::SupertypeOf(sub) => write!(f, ":> {sub}"), Self::SubtypeOf(sup) => write!(f, "<: {sup}"), - Self::Sandwiched{ sub, sup } => write!(f, ":> {sub}, <: {sup}"), + Self::Sandwiched { sub, sup } => write!(f, ":> {sub}, <: {sup}"), Self::TypeOf(ty) => write!(f, ": {}", ty), } } @@ -132,33 +132,58 @@ impl Constraint { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum FreeKind { Linked(T), - Unbound{ id: Id, lev: Level, constraint: Constraint }, - NamedUnbound{ name: Str, lev: Level, constraint: Constraint }, + Unbound { + id: Id, + lev: Level, + constraint: Constraint, + }, + NamedUnbound { + name: Str, + lev: Level, + constraint: Constraint, + }, } impl fmt::Display for FreeKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Linked(t) => write!(f, "({t})"), - Self::NamedUnbound{ name, lev, constraint } => write!(f, "?{name}({constraint})[{lev}]"), - Self::Unbound{ id, lev, constraint }=> write!(f, "?{id}({constraint})[{lev}]"), + Self::NamedUnbound { + name, + lev, + constraint, + } => write!(f, "?{name}({constraint})[{lev}]"), + Self::Unbound { + id, + lev, + constraint, + } => write!(f, "?{id}({constraint})[{lev}]"), } } } impl FreeKind { pub const fn unbound(id: Id, lev: Level, constraint: Constraint) -> Self { - Self::Unbound{ id, lev, constraint } + Self::Unbound { + id, + lev, + constraint, + } } pub const fn named_unbound(name: Str, lev: Level, constraint: Constraint) -> Self { - Self::NamedUnbound{ name, lev, constraint } + Self::NamedUnbound { + name, + lev, + constraint, + } } pub const fn constraint(&self) -> Option<&Constraint> { match self { - Self::Unbound{ constraint, .. } - | Self::NamedUnbound{ constraint, .. } => Some(constraint), + Self::Unbound { constraint, .. } | Self::NamedUnbound { constraint, .. } => { + Some(constraint) + } _ => None, } } @@ -174,17 +199,25 @@ impl fmt::Display for Free { } impl Free { - pub fn new(f: FreeKind) -> Self { Self(RcCell::new(f)) } + pub fn new(f: FreeKind) -> Self { + Self(RcCell::new(f)) + } pub fn new_unbound(level: Level, constraint: Constraint) -> Self { UNBOUND_ID.with(|id| { *id.borrow_mut() += 1; - Self(RcCell::new(FreeKind::unbound(*id.borrow(), level, constraint))) + Self(RcCell::new(FreeKind::unbound( + *id.borrow(), + level, + constraint, + ))) }) } pub fn new_named_unbound(name: Str, level: Level, constraint: Constraint) -> Self { - Self(RcCell::new(FreeKind::named_unbound(name, level, constraint))) + Self(RcCell::new(FreeKind::named_unbound( + name, level, constraint, + ))) } pub fn new_linked(t: T) -> Self { @@ -197,35 +230,41 @@ impl Free { pub fn update_level(&self, level: Level) { match &mut *self.0.borrow_mut() { - FreeKind::Unbound{ lev, .. } - | FreeKind::NamedUnbound{ lev, .. } if level < *lev => { *lev = level; }, - FreeKind::Linked(t) => { t.update_level(level); }, + FreeKind::Unbound { lev, .. } | FreeKind::NamedUnbound { lev, .. } if level < *lev => { + *lev = level; + } + FreeKind::Linked(t) => { + t.update_level(level); + } _ => {} } } pub fn lift(&self) { match &mut *self.0.borrow_mut() { - FreeKind::Unbound{ lev, .. } - | FreeKind::NamedUnbound{ lev, .. } => { *lev += 1; }, - FreeKind::Linked(t) => { if let Some(lev) = t.level() { t.update_level(lev+1); } }, + FreeKind::Unbound { lev, .. } | FreeKind::NamedUnbound { lev, .. } => { + *lev += 1; + } + FreeKind::Linked(t) => { + if let Some(lev) = t.level() { + t.update_level(lev + 1); + } + } } } pub fn level(&self) -> Option { match &*self.0.borrow() { - FreeKind::Unbound{ lev, .. } - | FreeKind::NamedUnbound{ lev, .. } => Some(*lev), + FreeKind::Unbound { lev, .. } | FreeKind::NamedUnbound { lev, .. } => Some(*lev), FreeKind::Linked(t) => t.level(), } } pub fn update_constraint(&self, new_constraint: Constraint) { match &mut *self.0.borrow_mut() { - FreeKind::Unbound{ constraint, .. } - | FreeKind::NamedUnbound{ constraint, .. } => { + FreeKind::Unbound { constraint, .. } | FreeKind::NamedUnbound { constraint, .. } => { *constraint = new_constraint; - }, + } _ => {} } } @@ -233,8 +272,9 @@ impl Free { pub fn unwrap(self) -> T { match self.0.clone_inner() { FreeKind::Linked(t) => t, - FreeKind::Unbound{ .. } - | FreeKind::NamedUnbound{ .. } => panic!("the value is unbounded"), + FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => { + panic!("the value is unbounded") + } } } @@ -243,23 +283,31 @@ impl Free { pub fn crack(&self) -> Ref<'_, T> { Ref::map(self.0.borrow(), |f| match f { FreeKind::Linked(t) => t, - FreeKind::Unbound{ .. } - | FreeKind::NamedUnbound{ .. } => panic!("the value is unbounded"), + FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => { + panic!("the value is unbounded") + } }) } pub fn type_of(&self) -> Option { - self.0.borrow().constraint() + self.0 + .borrow() + .constraint() .and_then(|c| c.typ().map(|t| t.clone())) } pub fn subtype_of(&self) -> Option { - self.0.borrow().constraint() + self.0 + .borrow() + .constraint() .and_then(|c| c.super_type().map(|t| t.clone())) } pub fn is_unbound(&self) -> bool { - matches!(&*self.0.borrow(), FreeKind::Unbound{ .. } | FreeKind::NamedUnbound{ .. }) + matches!( + &*self.0.borrow(), + FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } + ) } pub fn is_linked(&self) -> bool { @@ -268,21 +316,31 @@ impl Free { pub fn unbound_name(&self) -> Option { match &*self.0.borrow() { - FreeKind::NamedUnbound{ name, .. } => Some(name.clone()), + FreeKind::NamedUnbound { name, .. } => Some(name.clone()), _ => None, } } - pub fn borrow(&self) -> Ref<'_, FreeKind> { self.0.borrow() } - pub fn borrow_mut(&self) -> RefMut<'_, FreeKind> { self.0.borrow_mut() } + pub fn borrow(&self) -> Ref<'_, FreeKind> { + self.0.borrow() + } + pub fn borrow_mut(&self) -> RefMut<'_, FreeKind> { + self.0.borrow_mut() + } } impl Free { - pub fn map(&self, f: F) where F: Fn(TyParam) -> TyParam { + pub fn map(&self, f: F) + where + F: Fn(TyParam) -> TyParam, + { match &mut *self.0.borrow_mut() { - FreeKind::Unbound{ .. } - | FreeKind::NamedUnbound{ .. } => panic!("the value is unbounded"), - FreeKind::Linked(t) => { *t = f(mem::take(t)); }, + FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => { + panic!("the value is unbounded") + } + FreeKind::Linked(t) => { + *t = f(mem::take(t)); + } } } } @@ -337,7 +395,9 @@ impl fmt::Display for ConstObj { } impl ConstObj { - pub fn t(t: Type) -> Self { Self::Type(Box::new(t)) } + pub fn t(t: Type) -> Self { + Self::Type(Box::new(t)) + } pub fn try_cmp(&self, other: &Self) -> Option { match (self, other) { @@ -373,13 +433,29 @@ pub enum TyParam { Array(Vec), Tuple(Vec), Mono(Str), - MonoProj{ obj: Box, attr: Str }, - App{ name: Str, args: Vec }, - UnaryOp{ op: OpKind, val: Box }, - BinOp{ op: OpKind, lhs: Box, rhs: Box }, + MonoProj { + obj: Box, + attr: Str, + }, + App { + name: Str, + args: Vec, + }, + UnaryOp { + op: OpKind, + val: Box, + }, + BinOp { + op: OpKind, + lhs: Box, + rhs: Box, + }, Erased(Box), MonoQVar(Str), - PolyQVar{ name: Str, args: Vec }, + PolyQVar { + name: Str, + args: Vec, + }, FreeVar(FreeTyParam), Failure, } @@ -390,15 +466,15 @@ impl fmt::Display for TyParam { Self::ConstObj(c) => write!(f, "{c}"), Self::Type(t) => write!(f, "{t}"), Self::Mono(c) => write!(f, "{c}"), - Self::MonoProj{ obj, attr } => write!(f, "{obj}.{attr}"), + Self::MonoProj { obj, attr } => write!(f, "{obj}.{attr}"), Self::Array(a) => write!(f, "[{}]", fmt_vec(a)), Self::Tuple(t) => write!(f, "({})", fmt_vec(t)), - Self::App{ name, args } => write!(f, "{name}({})", fmt_vec(args)), + Self::App { name, args } => write!(f, "{name}({})", fmt_vec(args)), Self::MonoQVar(name) => write!(f, "'{name}"), - Self::PolyQVar{ name, args } => write!(f, "'{name}({})", fmt_vec(args)), + Self::PolyQVar { name, args } => write!(f, "'{name}({})", fmt_vec(args)), Self::FreeVar(fv) => write!(f, "{fv}"), - Self::UnaryOp{ op, val } => write!(f, "{op}{val}"), - Self::BinOp{ op, lhs, rhs } => write!(f, "{lhs} {op} {rhs}"), + Self::UnaryOp { op, val } => write!(f, "{op}{val}"), + Self::BinOp { op, lhs, rhs } => write!(f, "{lhs} {op} {rhs}"), Self::Erased(t) => write!(f, "_: {t}"), Self::Failure => write!(f, ""), } @@ -407,32 +483,44 @@ impl fmt::Display for TyParam { impl Default for TyParam { #[inline] - fn default() -> Self { Self::Failure } + fn default() -> Self { + Self::Failure + } } impl Add for TyParam { type Output = Self; - fn add(self, rhs: Self) -> Self::Output { Self::bin(OpKind::Add, self, rhs)} + fn add(self, rhs: Self) -> Self::Output { + Self::bin(OpKind::Add, self, rhs) + } } impl Sub for TyParam { type Output = Self; - fn sub(self, rhs: Self) -> Self::Output { Self::bin(OpKind::Sub, self, rhs) } + fn sub(self, rhs: Self) -> Self::Output { + Self::bin(OpKind::Sub, self, rhs) + } } impl Mul for TyParam { type Output = Self; - fn mul(self, rhs: Self) -> Self::Output { Self::bin(OpKind::Mul, self, rhs) } + fn mul(self, rhs: Self) -> Self::Output { + Self::bin(OpKind::Mul, self, rhs) + } } impl Div for TyParam { type Output = Self; - fn div(self, rhs: Self) -> Self::Output { Self::bin(OpKind::Div, self, rhs) } + fn div(self, rhs: Self) -> Self::Output { + Self::bin(OpKind::Div, self, rhs) + } } impl Neg for TyParam { type Output = Self; - fn neg(self) -> Self::Output { Self::unary(OpKind::Neg, self) } + fn neg(self) -> Self::Output { + Self::unary(OpKind::Neg, self) + } } impl From> for TyParam { @@ -443,7 +531,11 @@ impl From> for TyParam { impl From> for TyParam { fn from(r: Range<&TyParam>) -> Self { - Self::t(Type::int_interval(IntervalOp::RightOpen, r.start.clone(), r.end.clone())) + Self::t(Type::int_interval( + IntervalOp::RightOpen, + r.start.clone(), + r.end.clone(), + )) } } @@ -457,12 +549,18 @@ impl From> for TyParam { impl From> for TyParam { fn from(r: RangeInclusive<&TyParam>) -> Self { let (start, end) = r.into_inner(); - Self::t(Type::int_interval(IntervalOp::Closed, start.clone(), end.clone())) + Self::t(Type::int_interval( + IntervalOp::Closed, + start.clone(), + end.clone(), + )) } } impl> From for TyParam { - fn from(v: V) -> Self { Self::ConstObj(ConstObj::Value(v.into())) } + fn from(v: V) -> Self { + Self::ConstObj(ConstObj::Value(v.into())) + } } impl HasLevel for TyParam { @@ -470,8 +568,8 @@ impl HasLevel for TyParam { match self { Self::Type(t) => t.level(), Self::FreeVar(fv) => fv.level(), - Self::UnaryOp{ val, .. } => val.level(), - Self::BinOp{ lhs, rhs, .. } => lhs.level().and_then(|l| rhs.level().map(|r| l.max(r))), + Self::UnaryOp { val, .. } => val.level(), + Self::BinOp { lhs, rhs, .. } => lhs.level().and_then(|l| rhs.level().map(|r| l.max(r))), _ => None, } } @@ -479,17 +577,16 @@ impl HasLevel for TyParam { fn update_level(&self, level: Level) { match self { Self::FreeVar(fv) => fv.update_level(level), - Self::UnaryOp{ val, .. } => val.update_level(level), - Self::BinOp{ lhs, rhs, .. } => { + Self::UnaryOp { val, .. } => val.update_level(level), + Self::BinOp { lhs, rhs, .. } => { lhs.update_level(level); rhs.update_level(level); - }, - Self::App{ args, .. } - | Self::PolyQVar{ args, .. } => { + } + Self::App { args, .. } | Self::PolyQVar { args, .. } => { for arg in args.iter() { arg.update_level(level); } - }, + } _ => {} } } @@ -497,101 +594,150 @@ impl HasLevel for TyParam { fn lift(&self) { match self { Self::FreeVar(fv) => fv.lift(), - Self::UnaryOp{ val, .. } => val.lift(), - Self::BinOp{ lhs, rhs, .. } => { + Self::UnaryOp { val, .. } => val.lift(), + Self::BinOp { lhs, rhs, .. } => { lhs.lift(); rhs.lift(); - }, - Self::App{ args, .. } - | Self::PolyQVar{ args, .. } => { + } + Self::App { args, .. } | Self::PolyQVar { args, .. } => { for arg in args.iter() { arg.lift(); } - }, + } _ => {} } } } impl TyParam { - pub fn t(t: Type) -> Self { Self::Type(Box::new(t)) } + pub fn t(t: Type) -> Self { + Self::Type(Box::new(t)) + } - pub fn mono>(name: S) -> Self { Self::Mono(name.into()) } + pub fn mono>(name: S) -> Self { + Self::Mono(name.into()) + } - pub fn mono_q>(name: S) -> Self { Self::MonoQVar(name.into()) } + pub fn mono_q>(name: S) -> Self { + Self::MonoQVar(name.into()) + } pub fn mono_proj>(obj: TyParam, attr: S) -> Self { - Self::MonoProj{ obj: Box::new(obj), attr: attr.into() } + Self::MonoProj { + obj: Box::new(obj), + attr: attr.into(), + } } // TODO: polymorphic type - pub fn array_t(t: Str, len: TyParam) -> Self { Self::Array(vec![TyParam::t(Type::mono(t)), len]) } + pub fn array_t(t: Str, len: TyParam) -> Self { + Self::Array(vec![TyParam::t(Type::mono(t)), len]) + } pub fn free_var(level: usize, t: Type) -> Self { Self::FreeVar(FreeTyParam::new_unbound(level, Constraint::TypeOf(t))) } pub fn named_free_var(name: Str, level: usize, t: Type) -> Self { - Self::FreeVar(FreeTyParam::new_named_unbound(name, level, Constraint::TypeOf(t))) + Self::FreeVar(FreeTyParam::new_named_unbound( + name, + level, + Constraint::TypeOf(t), + )) } #[inline] - pub fn value>(v: V) -> Self { Self::ConstObj(ConstObj::Value(v.into())) } + pub fn value>(v: V) -> Self { + Self::ConstObj(ConstObj::Value(v.into())) + } #[inline] - pub fn cons>(l: C) -> Self { Self::ConstObj(l.into()) } + pub fn cons>(l: C) -> Self { + Self::ConstObj(l.into()) + } #[inline] - pub fn unary(op: OpKind, val: TyParam) -> Self { Self::UnaryOp{ op, val: Box::new(val) } } + pub fn unary(op: OpKind, val: TyParam) -> Self { + Self::UnaryOp { + op, + val: Box::new(val), + } + } #[inline] - pub fn mutate(self) -> Self { Self::unary(OpKind::Mutate, self) } + pub fn mutate(self) -> Self { + Self::unary(OpKind::Mutate, self) + } #[inline] pub fn bin(op: OpKind, lhs: TyParam, rhs: TyParam) -> Self { - Self::BinOp{ op, lhs: Box::new(lhs), rhs: Box::new(rhs) } + Self::BinOp { + op, + lhs: Box::new(lhs), + rhs: Box::new(rhs), + } } pub fn app(name: &'static str, args: Vec) -> Self { - Self::App{ name: Str::ever(name), args } + Self::App { + name: Str::ever(name), + args, + } } #[inline] - pub fn erased(t: Type) -> Self { Self::Erased(Box::new(t)) } + pub fn erased(t: Type) -> Self { + Self::Erased(Box::new(t)) + } // if self: Ratio, Succ(self) => self+ε - pub fn succ(self) -> Self { Self::app("Succ", vec![self]) } + pub fn succ(self) -> Self { + Self::app("Succ", vec![self]) + } // if self: Ratio, Pred(self) => self-ε - pub fn pred(self) -> Self { Self::app("Pred", vec![self]) } + pub fn pred(self) -> Self { + Self::app("Pred", vec![self]) + } /// 型変数の内容を考慮した再帰的(Recursive)比較を行う pub fn rec_eq(&self, other: &Self) -> bool { match (self, other) { (Self::Type(l), Self::Type(r)) => l.rec_eq(r), - (Self::FreeVar(fv), o) - | (o, Self::FreeVar(fv)) => match &*fv.borrow() { + (Self::FreeVar(fv), o) | (o, Self::FreeVar(fv)) => match &*fv.borrow() { FreeKind::Linked(tp) => tp.rec_eq(o), _ => self == o, }, + (Self::MonoProj { obj: lo, attr: la }, Self::MonoProj { obj: ro, attr: ra }) => { + lo.rec_eq(ro) && la == ra + } + (Self::Array(l), Self::Array(r)) | (Self::Tuple(l), Self::Tuple(r)) => { + l.iter().zip(r.iter()).all(|(l, r)| l.rec_eq(r)) + } ( - Self::MonoProj{ obj: lo, attr: la }, - Self::MonoProj{ obj: ro, attr: ra} - ) => lo.rec_eq(ro) && la == ra, - (Self::Array(l), Self::Array(r)) - | (Self::Tuple(l), Self::Tuple(r)) => - l.iter().zip(r.iter()).all(|(l, r)| l.rec_eq(r)), - ( - Self::App{ name: ln, args: lps }, - Self::App{ name: rn, args: rps} + Self::App { + name: ln, + args: lps, + }, + Self::App { + name: rn, + args: rps, + }, ) => ln == rn && lps.iter().zip(rps.iter()).all(|(l, r)| l.rec_eq(r)), + (Self::UnaryOp { op: lop, val: lv }, Self::UnaryOp { op: rop, val: rv }) => { + lop == rop && lv.rec_eq(rv) + } ( - Self::UnaryOp{ op: lop, val: lv }, - Self::UnaryOp{ op: rop, val: rv } - ) => lop == rop && lv.rec_eq(rv), - ( - Self::BinOp{ op: lop, lhs: ll, rhs: lr }, - Self::BinOp{ op: rop, lhs: rl, rhs: rr } + Self::BinOp { + op: lop, + lhs: ll, + rhs: lr, + }, + Self::BinOp { + op: rop, + lhs: rl, + rhs: rr, + }, ) => lop == rop && ll.rec_eq(rl) && lr.rec_eq(rr), (Self::Erased(l), Self::Erased(r)) => l.rec_eq(r), _ => self == other, @@ -628,23 +774,29 @@ impl TyParam { pub fn has_unbound_var(&self) -> bool { match self { - Self::FreeVar(fv) => - if fv.is_unbound() { true } else { fv.crack().has_unbound_var() }, + Self::FreeVar(fv) => { + if fv.is_unbound() { + true + } else { + fv.crack().has_unbound_var() + } + } Self::Type(t) => t.has_unbound_var(), - Self::MonoProj{ obj, .. } => obj.has_unbound_var(), - Self::Array(ts) - | Self::Tuple(ts) => ts.iter().any(|t| t.has_unbound_var()), - Self::UnaryOp{ val, .. } => val.has_unbound_var(), - Self::BinOp{ lhs, rhs, .. } => - lhs.has_unbound_var() || rhs.has_unbound_var(), - Self::App{ args, .. } - | Self::PolyQVar{ args, .. } => args.iter().any(|p| p.has_unbound_var()), + Self::MonoProj { obj, .. } => obj.has_unbound_var(), + Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.has_unbound_var()), + Self::UnaryOp { val, .. } => val.has_unbound_var(), + Self::BinOp { lhs, rhs, .. } => lhs.has_unbound_var() || rhs.has_unbound_var(), + Self::App { args, .. } | Self::PolyQVar { args, .. } => { + args.iter().any(|p| p.has_unbound_var()) + } Self::Erased(t) => t.has_unbound_var(), _ => false, } } - pub fn has_no_unbound_var(&self) -> bool { !self.has_unbound_var() } + pub fn has_no_unbound_var(&self) -> bool { + !self.has_unbound_var() + } pub fn has_upper_bound(&self) -> bool { match self { @@ -671,8 +823,8 @@ pub enum TyParamOrdering { Less, Equal, Greater, - LessEqual, // Less or Equal - NotEqual, // Less or Greater + LessEqual, // Less or Equal + NotEqual, // Less or Greater GreaterEqual, // Greater or Equal Any, } @@ -702,12 +854,24 @@ impl TryFrom for Ordering { } impl TyParamOrdering { - pub const fn is_lt(&self) -> bool { matches!(self, Less | LessEqual | Any) } - pub const fn is_le(&self) -> bool { matches!(self, Less | Equal | LessEqual | Any) } - pub const fn is_gt(&self) -> bool { matches!(self, Greater | GreaterEqual | Any) } - pub const fn is_ge(&self) -> bool { matches!(self, Greater | Equal | GreaterEqual | Any) } - pub const fn is_eq(&self) -> bool { matches!(self, Equal | Any) } - pub const fn is_ne(&self) -> bool { matches!(self, Less | Greater | NotEqual | Any) } + pub const fn is_lt(&self) -> bool { + matches!(self, Less | LessEqual | Any) + } + pub const fn is_le(&self) -> bool { + matches!(self, Less | Equal | LessEqual | Any) + } + pub const fn is_gt(&self) -> bool { + matches!(self, Greater | GreaterEqual | Any) + } + pub const fn is_ge(&self) -> bool { + matches!(self, Greater | Equal | GreaterEqual | Any) + } + pub const fn is_eq(&self) -> bool { + matches!(self, Equal | Any) + } + pub const fn is_ne(&self) -> bool { + matches!(self, Less | Greater | NotEqual | Any) + } pub const fn reverse(&self) -> Self { match self { Less => Greater, @@ -724,21 +888,21 @@ impl TyParamOrdering { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TyBound { // e.g. A <: Add => Subtype{sub: A, sup: Add}, A <: {a: Int} => Subtype{sub: A, sup: {a: Int}} - Subtype{ sub: Type, sup: Type }, - Supertype{ sup: Type, sub: Type }, - Sandwiched{ sub: Type, mid: Type, sup: Type }, + Subtype { sub: Type, sup: Type }, + Supertype { sup: Type, sub: Type }, + Sandwiched { sub: Type, mid: Type, sup: Type }, // TyParam::MonoQuantVarに型の情報が含まれているので、boundsからは除去される // e.g. N: Nat => Instance{name: N, t: Nat} - Instance{ name: Str, t: Type }, + Instance { name: Str, t: Type }, } impl fmt::Display for TyBound { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Subtype{ sub, sup } => write!(f, "{sub} <: {sup}"), - Self::Supertype{ sup, sub } => write!(f, "{sup} :> {sub}"), - Self::Sandwiched{ sub, mid, sup } => write!(f, "{sub} <: {mid} <: {sup}"), - Self::Instance{ name, t } => write!(f, "'{name}: {t}"), + Self::Subtype { sub, sup } => write!(f, "{sub} <: {sup}"), + Self::Supertype { sup, sub } => write!(f, "{sup} :> {sub}"), + Self::Sandwiched { sub, mid, sup } => write!(f, "{sub} <: {mid} <: {sup}"), + Self::Instance { name, t } => write!(f, "'{name}: {t}"), } } } @@ -750,47 +914,60 @@ impl HasLevel for TyBound { fn update_level(&self, level: usize) { match self { - Self::Subtype{ sub, sup } - | Self::Supertype { sup, sub } => { + Self::Subtype { sub, sup } | Self::Supertype { sup, sub } => { sub.update_level(level); sup.update_level(level); } - Self::Sandwiched{ sub, mid, sup } => { + Self::Sandwiched { sub, mid, sup } => { sub.update_level(level); mid.update_level(level); sup.update_level(level); } - Self::Instance{ t, .. } => { t.update_level(level); }, + Self::Instance { t, .. } => { + t.update_level(level); + } } } fn lift(&self) { match self { - Self::Subtype{ sub, sup } - | Self::Supertype { sup, sub } => { + Self::Subtype { sub, sup } | Self::Supertype { sup, sub } => { sub.lift(); sup.lift(); } - Self::Sandwiched{ sub, mid, sup } => { + Self::Sandwiched { sub, mid, sup } => { sub.lift(); mid.lift(); sup.lift(); } - Self::Instance{ t, .. } => { t.lift(); }, + Self::Instance { t, .. } => { + t.lift(); + } } } } impl TyBound { - pub const fn subtype(sub: Type, sup: Type) -> Self { Self::Subtype{ sub, sup } } - pub const fn supertype(sup: Type, sub: Type) -> Self { Self::Supertype{ sup, sub } } - pub const fn sandwiched(sub: Type, mid: Type, sup: Type) -> Self { Self::Sandwiched{ sub, mid, sup } } - - pub const fn static_instance(name: &'static str, t: Type) -> Self { - Self::Instance{ name: Str::ever(name), t } + pub const fn subtype(sub: Type, sup: Type) -> Self { + Self::Subtype { sub, sup } + } + pub const fn supertype(sup: Type, sub: Type) -> Self { + Self::Supertype { sup, sub } + } + pub const fn sandwiched(sub: Type, mid: Type, sup: Type) -> Self { + Self::Sandwiched { sub, mid, sup } } - pub const fn instance(name: Str, t: Type) -> Self { Self::Instance{ name, t } } + pub const fn static_instance(name: &'static str, t: Type) -> Self { + Self::Instance { + name: Str::ever(name), + t, + } + } + + pub const fn instance(name: Str, t: Type) -> Self { + Self::Instance { name, t } + } pub fn mentions_as_instance(&self, name: &str) -> bool { matches!(self, Self::Instance{ name: n, .. } if &n[..] == name) @@ -802,20 +979,22 @@ impl TyBound { pub fn has_unbound_var(&self) -> bool { match self { - Self::Subtype{ sub, sup } - | Self::Supertype{ sub, sup } => sub.has_unbound_var() || sup.has_unbound_var(), - Self::Sandwiched{ sub, mid, sup } => - sub.has_unbound_var() || mid.has_unbound_var() || sup.has_unbound_var(), - Self::Instance{ t, .. } => t.has_unbound_var(), + Self::Subtype { sub, sup } | Self::Supertype { sub, sup } => { + sub.has_unbound_var() || sup.has_unbound_var() + } + Self::Sandwiched { sub, mid, sup } => { + sub.has_unbound_var() || mid.has_unbound_var() || sup.has_unbound_var() + } + Self::Instance { t, .. } => t.has_unbound_var(), } } pub const fn t(&self) -> &Type { match self { - Self::Subtype{ sup, .. } => sup, - | Self::Supertype{ sub, .. } => sub, - Self::Sandwiched{ .. } => todo!(), - Self::Instance{ t, .. } => t, + Self::Subtype { sup, .. } => sup, + Self::Supertype { sub, .. } => sub, + Self::Sandwiched { .. } => todo!(), + Self::Instance { t, .. } => t, } } } @@ -825,11 +1004,23 @@ pub enum Predicate { Value(ValueObj), // True/False Const(Str), /// i == 0 => Eq{ lhs: "i", rhs: 0 } - Equal{ lhs: Str, rhs: TyParam }, + Equal { + lhs: Str, + rhs: TyParam, + }, /// i > 0 => i >= 0+ε => GreaterEqual{ lhs: "i", rhs: 0+ε } - GreaterEqual{ lhs: Str, rhs: TyParam }, - LessEqual{ lhs: Str, rhs: TyParam }, - NotEqual{ lhs: Str, rhs: TyParam }, + GreaterEqual { + lhs: Str, + rhs: TyParam, + }, + LessEqual { + lhs: Str, + rhs: TyParam, + }, + NotEqual { + lhs: Str, + rhs: TyParam, + }, Or(Box, Box), And(Box, Box), Not(Box, Box), @@ -840,10 +1031,10 @@ impl fmt::Display for Predicate { match self { Self::Value(v) => write!(f, "{v}"), Self::Const(c) => write!(f, "{c}"), - Self::Equal{ lhs, rhs } => write!(f, "{lhs} == {rhs}"), - Self::GreaterEqual{ lhs, rhs } => write!(f, "{lhs} >= {rhs}"), - Self::LessEqual{ lhs, rhs } => write!(f, "{lhs} <= {rhs}"), - Self::NotEqual{ lhs, rhs } => write!(f, "{lhs} != {rhs}"), + Self::Equal { lhs, rhs } => write!(f, "{lhs} == {rhs}"), + Self::GreaterEqual { lhs, rhs } => write!(f, "{lhs} >= {rhs}"), + Self::LessEqual { lhs, rhs } => write!(f, "{lhs} <= {rhs}"), + Self::NotEqual { lhs, rhs } => write!(f, "{lhs} != {rhs}"), Self::Or(l, r) => write!(f, "({l}) or ({r})"), Self::And(l, r) => write!(f, "({l}) and ({r})"), Self::Not(l, r) => write!(f, "({l}) not ({r})"), @@ -855,60 +1046,62 @@ impl HasLevel for Predicate { fn level(&self) -> Option { match self { Self::Value(_) | Self::Const(_) => None, - Self::Equal{ rhs, .. } - | Self::GreaterEqual{ rhs, .. } - | Self::LessEqual{ rhs, .. } - | Self::NotEqual{ rhs, .. } => rhs.level(), - Self::And(_lhs, _rhs) - | Self::Or(_lhs, _rhs) - | Self::Not(_lhs, _rhs) => todo!(), + Self::Equal { rhs, .. } + | Self::GreaterEqual { rhs, .. } + | Self::LessEqual { rhs, .. } + | Self::NotEqual { rhs, .. } => rhs.level(), + Self::And(_lhs, _rhs) | Self::Or(_lhs, _rhs) | Self::Not(_lhs, _rhs) => todo!(), } } fn update_level(&self, level: usize) { match self { - Self::Value(_) | Self::Const(_) => {}, - Self::Equal{ rhs, .. } - | Self::GreaterEqual{ rhs, .. } - | Self::LessEqual{ rhs, .. } - | Self::NotEqual{ rhs, .. } => { + Self::Value(_) | Self::Const(_) => {} + Self::Equal { rhs, .. } + | Self::GreaterEqual { rhs, .. } + | Self::LessEqual { rhs, .. } + | Self::NotEqual { rhs, .. } => { rhs.update_level(level); - }, - Self::And(lhs, rhs) - | Self::Or(lhs, rhs) - | Self::Not(lhs, rhs) => { + } + Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => { lhs.update_level(level); rhs.update_level(level); - }, + } } } fn lift(&self) { match self { - Self::Value(_) | Self::Const(_) => {}, - Self::Equal{ rhs, .. } - | Self::GreaterEqual{ rhs, .. } - | Self::LessEqual{ rhs, .. } - | Self::NotEqual{ rhs, .. } => { + Self::Value(_) | Self::Const(_) => {} + Self::Equal { rhs, .. } + | Self::GreaterEqual { rhs, .. } + | Self::LessEqual { rhs, .. } + | Self::NotEqual { rhs, .. } => { rhs.lift(); - }, - Self::And(lhs, rhs) - | Self::Or(lhs, rhs) - | Self::Not(lhs, rhs) => { + } + Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => { lhs.lift(); rhs.lift(); - }, + } } } } impl Predicate { - pub const fn eq(lhs: Str, rhs: TyParam) -> Self { Self::Equal{ lhs, rhs } } - pub const fn ne(lhs: Str, rhs: TyParam) -> Self { Self::NotEqual{ lhs, rhs } } + pub const fn eq(lhs: Str, rhs: TyParam) -> Self { + Self::Equal { lhs, rhs } + } + pub const fn ne(lhs: Str, rhs: TyParam) -> Self { + Self::NotEqual { lhs, rhs } + } /// >= - pub const fn ge(lhs: Str, rhs: TyParam) -> Self { Self::GreaterEqual{ lhs, rhs } } + pub const fn ge(lhs: Str, rhs: TyParam) -> Self { + Self::GreaterEqual { lhs, rhs } + } /// <= - pub const fn le(lhs: Str, rhs: TyParam) -> Self { Self::LessEqual{ lhs, rhs } } + pub const fn le(lhs: Str, rhs: TyParam) -> Self { + Self::LessEqual { lhs, rhs } + } pub fn and(lhs: Predicate, rhs: Predicate) -> Self { Self::And(Box::new(lhs), Box::new(rhs)) @@ -924,31 +1117,41 @@ impl Predicate { pub fn subject(&self) -> Option<&str> { match self { - Self::Equal{ lhs, .. } - | Self::LessEqual{ lhs, .. } - | Self::GreaterEqual{ lhs, .. } - | Self::NotEqual{ lhs, .. } => Some(&lhs[..]), - Self::And(lhs, rhs) - | Self::Or(lhs, rhs) - | Self::Not(lhs, rhs) => { + Self::Equal { lhs, .. } + | Self::LessEqual { lhs, .. } + | Self::GreaterEqual { lhs, .. } + | Self::NotEqual { lhs, .. } => Some(&lhs[..]), + Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => { let l = lhs.subject(); let r = rhs.subject(); - if l != r { todo!() } - else { l } - }, + if l != r { + todo!() + } else { + l + } + } _ => None, } } pub fn change_subject_name(self, name: Str) -> Self { match self { - Self::Equal{ rhs, .. } => Self::eq(name, rhs), - Self::GreaterEqual{ rhs, .. } => Self::ge(name, rhs), - Self::LessEqual{ rhs, .. } => Self::le(name, rhs), - Self::NotEqual{ rhs, .. } => Self::ne(name, rhs), - Self::And(lhs, rhs) => Self::and(lhs.change_subject_name(name.clone()), rhs.change_subject_name(name)), - Self::Or(lhs, rhs) => Self::or(lhs.change_subject_name(name.clone()), rhs.change_subject_name(name)), - Self::Not(lhs, rhs) => Self::not(lhs.change_subject_name(name.clone()), rhs.change_subject_name(name)), + Self::Equal { rhs, .. } => Self::eq(name, rhs), + Self::GreaterEqual { rhs, .. } => Self::ge(name, rhs), + Self::LessEqual { rhs, .. } => Self::le(name, rhs), + Self::NotEqual { rhs, .. } => Self::ne(name, rhs), + Self::And(lhs, rhs) => Self::and( + lhs.change_subject_name(name.clone()), + rhs.change_subject_name(name), + ), + Self::Or(lhs, rhs) => Self::or( + lhs.change_subject_name(name.clone()), + rhs.change_subject_name(name), + ), + Self::Not(lhs, rhs) => Self::not( + lhs.change_subject_name(name.clone()), + rhs.change_subject_name(name), + ), _ => self, } } @@ -956,13 +1159,13 @@ impl Predicate { pub fn mentions(&self, name: &str) -> bool { match self { Self::Const(n) => &n[..] == name, - Self::Equal{ lhs, .. } - | Self::LessEqual{ lhs, .. } - | Self::GreaterEqual{ lhs, .. } - | Self::NotEqual{ lhs, .. } => &lhs[..] == name, - Self::And(lhs, rhs) - | Self::Or(lhs, rhs) - | Self::Not(lhs, rhs) => lhs.mentions(name) || rhs.mentions(name), + Self::Equal { lhs, .. } + | Self::LessEqual { lhs, .. } + | Self::GreaterEqual { lhs, .. } + | Self::NotEqual { lhs, .. } => &lhs[..] == name, + Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => { + lhs.mentions(name) || rhs.mentions(name) + } _ => false, } } @@ -982,35 +1185,43 @@ impl Predicate { match self { Self::Value(_) => false, Self::Const(_) => false, - Self::Equal{ rhs, .. } - |Self::GreaterEqual{ rhs, .. } - | Self::LessEqual{ rhs, .. } - | Self::NotEqual{ rhs, .. } => rhs.has_unbound_var(), - Self::Or(lhs, rhs) - | Self::And(lhs, rhs) - | Self::Not(lhs, rhs) => lhs.has_unbound_var() || rhs.has_unbound_var(), + Self::Equal { rhs, .. } + | Self::GreaterEqual { rhs, .. } + | Self::LessEqual { rhs, .. } + | Self::NotEqual { rhs, .. } => rhs.has_unbound_var(), + Self::Or(lhs, rhs) | Self::And(lhs, rhs) | Self::Not(lhs, rhs) => { + lhs.has_unbound_var() || rhs.has_unbound_var() + } } } - pub fn min_max<'a>(&'a self, min: Option<&'a TyParam>, max: Option<&'a TyParam>) -> (Option<&'a TyParam>, Option<&'a TyParam>) { + pub fn min_max<'a>( + &'a self, + min: Option<&'a TyParam>, + max: Option<&'a TyParam>, + ) -> (Option<&'a TyParam>, Option<&'a TyParam>) { match self { - Predicate::Equal{ rhs: _, .. } => todo!(), + Predicate::Equal { rhs: _, .. } => todo!(), // {I | I <= 1; I <= 2} - Predicate::LessEqual { rhs, .. } => { - (min, max.map(|l: &TyParam| match l.cheap_cmp(rhs) { + Predicate::LessEqual { rhs, .. } => ( + min, + max.map(|l: &TyParam| match l.cheap_cmp(rhs) { Some(c) if c.is_ge() => l, Some(_) => rhs, _ => l, - }).or(Some(rhs))) - }, + }) + .or(Some(rhs)), + ), // {I | I >= 1; I >= 2} - Predicate::GreaterEqual { rhs, .. } => { - (min.map(|l: &TyParam| match l.cheap_cmp(rhs) { + Predicate::GreaterEqual { rhs, .. } => ( + min.map(|l: &TyParam| match l.cheap_cmp(rhs) { Some(c) if c.is_le() => l, Some(_) => rhs, _ => l, - }).or(Some(rhs)), max) - }, + }) + .or(Some(rhs)), + max, + ), Predicate::And(_l, _r) => todo!(), _ => todo!(), } @@ -1019,28 +1230,28 @@ impl Predicate { pub fn typarams(&self) -> Vec<&TyParam> { match self { Self::Value(_) | Self::Const(_) => vec![], - Self::Equal{ rhs, .. } - | Self::GreaterEqual{ rhs, .. } - | Self::LessEqual{ rhs, .. } - | Self::NotEqual{ rhs, .. } => vec![rhs], - Self::And(lhs, rhs) - | Self::Or(lhs, rhs) - | Self::Not(lhs, rhs) => - lhs.typarams().into_iter().chain(rhs.typarams()).collect(), + Self::Equal { rhs, .. } + | Self::GreaterEqual { rhs, .. } + | Self::LessEqual { rhs, .. } + | Self::NotEqual { rhs, .. } => vec![rhs], + Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => { + lhs.typarams().into_iter().chain(rhs.typarams()).collect() + } } } pub fn typarams_mut(&mut self) -> Vec<&mut TyParam> { match self { Self::Value(_) | Self::Const(_) => vec![], - Self::Equal{ rhs, .. } - | Self::GreaterEqual{ rhs, .. } - | Self::LessEqual{ rhs, .. } - | Self::NotEqual{ rhs, .. } => vec![rhs], - Self::And(lhs, rhs) - | Self::Or(lhs, rhs) - | Self::Not(lhs, rhs) => - lhs.typarams_mut().into_iter().chain(rhs.typarams_mut()).collect(), + Self::Equal { rhs, .. } + | Self::GreaterEqual { rhs, .. } + | Self::LessEqual { rhs, .. } + | Self::NotEqual { rhs, .. } => vec![rhs], + Self::And(lhs, rhs) | Self::Or(lhs, rhs) | Self::Not(lhs, rhs) => lhs + .typarams_mut() + .into_iter() + .chain(rhs.typarams_mut()) + .collect(), } } } @@ -1058,10 +1269,18 @@ pub enum IntervalOp { } impl IntervalOp { - pub const fn is_closed(&self) -> bool { matches!(self, Self::Closed) } - pub const fn is_left_open(&self) -> bool { matches!(self, Self::LeftOpen | Self::Open) } - pub const fn is_right_open(&self) -> bool { matches!(self, Self::RightOpen | Self::Open) } - pub const fn is_open(&self) -> bool { matches!(self, Self::Open) } + pub const fn is_closed(&self) -> bool { + matches!(self, Self::Closed) + } + pub const fn is_left_open(&self) -> bool { + matches!(self, Self::LeftOpen | Self::Open) + } + pub const fn is_right_open(&self) -> bool { + matches!(self, Self::RightOpen | Self::Open) + } + pub const fn is_open(&self) -> bool { + matches!(self, Self::Open) + } } impl fmt::Display for IntervalOp { @@ -1092,9 +1311,13 @@ impl fmt::Display for ParamTy { } impl ParamTy { - pub const fn new(name: Option, ty: Type) -> Self { Self { name, ty } } + pub const fn new(name: Option, ty: Type) -> Self { + Self { name, ty } + } - pub const fn anonymous(ty: Type) -> Self { Self::new(None, ty) } + pub const fn anonymous(ty: Type) -> Self { + Self::new(None, ty) + } } /// e.g. @@ -1134,15 +1357,25 @@ impl fmt::Display for SubrType { } impl SubrType { - pub fn new(kind: SubrKind, non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - Self{ kind, non_default_params, default_params, return_t: Box::new(return_t) } + pub fn new( + kind: SubrKind, + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + Self { + kind, + non_default_params, + default_params, + return_t: Box::new(return_t), + } } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum RefineKind { - Interval{ min: TyParam, max: TyParam }, // e.g. {I: Int | I >= 2; I <= 10} 2..10 - Enum(Set), // e.g. {I: Int | I == 1 or I == 2} {1, 2} + Interval { min: TyParam, max: TyParam }, // e.g. {I: Int | I >= 2; I <= 10} 2..10 + Enum(Set), // e.g. {I: Int | I == 1 or I == 2} {1, 2} Complex, } @@ -1161,13 +1394,23 @@ pub struct RefinementType { impl fmt::Display for RefinementType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{{{}: {} | {}}}", self.var, self.t, fmt_set_split_with(&self.preds, "; ")) + write!( + f, + "{{{}: {} | {}}}", + self.var, + self.t, + fmt_set_split_with(&self.preds, "; ") + ) } } impl RefinementType { pub fn new(var: Str, t: Type, preds: Set) -> Self { - Self { var, t: Box::new(t), preds } + Self { + var, + t: Box::new(t), + preds, + } } pub fn bound(&self) -> TyBound { @@ -1193,7 +1436,10 @@ impl fmt::Display for QuantifiedType { impl QuantifiedType { pub fn new(unbound_callable: Type, bounds: Set) -> Self { - Self { unbound_callable: Box::new(unbound_callable), bounds } + Self { + unbound_callable: Box::new(unbound_callable), + bounds, + } } } @@ -1204,18 +1450,25 @@ pub enum SubrKind { Func, Proc, FuncMethod(Box), - ProcMethod{ before: Box, after: Option> }, + ProcMethod { + before: Box, + after: Option>, + }, } impl HasLevel for SubrKind { - fn level(&self) -> Option { todo!() } + fn level(&self) -> Option { + todo!() + } fn update_level(&self, level: usize) { match self { Self::FuncMethod(t) => t.update_level(level), - Self::ProcMethod{ before, after } => { + Self::ProcMethod { before, after } => { before.update_level(level); - after.as_ref().map(|t| { t.update_level(level); }); + after.as_ref().map(|t| { + t.update_level(level); + }); } _ => {} } @@ -1224,9 +1477,11 @@ impl HasLevel for SubrKind { fn lift(&self) { match self { Self::FuncMethod(t) => t.lift(), - Self::ProcMethod{ before, after } => { + Self::ProcMethod { before, after } => { before.lift(); - after.as_ref().map(|t| { t.lift(); }); + after.as_ref().map(|t| { + t.lift(); + }); } _ => {} } @@ -1234,23 +1489,28 @@ impl HasLevel for SubrKind { } impl SubrKind { - pub fn fn_met(t: SelfType) -> Self { SubrKind::FuncMethod(Box::new(t)) } + pub fn fn_met(t: SelfType) -> Self { + SubrKind::FuncMethod(Box::new(t)) + } pub fn pr_met(before: SelfType, after: Option) -> Self { - Self::ProcMethod{ before: Box::new(before), after: after.map(Box::new) } + Self::ProcMethod { + before: Box::new(before), + after: after.map(Box::new), + } } pub const fn arrow(&self) -> &str { match self { Self::Func | Self::FuncMethod(_) => "->", - Self::Proc | Self::ProcMethod{ .. } => "=>", + Self::Proc | Self::ProcMethod { .. } => "=>", } } pub const fn inner_len(&self) -> usize { match self { Self::Func | Self::Proc => 0, - Self::FuncMethod(_) | Self::ProcMethod{ .. } => 1, + Self::FuncMethod(_) | Self::ProcMethod { .. } => 1, } } @@ -1258,9 +1518,13 @@ impl SubrKind { match self { Self::Func | Self::Proc => "".to_string(), Self::FuncMethod(t) => format!("{t}."), - Self::ProcMethod{ before, after } => - if let Some(after) = after { format!("({before} ~> {after}).") } - else { format!("{before}.") }, + Self::ProcMethod { before, after } => { + if let Some(after) = after { + format!("({before} ~> {after}).") + } else { + format!("{before}.") + } + } } } @@ -1268,22 +1532,26 @@ impl SubrKind { match self { Self::Func | Self::Proc => false, Self::FuncMethod(t) => t.has_unbound_var(), - Self::ProcMethod{ before, after } => - before.has_unbound_var() || after.as_ref().map(|t| t.has_unbound_var()).unwrap_or(false), + Self::ProcMethod { before, after } => { + before.has_unbound_var() + || after.as_ref().map(|t| t.has_unbound_var()).unwrap_or(false) + } } } pub fn same_kind_as(&self, other: &Self) -> bool { match (self, other) { - (Self::Func, Self::Func) | (Self::Proc, Self::Proc) - | (Self::FuncMethod(_), Self::FuncMethod(_)) | (Self::ProcMethod{ .. }, Self::ProcMethod{ .. }) => true, + (Self::Func, Self::Func) + | (Self::Proc, Self::Proc) + | (Self::FuncMethod(_), Self::FuncMethod(_)) + | (Self::ProcMethod { .. }, Self::ProcMethod { .. }) => true, _ => false, } } pub fn self_t(&self) -> Option<&SelfType> { match self { - Self::FuncMethod(t) | Self::ProcMethod{ before: t, .. } => Some(t), + Self::FuncMethod(t) | Self::ProcMethod { before: t, .. } => Some(t), _ => None, } } @@ -1297,21 +1565,39 @@ pub enum Ownership { } impl Ownership { - pub const fn is_owned(&self) -> bool { matches!(self, Self::Owned) } - pub const fn is_ref(&self) -> bool { matches!(self, Self::Ref) } - pub const fn is_refmut(&self) -> bool { matches!(self, Self::RefMut) } + pub const fn is_owned(&self) -> bool { + matches!(self, Self::Owned) + } + pub const fn is_ref(&self) -> bool { + matches!(self, Self::Ref) + } + pub const fn is_refmut(&self) -> bool { + matches!(self, Self::RefMut) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ArgsOwnership { - Args{ self_: Option, non_defaults: Vec, defaults: Vec }, + Args { + self_: Option, + non_defaults: Vec, + defaults: Vec, + }, VarArgs(Ownership), // TODO: defaults VarArgsDefault(Ownership), } impl ArgsOwnership { - pub const fn args(self_: Option, non_defaults: Vec, defaults: Vec) -> Self { - Self::Args{ self_, non_defaults, defaults } + pub const fn args( + self_: Option, + non_defaults: Vec, + defaults: Vec, + ) -> Self { + Self::Args { + self_, + non_defaults, + defaults, + } } } @@ -1342,7 +1628,7 @@ pub enum Type { Module, Frame, Error, - Inf, // {∞} + Inf, // {∞} NegInf, // {-∞} // TODO: PolyType/Class Type, @@ -1358,8 +1644,8 @@ pub enum Type { ArrayCommon, DictCommon, NotImplemented, - Ellipsis, // これはクラスのほうで型推論用のマーカーではない - Never, // {} + Ellipsis, // これはクラスのほうで型推論用のマーカーではない + Never, // {} Mono(Str), // others /* Polymorphic types */ Range(Box), @@ -1370,11 +1656,20 @@ pub enum Type { OptionMut(Box), Subr(SubrType), // CallableはProcの上位型なので、変数に!をつける - Callable{ param_ts: Vec, return_t: Box }, + Callable { + param_ts: Vec, + return_t: Box, + }, // e.g. [Int] == Array{ t: Int, len: _ }, [Int; 3] == Array { t: Int, len: 3 } - Array{ t: Box, len: TyParam }, + Array { + t: Box, + len: TyParam, + }, // TODO: heterogeneous dict - Dict{ k: Box, v: Box }, + Dict { + k: Box, + v: Box, + }, Tuple(Vec), Record(Dict), // e.g. {x = Int} // e.g. {T -> T | T: Type}, {I: Int | I > 0}, {S | N: Nat; S: Str N; N > 1} @@ -1390,14 +1685,23 @@ pub enum Type { Not(Vec), Or(Vec), VarArgs(Box), // ...T - Poly{ name: Str, params: Vec }, // T(params) + Poly { + name: Str, + params: Vec, + }, // T(params) /* Special types (inference-time types) */ MonoQVar(Str), // QuantifiedTyの中で使う一般化型変数、利便性のためMonoとは区別する - PolyQVar{ name: Str, params: Vec }, + PolyQVar { + name: Str, + params: Vec, + }, FreeVar(FreeTyVar), // a reference to the type of other expression, see docs/compiler/inference.md - MonoProj{ lhs: Box, rhs: Str }, // e.g. T.U - ASTOmitted, // call中のcalleeの型など、不要な部分に付ける - Failure, // when failed to infer + MonoProj { + lhs: Box, + rhs: Str, + }, // e.g. T.U + ASTOmitted, // call中のcalleeの型など、不要な部分に付ける + Failure, // when failed to infer } impl fmt::Display for Type { @@ -1412,30 +1716,32 @@ impl fmt::Display for Type { Self::Option(t) => write!(f, "Option({t})"), Self::OptionMut(t) => write!(f, "Option!({t})"), Self::Subr(sub) => write!(f, "{sub}"), - Self::Callable{ param_ts, return_t } => { + Self::Callable { param_ts, return_t } => { write!(f, "Callable(({}), {return_t})", fmt_vec(param_ts)) } - Self::Array{ t, len } => write!(f, "[{t}; {len}]"), - Self::Dict{ k, v } => write!(f, "{{{k}: {v}}}"), + Self::Array { t, len } => write!(f, "[{t}; {len}]"), + Self::Dict { k, v } => write!(f, "{{{k}: {v}}}"), Self::Tuple(ts) => write!(f, "({})", fmt_vec(ts)), Self::Record(attrs) => write!(f, "{{{attrs}}}"), Self::Refinement(refinement) => write!(f, "{}", refinement), Self::Quantified(quantified) => write!(f, "{}", quantified), Self::And(types) => write!(f, "{}", fmt_vec_split_with(types, " and ")), Self::Not(types) => write!(f, "{}", fmt_vec_split_with(types, " not ")), - Self::Or(types) => write!(f, "{}", fmt_vec_split_with(types, " or ")), + Self::Or(types) => write!(f, "{}", fmt_vec_split_with(types, " or ")), Self::VarArgs(t) => write!(f, "...{t}"), - Self::Poly{ name, params } => write!(f, "{name}({})", fmt_vec(params)), + Self::Poly { name, params } => write!(f, "{name}({})", fmt_vec(params)), Self::MonoQVar(name) => write!(f, "'{name}"), Self::FreeVar(v) => write!(f, "{v}"), - Self::MonoProj{ lhs, rhs } => write!(f, "{lhs}.{rhs}"), + Self::MonoProj { lhs, rhs } => write!(f, "{lhs}.{rhs}"), _ => write!(f, "{}", self.name()), } } } impl Default for Type { - fn default() -> Self { Self::Failure } + fn default() -> Self { + Self::Failure + } } impl From> for Type { @@ -1503,33 +1809,33 @@ impl From<&str> for Type { impl HasType for Type { #[inline] - fn ref_t(&self) -> &Type { self } + fn ref_t(&self) -> &Type { + self + } fn inner_ts(&self) -> Vec { match self { Self::RangeCommon => vec![Type::Int], - Self::Dict{k, v} => vec![ - k.as_ref().clone(), - v.as_ref().clone() - ], + Self::Dict { k, v } => vec![k.as_ref().clone(), v.as_ref().clone()], Self::Ref(t) | Self::RefMut(t) | Self::Option(t) | Self::OptionMut(t) | Self::Range(t) | Self::Iter(t) - | Self::Array{ t, .. } + | Self::Array { t, .. } | Self::VarArgs(t) => vec![t.as_ref().clone()], // Self::And(ts) | Self::Or(ts) => , Self::Subr(_sub) => todo!(), - | Self::Callable{ param_ts, .. } - | Self::Tuple(param_ts) => param_ts.clone(), - Self::Poly{ .. } => { + Self::Callable { param_ts, .. } | Self::Tuple(param_ts) => param_ts.clone(), + Self::Poly { .. } => { todo!() - }, + } _ => vec![], } } - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl HasLevel for Type { @@ -1550,9 +1856,9 @@ impl HasLevel for Type { | Self::OptionMut(t) | Self::Range(t) | Self::Iter(t) - | Self::Array{ t, .. } + | Self::Array { t, .. } | Self::VarArgs(t) => t.update_level(level), - Self::Callable{ param_ts, return_t } => { + Self::Callable { param_ts, return_t } => { for p in param_ts.iter() { p.update_level(level); } @@ -1560,37 +1866,37 @@ impl HasLevel for Type { } Self::Subr(subr) => { subr.kind.update_level(level); - for p in subr.non_default_params.iter() - .chain(subr.default_params.iter()) { + for p in subr + .non_default_params + .iter() + .chain(subr.default_params.iter()) + { p.ty.update_level(level); } subr.return_t.update_level(level); } - Self::And(ts) - | Self::Or(ts) - | Self::Not(ts) - | Self::Tuple(ts) => { + Self::And(ts) | Self::Or(ts) | Self::Not(ts) | Self::Tuple(ts) => { for t in ts.iter() { t.update_level(level); } - }, - Self::Dict{ k, v } => { + } + Self::Dict { k, v } => { k.update_level(level); v.update_level(level); - }, + } Self::Record(attrs) => { for t in attrs.values() { t.update_level(level); } - }, - Self::Poly{ params, .. } => { + } + Self::Poly { params, .. } => { for p in params.iter() { p.update_level(level); } - }, - Self::MonoProj{ lhs, .. } => { + } + Self::MonoProj { lhs, .. } => { lhs.update_level(level); - }, + } Self::Refinement(refine) => { refine.t.update_level(level); for pred in refine.preds.iter() { @@ -1603,7 +1909,7 @@ impl HasLevel for Type { bound.update_level(level); } } - _ => {}, + _ => {} } } @@ -1616,9 +1922,9 @@ impl HasLevel for Type { | Self::OptionMut(t) | Self::Range(t) | Self::Iter(t) - | Self::Array{ t, .. } + | Self::Array { t, .. } | Self::VarArgs(t) => t.lift(), - Self::Callable{ param_ts, return_t } => { + Self::Callable { param_ts, return_t } => { for p in param_ts.iter() { p.lift(); } @@ -1626,35 +1932,37 @@ impl HasLevel for Type { } Self::Subr(subr) => { subr.kind.lift(); - for p in subr.non_default_params.iter() - .chain(subr.default_params.iter()) { + for p in subr + .non_default_params + .iter() + .chain(subr.default_params.iter()) + { p.ty.lift(); } subr.return_t.lift(); } - Self::And(ts) - | Self::Or(ts) - | Self::Not(ts) - | Self::Tuple(ts) => { + Self::And(ts) | Self::Or(ts) | Self::Not(ts) | Self::Tuple(ts) => { for t in ts.iter() { t.lift(); } - }, - Self::Dict{ k, v } => { + } + Self::Dict { k, v } => { k.lift(); v.lift(); - }, + } Self::Record(attrs) => { for t in attrs.values() { t.lift(); } - }, - Self::Poly{ params, .. } => { + } + Self::Poly { params, .. } => { for p in params.iter() { p.lift(); } - }, - Self::MonoProj{ lhs, .. } => { lhs.lift(); }, + } + Self::MonoProj { lhs, .. } => { + lhs.lift(); + } Self::Refinement(refine) => { refine.t.lift(); for pred in refine.preds.iter() { @@ -1667,7 +1975,7 @@ impl HasLevel for Type { bound.lift(); } } - _ => {}, + _ => {} } } } @@ -1684,10 +1992,14 @@ impl Type { /// Top := {=} #[allow(non_snake_case)] - pub const fn Top() -> Self { Self::Mono(Str::ever("Top")) } + pub const fn Top() -> Self { + Self::Mono(Str::ever("Top")) + } /// Bottom := {} #[allow(non_snake_case)] - pub const fn Bottom() -> Self { Self::Mono(Str::ever("Bottom")) } + pub const fn Bottom() -> Self { + Self::Mono(Str::ever("Bottom")) + } #[inline] pub fn free_var(level: usize, constraint: Constraint) -> Self { @@ -1700,23 +2012,36 @@ impl Type { } #[inline] - pub fn array(elem_t: Type, len: TyParam) -> Self { Self::Array{ t: Box::new(elem_t), len } } - - #[inline] - pub fn dict(k_t: Type, v_t: Type) -> Self { - Self::Dict{ k: Box::new(k_t), v: Box::new(v_t) } + pub fn array(elem_t: Type, len: TyParam) -> Self { + Self::Array { + t: Box::new(elem_t), + len, + } } #[inline] - pub fn var_args(elem_t: Type) -> Self { Self::VarArgs(Box::new(elem_t)) } + pub fn dict(k_t: Type, v_t: Type) -> Self { + Self::Dict { + k: Box::new(k_t), + v: Box::new(v_t), + } + } #[inline] - pub fn range(t: Type) -> Self { Self::Range(Box::new(t)) } + pub fn var_args(elem_t: Type) -> Self { + Self::VarArgs(Box::new(elem_t)) + } + + #[inline] + pub fn range(t: Type) -> Self { + Self::Range(Box::new(t)) + } pub fn enum_t(s: Set) -> Self { assert!(s.is_homogeneous()); let name = Str::from(fresh_varname()); - let preds = s.iter() + let preds = s + .iter() .map(|o| Predicate::eq(name.clone(), TyParam::value(o.clone()))) .collect(); let refine = RefinementType::new(name, s.inner_class(), preds); @@ -1735,65 +2060,118 @@ impl Type { // l<..r => {I: classof(l) | I >= l+ε and I <= r} IntervalOp::LeftOpen => Predicate::and( Predicate::ge(name.clone(), TyParam::succ(l)), - Predicate::le(name.clone(), r) + Predicate::le(name.clone(), r), ), IntervalOp::RightOpen if r == TyParam::value(Inf) => Predicate::ge(name.clone(), l), // l.. {I: classof(l) | I >= l and I <= r-ε} IntervalOp::RightOpen => Predicate::and( Predicate::ge(name.clone(), l), - Predicate::le(name.clone(), TyParam::pred(r)) + Predicate::le(name.clone(), TyParam::pred(r)), ), // l..r => {I: classof(l) | I >= l and I <= r} IntervalOp::Closed => Predicate::and( Predicate::ge(name.clone(), l), - Predicate::le(name.clone(), r) + 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.clone(), Type::Int, set! {}) + } // l<.. {I: classof(l) | I >= l+ε and I <= r-ε} IntervalOp::Open => Predicate::and( Predicate::ge(name.clone(), TyParam::succ(l)), - 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.clone(), Type::Int, set! {pred}) } - pub fn iter(t: Type) -> Self { Self::Iter(Box::new(t)) } - - pub fn refer(t: Type) -> Self { Self::Ref(Box::new(t)) } - - pub fn ref_mut(t: Type) -> Self { Self::RefMut(Box::new(t)) } - - pub fn option(t: Type) -> Self { Self::Option(Box::new(t)) } - - pub fn option_mut(t: Type) -> Self { Self::OptionMut(Box::new(t)) } - - pub fn subr(kind: SubrKind, non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - Self::Subr(SubrType::new(kind, non_default_params, default_params, return_t)) + pub fn iter(t: Type) -> Self { + Self::Iter(Box::new(t)) } - pub fn func(non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - Self::Subr(SubrType::new(SubrKind::Func, non_default_params, default_params, return_t)) + pub fn refer(t: Type) -> Self { + Self::Ref(Box::new(t)) } - pub fn func1(param_t: Type, return_t: Type) -> Self { Self::func(vec![ParamTy::anonymous(param_t)], vec![], return_t) } + pub fn ref_mut(t: Type) -> Self { + Self::RefMut(Box::new(t)) + } - pub fn kind1(param: Type) -> Self { Self::func1(param, Type::Type) } + pub fn option(t: Type) -> Self { + Self::Option(Box::new(t)) + } + + pub fn option_mut(t: Type) -> Self { + Self::OptionMut(Box::new(t)) + } + + pub fn subr( + kind: SubrKind, + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + Self::Subr(SubrType::new( + kind, + non_default_params, + default_params, + return_t, + )) + } + + pub fn func( + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + Self::Subr(SubrType::new( + SubrKind::Func, + non_default_params, + default_params, + return_t, + )) + } + + pub fn func1(param_t: Type, return_t: Type) -> Self { + Self::func(vec![ParamTy::anonymous(param_t)], vec![], return_t) + } + + pub fn kind1(param: Type) -> Self { + Self::func1(param, Type::Type) + } pub fn func2(l: Type, r: Type, return_t: Type) -> Self { - Self::func(vec![ParamTy::anonymous(l), ParamTy::anonymous(r)], vec![], return_t) + Self::func( + vec![ParamTy::anonymous(l), ParamTy::anonymous(r)], + vec![], + return_t, + ) } - pub fn anon_param_func(non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - let non_default_params = non_default_params.into_iter().map(ParamTy::anonymous).collect(); + pub fn anon_param_func( + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + let non_default_params = non_default_params + .into_iter() + .map(ParamTy::anonymous) + .collect(); let default_params = default_params.into_iter().map(ParamTy::anonymous).collect(); Self::func(non_default_params, default_params, return_t) } - pub fn proc(non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - Self::Subr(SubrType::new(SubrKind::Proc, non_default_params, default_params, return_t)) + pub fn proc( + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + Self::Subr(SubrType::new( + SubrKind::Proc, + non_default_params, + default_params, + return_t, + )) } pub fn proc1(param_t: Type, return_t: Type) -> Self { @@ -1801,17 +2179,38 @@ impl Type { } pub fn proc2(l: Type, r: Type, return_t: Type) -> Self { - Self::proc(vec![ParamTy::anonymous(l), ParamTy::anonymous(r)], vec![], return_t) + Self::proc( + vec![ParamTy::anonymous(l), ParamTy::anonymous(r)], + vec![], + return_t, + ) } - pub fn anon_param_proc(non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - let non_default_params = non_default_params.into_iter().map(ParamTy::anonymous).collect(); + pub fn anon_param_proc( + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + let non_default_params = non_default_params + .into_iter() + .map(ParamTy::anonymous) + .collect(); let default_params = default_params.into_iter().map(ParamTy::anonymous).collect(); Self::proc(non_default_params, default_params, return_t) } - pub fn fn_met(self_t: Type, non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - Self::Subr(SubrType::new(SubrKind::FuncMethod(Box::new(self_t)), non_default_params, default_params, return_t)) + pub fn fn_met( + self_t: Type, + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + Self::Subr(SubrType::new( + SubrKind::FuncMethod(Box::new(self_t)), + non_default_params, + default_params, + return_t, + )) } pub fn fn0_met(self_t: Type, return_t: Type) -> Self { @@ -1819,31 +2218,76 @@ impl Type { } pub fn fn1_met(self_t: Type, input_t: Type, return_t: Type) -> Self { - Self::fn_met(self_t, vec![ParamTy::anonymous(input_t)], vec![], return_t) + Self::fn_met(self_t, vec![ParamTy::anonymous(input_t)], vec![], return_t) } - pub fn anon_param_fn_met(self_t: Type, non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - let non_default_params = non_default_params.into_iter().map(ParamTy::anonymous).collect(); + pub fn anon_param_fn_met( + self_t: Type, + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + let non_default_params = non_default_params + .into_iter() + .map(ParamTy::anonymous) + .collect(); let default_params = default_params.into_iter().map(ParamTy::anonymous).collect(); Self::fn_met(self_t, non_default_params, default_params, return_t) } - pub fn pr_met(self_before: Type, self_after: Option, non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - Self::Subr(SubrType::new(SubrKind::pr_met(self_before, self_after), non_default_params, default_params, return_t)) + pub fn pr_met( + self_before: Type, + self_after: Option, + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + Self::Subr(SubrType::new( + SubrKind::pr_met(self_before, self_after), + non_default_params, + default_params, + return_t, + )) } pub fn pr0_met(self_before: Type, self_after: Option, return_t: Type) -> Self { Self::pr_met(self_before, self_after, vec![], vec![], return_t) } - pub fn pr1_met(self_before: Type, self_after: Option, input_t: Type, return_t: Type) -> Self { - Self::pr_met(self_before, self_after, vec![ParamTy::anonymous(input_t)], vec![], return_t) + pub fn pr1_met( + self_before: Type, + self_after: Option, + input_t: Type, + return_t: Type, + ) -> Self { + Self::pr_met( + self_before, + self_after, + vec![ParamTy::anonymous(input_t)], + vec![], + return_t, + ) } - pub fn anon_param_pr_met(self_before: Type, self_after: Option, non_default_params: Vec, default_params: Vec, return_t: Type) -> Self { - let non_default_params = non_default_params.into_iter().map(ParamTy::anonymous).collect(); + pub fn anon_param_pr_met( + self_before: Type, + self_after: Option, + non_default_params: Vec, + default_params: Vec, + return_t: Type, + ) -> Self { + let non_default_params = non_default_params + .into_iter() + .map(ParamTy::anonymous) + .collect(); let default_params = default_params.into_iter().map(ParamTy::anonymous).collect(); - Self::pr_met(self_before, self_after, non_default_params, default_params, return_t) + Self::pr_met( + self_before, + self_after, + non_default_params, + default_params, + return_t, + ) } /// function type with non-default parameters @@ -1858,28 +2302,44 @@ impl Type { } pub fn callable(param_ts: Vec, return_t: Type) -> Self { - Self::Callable{ param_ts, return_t: Box::new(return_t) } + Self::Callable { + param_ts, + return_t: Box::new(return_t), + } } #[inline] - pub fn mono>(name: S) -> Self { Self::Mono(name.into()) } + pub fn mono>(name: S) -> Self { + Self::Mono(name.into()) + } #[inline] - pub fn mono_q>(name: S) -> Self { Self::MonoQVar(name.into()) } + pub fn mono_q>(name: S) -> Self { + Self::MonoQVar(name.into()) + } #[inline] pub fn poly>(name: S, params: Vec) -> Self { - Self::Poly{ name: name.into(), params } + Self::Poly { + name: name.into(), + params, + } } #[inline] pub fn poly_q>(name: S, params: Vec) -> Self { - Self::PolyQVar{ name: name.into(), params } + Self::PolyQVar { + name: name.into(), + params, + } } #[inline] pub fn mono_proj>(lhs: Type, rhs: S) -> Self { - Self::MonoProj{ lhs: Box::new(lhs), rhs: rhs.into() } + Self::MonoProj { + lhs: Box::new(lhs), + rhs: rhs.into(), + } } /// ```rust @@ -1909,19 +2369,20 @@ impl Type { Self::Bool => Self::BoolMut, Self::Str => Self::StrMut, Self::Option(t) => Self::OptionMut(t), - Self::Array{ t, len } => - Self::poly("Array!", vec![TyParam::t(*t), len.mutate()]), + Self::Array { t, len } => Self::poly("Array!", vec![TyParam::t(*t), len.mutate()]), _ => todo!(), } } pub fn is_mut(&self) -> bool { match self { - Self::FreeVar(fv) => if fv.is_linked() { - fv.crack().is_mut() - } else { - fv.unbound_name().unwrap().ends_with("!") - }, + Self::FreeVar(fv) => { + if fv.is_linked() { + fv.crack().is_mut() + } else { + fv.unbound_name().unwrap().ends_with("!") + } + } Self::IntMut | Self::NatMut | Self::RatioMut @@ -1941,8 +2402,7 @@ impl Type { pub fn is_nonelike(&self) -> bool { match self { Self::NoneType => true, - Self::Option(t) - | Self::OptionMut(t) => t.is_nonelike(), + Self::Option(t) | Self::OptionMut(t) => t.is_nonelike(), Self::Tuple(ts) => ts.len() == 0, _ => false, } @@ -1957,7 +2417,7 @@ impl Type { let ownership = match &nd_param.ty { Self::Ref(_) => Ownership::Ref, Self::RefMut(_) => Ownership::RefMut, - Self::VarArgs(t) => { return ArgsOwnership::VarArgs(t.ownership()) }, + Self::VarArgs(t) => return ArgsOwnership::VarArgs(t.ownership()), _ => Ownership::Owned, }; nd_args.push(ownership); @@ -1967,13 +2427,13 @@ impl Type { let ownership = match &d_param.ty { Self::Ref(_) => Ownership::Ref, Self::RefMut(_) => Ownership::RefMut, - Self::VarArgs(t) => { return ArgsOwnership::VarArgsDefault(t.ownership()) }, + Self::VarArgs(t) => return ArgsOwnership::VarArgsDefault(t.ownership()), _ => Ownership::Owned, }; d_args.push(ownership); } ArgsOwnership::args(self_, nd_args, d_args) - }, + } _ => todo!(), } } @@ -1988,8 +2448,7 @@ impl Type { pub fn rec_eq(&self, other: &Self) -> bool { match (self, other) { - (Self::FreeVar(v), other) - | (other, Self::FreeVar(v)) => match &*v.borrow() { + (Self::FreeVar(v), other) | (other, Self::FreeVar(v)) => match &*v.borrow() { FreeKind::Linked(t) => t.rec_eq(other), _ => self == other, }, @@ -2001,53 +2460,96 @@ impl Type { | (Self::OptionMut(l), Self::OptionMut(r)) => l.rec_eq(r), (Self::Subr(l), Self::Subr(r)) => { match (&l.kind, &r.kind) { - (SubrKind::Func, SubrKind::Func) - | (SubrKind::Proc, SubrKind::Proc) => {}, - (SubrKind::FuncMethod(l), SubrKind::FuncMethod(r)) if !l.rec_eq(r.as_ref()) => { return false }, - (SubrKind::ProcMethod{ before, after }, SubrKind::ProcMethod{ before: rbefore, after: rafter }) - if !before.rec_eq(rbefore.as_ref()) - || !after.as_ref().zip(rafter.as_ref()).map(|(l, r)| l.rec_eq(r)).unwrap_or(false) => { return false }, - _ => { return false }, + (SubrKind::Func, SubrKind::Func) | (SubrKind::Proc, SubrKind::Proc) => {} + (SubrKind::FuncMethod(l), SubrKind::FuncMethod(r)) if !l.rec_eq(r.as_ref()) => { + return false + } + ( + SubrKind::ProcMethod { before, after }, + SubrKind::ProcMethod { + before: rbefore, + after: rafter, + }, + ) if !before.rec_eq(rbefore.as_ref()) + || !after + .as_ref() + .zip(rafter.as_ref()) + .map(|(l, r)| l.rec_eq(r)) + .unwrap_or(false) => + { + return false + } + _ => return false, + } + if !l + .default_params + .iter() + .zip(r.default_params.iter()) + .all(|(l, r)| l.name == r.name && l.ty.rec_eq(&r.ty)) + { + return false; + } + if !l + .non_default_params + .iter() + .zip(r.non_default_params.iter()) + .all(|(l, r)| l.name == r.name && l.ty.rec_eq(&r.ty)) + { + return false; } - if !l.default_params.iter().zip(r.default_params.iter()).all(|(l, r)| { - l.name == r.name && l.ty.rec_eq(&r.ty) - }) { return false } - if !l.non_default_params.iter().zip(r.non_default_params.iter()).all(|(l, r)| { - l.name == r.name && l.ty.rec_eq(&r.ty) - }) { return false } l.return_t.rec_eq(&r.return_t) - }, + } ( - Self::Callable{ param_ts: _lps, return_t: _lr }, - Self::Callable{ param_ts: _rps, return_t: _rr }, + Self::Callable { + param_ts: _lps, + return_t: _lr, + }, + Self::Callable { + param_ts: _rps, + return_t: _rr, + }, ) => todo!(), - ( - Self::Array{ t: lt, len: ll}, - Self::Array{ t: rt, len: rl } - ) => lt.rec_eq(rt) && ll.rec_eq(rl), - ( - Self::Dict{ k: lk, v: lv }, - Self::Dict{ k: rk, v: rv } - ) => lk.rec_eq(rk) && lv.rec_eq(rv), + (Self::Array { t: lt, len: ll }, Self::Array { t: rt, len: rl }) => { + lt.rec_eq(rt) && ll.rec_eq(rl) + } + (Self::Dict { k: lk, v: lv }, Self::Dict { k: rk, v: rv }) => { + lk.rec_eq(rk) && lv.rec_eq(rv) + } (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 - }, + } (Self::Tuple(l), Self::Tuple(r)) | (Self::And(l), Self::And(r)) | (Self::Not(l), Self::Not(r)) | (Self::Or(l), Self::Or(r)) => l.iter().zip(r.iter()).all(|(l, r)| l.rec_eq(r)), (Self::VarArgs(l), Self::VarArgs(r)) => l.rec_eq(r), ( - Self::Poly{ name: ln, params: lps } | Self::PolyQVar{ name: ln, params: lps }, - Self::Poly{ name: rn, params: rps } | Self::PolyQVar{ name: rn, params: rps }, + Self::Poly { + name: ln, + params: lps, + } + | Self::PolyQVar { + name: ln, + params: lps, + }, + Self::Poly { + name: rn, + params: rps, + } + | Self::PolyQVar { + name: rn, + params: rps, + }, ) => ln == rn && lps.iter().zip(rps.iter()).all(|(l, r)| l.rec_eq(r)), - (Self::MonoProj{ lhs, rhs }, Self::MonoProj{ lhs: rlhs, rhs: rrhs }) => { - lhs.rec_eq(rlhs) && rhs == rrhs - }, + ( + Self::MonoProj { lhs, rhs }, + Self::MonoProj { + lhs: rlhs, + rhs: rrhs, + }, + ) => lhs.rec_eq(rlhs) && rhs == rrhs, _ => self == other, } } @@ -2055,14 +2557,15 @@ impl Type { /// 共通部分(A and B)を返す /// 型同士の包含関係はここでは検査しない(TypeCheckerでする) pub fn intersection(lhs: &Self, rhs: &Self) -> Self { - if lhs == rhs { return lhs.clone() } + if lhs == rhs { + return lhs.clone(); + } match (lhs, rhs) { // { .i: Int } and { .s: Str } == { .i: Int, .s: Str } - (Self::Record(l), Self::Record(r)) => { - Self::Record(l.clone().concat(r.clone())) + (Self::Record(l), Self::Record(r)) => Self::Record(l.clone().concat(r.clone())), + (Self::And(ts), t) | (t, Self::And(ts)) => { + Self::And([vec![t.clone()], ts.clone()].concat()) } - (Self::And(ts), t) - | (t, Self::And(ts)) => Self::And([vec![t.clone()], ts.clone()].concat()), (t, Self::Obj) | (Self::Obj, t) => t.clone(), (_, Self::Never) | (Self::Never, _) => Self::Never, (l, r) => Self::And(vec![l.clone(), r.clone()]), @@ -2096,8 +2599,7 @@ impl Type { Self::Error => "Error", Self::Inf => "Inf", Self::NegInf => "NegInf", - Self::Mono(name) - | Self::MonoQVar(name) => name, + Self::Mono(name) | Self::MonoQVar(name) => name, Self::Range(_) | Self::RangeCommon => "Range", Self::Iter(_) => "Iter", Self::And(_) => "And", @@ -2107,26 +2609,41 @@ impl Type { Self::RefMut(_) => "Ref!", Self::Option(_) => "Option", Self::OptionMut(_) => "Option!", - Self::Subr(SubrType{ kind: SubrKind::Func, .. }) | Self::FuncCommon => "Func", - Self::Subr(SubrType{ kind: SubrKind::Proc, .. }) | Self::ProcCommon => "Proc", - Self::Subr(SubrType{ kind: SubrKind::FuncMethod(_), .. }) | Self::FuncMethodCommon => "FuncMethod", - Self::Subr(SubrType{ kind: SubrKind::ProcMethod{ .. }, .. }) | Self::ProcMethodCommon => "ProcMethod", - Self::Callable{ .. } | Self::CallableCommon => "Callable", - Self::Array{ .. } | Self::ArrayCommon => "Array", - Self::Dict{ .. } | Self::DictCommon => "Dict", + Self::Subr(SubrType { + kind: SubrKind::Func, + .. + }) + | Self::FuncCommon => "Func", + Self::Subr(SubrType { + kind: SubrKind::Proc, + .. + }) + | Self::ProcCommon => "Proc", + Self::Subr(SubrType { + kind: SubrKind::FuncMethod(_), + .. + }) + | Self::FuncMethodCommon => "FuncMethod", + Self::Subr(SubrType { + kind: SubrKind::ProcMethod { .. }, + .. + }) + | Self::ProcMethodCommon => "ProcMethod", + Self::Callable { .. } | Self::CallableCommon => "Callable", + Self::Array { .. } | Self::ArrayCommon => "Array", + Self::Dict { .. } | Self::DictCommon => "Dict", Self::Tuple(..) => "Tuple", 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::Refinement(refine) => refine.t.name(), Self::Quantified(_) => "Quantified", Self::Ellipsis => "Ellipsis", Self::NotImplemented => "NotImplemented", Self::Never => "Never", Self::FreeVar(_) => "?", // TODO: 中身がSomeなら表示したい - Self::MonoProj{ .. } => "MonoProj", + Self::MonoProj { .. } => "MonoProj", Self::ASTOmitted => "ASTOmitted", Self::Failure => "", } @@ -2136,18 +2653,27 @@ impl Type { matches!(self, Self::FreeVar(_)) } - pub const fn is_varargs(&self) -> bool { matches!(self, Self::VarArgs(_)) } + pub const fn is_varargs(&self) -> bool { + matches!(self, Self::VarArgs(_)) + } - pub fn is_monomorphic(&self) -> bool { self.typaram_len() == 0 } + pub fn is_monomorphic(&self) -> bool { + self.typaram_len() == 0 + } pub const fn is_callable(&self) -> bool { - matches!(self, Self::Subr{ .. } | Self::Callable{ .. }) + matches!(self, Self::Subr { .. } | Self::Callable { .. }) } pub fn has_unbound_var(&self) -> bool { match self { - Self::FreeVar(fv) => - if fv.is_unbound() { true } else { fv.crack().has_unbound_var() }, + Self::FreeVar(fv) => { + if fv.is_unbound() { + true + } else { + fv.crack().has_unbound_var() + } + } Self::Range(t) | Self::Iter(t) | Self::Ref(t) @@ -2155,51 +2681,56 @@ impl Type { | Self::Option(t) | Self::OptionMut(t) | Self::VarArgs(t) => t.has_unbound_var(), - Self::And(param_ts) - | Self::Not(param_ts) - | Self::Or(param_ts) => param_ts.iter().any(|t| t.has_unbound_var()), - Self::Array{ t, len } => t.has_unbound_var() || len.has_unbound_var(), - Self::Dict{ k, v } => k.has_unbound_var() || v.has_unbound_var(), - Self::Callable{ param_ts, return_t } => { + Self::And(param_ts) | Self::Not(param_ts) | Self::Or(param_ts) => { + param_ts.iter().any(|t| t.has_unbound_var()) + } + Self::Array { t, len } => t.has_unbound_var() || len.has_unbound_var(), + Self::Dict { k, v } => k.has_unbound_var() || v.has_unbound_var(), + Self::Callable { param_ts, return_t } => { param_ts.iter().any(|t| t.has_unbound_var()) || return_t.has_unbound_var() - }, + } Self::Subr(subr) => { subr.kind.has_unbound_var() - || subr.non_default_params.iter().any(|p| p.ty.has_unbound_var()) - || subr.default_params.iter().any(|p| p.ty.has_unbound_var()) - || subr.return_t.has_unbound_var() - }, + || subr + .non_default_params + .iter() + .any(|p| p.ty.has_unbound_var()) + || subr.default_params.iter().any(|p| p.ty.has_unbound_var()) + || subr.return_t.has_unbound_var() + } Self::Record(r) => r.values().any(|t| t.has_unbound_var()), - Self::Refinement(refine) => - refine.t.has_unbound_var() - || refine.preds.iter().any(|p| p.has_unbound_var()), - Self::Quantified(quant) => + Self::Refinement(refine) => { + refine.t.has_unbound_var() || refine.preds.iter().any(|p| p.has_unbound_var()) + } + Self::Quantified(quant) => { quant.unbound_callable.has_unbound_var() - || quant.bounds.iter().any(|b| b.has_unbound_var()), - Self::Poly{ params, .. } - | Self::PolyQVar{ params, .. }=> params.iter().any(|p| p.has_unbound_var()), - Self::MonoProj{ lhs, .. } => lhs.has_no_unbound_var(), + || quant.bounds.iter().any(|b| b.has_unbound_var()) + } + Self::Poly { params, .. } | Self::PolyQVar { params, .. } => { + params.iter().any(|p| p.has_unbound_var()) + } + Self::MonoProj { lhs, .. } => lhs.has_no_unbound_var(), _ => false, } } - pub fn has_no_unbound_var(&self) -> bool { !self.has_unbound_var() } + pub fn has_no_unbound_var(&self) -> bool { + !self.has_unbound_var() + } pub fn typaram_len(&self) -> usize { match self { - Self::Range(_) - | Self::Iter(_) - | Self::Option(_) - | Self::OptionMut(_) => 1, - Self::Array{ .. } | Self::Dict{ .. } => 2, - Self::And(param_ts) - | Self::Or(param_ts) - | Self::Tuple(param_ts) => param_ts.len() + 1, - Self::Subr(subr) => - subr.kind.inner_len() + subr.non_default_params.len() + subr.default_params.len() + 1, - Self::Callable{ param_ts, .. } => param_ts.len() + 1, - Self::Poly{ params, .. } - | Self::PolyQVar{ params, .. } => params.len(), + Self::Range(_) | Self::Iter(_) | Self::Option(_) | Self::OptionMut(_) => 1, + Self::Array { .. } | Self::Dict { .. } => 2, + Self::And(param_ts) | Self::Or(param_ts) | Self::Tuple(param_ts) => param_ts.len() + 1, + Self::Subr(subr) => { + subr.kind.inner_len() + + subr.non_default_params.len() + + subr.default_params.len() + + 1 + } + Self::Callable { param_ts, .. } => param_ts.len() + 1, + Self::Poly { params, .. } | Self::PolyQVar { params, .. } => params.len(), _ => 0, } } @@ -2214,35 +2745,50 @@ impl Type { | Self::RefMut(t) | Self::Option(t) | Self::OptionMut(t) => vec![TyParam::t(*t.clone())], - Self::Array{ t, len } => vec![TyParam::t(*t.clone()), len.clone()], - Self::Dict{ k, v } => vec![TyParam::t(*k.clone()), TyParam::t(*v.clone())], + Self::Array { t, len } => vec![TyParam::t(*t.clone()), len.clone()], + Self::Dict { k, v } => vec![TyParam::t(*k.clone()), TyParam::t(*v.clone())], Self::And(param_ts) | Self::Or(param_ts) | Self::Not(param_ts) | Self::Tuple(param_ts) => param_ts.iter().map(|t| TyParam::t(t.clone())).collect(), - Self::Subr(subr) => if let Some(self_t) = subr.kind.self_t() { - [ - vec![TyParam::t(self_t.clone())], - subr.non_default_params.iter().map(|t| TyParam::t(t.ty.clone())).collect(), - subr.default_params.iter().map(|t| TyParam::t(t.ty.clone())).collect(), - ].concat() - } else { - [ - subr.non_default_params.iter().map(|t| TyParam::t(t.ty.clone())).collect::>(), - subr.default_params.iter().map(|t| TyParam::t(t.ty.clone())).collect(), - ].concat() - }, - Self::Callable{ param_ts: _, .. } => todo!(), - Self::Poly{ params, .. } - | Self::PolyQVar{ params, .. } => params.clone(), + Self::Subr(subr) => { + if let Some(self_t) = subr.kind.self_t() { + [ + vec![TyParam::t(self_t.clone())], + subr.non_default_params + .iter() + .map(|t| TyParam::t(t.ty.clone())) + .collect(), + subr.default_params + .iter() + .map(|t| TyParam::t(t.ty.clone())) + .collect(), + ] + .concat() + } else { + [ + subr.non_default_params + .iter() + .map(|t| TyParam::t(t.ty.clone())) + .collect::>(), + subr.default_params + .iter() + .map(|t| TyParam::t(t.ty.clone())) + .collect(), + ] + .concat() + } + } + Self::Callable { param_ts: _, .. } => todo!(), + Self::Poly { params, .. } | Self::PolyQVar { params, .. } => params.clone(), _ => vec![], } } pub const fn self_t(&self) -> Option<&Type> { match self { - Self::Subr(SubrType{ kind: - SubrKind::FuncMethod(self_t) | SubrKind::ProcMethod{ before: self_t, .. }, + Self::Subr(SubrType { + kind: SubrKind::FuncMethod(self_t) | SubrKind::ProcMethod { before: self_t, .. }, .. }) => Some(self_t), _ => None, @@ -2251,31 +2797,35 @@ impl Type { pub const fn non_default_params(&self) -> Option<&Vec> { match self { - Self::Subr(SubrType{ non_default_params, .. }) => Some(non_default_params), - Self::Callable{ param_ts: _, .. } => todo!(), + Self::Subr(SubrType { + non_default_params, .. + }) => Some(non_default_params), + Self::Callable { param_ts: _, .. } => todo!(), _ => None, } } pub const fn default_params(&self) -> Option<&Vec> { match self { - Self::Subr(SubrType{ default_params, .. }) => Some(default_params), + Self::Subr(SubrType { default_params, .. }) => Some(default_params), _ => None, } } pub const fn return_t(&self) -> Option<&Type> { match self { - Self::Subr(SubrType{ return_t, .. }) - | Self::Callable{ return_t, .. } => Some(return_t), + Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => { + Some(return_t) + } _ => None, } } pub fn mut_return_t(&mut self) -> Option<&mut Type> { match self { - Self::Subr(SubrType{ return_t, .. }) - | Self::Callable{ return_t, .. } => Some(return_t), + Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => { + Some(return_t) + } _ => None, } } @@ -2290,19 +2840,29 @@ pub mod type_constrs { } #[inline] - pub const fn anon(ty: Type) -> ParamTy { ParamTy::anonymous(ty) } + pub const fn anon(ty: Type) -> ParamTy { + ParamTy::anonymous(ty) + } #[inline] - pub fn mono>(name: S) -> Type { Type::mono(name) } + pub fn mono>(name: S) -> Type { + Type::mono(name) + } #[inline] - pub fn mono_q>(name: S) -> Type { Type::mono_q(name) } + pub fn mono_q>(name: S) -> Type { + Type::mono_q(name) + } #[inline] - pub fn poly>(name: S, params: Vec) -> Type { Type::poly(name, params) } + pub fn poly>(name: S, params: Vec) -> Type { + Type::poly(name, params) + } #[inline] - pub fn poly_q>(name: S, params: Vec) -> Type { Type::poly_q(name, params) } + pub fn poly_q>(name: S, params: Vec) -> Type { + Type::poly_q(name, params) + } #[inline] pub fn func(non_default_params: Vec, default_params: Vec, ret: Type) -> Type { @@ -2315,40 +2875,64 @@ pub mod type_constrs { } #[inline] - pub fn nd_func(params: Vec, ret: Type) -> Type { Type::nd_func(params, ret) } + pub fn nd_func(params: Vec, ret: Type) -> Type { + Type::nd_func(params, ret) + } #[inline] - pub fn nd_proc(params: Vec, ret: Type) -> Type { Type::nd_proc(params, ret) } + pub fn nd_proc(params: Vec, ret: Type) -> Type { + Type::nd_proc(params, ret) + } #[inline] - pub fn fn0_met(self_t: Type, return_t: Type) -> Type { Type::fn0_met(self_t, return_t) } + pub fn fn0_met(self_t: Type, return_t: Type) -> Type { + Type::fn0_met(self_t, return_t) + } #[inline] - pub fn fn1_met(self_t: Type, input_t: Type, return_t: Type) -> Type { Type::fn1_met(self_t, input_t, return_t) } + pub fn fn1_met(self_t: Type, input_t: Type, return_t: Type) -> Type { + Type::fn1_met(self_t, input_t, return_t) + } #[inline] - pub fn quant(unbound_t: Type, bounds: Set) -> Type { Type::quantified(unbound_t, bounds) } + pub fn quant(unbound_t: Type, bounds: Set) -> Type { + Type::quantified(unbound_t, bounds) + } #[inline] - pub fn instance(name: Str, t: Type) -> TyBound { TyBound::instance(name, t) } + pub fn instance(name: Str, t: Type) -> TyBound { + TyBound::instance(name, t) + } #[inline] - pub fn static_instance(name: &'static str, t: Type) -> TyBound { TyBound::static_instance(name, t) } + pub fn static_instance(name: &'static str, t: Type) -> TyBound { + TyBound::static_instance(name, t) + } #[inline] - pub fn subtype(sub: Type, sup: Type) -> TyBound { TyBound::subtype(sub, sup) } + pub fn subtype(sub: Type, sup: Type) -> TyBound { + TyBound::subtype(sub, sup) + } #[inline] - pub fn mono_q_tp>(name: S) -> TyParam { TyParam::mono_q(name) } + pub fn mono_q_tp>(name: S) -> TyParam { + TyParam::mono_q(name) + } #[inline] - pub fn mono_tp>(name: S) -> TyParam { TyParam::mono(name) } + pub fn mono_tp>(name: S) -> TyParam { + TyParam::mono(name) + } #[inline] - pub fn ty_tp(t: Type) -> TyParam { TyParam::t(t) } + pub fn ty_tp(t: Type) -> TyParam { + TyParam::t(t) + } #[inline] - pub fn value>(v: V) -> TyParam { TyParam::value(v) } + pub fn value>(v: V) -> TyParam { + TyParam::value(v) + } } /// バイトコード命令で、in-place型付けをするオブジェクト @@ -2384,7 +2968,7 @@ impl From<&Type> for TypeCode { Type::Float => Self::Float64, Type::Bool => Self::Bool, Type::Str => Self::Str, - Type::Array{ .. } => Self::Array, + Type::Array { .. } => Self::Array, Type::FuncCommon => Self::Func, Type::ProcCommon => Self::Proc, _ => Self::Other, @@ -2548,7 +3132,7 @@ impl TypePair { (Type::Int, Type::Float) => Self::IntFloat, (Type::Int, Type::Str) => Self::IntStr, (Type::Int, Type::Bool) => Self::IntBool, - (Type::Int, Type::Array{ .. }) => Self::IntArray, + (Type::Int, Type::Array { .. }) => Self::IntArray, (Type::Int, Type::FuncCommon) => Self::IntFunc, (Type::Int, Type::ProcCommon) => Self::IntProc, (Type::Nat, Type::Int) => Self::NatInt, @@ -2556,7 +3140,7 @@ impl TypePair { (Type::Nat, Type::Float) => Self::NatFloat, (Type::Nat, Type::Str) => Self::NatStr, (Type::Nat, Type::Bool) => Self::NatBool, - (Type::Nat, Type::Array{ .. }) => Self::NatArray, + (Type::Nat, Type::Array { .. }) => Self::NatArray, (Type::Nat, Type::FuncCommon) => Self::NatFunc, (Type::Nat, Type::ProcCommon) => Self::NatProc, (Type::Float, Type::Int) => Self::FloatInt, @@ -2564,7 +3148,7 @@ impl TypePair { (Type::Float, Type::Float) => Self::FloatFloat, (Type::Float, Type::Str) => Self::FloatStr, (Type::Float, Type::Bool) => Self::FloatBool, - (Type::Float, Type::Array{ .. }) => Self::FloatArray, + (Type::Float, Type::Array { .. }) => Self::FloatArray, (Type::Float, Type::FuncCommon) => Self::FloatFunc, (Type::Float, Type::ProcCommon) => Self::FloatProc, (Type::Bool, Type::Int) => Self::BoolInt, @@ -2572,7 +3156,7 @@ impl TypePair { (Type::Bool, Type::Float) => Self::BoolFloat, (Type::Bool, Type::Str) => Self::BoolStr, (Type::Bool, Type::Bool) => Self::BoolBool, - (Type::Bool, Type::Array{ .. }) => Self::BoolArray, + (Type::Bool, Type::Array { .. }) => Self::BoolArray, (Type::Bool, Type::FuncCommon) => Self::BoolFunc, (Type::Bool, Type::ProcCommon) => Self::BoolProc, (Type::Str, Type::Int) => Self::StrInt, @@ -2580,24 +3164,24 @@ impl TypePair { (Type::Str, Type::Float) => Self::StrFloat, (Type::Str, Type::Bool) => Self::StrBool, (Type::Str, Type::Str) => Self::StrStr, - (Type::Str, Type::Array{ .. }) => Self::StrArray, + (Type::Str, Type::Array { .. }) => Self::StrArray, (Type::Str, Type::FuncCommon) => Self::StrFunc, (Type::Str, Type::ProcCommon) => Self::StrProc, // 要素数は検査済みなので、気にする必要はない - (Type::Array{ .. }, Type::Int) => Self::ArrayInt, - (Type::Array{ .. }, Type::Nat) => Self::ArrayNat, - (Type::Array{ .. }, Type::Float) => Self::ArrayFloat, - (Type::Array{ .. }, Type::Str) => Self::ArrayStr, - (Type::Array{ .. }, Type::Bool) => Self::ArrayBool, - (Type::Array{ .. }, Type::Array{ .. }) => Self::ArrayArray, - (Type::Array{ .. }, Type::FuncCommon) => Self::ArrayFunc, - (Type::Array{ .. }, Type::ProcCommon) => Self::ArrayProc, + (Type::Array { .. }, Type::Int) => Self::ArrayInt, + (Type::Array { .. }, Type::Nat) => Self::ArrayNat, + (Type::Array { .. }, Type::Float) => Self::ArrayFloat, + (Type::Array { .. }, Type::Str) => Self::ArrayStr, + (Type::Array { .. }, Type::Bool) => Self::ArrayBool, + (Type::Array { .. }, Type::Array { .. }) => Self::ArrayArray, + (Type::Array { .. }, Type::FuncCommon) => Self::ArrayFunc, + (Type::Array { .. }, Type::ProcCommon) => Self::ArrayProc, (Type::FuncCommon, Type::Int) => Self::FuncInt, (Type::FuncCommon, Type::Nat) => Self::FuncNat, (Type::FuncCommon, Type::Float) => Self::FuncFloat, (Type::FuncCommon, Type::Str) => Self::FuncStr, (Type::FuncCommon, Type::Bool) => Self::FuncBool, - (Type::FuncCommon, Type::Array{ .. }) => Self::FuncArray, + (Type::FuncCommon, Type::Array { .. }) => Self::FuncArray, (Type::FuncCommon, Type::FuncCommon) => Self::FuncFunc, (Type::FuncCommon, Type::ProcCommon) => Self::FuncProc, (Type::ProcCommon, Type::Int) => Self::ProcInt, @@ -2605,7 +3189,7 @@ impl TypePair { (Type::ProcCommon, Type::Float) => Self::ProcFloat, (Type::ProcCommon, Type::Str) => Self::ProcStr, (Type::ProcCommon, Type::Bool) => Self::ProcBool, - (Type::ProcCommon, Type::Array{ .. }) => Self::ProcArray, + (Type::ProcCommon, Type::Array { .. }) => Self::ProcArray, (Type::ProcCommon, Type::ProcCommon) => Self::ProcProc, (_, _) => Self::Others, } diff --git a/compiler/erg_common/value.rs b/compiler/erg_common/value.rs index 2ceee5d6..16ec77cf 100644 --- a/compiler/erg_common/value.rs +++ b/compiler/erg_common/value.rs @@ -1,19 +1,19 @@ //! defines `ValueObj` (used in the compiler, VM). //! //! コンパイラ、VM等で使われる(データも保持した)値オブジェクトを定義する +use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::ops::Neg; use std::rc::Rc; -use std::cmp::Ordering; -use crate::{Str, RcArray}; -use crate::set; -use crate::{fmt_iter, switch_lang, impl_display_from_debug}; use crate::codeobj::CodeObj; use crate::serialize::*; +use crate::set; use crate::traits::HasType; -use crate::ty::{Type, TyParam, Predicate, ConstObj, fresh_varname}; +use crate::ty::{fresh_varname, ConstObj, Predicate, TyParam, Type}; +use crate::{fmt_iter, impl_display_from_debug, switch_lang}; +use crate::{RcArray, Str}; /// 値オブジェクト /// コンパイル時評価ができ、シリアライズも可能 @@ -43,9 +43,12 @@ impl fmt::Debug for ValueObj { Self::Nat(n) => write!(f, "{n}"), Self::Float(fl) => { // In Rust, .0 is shown omitted. - if fl.fract() < 1e-10 { write!(f, "{fl:.1}") } - else { write!(f, "{fl}") } - }, + if fl.fract() < 1e-10 { + write!(f, "{fl:.1}") + } else { + write!(f, "{fl}") + } + } Self::Str(s) => write!(f, "\"{s}\""), Self::True => write!(f, "True"), Self::False => write!(f, "False"), @@ -58,7 +61,7 @@ impl fmt::Debug for ValueObj { s.pop(); s.pop(); write!(f, "[{s}]") - }, + } Self::Code(code) => write!(f, "{code}"), Self::None => write!(f, "None"), Self::Ellipsis => write!(f, "Ellipsis"), @@ -132,39 +135,61 @@ impl Hash for ValueObj { } impl From for ValueObj { - fn from(item: i32) -> Self { ValueObj::Int(item) } + fn from(item: i32) -> Self { + ValueObj::Int(item) + } } impl From for ValueObj { - fn from(item: u64) -> Self { ValueObj::Nat(item) } + fn from(item: u64) -> Self { + ValueObj::Nat(item) + } } impl From for ValueObj { - fn from(item: usize) -> Self { ValueObj::Nat(item as u64) } + fn from(item: usize) -> Self { + ValueObj::Nat(item as u64) + } } impl From for ValueObj { - fn from(item: f64) -> Self { ValueObj::Float(item) } + fn from(item: f64) -> Self { + ValueObj::Float(item) + } } impl From<&str> for ValueObj { - fn from(item: &str) -> Self { ValueObj::Str(Str::rc(item)) } + fn from(item: &str) -> Self { + ValueObj::Str(Str::rc(item)) + } } impl From for ValueObj { - fn from(item: Str) -> Self { ValueObj::Str(item) } + fn from(item: Str) -> Self { + ValueObj::Str(item) + } } impl From for ValueObj { - fn from(item: bool) -> Self { if item { ValueObj::True } else { ValueObj::False } } + fn from(item: bool) -> Self { + if item { + ValueObj::True + } else { + ValueObj::False + } + } } impl From for ValueObj { - fn from(item: CodeObj) -> Self { ValueObj::Code(Box::new(item)) } + fn from(item: CodeObj) -> Self { + ValueObj::Code(Box::new(item)) + } } impl From> for ValueObj { - fn from(item: Vec) -> Self { ValueObj::Array(RcArray::from(&item[..])) } + fn from(item: Vec) -> Self { + ValueObj::Array(RcArray::from(&item[..])) + } } impl TryFrom<&ValueObj> for f64 { @@ -182,15 +207,22 @@ impl TryFrom<&ValueObj> for f64 { } impl HasType for ValueObj { - fn ref_t(&self) -> &Type { panic!("cannot get reference of the const") } + fn ref_t(&self) -> &Type { + panic!("cannot get reference of the const") + } /// その要素だけの集合型を返す、クラスが欲しい場合は.classで #[inline] fn t(&self) -> Type { let name = Str::from(fresh_varname()); - let pred = Predicate::eq(name.clone(), TyParam::ConstObj(ConstObj::Value(self.clone()))); - Type::refinement(name, self.class(), set!{pred}) + let pred = Predicate::eq( + name.clone(), + TyParam::ConstObj(ConstObj::Value(self.clone())), + ); + Type::refinement(name, self.class(), set! {pred}) + } + fn signature_t(&self) -> Option<&Type> { + None } - fn signature_t(&self) -> Option<&Type> { None } } impl ValueObj { @@ -210,10 +242,14 @@ impl ValueObj { let replaced = content.trim_start_matches('\"').trim_end_matches('\"'); Self::Str(Str::rc(replaced)) } - }, + } Type::Bool => { - if &content[..] == "True" { Self::True } else { Self::False } - }, + if &content[..] == "True" { + Self::True + } else { + Self::False + } + } Type::NoneType => Self::None, Type::Ellipsis => Self::Ellipsis, Type::NotImplemented => Self::NotImplemented, @@ -225,17 +261,23 @@ impl ValueObj { pub fn into_bytes(self) -> Vec { match self { - Self::Int(i) => { - [vec![DataTypePrefix::Int32 as u8], i32::from(i).to_le_bytes().to_vec()].concat() - }, + Self::Int(i) => [ + vec![DataTypePrefix::Int32 as u8], + i32::from(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()].concat() - }, - Self::Float(f) => { - [vec![DataTypePrefix::BinFloat as u8], f64::from(f).to_le_bytes().to_vec()].concat() - }, - Self::Str(s) => { str_into_bytes(s, false) }, + Self::Nat(n) => [ + vec![DataTypePrefix::Int32 as u8], + i32::from(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(), + ] + .concat(), + Self::Str(s) => str_into_bytes(s, false), Self::True => vec![DataTypePrefix::True as u8], Self::False => vec![DataTypePrefix::False as u8], // TODO: SmallTuple @@ -247,14 +289,21 @@ impl ValueObj { bytes.append(&mut obj.into_bytes()); } bytes - }, - Self::None => { vec![DataTypePrefix::None as u8] }, + } + Self::None => { + vec![DataTypePrefix::None as u8] + } Self::Code(c) => c.into_bytes(3425), // Dict - other => { panic!("{}", switch_lang!( - format!("this object cannot be serialized: {other}"), - format!("このオブジェクトはシリアライズできません: {other}") - )) }, + other => { + panic!( + "{}", + switch_lang!( + format!("this object cannot be serialized: {other}"), + format!("このオブジェクトはシリアライズできません: {other}") + ) + ) + } } } @@ -266,9 +315,9 @@ impl ValueObj { Self::Str(_) => Type::Str, Self::True | Self::False => Type::Bool, // TODO: - Self::Array(arr) =>Type::array( + Self::Array(arr) => Type::array( arr.iter().next().unwrap().class(), - TyParam::value(arr.len()) + TyParam::value(arr.len()), ), Self::Dict(_dict) => todo!(), Self::Code(_) => Type::Code, @@ -283,13 +332,11 @@ impl ValueObj { pub fn try_cmp(&self, other: &Self) -> Option { match (self, other) { - (l, r) if l.is_num() && r.is_num() => { - f64::try_from(l).unwrap().partial_cmp(&f64::try_from(r).unwrap()) - } - (Self::Inf, n) - | (n, Self::NegInf) if n.is_num() => Some(Ordering::Greater), - (n, Self::Inf) - | (Self::NegInf, n) if n.is_num() => Some(Ordering::Less), + (l, r) if l.is_num() && r.is_num() => f64::try_from(l) + .unwrap() + .partial_cmp(&f64::try_from(r).unwrap()), + (Self::Inf, n) | (n, Self::NegInf) if n.is_num() => Some(Ordering::Greater), + (n, Self::Inf) | (Self::NegInf, n) if n.is_num() => Some(Ordering::Less), (Self::NegInf, Self::Inf) => Some(Ordering::Less), (Self::Inf, Self::NegInf) => Some(Ordering::Greater), // REVIEW: 等しいとみなしてよいのか? @@ -317,8 +364,9 @@ impl ValueObj { (Self::Float(l), Self::Int(r)) => Some(Self::Float(l + r as f64)), (Self::Int(l), Self::Float(r)) => Some(Self::Float(l as f64 + r)), (Self::Str(l), Self::Str(r)) => Some(Self::Str(Str::from(format!("{}{}", l, r)))), - (inf @ (Self::Inf | Self::NegInf), _) - | (_, inf @ (Self::Inf | Self::NegInf)) => Some(inf), + (inf @ (Self::Inf | Self::NegInf), _) | (_, inf @ (Self::Inf | Self::NegInf)) => { + Some(inf) + } _ => None, } } @@ -336,7 +384,10 @@ impl ValueObj { (Self::Int(l), Self::Float(r)) => Some(Self::Float(l as f64 - r)), (inf @ (Self::Inf | Self::NegInf), other) | (other, inf @ (Self::Inf | Self::NegInf)) - if other != Self::Inf && other != Self::NegInf => Some(inf), + if other != Self::Inf && other != Self::NegInf => + { + Some(inf) + } _ => None, } } @@ -353,8 +404,9 @@ impl ValueObj { (Self::Float(l), Self::Int(r)) => Some(Self::Float(l * r as f64)), (Self::Int(l), Self::Float(r)) => Some(Self::Float(l as f64 * r)), (Self::Str(l), Self::Nat(r)) => Some(Self::Str(Str::from(l.repeat(r as usize)))), - (inf @ (Self::Inf | Self::NegInf), _) - | (_, inf @ (Self::Inf | Self::NegInf)) => Some(inf), + (inf @ (Self::Inf | Self::NegInf), _) | (_, inf @ (Self::Inf | Self::NegInf)) => { + Some(inf) + } _ => None, } } @@ -417,10 +469,8 @@ impl ValueObj { (Self::Float(l), Self::Int(r)) => Some(Self::from(l == r as f64)), (Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 == r)), (Self::Str(l), Self::Str(r)) => Some(Self::from(l == r)), - (Self::True, Self::True) | - (Self::False, Self::False) => Some(Self::True), - (Self::True, Self::False) | - (Self::False, Self::True) => Some(Self::False), + (Self::True, Self::True) | (Self::False, Self::False) => Some(Self::True), + (Self::True, Self::False) | (Self::False, Self::True) => Some(Self::False), // TODO: _ => None, } @@ -438,10 +488,8 @@ impl ValueObj { (Self::Float(l), Self::Int(r)) => Some(Self::from(l != r as f64)), (Self::Int(l), Self::Float(r)) => Some(Self::from(l as f64 != r)), (Self::Str(l), Self::Str(r)) => Some(Self::from(l != r)), - (Self::True, Self::True) | - (Self::False, Self::False) => Some(Self::False), - (Self::True, Self::False) | - (Self::False, Self::True) => Some(Self::True), + (Self::True, Self::True) | (Self::False, Self::False) => Some(Self::False), + (Self::True, Self::False) | (Self::False, Self::True) => Some(Self::True), _ => None, } } diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index d26c33fc..4a058a1b 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -4,32 +4,35 @@ use std::fmt; use std::process; -use erg_common::Str; use erg_common::cache::Cache; -use erg_common::{fn_name_full, enum_unwrap, switch_unreachable, debug_power_assert, log, impl_stream_for_wrapper}; use erg_common::codeobj::{CodeObj, CodeObjFlags}; use erg_common::color::{GREEN, RESET}; use erg_common::config::{ErgConfig, Input}; use erg_common::error::{Location, MultiErrorDisplay}; -use erg_common::value::ValueObj; use erg_common::opcode::Opcode; -use Opcode::*; use erg_common::traits::{HasType, Locational, Stream}; use erg_common::ty::{TypeCode, TypePair}; +use erg_common::value::ValueObj; +use erg_common::Str; +use erg_common::{ + debug_power_assert, enum_unwrap, fn_name_full, impl_stream_for_wrapper, log, switch_unreachable, +}; +use Opcode::*; -use erg_parser::token::{Token, TokenKind, TokenCategory}; -use erg_parser::ast::{VarPattern, ParamPattern, Params}; +use erg_parser::ast::{ParamPattern, Params, VarPattern}; +use erg_parser::token::{Token, TokenCategory, TokenKind}; use crate::compile::{AccessKind, Name, StoreLoadKind}; use crate::error::{CompileError, CompileErrors, CompileResult}; -use crate::hir::{Args, Expr, Signature, VarSignature, SubrSignature, DefBody, Accessor, Block, HIR}; +use crate::hir::{ + Accessor, Args, Block, DefBody, Expr, Signature, SubrSignature, VarSignature, HIR, +}; use AccessKind::*; fn obj_name(obj: &Expr) -> Option { match obj { Expr::Accessor(Accessor::Local(n)) => Some(n.inspect().to_string()), - Expr::Accessor(Accessor::Attr(a)) => - Some(obj_name(&a.obj)? + "." + a.name.inspect()), + Expr::Accessor(Accessor::Attr(a)) => Some(obj_name(&a.obj)? + "." + a.name.inspect()), Expr::Accessor(Accessor::SelfDot(n)) => Some(format!(".{}", n.inspect())), _ => None, } @@ -38,8 +41,8 @@ fn obj_name(obj: &Expr) -> Option { fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -> Str { match (class, uniq_obj_name, &name[..]) { ("Array!", _, "push!") => Str::ever("append"), - ("Complex" | "Real"| "Int" | "Nat" | "Float", _, "Real") => Str::ever("real"), - ("Complex" | "Real"| "Int" | "Nat" | "Float", _, "Imag") => Str::ever("imag"), + ("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Real") => Str::ever("real"), + ("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Imag") => Str::ever("imag"), ("Module", Some("random"), "randint!") => Str::ever("randint"), _ => name, } @@ -92,7 +95,9 @@ pub struct CodeGenUnit { impl PartialEq for CodeGenUnit { #[inline] - fn eq(&self, other: &Self) -> bool { self.id == other.id } + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } } impl fmt::Display for CodeGenUnit { @@ -157,7 +162,9 @@ impl CodeGenerator { } #[inline] - fn input(&self) -> &Input { &self.cfg.input } + fn input(&self) -> &Input { + &self.cfg.input + } fn get_cached(&self, s: &str) -> Str { self.str_cache.get(s) @@ -264,21 +271,30 @@ impl CodeGenerator { .cur_block_codeobj() .names .iter() - .position(|n| &**n == name) { - if current_is_toplevel || !acc_kind.is_local() { Some(Name::local(idx)) } - else { Some(Name::global(idx)) } + .position(|n| &**n == name) + { + if current_is_toplevel || !acc_kind.is_local() { + Some(Name::local(idx)) + } else { + Some(Name::global(idx)) + } } else if let Some(idx) = self .cur_block_codeobj() .varnames .iter() - .position(|v| &**v == name) { - if current_is_toplevel { Some(Name::local(idx)) } - else { Some(Name::fast(idx)) } + .position(|v| &**v == name) + { + if current_is_toplevel { + Some(Name::local(idx)) + } else { + Some(Name::fast(idx)) + } } else if let Some(idx) = self .cur_block_codeobj() .freevars .iter() - .position(|f| &**f == name) { + .position(|f| &**f == name) + { Some(Name::deref(idx)) } else { None @@ -291,20 +307,20 @@ impl CodeGenerator { 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) { - return Some(StoreLoadKind::Deref) + return Some(StoreLoadKind::Deref); } else if let Some(idx) = block.codeobj.varnames.iter().position(|v| &**v == name) { if block_is_toplevel { - return Some(StoreLoadKind::Global) + return Some(StoreLoadKind::Global); } else { // the outer scope variable let cellvar_name = block.codeobj.varnames.get(idx).unwrap().clone(); block.codeobj.cellvars.push(cellvar_name); - return Some(StoreLoadKind::Deref) + return Some(StoreLoadKind::Deref); } } if block_is_toplevel { if let Some(_) = block.codeobj.names.iter().position(|n| &**n == name) { - return Some(StoreLoadKind::Global) + return Some(StoreLoadKind::Global); } } } @@ -317,7 +333,11 @@ impl CodeGenerator { let name = escape_name(name); match self.rec_search(&name) { Some(st @ (StoreLoadKind::Local | StoreLoadKind::Global)) => { - let st = if current_is_toplevel { StoreLoadKind::Local } else { st }; + let st = if current_is_toplevel { + StoreLoadKind::Local + } else { + st + }; self.mut_cur_block_codeobj().names.push(name); Name::new(st, self.cur_block_codeobj().names.len() - 1) } @@ -356,9 +376,9 @@ impl CodeGenerator { } fn emit_load_name_instr(&mut self, name: Str) -> CompileResult<()> { - let name = self.local_search(&name, Name).unwrap_or_else(|| { - self.register_name(name) - }); + let name = self + .local_search(&name, Name) + .unwrap_or_else(|| self.register_name(name)); let instr = match name.kind { StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST, StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL, @@ -371,10 +391,15 @@ impl CodeGenerator { Ok(()) } - fn emit_load_attr_instr(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> CompileResult<()> { - let name = self.local_search(&name, Attr).unwrap_or_else(|| { - self.register_attr(class, uniq_obj_name, name) - }); + fn emit_load_attr_instr( + &mut self, + class: &str, + uniq_obj_name: Option<&str>, + name: Str, + ) -> CompileResult<()> { + let name = self + .local_search(&name, Attr) + .unwrap_or_else(|| self.register_attr(class, uniq_obj_name, name)); let instr = match name.kind { StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST, StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL, @@ -386,10 +411,15 @@ impl CodeGenerator { Ok(()) } - fn emit_load_method_instr(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> CompileResult<()> { - let name = self.local_search(&name, Method).unwrap_or_else(|| { - self.register_method(class, uniq_obj_name, name) - }); + fn emit_load_method_instr( + &mut self, + class: &str, + uniq_obj_name: Option<&str>, + name: Str, + ) -> CompileResult<()> { + let name = self + .local_search(&name, Method) + .unwrap_or_else(|| self.register_method(class, uniq_obj_name, name)); let instr = match name.kind { StoreLoadKind::Fast | StoreLoadKind::FastConst => Opcode::LOAD_FAST, StoreLoadKind::Global | StoreLoadKind::GlobalConst => Opcode::LOAD_GLOBAL, @@ -402,9 +432,9 @@ impl CodeGenerator { } fn emit_store_instr(&mut self, name: Str, acc_kind: AccessKind) { - let name = self.local_search(&name, acc_kind).unwrap_or_else(|| { - self.register_name(name) - }); + let name = self + .local_search(&name, acc_kind) + .unwrap_or_else(|| self.register_name(name)); let instr = match name.kind { StoreLoadKind::Fast => Opcode::STORE_FAST, StoreLoadKind::FastConst => Opcode::ERG_STORE_FAST_IMMUT, @@ -453,8 +483,15 @@ impl CodeGenerator { fn gen_param_names(&self, params: &Params) -> Vec { params - .non_defaults.iter().map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")) - .chain(params.defaults.iter().map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_"))) + .non_defaults + .iter() + .map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")) + .chain( + params + .defaults + .iter() + .map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")), + ) .map(|s| self.get_cached(&s)) .collect() } @@ -504,7 +541,7 @@ impl CodeGenerator { fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) { if body.is_type() { - return self.emit_mono_type_def(sig, body) + return self.emit_mono_type_def(sig, body); } if body.block.len() == 1 { self.codegen_expr(body.block.remove(0)); @@ -586,7 +623,7 @@ impl CodeGenerator { } else { // no else block let idx_end = self.cur_block().lasti; - self.edit_code(idx_pop_jump_if_false + 1,idx_end / 2); + self.edit_code(idx_pop_jump_if_false + 1, idx_end / 2); self.stack_dec(); } Ok(()) @@ -630,8 +667,8 @@ impl CodeGenerator { let mut lambda = enum_unwrap!(expr, Expr::Lambda); debug_power_assert!(lambda.params.len(), ==, 1); if !lambda.params.defaults.is_empty() { - todo!("default values in match expression are not supported yet") - } + todo!("default values in match expression are not supported yet") + } let pat = lambda.params.non_defaults.remove(0).pat; let pop_jump_points = self.emit_match_pattern(pat)?; self.codegen_frameless_block(lambda.body, Vec::new()); @@ -772,7 +809,7 @@ impl CodeGenerator { self.emit_load_method_instr(&class, uniq_obj_name.as_ref().map(|s| &s[..]), name) .unwrap_or_else(|err| { self.errs.push(err); - }); + }); let argc = args.len(); let mut kws = Vec::with_capacity(args.kw_len()); while let Some(arg) = args.try_remove_pos(0) { @@ -879,25 +916,28 @@ impl CodeGenerator { self.emit_load_const(lit.data); } Expr::Accessor(Accessor::Local(l)) => { - self.emit_load_name_instr(l.inspect().clone()).unwrap_or_else(|err| { - self.errs.push(err); - }); + self.emit_load_name_instr(l.inspect().clone()) + .unwrap_or_else(|err| { + self.errs.push(err); + }); } Expr::Accessor(Accessor::Attr(a)) => { let class = Str::rc(a.obj.ref_t().name()); let uniq_obj_name = a.obj.__name__().map(Str::rc); self.codegen_expr(*a.obj); - self.emit_load_attr_instr(&class, uniq_obj_name.as_ref().map(|s| &s[..]), a.name.content.clone()) - .unwrap_or_else(|err| { - self.errs.push(err); + self.emit_load_attr_instr( + &class, + uniq_obj_name.as_ref().map(|s| &s[..]), + a.name.content.clone(), + ) + .unwrap_or_else(|err| { + self.errs.push(err); }); } - Expr::Def(def) => { - match def.sig { - Signature::Subr(sig) => { self.emit_subr_def(sig, def.body) } - Signature::Var(sig) => { self.emit_var_def(sig, def.body) } - } - } + Expr::Def(def) => match def.sig { + Signature::Subr(sig) => self.emit_subr_def(sig, def.body), + Signature::Var(sig) => self.emit_var_def(sig, def.body), + }, // TODO: Expr::Lambda(lambda) => { let params = self.gen_param_names(&lambda.params); @@ -936,7 +976,9 @@ impl CodeGenerator { // Range operators are not operators in Python match &bin.op.kind { // l.. { self.emit_load_name_instr(Str::ever("range")).unwrap(); }, + TokenKind::RightOpen => { + self.emit_load_name_instr(Str::ever("range")).unwrap(); + } TokenKind::LeftOpen | TokenKind::Closed | TokenKind::Open => todo!(), _ => {} } @@ -958,14 +1000,16 @@ impl CodeGenerator { | TokenKind::NotEq | TokenKind::Gre | TokenKind::GreEq => COMPARE_OP, - TokenKind::LeftOpen | TokenKind::RightOpen - | TokenKind::Closed | TokenKind::Open => CALL_FUNCTION, // ERG_BINARY_RANGE, + TokenKind::LeftOpen + | TokenKind::RightOpen + | TokenKind::Closed + | TokenKind::Open => CALL_FUNCTION, // ERG_BINARY_RANGE, _ => { self.errs.push(CompileError::feature_error( self.cfg.input.clone(), bin.op.loc(), "", - bin.op.content.clone() + bin.op.content.clone(), )); NOT_IMPLEMENTED } @@ -977,16 +1021,22 @@ impl CodeGenerator { TokenKind::NotEq => 3, TokenKind::Gre => 4, TokenKind::GreEq => 5, - TokenKind::LeftOpen | TokenKind::RightOpen - | TokenKind::Closed | TokenKind::Open => 2, + TokenKind::LeftOpen + | TokenKind::RightOpen + | TokenKind::Closed + | TokenKind::Open => 2, _ => type_pair as u8, }; self.write_instr(instr); self.write_arg(arg); self.stack_dec(); match &bin.op.kind { - TokenKind::LeftOpen | TokenKind::RightOpen - | TokenKind::Open | TokenKind::Closed => { self.stack_dec(); }, + TokenKind::LeftOpen + | TokenKind::RightOpen + | TokenKind::Open + | TokenKind::Closed => { + self.stack_dec(); + } _ => {} } } @@ -1005,7 +1055,7 @@ impl CodeGenerator { self.emit_call_callable_obj(obj, call.args); } } - }, + } // TODO: list comprehension Expr::Array(mut arr) => { let len = arr.elems.len(); @@ -1021,7 +1071,12 @@ impl CodeGenerator { } } other => { - self.errs.push(CompileError::feature_error(self.cfg.input.clone(), other.loc(), "", "".into())); + self.errs.push(CompileError::feature_error( + self.cfg.input.clone(), + other.loc(), + "", + "".into(), + )); self.crash("cannot compile this expression at this time"); } } @@ -1076,7 +1131,7 @@ impl CodeGenerator { Location::Unknown, stack_len, block_id, - fn_name_full!() + fn_name_full!(), )); self.crash("error in codegen_typedef_block: invalid stack size"); } @@ -1089,7 +1144,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| { *l += ld as u8; }); + self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| { + *l += ld as u8; + }); self.mut_cur_block().prev_lineno += ld; } } @@ -1098,7 +1155,11 @@ impl CodeGenerator { fn codegen_block(&mut self, block: Block, opt_name: Option, params: Vec) -> CodeObj { self.unit_size += 1; - let name = if let Some(name) = opt_name { name } else { "".into() }; + let name = if let Some(name) = opt_name { + name + } else { + "".into() + }; let firstlineno = block.first().unwrap().ln_begin().unwrap(); self.units.push(CodeGenUnit::new( self.unit_size, @@ -1127,7 +1188,7 @@ impl CodeGenerator { Location::Unknown, stack_len, block_id, - fn_name_full!() + fn_name_full!(), )); self.crash("error in codegen_block: invalid stack size"); } @@ -1142,7 +1203,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| { *l += ld as u8; }); + self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| { + *l += ld as u8; + }); self.mut_cur_block().prev_lineno += ld; } } @@ -1157,7 +1220,7 @@ impl CodeGenerator { vec![], Str::rc(self.cfg.input.enclosed_name()), "", - 1 + 1, )); for expr in hir.module.into_iter() { self.codegen_expr(expr); @@ -1177,7 +1240,7 @@ impl CodeGenerator { Location::Unknown, stack_len, block_id, - fn_name_full!() + fn_name_full!(), )); self.crash("error in codegen_module: invalid stack size"); } @@ -1192,7 +1255,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| { *l += ld as u8; }); + self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| { + *l += ld as u8; + }); self.mut_cur_block().prev_lineno += ld; } } diff --git a/compiler/erg_compiler/compile.rs b/compiler/erg_compiler/compile.rs index 5a455cb6..3810f09a 100644 --- a/compiler/erg_compiler/compile.rs +++ b/compiler/erg_compiler/compile.rs @@ -3,19 +3,19 @@ //! コンパイラーを定義する use std::path::Path; -use erg_common::Str; -use erg_common::{log}; use erg_common::codeobj::{CodeObj, CodeObjFlags}; use erg_common::color::{GREEN, RESET}; -use erg_common::config::{Input, ErgConfig, SEMVER, BUILD_INFO}; +use erg_common::config::{ErgConfig, Input, BUILD_INFO, SEMVER}; use erg_common::error::MultiErrorDisplay; +use erg_common::log; use erg_common::traits::{Runnable, Stream}; +use erg_common::Str; use erg_parser::ParserRunner; use crate::codegen::CodeGenerator; use crate::effectcheck::SideEffectChecker; -use crate::error::{TyCheckErrors, CompileError, CompileErrors}; +use crate::error::{CompileError, CompileErrors, TyCheckErrors}; use crate::lower::ASTLowerer; use crate::ownercheck::OwnershipChecker; @@ -43,12 +43,34 @@ pub struct Name { } impl Name { - pub const fn new(kind: StoreLoadKind, idx: usize) -> Self { Self{ kind, idx } } + pub const fn new(kind: StoreLoadKind, idx: usize) -> Self { + Self { kind, idx } + } - pub const fn local(idx: usize) -> Self { Self{ kind: StoreLoadKind::Local, idx } } - pub const fn global(idx: usize) -> Self { Self{ kind: StoreLoadKind::Global, idx } } - pub const fn deref(idx: usize) -> Self { Self{ kind: StoreLoadKind::Deref, idx } } - pub const fn fast(idx: usize) -> Self { Self{ kind: StoreLoadKind::Fast, idx } } + pub const fn local(idx: usize) -> Self { + Self { + kind: StoreLoadKind::Local, + idx, + } + } + pub const fn global(idx: usize) -> Self { + Self { + kind: StoreLoadKind::Global, + idx, + } + } + pub const fn deref(idx: usize) -> Self { + Self { + kind: StoreLoadKind::Deref, + idx, + } + } + pub const fn fast(idx: usize) -> Self { + Self { + kind: StoreLoadKind::Fast, + idx, + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -59,9 +81,15 @@ pub enum AccessKind { } impl AccessKind { - pub const fn is_local(&self) -> bool { matches!(self, Self::Name) } - pub const fn is_attr(&self) -> bool { matches!(self, Self::Attr) } - pub const fn is_method(&self) -> bool { matches!(self, Self::Method) } + pub const fn is_local(&self) -> bool { + matches!(self, Self::Name) + } + pub const fn is_attr(&self) -> bool { + matches!(self, Self::Attr) + } + pub const fn is_method(&self) -> bool { + matches!(self, Self::Method) + } } /// Generates a `CodeObj` from an `AST`. @@ -86,10 +114,14 @@ impl Runnable for Compiler { } #[inline] - fn input(&self) -> &Input { &self.cfg.input } + fn input(&self) -> &Input { + &self.cfg.input + } #[inline] - fn start_message(&self) -> String { format!("Erg compiler {} {}\n", SEMVER, &*BUILD_INFO) } + fn start_message(&self) -> String { + format!("Erg compiler {} {}\n", SEMVER, &*BUILD_INFO) + } #[inline] fn finish(&mut self) {} @@ -106,12 +138,20 @@ impl Runnable for Compiler { impl Compiler { fn convert(&self, errs: TyCheckErrors) -> CompileErrors { - errs.into_iter().map(|e| CompileError::new(e.core, self.input().clone(), e.caused_by)).collect::>().into() + errs.into_iter() + .map(|e| CompileError::new(e.core, self.input().clone(), e.caused_by)) + .collect::>() + .into() } - pub fn compile_and_dump_as_pyc>(&mut self, src: Str, path: P) -> Result<(), CompileErrors> { + pub fn compile_and_dump_as_pyc>( + &mut self, + src: Str, + path: P, + ) -> Result<(), CompileErrors> { let code = self.compile(src, "exec")?; - code.dump_as_pyc(path, self.cfg.python_ver).expect("failed to dump a .pyc file"); + code.dump_as_pyc(path, self.cfg.python_ver) + .expect("failed to dump a .pyc file"); Ok(()) } @@ -121,24 +161,41 @@ impl Compiler { let mut parser = ParserRunner::new(self.cfg.copy()); let ast = parser.parse_from_str(src)?; if ast.is_empty() { - return Ok(CodeObj::empty(vec![], Str::rc(self.input().enclosed_name()), "", 1)) + return Ok(CodeObj::empty( + vec![], + Str::rc(self.input().enclosed_name()), + "", + 1, + )); + } + let (hir, warns) = self + .lowerer + .lower(ast, mode) + .map_err(|errs| self.convert(errs))?; + if warns.is_empty() { + dynamic = false; } - let (hir, warns) = self.lowerer.lower(ast, mode).map_err(|errs| self.convert(errs))?; - if warns.is_empty() { dynamic = false; } if self.cfg.verbose >= 2 { let warns = self.convert(warns); warns.fmt_all_stderr(); } let effect_checker = SideEffectChecker::new(); - let hir = effect_checker.check(hir).map_err(|errs| self.convert(errs))?; + let hir = effect_checker + .check(hir) + .map_err(|errs| self.convert(errs))?; let ownership_checker = OwnershipChecker::new(); - let hir = ownership_checker.check(hir).map_err(|errs| self.convert(errs))?; + let hir = ownership_checker + .check(hir) + .map_err(|errs| self.convert(errs))?; let mut codeobj = self.code_generator.codegen(hir); if dynamic { codeobj.flags += CodeObjFlags::EvmDynamic as u32; } log!("{GREEN}code object:\n{}", codeobj.code_info()); - log!("[DEBUG] the compiling process has completed, found errors: {}{RESET}", self.code_generator.errs.len()); + log!( + "[DEBUG] the compiling process has completed, found errors: {}{RESET}", + self.code_generator.errs.len() + ); if self.code_generator.errs.is_empty() { Ok(codeobj) } else { diff --git a/compiler/erg_compiler/context.rs b/compiler/erg_compiler/context.rs index b53bf2ca..4db94cdd 100644 --- a/compiler/erg_compiler/context.rs +++ b/compiler/erg_compiler/context.rs @@ -4,34 +4,39 @@ use std::fmt; use std::mem; use std::option::Option; // conflicting to Type::Option -use erg_common::Str; +use erg_common::dict::Dict; +use erg_common::error::{ErrorCore, Location}; +use erg_common::levenshtein::levenshtein; +use erg_common::set::Set; +use erg_common::traits::{HasType, Locational, Stream}; +use erg_common::ty::fresh_varname; use erg_common::ty::Constraint; use erg_common::ty::RefinementType; -use erg_common::ty::fresh_varname; -use erg_common::{fn_name, get_hash, log, assume_unreachable, set, try_map, fmt_slice, enum_unwrap}; -use erg_common::dict::Dict; -use erg_common::set::Set; -use erg_common::error::{Location, ErrorCore}; -use erg_common::value::ValueObj; -use erg_common::levenshtein::levenshtein; -use erg_common::traits::{HasType, Locational, Stream}; use erg_common::ty::{ - Type, TyParam, TyParamOrdering, TyBound, ConstObj, - IntervalOp, FreeKind, HasLevel, SubrKind, SubrType, ParamTy, Predicate, + ConstObj, FreeKind, HasLevel, IntervalOp, ParamTy, Predicate, SubrKind, SubrType, TyBound, + TyParam, TyParamOrdering, Type, }; +use erg_common::value::ValueObj; +use erg_common::Str; +use erg_common::{ + assume_unreachable, enum_unwrap, fmt_slice, fn_name, get_hash, log, set, try_map, +}; +use Predicate as Pred; use TyParamOrdering::*; use Type::*; -use Predicate as Pred; use ValueObj::{Inf, NegInf}; +use ast::{ + DefId, ParamSig, ParamTySpec, PreDeclTypeSpec, SimpleTypeSpec, TypeBoundSpec, TypeBoundSpecs, + TypeSpec, VarName, +}; use erg_parser::ast; -use ast::{VarName, DefId, TypeSpec, ParamTySpec, PreDeclTypeSpec, SimpleTypeSpec, TypeBoundSpec, TypeBoundSpecs, ParamSig}; use erg_parser::token::{Token, TokenKind}; +use crate::error::{binop_to_dname, unaryop_to_dname, TyCheckError, TyCheckErrors, TyCheckResult}; +use crate::eval::Evaluator; use crate::hir; -use crate::eval::{Evaluator}; -use crate::error::{TyCheckError, TyCheckErrors, TyCheckResult, binop_to_dname, unaryop_to_dname}; -use crate::varinfo::{VarInfo, Mutability, Visibility, VarKind, ParamId}; +use crate::varinfo::{Mutability, ParamId, VarInfo, VarKind, Visibility}; use Mutability::*; use Visibility::*; @@ -42,7 +47,9 @@ pub enum DefaultInfo { } impl DefaultInfo { - pub const fn has_default(&self) -> bool { matches!(self, DefaultInfo::WithDefault) } + pub const fn has_default(&self) -> bool { + matches!(self, DefaultInfo::WithDefault) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -54,7 +61,11 @@ pub struct ParamSpec { impl ParamSpec { pub const fn new(name: Option<&'static str>, t: Type, default: DefaultInfo) -> Self { - Self { name, t, default_info: default } + Self { + name, + t, + default_info: default, + } } pub const fn named(name: &'static str, t: Type, default: DefaultInfo) -> Self { @@ -65,9 +76,13 @@ impl ParamSpec { Self::new(Some(name), t, DefaultInfo::NonDefault) } - pub const fn t(name: &'static str, default: DefaultInfo) -> Self { Self::new(Some(name), Type, default) } + pub const fn t(name: &'static str, default: DefaultInfo) -> Self { + Self::new(Some(name), Type, default) + } - pub const fn t_nd(name: &'static str) -> Self { Self::new(Some(name), Type, DefaultInfo::NonDefault) } + pub const fn t_nd(name: &'static str) -> Self { + Self::new(Some(name), Type, DefaultInfo::NonDefault) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -108,7 +123,11 @@ pub struct TyVarContext { impl TyVarContext { pub fn new(level: usize, bounds: Set) -> Self { - let mut self_ = Self{ level, tyvar_instances: Dict::new(), typaram_instances: Dict::new() }; + let mut self_ = Self { + level, + tyvar_instances: Dict::new(), + typaram_instances: Dict::new(), + }; for bound in bounds.into_iter() { self_.instantiate_bound(bound); } @@ -117,74 +136,84 @@ impl TyVarContext { fn instantiate_bound(&mut self, bound: TyBound) { match bound { - TyBound::Subtype{ sub, sup } => { + TyBound::Subtype { sub, sup } => { let sup = match sup { - Type::Poly{ name, params } => { - let sup = Type::poly(name, params.into_iter().map(|p| self.instantiate_tp(p)).collect()); + Type::Poly { name, params } => { + let sup = 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) } + Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs), sup => sup, }; let constraint = Constraint::SubtypeOf(sup); self.push_tyvar(Str::rc(sub.name()), Type::free_var(self.level, constraint)); - }, - TyBound::Supertype{ sup, sub } => { + } + TyBound::Supertype { sup, sub } => { let sub = match sub { - Type::Poly{ name, params } => { - let sub = Type::poly(name, params.into_iter().map(|p| self.instantiate_tp(p)).collect()); + Type::Poly { name, params } => { + let sub = 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) } + Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs), sub => sub, }; let constraint = Constraint::SupertypeOf(sub); self.push_tyvar(Str::rc(sup.name()), Type::free_var(self.level, constraint)); - }, - TyBound::Sandwiched{ sub, mid, sup } => { + } + TyBound::Sandwiched { sub, mid, sup } => { let sub = match sub { - Type::Poly{ name, params } => { - let sub = Type::poly(name, params.into_iter().map(|p| self.instantiate_tp(p)).collect()); + Type::Poly { name, params } => { + let sub = 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) } + 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(name, params.into_iter().map(|p| self.instantiate_tp(p)).collect()); + Type::Poly { name, params } => { + let sup = 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) } + Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs), sup => sup, }; - let constraint = Constraint::Sandwiched{sub, sup}; + let constraint = Constraint::Sandwiched { sub, sup }; self.push_tyvar(Str::rc(mid.name()), Type::free_var(self.level, constraint)); - }, - TyBound::Instance{ name, t } => { + } + TyBound::Instance { name, t } => { let t = match t { - Type::Poly{ name, params } => { - let t = Type::poly(name, params.into_iter().map(|p| self.instantiate_tp(p)).collect()); + Type::Poly { name, params } => { + let t = Type::poly( + name, + params.into_iter().map(|p| self.instantiate_tp(p)).collect(), + ); t - }, + } t => t, }; // TODO: type-like types if &t == &Type { let constraint = Constraint::TypeOf(t); - self.push_tyvar(name.clone(), Type::named_free_var(name, self.level, constraint)); + self.push_tyvar( + name.clone(), + Type::named_free_var(name, self.level, constraint), + ); } else { self.push_typaram(name.clone(), TyParam::named_free_var(name, self.level, t)); } - }, + } } } @@ -196,12 +225,17 @@ impl TyVarContext { match quantified { Type::MonoQVar(n) => { if let Some(t) = self.get_tyvar(&n) { - return t.clone() + return t.clone(); } else if let Some(t) = self.get_typaram(&n) { - if let TyParam::Type(t) = t { return *t.clone() } - else { todo!() } - } else { todo!() } - }, + if let TyParam::Type(t) = t { + return *t.clone(); + } else { + todo!() + } + } else { + todo!() + } + } other => todo!("{other}"), } } @@ -210,20 +244,22 @@ impl TyVarContext { match quantified { TyParam::MonoQVar(n) => { if let Some(t) = self.get_typaram(&n) { - return t.clone() + return t.clone(); } else if let Some(t) = self.get_tyvar(&n) { - return TyParam::t(t.clone()) - } else { todo!() } - }, - TyParam::UnaryOp{ op, val } => { + return TyParam::t(t.clone()); + } else { + todo!() + } + } + TyParam::UnaryOp { op, val } => { let res = self.instantiate_tp(*val); TyParam::unary(op, res) - }, - TyParam::BinOp{ op, lhs, rhs } => { + } + TyParam::BinOp { op, lhs, rhs } => { let lhs = self.instantiate_tp(*lhs); let rhs = self.instantiate_tp(*rhs); TyParam::bin(op, lhs, rhs) - }, + } p @ TyParam::ConstObj(_) => p, other => todo!("{other}"), } @@ -259,7 +295,7 @@ pub struct Context { pub(crate) outer: Option>, // patchによってsuper class/traitになったものはここに含まれない pub(crate) super_classes: Vec, // if self is a patch, means patch classes - pub(crate) super_traits: Vec, // if self is not a trait, means implemented traits + pub(crate) super_traits: Vec, // if self is not a trait, means implemented traits // K: メソッド名, V: それを実装するパッチたち // 提供メソッドはスコープごとに実装を切り替えることができる pub(crate) _method_impl_patches: Dict>, @@ -286,7 +322,15 @@ pub struct Context { impl Default for Context { #[inline] fn default() -> Self { - Self::new("".into(), ContextKind::Dummy, vec![], None, vec![], vec![], Self::TOP_LEVEL) + Self::new( + "".into(), + ContextKind::Dummy, + vec![], + None, + vec![], + vec![], + Self::TOP_LEVEL, + ) } } @@ -316,9 +360,18 @@ impl Context { outer: Option, super_classes: Vec, super_traits: Vec, - level: usize + level: usize, ) -> Self { - Self::with_capacity(name, kind, params, outer, super_classes, super_traits, 0, level) + Self::with_capacity( + name, + kind, + params, + outer, + super_classes, + super_traits, + 0, + level, + ) } pub fn with_capacity( @@ -338,7 +391,9 @@ impl Context { if let Some(name) = param.name { let param_id = if param.default_info.has_default() { ParamId::var_default(name.into(), pos) - } else { ParamId::var_non_default(name.into(), pos) }; + } else { + ParamId::var_non_default(name.into(), pos) + }; let kind = VarKind::parameter(id, param_id); // TODO: is_const { Const } else { Immutable } let vi = VarInfo::new(param.t, Immutable, Private, kind); @@ -346,7 +401,9 @@ impl Context { } else { let param_id = if param.default_info.has_default() { ParamId::PatWithDefault(pos) - } else { ParamId::PatNonDefault(pos) }; + } else { + ParamId::PatNonDefault(pos) + }; let kind = VarKind::parameter(id, param_id); let vi = VarInfo::new(param.t, Immutable, Private, kind); unnamed_params.push(vi); @@ -382,9 +439,18 @@ impl Context { outer: Option, super_classes: Vec, super_traits: Vec, - level: usize + level: usize, ) -> Self { - Self::with_capacity(name, kind, vec![], outer, super_classes, super_traits, 0, level) + Self::with_capacity( + name, + kind, + vec![], + outer, + super_classes, + super_traits, + 0, + level, + ) } #[inline] @@ -395,19 +461,55 @@ impl Context { outer: Option, super_classes: Vec, super_traits: Vec, - level: usize + level: usize, ) -> Self { - Self::with_capacity(name, kind, params, outer, super_classes, super_traits, 0, level) + Self::with_capacity( + name, + kind, + params, + outer, + super_classes, + super_traits, + 0, + level, + ) } - pub fn poly_trait>(name: S, params: Vec, supers: Vec, level: usize) -> Self { + pub fn poly_trait>( + name: S, + params: Vec, + supers: Vec, + level: usize, + ) -> Self { let name = name.into(); - Self::poly(name, ContextKind::Trait, params, None, vec![], supers, level) + Self::poly( + name, + ContextKind::Trait, + params, + None, + vec![], + supers, + level, + ) } - pub fn poly_class>(name: S, params: Vec, super_classes: Vec, impl_traits: Vec, level: usize) -> Self { + pub fn poly_class>( + name: S, + params: Vec, + super_classes: Vec, + impl_traits: Vec, + level: usize, + ) -> Self { let name = name.into(); - Self::poly(name, ContextKind::Class, params, None, super_classes, impl_traits, level) + Self::poly( + name, + ContextKind::Class, + params, + None, + super_classes, + impl_traits, + level, + ) } #[inline] @@ -416,54 +518,113 @@ impl Context { } #[inline] - pub fn mono_class>(name: S, super_classes: Vec, super_traits: Vec, level: usize) -> Self { + pub fn mono_class>( + name: S, + super_classes: Vec, + super_traits: Vec, + level: usize, + ) -> Self { Self::poly_class(name, vec![], super_classes, super_traits, level) } #[inline] - pub fn poly_patch>(name: S, params: Vec, patch_classes: Vec, impl_traits: Vec, level: usize) -> Self { - Self::poly(name.into(), ContextKind::Trait, params, None, patch_classes, impl_traits, level) + pub fn poly_patch>( + name: S, + params: Vec, + patch_classes: Vec, + impl_traits: Vec, + level: usize, + ) -> Self { + Self::poly( + name.into(), + ContextKind::Trait, + params, + None, + patch_classes, + impl_traits, + level, + ) } #[inline] pub fn module(name: Str, capacity: usize) -> Self { - Self::with_capacity(name, ContextKind::Module, vec![], None, vec![], vec![], capacity, Self::TOP_LEVEL) + Self::with_capacity( + name, + ContextKind::Module, + vec![], + None, + vec![], + vec![], + capacity, + Self::TOP_LEVEL, + ) } #[inline] - pub fn caused_by(&self) -> Str { self.name.clone() } + pub fn caused_by(&self) -> Str { + self.name.clone() + } fn registered(&self, name: &Q, recursive: bool) -> bool - where VarName: std::borrow::Borrow { - if self.impls.contains_key(name) { return true } + where + VarName: std::borrow::Borrow, + { + if self.impls.contains_key(name) { + return true; + } if recursive { if let Some(outer) = &self.outer { outer.registered(name, recursive) - } else { false } - } else { false } + } else { + false + } + } else { + false + } } } // setters impl Context { - pub(crate) fn declare_var(&mut self, sig: &ast::VarSignature, opt_t: Option, id: Option) -> TyCheckResult<()> { + pub(crate) fn declare_var( + &mut self, + sig: &ast::VarSignature, + opt_t: Option, + id: Option, + ) -> TyCheckResult<()> { self.declare_var_pat(sig, opt_t, id) } - fn declare_var_pat(&mut self, sig: &ast::VarSignature, opt_t: Option, id: Option) -> TyCheckResult<()> { + fn declare_var_pat( + &mut self, + sig: &ast::VarSignature, + opt_t: Option, + id: Option, + ) -> TyCheckResult<()> { let vis = Private; // TODO: let muty = Mutability::from(&sig.inspect().unwrap()[..]); match &sig.pat { ast::VarPattern::VarName(v) => { if sig.t_spec.is_none() && opt_t.is_none() { - Err(TyCheckError::no_type_spec_error(sig.loc(), self.caused_by(), v.inspect())) + Err(TyCheckError::no_type_spec_error( + sig.loc(), + self.caused_by(), + v.inspect(), + )) } else { if self.registered(v, v.inspect().is_uppercase()) { - return Err(TyCheckError::duplicate_decl_error(sig.loc(), self.caused_by(), v.inspect())) + return Err(TyCheckError::duplicate_decl_error( + sig.loc(), + self.caused_by(), + v.inspect(), + )); } - let kind = id.map(|id| VarKind::Defined(id)).unwrap_or(VarKind::Declared); + let kind = id + .map(|id| VarKind::Defined(id)) + .unwrap_or(VarKind::Declared); let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?; - self.decls.insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind)); + self.decls + .insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind)); Ok(()) } } @@ -483,28 +644,53 @@ impl Context { } } - pub(crate) fn declare_sub(&mut self, sig: &ast::SubrSignature, opt_ret_t: Option, id: Option) -> TyCheckResult<()> { + pub(crate) fn declare_sub( + &mut self, + sig: &ast::SubrSignature, + opt_ret_t: Option, + id: Option, + ) -> 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(|id| VarKind::Defined(id)) + .unwrap_or(VarKind::Declared); if self.registered(name, name.is_uppercase()) { - return Err(TyCheckError::duplicate_decl_error(sig.loc(), self.caused_by(), name)) + return Err(TyCheckError::duplicate_decl_error( + sig.loc(), + self.caused_by(), + name, + )); } let t = self.instantiate_sub_sig_t(sig, opt_ret_t, PreRegister)?; let vi = VarInfo::new(t, muty, Private, kind); if let Some(_decl) = self.decls.remove(name) { - return Err(TyCheckError::duplicate_decl_error(sig.loc(), self.caused_by(), name)) + return Err(TyCheckError::duplicate_decl_error( + sig.loc(), + self.caused_by(), + name, + )); } else { self.decls.insert(sig.name.clone(), vi); } Ok(()) } - pub(crate) fn assign_var(&mut self, sig: &ast::VarSignature, id: DefId, body_t: &Type) -> TyCheckResult<()> { + pub(crate) fn assign_var( + &mut self, + sig: &ast::VarSignature, + id: DefId, + body_t: &Type, + ) -> TyCheckResult<()> { self.assign_var_sig(sig, body_t, id) } - fn assign_var_sig(&mut self, sig: &ast::VarSignature, body_t: &Type, id: DefId) -> TyCheckResult<()> { + fn assign_var_sig( + &mut self, + sig: &ast::VarSignature, + body_t: &Type, + id: DefId, + ) -> TyCheckResult<()> { self.validate_var_sig_t(sig, body_t, Normal)?; let vis = Private; // TODO: let muty = Mutability::from(&sig.inspect().unwrap()[..]); @@ -512,13 +698,21 @@ impl Context { let generalized = if !bounds.is_empty() { if self.rec_supertype_of(&Type::CallableCommon, &generalized) { Type::quantified(generalized, bounds) - } else { panic!() } - } else { generalized }; + } else { + panic!() + } + } else { + generalized + }; match &sig.pat { ast::VarPattern::Discard(_token) => Ok(()), ast::VarPattern::VarName(v) => { if self.registered(v, v.inspect().is_uppercase()) { - Err(TyCheckError::reassign_error(v.loc(), self.caused_by(), v.inspect())) + Err(TyCheckError::reassign_error( + v.loc(), + self.caused_by(), + v.inspect(), + )) } else { if let Some(_) = self.decls.remove(v.inspect()) { // something to do? @@ -537,33 +731,56 @@ impl Context { Ok(()) } ast::VarPattern::Tuple(_) => todo!(), - ast::VarPattern::Record{ .. } => todo!(), + ast::VarPattern::Record { .. } => todo!(), } } /// 宣言が既にある場合、opt_decl_tに宣言の型を渡す - fn assign_non_default_param(&mut self, sig: &ast::NonDefaultParamSignature, opt_param_pos: Option, opt_decl_t: Option<&ParamTy>) -> TyCheckResult<()> { + fn assign_non_default_param( + &mut self, + sig: &ast::NonDefaultParamSignature, + opt_param_pos: Option, + opt_decl_t: Option<&ParamTy>, + ) -> TyCheckResult<()> { match &sig.pat { ast::ParamPattern::Discard(_token) => Ok(()), ast::ParamPattern::VarName(v) => { if self.registered(v, v.inspect().is_uppercase()) { - Err(TyCheckError::reassign_error(v.loc(), self.caused_by(), v.inspect())) - } else { // ok, impl not found + Err(TyCheckError::reassign_error( + v.loc(), + self.caused_by(), + v.inspect(), + )) + } else { + // ok, impl not found let spec_t = self.instantiate_param_sig_t(sig, opt_decl_t, Normal)?; let param_id = if let Some(param_pos) = opt_param_pos { ParamId::var_non_default(v.inspect().into(), param_pos) - } else { ParamId::Embedded(v.inspect().into()) }; + } else { + ParamId::Embedded(v.inspect().into()) + }; let kind = VarKind::parameter(DefId(get_hash(&(&self.name, v))), param_id); - self.impls.insert(v.clone(), VarInfo::new(spec_t, Immutable, Private, kind)); + self.impls + .insert(v.clone(), VarInfo::new(spec_t, Immutable, Private, kind)); Ok(()) } } ast::ParamPattern::Array(arr) => { if let Some(decl_t) = opt_decl_t { - for (elem, p) in arr.elems.non_defaults.iter().zip(decl_t.ty.non_default_params().unwrap()) { + for (elem, p) in arr + .elems + .non_defaults + .iter() + .zip(decl_t.ty.non_default_params().unwrap()) + { self.assign_non_default_param(elem, None, Some(p))?; } - for (elem, p) in arr.elems.defaults.iter().zip(decl_t.ty.default_params().unwrap()) { + for (elem, p) in arr + .elems + .defaults + .iter() + .zip(decl_t.ty.default_params().unwrap()) + { self.assign_default_param(elem, None, Some(p))?; } } else { @@ -581,28 +798,51 @@ impl Context { } } - fn assign_default_param(&mut self, sig: &ast::DefaultParamSignature, opt_param_pos: Option, opt_decl_t: Option<&ParamTy>) -> TyCheckResult<()> { + fn assign_default_param( + &mut self, + sig: &ast::DefaultParamSignature, + opt_param_pos: Option, + opt_decl_t: Option<&ParamTy>, + ) -> TyCheckResult<()> { match &sig.pat { ast::ParamPattern::Discard(_token) => Ok(()), ast::ParamPattern::VarName(v) => { if self.registered(v, v.inspect().is_uppercase()) { - Err(TyCheckError::reassign_error(v.loc(), self.caused_by(), v.inspect())) - } else { // ok, impl not found + Err(TyCheckError::reassign_error( + v.loc(), + self.caused_by(), + v.inspect(), + )) + } else { + // ok, impl not found let spec_t = self.instantiate_param_sig_t(sig, opt_decl_t, Normal)?; let param_id = if let Some(param_pos) = opt_param_pos { ParamId::var_default(v.inspect().into(), param_pos) - } else { ParamId::Embedded(v.inspect().into()) }; + } else { + ParamId::Embedded(v.inspect().into()) + }; let kind = VarKind::parameter(DefId(get_hash(&(&self.name, v))), param_id); - self.impls.insert(v.clone(), VarInfo::new(spec_t, Immutable, Private, kind)); + self.impls + .insert(v.clone(), VarInfo::new(spec_t, Immutable, Private, kind)); Ok(()) } } ast::ParamPattern::Array(arr) => { if let Some(decl_t) = opt_decl_t { - for (elem, p) in arr.elems.non_defaults.iter().zip(decl_t.ty.non_default_params().unwrap()) { + for (elem, p) in arr + .elems + .non_defaults + .iter() + .zip(decl_t.ty.non_default_params().unwrap()) + { self.assign_non_default_param(elem, None, Some(p))?; } - for (elem, p) in arr.elems.defaults.iter().zip(decl_t.ty.default_params().unwrap()) { + for (elem, p) in arr + .elems + .defaults + .iter() + .zip(decl_t.ty.default_params().unwrap()) + { self.assign_default_param(elem, None, Some(p))?; } } else { @@ -620,12 +860,26 @@ impl Context { } } - pub(crate) fn assign_params(&mut self, params: &ast::Params, opt_decl_subr_t: Option) -> TyCheckResult<()> { + pub(crate) fn assign_params( + &mut self, + params: &ast::Params, + opt_decl_subr_t: Option, + ) -> TyCheckResult<()> { if let Some(decl_subr_t) = opt_decl_subr_t { - for (pos, (sig, pt)) in params.non_defaults.iter().zip(decl_subr_t.non_default_params.iter()).enumerate() { + for (pos, (sig, pt)) in params + .non_defaults + .iter() + .zip(decl_subr_t.non_default_params.iter()) + .enumerate() + { self.assign_non_default_param(sig, Some(pos), Some(pt))?; } - for (pos, (sig, pt)) in params.defaults.iter().zip(decl_subr_t.default_params.iter()).enumerate() { + for (pos, (sig, pt)) in params + .defaults + .iter() + .zip(decl_subr_t.default_params.iter()) + .enumerate() + { self.assign_default_param(sig, Some(pos), Some(pt))?; } } else { @@ -642,35 +896,68 @@ impl Context { /// ## Errors /// * TypeError: if `return_t` != typeof `body` /// * AssignError: if `name` has already been registered - pub(crate) fn assign_subr(&mut self, sig: &ast::SubrSignature, id: DefId, body_t: &Type) -> TyCheckResult<()> { - let muty = if sig.name.is_const() { Mutability::Const } else { Mutability::Immutable }; + pub(crate) fn assign_subr( + &mut self, + sig: &ast::SubrSignature, + id: DefId, + body_t: &Type, + ) -> TyCheckResult<()> { + let muty = if sig.name.is_const() { + Mutability::Const + } else { + Mutability::Immutable + }; let name = &sig.name; // FIXME: constでない関数 - let t = self.get_current_scope_local_var(&name.inspect()) + let t = self + .get_current_scope_local_var(&name.inspect()) .map(|v| &v.t) .unwrap(); let non_default_params = t.non_default_params().unwrap(); let default_params = t.default_params().unwrap(); if let Some(spec_ret_t) = t.return_t() { - self.unify(spec_ret_t, body_t, Some(sig.loc()), None).map_err(|e| { - TyCheckError::return_type_error(e.core.loc, e.caused_by, name.inspect(), spec_ret_t, body_t) - })?; + self.unify(spec_ret_t, body_t, Some(sig.loc()), None) + .map_err(|e| { + TyCheckError::return_type_error( + e.core.loc, + e.caused_by, + name.inspect(), + spec_ret_t, + body_t, + ) + })?; } if self.registered(name, name.inspect().is_uppercase()) { - Err(TyCheckError::reassign_error(name.loc(), self.caused_by(), name.inspect())) + Err(TyCheckError::reassign_error( + name.loc(), + self.caused_by(), + name.inspect(), + )) } else { let sub_t = if sig.name.is_procedural() { - Type::proc(non_default_params.clone(), default_params.clone(), body_t.clone()) + Type::proc( + non_default_params.clone(), + default_params.clone(), + body_t.clone(), + ) } else { - Type::func(non_default_params.clone(), default_params.clone(), body_t.clone()) + Type::func( + non_default_params.clone(), + default_params.clone(), + body_t.clone(), + ) }; sub_t.lift(); let (generalized, bounds) = self.generalize_t(sub_t); let found_t = if !bounds.is_empty() { if self.rec_supertype_of(&Type::CallableCommon, &generalized) { Type::quantified(generalized, bounds) - } else { panic!() } - } else { generalized }; + } else { + panic!() + } + } else { + generalized + }; if let Some(mut vi) = self.decls.remove(name) { if vi.t.has_unbound_var() { vi.t.lift(); @@ -678,8 +965,12 @@ impl Context { let generalized = if !bounds.is_empty() { if self.rec_supertype_of(&Type::CallableCommon, &generalized) { Type::quantified(generalized, bounds) - } else { panic!() } - } else { generalized }; + } else { + panic!() + } + } else { + generalized + }; vi.t = generalized; } self.decls.insert(name.clone(), vi); @@ -692,7 +983,7 @@ impl Context { name.inspect(), &vi.t, &found_t, - )) + )); } } // TODO: visibility @@ -703,14 +994,23 @@ impl Context { } } - pub(crate) fn import_mod(&mut self, var_name: &VarName, mod_name: &hir::Expr) -> TyCheckResult<()> { + pub(crate) fn import_mod( + &mut self, + var_name: &VarName, + mod_name: &hir::Expr, + ) -> TyCheckResult<()> { match mod_name { hir::Expr::Lit(lit) => { if self.rec_subtype_of(&lit.data.class(), &Str) { let name = enum_unwrap!(lit.data.clone(), ValueObj::Str); match &name[..] { - "math" => { self.mods.insert(var_name.clone(), Self::init_py_math_mod()); }, - "random" => { self.mods.insert(var_name.clone(), Self::init_py_random_mod()); }, + "math" => { + self.mods.insert(var_name.clone(), Self::init_py_math_mod()); + } + "random" => { + self.mods + .insert(var_name.clone(), Self::init_py_random_mod()); + } other => todo!("importing {other}"), } } else { @@ -719,13 +1019,17 @@ impl Context { self.caused_by(), "import::name", &Str, - mod_name.ref_t() - )) + mod_name.ref_t(), + )); } - }, + } _ => { - return Err(TyCheckError::feature_error(mod_name.loc(), "non-literal importing", self.caused_by())) - }, + return Err(TyCheckError::feature_error( + mod_name.loc(), + "non-literal importing", + self.caused_by(), + )) + } } Ok(()) } @@ -756,35 +1060,49 @@ impl Context { let bounds: Set; if let FreeKind::Linked(tp) = &mut *v.borrow_mut() { (*tp, bounds) = self._generalize_tp(tp.clone()); - } else { assume_unreachable!() } - (TyParam::FreeVar(v), bounds) - }, - // TODO: Polymorphic generalization - TyParam::FreeVar(fv) if fv.level() > Some(self.level) => { - match &*fv.borrow() { - FreeKind::Unbound{ id, constraint, .. } => { - let name = id.to_string(); - let bound = match constraint { - Constraint::SubtypeOf(sup) => TyBound::subtype(Type::mono(name.clone()), sup.clone()), - Constraint::SupertypeOf(sub) => TyBound::supertype(Type::mono(name.clone()), sub.clone()), - Constraint::Sandwiched{ sub, sup } => TyBound::sandwiched(sub.clone(), Type::mono(name.clone()), sup.clone()), - Constraint::TypeOf(t) => TyBound::instance(Str::rc(&name[..]), t.clone()), - }; - (TyParam::mono_q(&name), set!{bound}) - }, - FreeKind::NamedUnbound{ name, constraint, .. } => { - let bound = match constraint { - Constraint::SubtypeOf(sup) => TyBound::subtype(Type::mono(name.clone()), sup.clone()), - Constraint::SupertypeOf(sub) => TyBound::supertype(Type::mono(name.clone()), sub.clone()), - Constraint::Sandwiched{ sub, sup } => TyBound::sandwiched(sub.clone(), Type::mono(name.clone()), sup.clone()), - Constraint::TypeOf(t) => TyBound::instance(Str::rc(&name[..]), t.clone()), - }; - (TyParam::mono_q(name), set!{bound}) - } - _ => assume_unreachable!(), + } else { + assume_unreachable!() } + (TyParam::FreeVar(v), bounds) + } + // TODO: Polymorphic generalization + TyParam::FreeVar(fv) if fv.level() > Some(self.level) => match &*fv.borrow() { + FreeKind::Unbound { id, constraint, .. } => { + let name = id.to_string(); + let bound = match constraint { + Constraint::SubtypeOf(sup) => { + TyBound::subtype(Type::mono(name.clone()), sup.clone()) + } + Constraint::SupertypeOf(sub) => { + TyBound::supertype(Type::mono(name.clone()), sub.clone()) + } + Constraint::Sandwiched { sub, sup } => { + TyBound::sandwiched(sub.clone(), Type::mono(name.clone()), sup.clone()) + } + Constraint::TypeOf(t) => TyBound::instance(Str::rc(&name[..]), t.clone()), + }; + (TyParam::mono_q(&name), set! {bound}) + } + FreeKind::NamedUnbound { + name, constraint, .. + } => { + let bound = match constraint { + Constraint::SubtypeOf(sup) => { + TyBound::subtype(Type::mono(name.clone()), sup.clone()) + } + Constraint::SupertypeOf(sub) => { + TyBound::supertype(Type::mono(name.clone()), sub.clone()) + } + Constraint::Sandwiched { sub, sup } => { + TyBound::sandwiched(sub.clone(), Type::mono(name.clone()), sup.clone()) + } + Constraint::TypeOf(t) => TyBound::instance(Str::rc(&name[..]), t.clone()), + }; + (TyParam::mono_q(name), set! {bound}) + } + _ => assume_unreachable!(), }, - other if other.has_no_unbound_var() => (other, set!{}), + other if other.has_no_unbound_var() => (other, set! {}), other => todo!("{other}"), } } @@ -801,44 +1119,56 @@ impl Context { let bounds: Set; if let FreeKind::Linked(t) = &mut *v.borrow_mut() { (*t, bounds) = self.generalize_t(t.clone()); - } else { assume_unreachable!() } - (Type::FreeVar(v), bounds) - }, - // TODO: Polymorphic generalization - FreeVar(fv) if fv.level() > Some(self.level) => { - match &*fv.borrow() { - FreeKind::Unbound{ id, constraint, .. } => { - let name = id.to_string(); - let bound = match constraint { - Constraint::SubtypeOf(sup) => TyBound::subtype(Type::mono(name.clone()), sup.clone()), - Constraint::SupertypeOf(sub) => TyBound::supertype(Type::mono(name.clone()), sub.clone()), - Constraint::Sandwiched{ sub, sup } => - TyBound::sandwiched(sub.clone(), Type::mono(name.clone()), sup.clone()), - Constraint::TypeOf(t) => TyBound::instance(Str::rc(&name[..]), t.clone()), - }; - (Type::mono_q(&name), set!{bound}) - }, - FreeKind::NamedUnbound{ name, constraint, .. } => { - let bound = match constraint { - Constraint::SubtypeOf(sup) => TyBound::subtype(Type::mono(name.clone()), sup.clone()), - Constraint::SupertypeOf(sub) => TyBound::supertype(Type::mono(name.clone()), sub.clone()), - Constraint::Sandwiched{ sub, sup } => - TyBound::sandwiched(sub.clone(), Type::mono(name.clone()), sup.clone()), - Constraint::TypeOf(t) => TyBound::instance(Str::rc(&name[..]), t.clone()), - }; - (Type::mono_q(name), set!{bound}) - } - _ => assume_unreachable!(), + } else { + assume_unreachable!() } + (Type::FreeVar(v), bounds) + } + // TODO: Polymorphic generalization + FreeVar(fv) if fv.level() > Some(self.level) => match &*fv.borrow() { + FreeKind::Unbound { id, constraint, .. } => { + let name = id.to_string(); + let bound = match constraint { + Constraint::SubtypeOf(sup) => { + TyBound::subtype(Type::mono(name.clone()), sup.clone()) + } + Constraint::SupertypeOf(sub) => { + TyBound::supertype(Type::mono(name.clone()), sub.clone()) + } + Constraint::Sandwiched { sub, sup } => { + TyBound::sandwiched(sub.clone(), Type::mono(name.clone()), sup.clone()) + } + Constraint::TypeOf(t) => TyBound::instance(Str::rc(&name[..]), t.clone()), + }; + (Type::mono_q(&name), set! {bound}) + } + FreeKind::NamedUnbound { + name, constraint, .. + } => { + let bound = match constraint { + Constraint::SubtypeOf(sup) => { + TyBound::subtype(Type::mono(name.clone()), sup.clone()) + } + Constraint::SupertypeOf(sub) => { + TyBound::supertype(Type::mono(name.clone()), sub.clone()) + } + Constraint::Sandwiched { sub, sup } => { + TyBound::sandwiched(sub.clone(), Type::mono(name.clone()), sup.clone()) + } + Constraint::TypeOf(t) => TyBound::instance(Str::rc(&name[..]), t.clone()), + }; + (Type::mono_q(name), set! {bound}) + } + _ => assume_unreachable!(), }, Subr(mut subr) => { - let mut bounds = set!{}; + let mut bounds = set! {}; let kind = match subr.kind { SubrKind::FuncMethod(self_t) => { let (t, bs) = self.generalize_t(*self_t); bounds.merge(bs); SubrKind::fn_met(t) - }, + } SubrKind::ProcMethod { before, after } => { let (before, bs) = self.generalize_t(*before); bounds.merge(bs); @@ -849,35 +1179,37 @@ impl Context { } else { SubrKind::pr_met(before, None) } - }, + } other => other, }; - subr.non_default_params.iter_mut() - .for_each(|p| { - let (t, bs) = self.generalize_t(mem::take(&mut p.ty)); - p.ty = t; - bounds.merge(bs); - }); - subr.default_params.iter_mut() - .for_each(|p| { - let (t, bs) = self.generalize_t(mem::take(&mut p.ty)); - p.ty = t; - bounds.merge(bs); - }); + subr.non_default_params.iter_mut().for_each(|p| { + let (t, bs) = self.generalize_t(mem::take(&mut p.ty)); + p.ty = t; + bounds.merge(bs); + }); + subr.default_params.iter_mut().for_each(|p| { + let (t, bs) = self.generalize_t(mem::take(&mut p.ty)); + p.ty = t; + bounds.merge(bs); + }); let (return_t, bs) = self.generalize_t(*subr.return_t); bounds.merge(bs); - (Type::subr(kind, subr.non_default_params, subr.default_params, return_t), bounds) - }, + ( + Type::subr(kind, subr.non_default_params, subr.default_params, return_t), + bounds, + ) + } // REVIEW: その他何でもそのまま通していいのか? - other => (other, set!{}), + other => (other, set! {}), } } pub(crate) fn bounds(&self) -> Set { - self.impls.iter() - .filter(|(_, vi)| vi.kind.is_parameter()) - .map(|(name, vi)| TyBound::instance(name.inspect().clone(), vi.t.clone())) - .collect() + self.impls + .iter() + .filter(|(_, vi)| vi.kind.is_parameter()) + .map(|(name, vi)| TyBound::instance(name.inspect().clone(), vi.t.clone())) + .collect() } fn instantiate_tp(quantified: TyParam, tv_ctx: TyVarContext) -> (TyParam, TyVarContext) { @@ -890,27 +1222,30 @@ impl Context { } else { panic!("type parameter {n} is not defined") } - }, - TyParam::UnaryOp{ op, val } => { + } + TyParam::UnaryOp { op, val } => { let (res, tv_ctx) = Self::instantiate_tp(*val, tv_ctx); (TyParam::unary(op, res), tv_ctx) - }, - TyParam::BinOp{ op, lhs, rhs } => { + } + TyParam::BinOp { op, lhs, rhs } => { let (lhs, tv_ctx) = Self::instantiate_tp(*lhs, tv_ctx); let (rhs, tv_ctx) = Self::instantiate_tp(*rhs, tv_ctx); (TyParam::bin(op, lhs, rhs), tv_ctx) - }, + } TyParam::Type(t) => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); (TyParam::t(t), tv_ctx) - }, + } p @ (TyParam::ConstObj(_) | TyParam::Mono(_)) => (p, tv_ctx), other => todo!("{other}"), } } /// 'T -> ?T (quantified to free) - pub(crate) fn instantiate_t(quantified: Type, mut tv_ctx: TyVarContext) -> (Type, TyVarContext) { + pub(crate) fn instantiate_t( + quantified: Type, + mut tv_ctx: TyVarContext, + ) -> (Type, TyVarContext) { match quantified { MonoQVar(n) => { if let Some(t) = tv_ctx.get_tyvar(&n) { @@ -920,30 +1255,34 @@ impl Context { } else { panic!("the type variable {n} is not defined") } - }, - PolyQVar{ name, mut params } => { + } + PolyQVar { name, mut params } => { for param in params.iter_mut() { (*param, tv_ctx) = Self::instantiate_tp(mem::take(param), tv_ctx); } (Type::poly_q(name, params), tv_ctx) - }, + } Refinement(mut refine) => { - refine.preds = refine.preds.into_iter().map(|mut pred| { - for tp in pred.typarams_mut() { - (*tp, tv_ctx) = Self::instantiate_tp(mem::take(tp), tv_ctx.clone()); - } - pred - }).collect(); + refine.preds = refine + .preds + .into_iter() + .map(|mut pred| { + for tp in pred.typarams_mut() { + (*tp, tv_ctx) = Self::instantiate_tp(mem::take(tp), tv_ctx.clone()); + } + pred + }) + .collect(); (Type::Refinement(refine), tv_ctx) - }, + } Subr(mut subr) => { let kind = match subr.kind { - SubrKind::FuncMethod(self_t) => { + SubrKind::FuncMethod(self_t) => { let (res, _tv_ctx) = Self::instantiate_t(*self_t, tv_ctx); tv_ctx = _tv_ctx; SubrKind::FuncMethod(Box::new(res)) } - SubrKind::ProcMethod{ before, after } => { + SubrKind::ProcMethod { before, after } => { let (before, _tv_ctx) = Self::instantiate_t(*before, tv_ctx); let (after, _tv_ctx) = if let Some(after) = after { let (after, _tv_ctx) = Self::instantiate_t(*after, _tv_ctx); @@ -963,63 +1302,66 @@ impl Context { (p.ty, tv_ctx) = Self::instantiate_t(mem::take(&mut p.ty), tv_ctx); } let (return_t, tv_ctx) = Self::instantiate_t(*subr.return_t, tv_ctx); - (Type::subr(kind, subr.non_default_params, subr.default_params, return_t), tv_ctx) - }, - Type::Array{ t, len } => { + ( + Type::subr(kind, subr.non_default_params, subr.default_params, return_t), + tv_ctx, + ) + } + Type::Array { t, len } => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); let (len, tv_ctx) = Self::instantiate_tp(len, tv_ctx); (Type::array(t, len), tv_ctx) - }, - Type::Dict{ k, v } => { + } + Type::Dict { k, v } => { let (k, tv_ctx) = Self::instantiate_t(*k, tv_ctx); let (v, tv_ctx) = Self::instantiate_t(*v, tv_ctx); (Type::dict(k, v), tv_ctx) - }, + } Tuple(mut ts) => { for t in ts.iter_mut() { (*t, tv_ctx) = Self::instantiate_t(mem::take(t), tv_ctx); } (Type::Tuple(ts), tv_ctx) - }, + } Record(mut dict) => { for v in dict.values_mut() { (*v, tv_ctx) = Self::instantiate_t(mem::take(v), tv_ctx); } (Type::Record(dict), tv_ctx) - }, + } Range(t) => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); (Type::range(t), tv_ctx) - }, + } Iter(t) => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); (Type::iter(t), tv_ctx) - }, + } Option(t) => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); (Type::option(t), tv_ctx) - }, + } OptionMut(t) => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); (Type::option_mut(t), tv_ctx) - }, + } Ref(t) => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); (Type::refer(t), tv_ctx) - }, + } RefMut(t) => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); (Type::ref_mut(t), tv_ctx) - }, + } VarArgs(t) => { let (t, tv_ctx) = Self::instantiate_t(*t, tv_ctx); (Type::var_args(t), tv_ctx) } - MonoProj{ lhs, rhs } => { + MonoProj { lhs, rhs } => { let (lhs, tv_ctx) = Self::instantiate_t(*lhs, tv_ctx); (Type::mono_proj(lhs, rhs), tv_ctx) } - Poly{ name, mut params } => { + Poly { name, mut params } => { for param in params.iter_mut() { (*param, tv_ctx) = Self::instantiate_tp(mem::take(param), tv_ctx); } @@ -1040,17 +1382,17 @@ impl Context { match (subr.kind.self_t(), callee.receiver_t()) { (Some(l), Some(r)) => { self.unify(l, r, None, Some(callee.loc()))?; - }, + } // if callee is a Module object or some named one - (None, Some(r)) if self.rec_subtype_of(r, &Type::mono("Named")) => {}, - (None, None) => {}, + (None, Some(r)) if self.rec_subtype_of(r, &Type::mono("Named")) => {} + (None, None) => {} (l, r) => todo!("{l:?}, {r:?}"), } } _ => unreachable!(), } Ok(t) - }, + } // rank-1制限により、通常の型(rank-0型)の内側に量化型は存在しない other => Ok(other), } @@ -1063,12 +1405,16 @@ impl Context { /// substitute_call(instance: ((?M(: Nat)..?N(: Nat)) -> ?M+?N), [1..2], []) => instance: (1..2) -> {3} /// substitute_call(instance: ((?L(: Add(?R, ?O)), ?R) -> ?O), [1, 2], []) => instance: (Nat, Nat) -> Nat /// ``` - fn substitute_call(&self, callee: &hir::Expr, instance: &Type, pos_args: &[hir::PosArg], kw_args: &[hir::KwArg]) -> TyCheckResult<()> { + fn substitute_call( + &self, + callee: &hir::Expr, + instance: &Type, + pos_args: &[hir::PosArg], + kw_args: &[hir::KwArg], + ) -> TyCheckResult<()> { match instance { Type::Subr(subr) => { - let params_len = - subr.non_default_params.len() - + subr.default_params.len(); + let params_len = subr.non_default_params.len() + subr.default_params.len(); if params_len < pos_args.len() + kw_args.len() { return Err(TyCheckError::too_many_args_error( callee.loc(), @@ -1077,21 +1423,31 @@ impl Context { params_len, pos_args.len(), kw_args.len(), - )) + )); } - let mut passed_params = set!{}; - let params = subr.non_default_params.iter().chain(subr.default_params.iter()); + let mut passed_params = set! {}; + let params = subr + .non_default_params + .iter() + .chain(subr.default_params.iter()); for (param_ty, pos_arg) in params.clone().zip(pos_args) { - self.sub_unify(pos_arg.expr.ref_t(), ¶m_ty.ty, None, Some(pos_arg.loc())).map_err(|e| { + self.sub_unify( + pos_arg.expr.ref_t(), + ¶m_ty.ty, + None, + Some(pos_arg.loc()), + ) + .map_err(|e| { // REVIEW: let name = callee.var_full_name().unwrap_or("".to_string()); - let name = name + "::" + param_ty.name.as_ref().map(|s| &s[..]).unwrap_or(""); + let name = + name + "::" + param_ty.name.as_ref().map(|s| &s[..]).unwrap_or(""); TyCheckError::type_mismatch_error( e.core.loc, e.caused_by, &name[..], ¶m_ty.ty, - pos_arg.expr.ref_t() + pos_arg.expr.ref_t(), ) })?; if let Some(name) = ¶m_ty.name { @@ -1101,7 +1457,7 @@ impl Context { &callee.to_string(), self.caused_by(), name, - )) + )); } else { passed_params.insert(name); } @@ -1124,12 +1480,12 @@ impl Context { kw_arg.keyword.loc(), &callee.to_string(), self.caused_by(), - kw_arg.keyword.inspect() - )) + kw_arg.keyword.inspect(), + )); } } Ok(()) - }, + } other => todo!("{other}"), } } @@ -1139,11 +1495,11 @@ impl Context { match tp { TyParam::FreeVar(fv) if fv.is_linked() => Ok(fv.unwrap()), TyParam::Type(t) => Ok(TyParam::t(Self::eliminate_linked_vars(*t)?)), - TyParam::App{ name, mut args } => { + TyParam::App { name, mut args } => { for param in args.iter_mut() { *param = Self::eliminate_linked_tp(mem::take(param))?; } - Ok(TyParam::App{ name, args }) + Ok(TyParam::App { name, args }) } t => Ok(t), } @@ -1156,35 +1512,39 @@ impl Context { // 未連携型変数のチェックはモジュール全体の型検査が終わった後にやる // Type::FreeVar(_) => // Err(TyCheckError::checker_bug(0, Location::Unknown, fn_name!(), line!())), - Type::Poly{ name, mut params } => { + Type::Poly { name, mut params } => { for param in params.iter_mut() { *param = Self::eliminate_linked_tp(mem::take(param))?; } Ok(Type::poly(name, params)) - }, - Type::Array{ mut t, mut len } => { + } + Type::Array { mut t, mut len } => { let t = Self::eliminate_linked_vars(mem::take(&mut t))?; let len = Self::eliminate_linked_tp(mem::take(&mut len))?; Ok(Type::array(t, len)) - }, + } Type::Subr(mut subr) => { match &mut subr.kind { SubrKind::FuncMethod(t) => { *t = Box::new(Self::eliminate_linked_vars(mem::take(t))?); - }, - SubrKind::ProcMethod{ before, after } => { + } + SubrKind::ProcMethod { before, after } => { *before = Box::new(Self::eliminate_linked_vars(mem::take(before))?); if let Some(after) = after { *after = Box::new(Self::eliminate_linked_vars(mem::take(after))?); } - }, - _ => {}, + } + _ => {} } - let params = subr.non_default_params.iter_mut().chain(subr.default_params.iter_mut()); + let params = subr + .non_default_params + .iter_mut() + .chain(subr.default_params.iter_mut()); for param in params { param.ty = Self::eliminate_linked_vars(mem::take(&mut param.ty))?; } - subr.return_t = Box::new(Self::eliminate_linked_vars(mem::take(&mut subr.return_t))?); + subr.return_t = + Box::new(Self::eliminate_linked_vars(mem::take(&mut subr.return_t))?); Ok(Type::Subr(subr)) } t => Ok(t), @@ -1194,53 +1554,64 @@ 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)?; - }, - _ => {}, + 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)?; } + _ => {} }, - _ => {}, + _ => {} } Ok(()) } - fn _occur(&self, _t: Type) -> TyCheckResult { todo!() } + fn _occur(&self, _t: Type) -> TyCheckResult { + todo!() + } /// allow_divergence = trueにすると、Num型変数と±Infの単一化を許す - pub(crate) fn unify_tp(&self, l: &TyParam, r: &TyParam, bounds: Option<&Set>, allow_divergence: bool) -> TyCheckResult<()> { - if l.has_no_unbound_var() && r.has_no_unbound_var() && l.rec_eq(r) { return Ok(()) } + pub(crate) fn unify_tp( + &self, + l: &TyParam, + r: &TyParam, + bounds: Option<&Set>, + allow_divergence: bool, + ) -> TyCheckResult<()> { + if l.has_no_unbound_var() && r.has_no_unbound_var() && l.rec_eq(r) { + return Ok(()); + } match (l, r) { - (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() => { - if lfv.level().unwrap() > rfv.level().unwrap() { lfv.link(rtp); } - else { rfv.link(ltp); } + (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() => + { + if lfv.level().unwrap() > rfv.level().unwrap() { + lfv.link(rtp); + } else { + rfv.link(ltp); + } Ok(()) - }, - (TyParam::FreeVar(fv), tp) - | (tp, TyParam::FreeVar(fv)) => { + } + (TyParam::FreeVar(fv), tp) | (tp, TyParam::FreeVar(fv)) => { match &*fv.borrow() { - FreeKind::Linked(l) => { return self.unify_tp(l, tp, bounds, allow_divergence) }, - FreeKind::Unbound{ .. } | FreeKind::NamedUnbound{ .. } => {}, + FreeKind::Linked(l) => return self.unify_tp(l, tp, bounds, allow_divergence), + FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {} } // &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)?; if self.rec_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()); - if self.is_sub_constraint_of(fv.borrow().constraint().unwrap(), &new_constraint) - || fv.borrow().constraint().unwrap().typ() == Some(&Type) { + if self.is_sub_constraint_of( + fv.borrow().constraint().unwrap(), + &new_constraint, + ) || fv.borrow().constraint().unwrap().typ() == Some(&Type) + { fv.update_constraint(new_constraint); } } else { @@ -1249,57 +1620,72 @@ impl Context { Ok(()) } else { if allow_divergence - && ( - self.eq_tp(&tp, &TyParam::value(Inf), None) - || self.eq_tp(&tp, &TyParam::value(NegInf), None) - ) && self.rec_subtype_of(&fv_t, &Type::mono("Num")) { + && (self.eq_tp(&tp, &TyParam::value(Inf), None) + || self.eq_tp(&tp, &TyParam::value(NegInf), None)) + && self.rec_subtype_of(&fv_t, &Type::mono("Num")) + { fv.link(tp); Ok(()) } else { Err(TyCheckError::unreachable(fn_name!(), line!())) } } - }, - ( TyParam::UnaryOp{ op: lop, val: lval }, - TyParam::UnaryOp{ op: rop, val: rval } - ) if lop == rop => { + } + (TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval }) + if lop == rop => + { self.unify_tp(lval, rval, bounds, allow_divergence) - }, + } ( - TyParam::BinOp{ op: lop, lhs, rhs }, - TyParam::BinOp{ op: rop, lhs: lhs2, rhs: rhs2 } + TyParam::BinOp { op: lop, lhs, rhs }, + TyParam::BinOp { + op: rop, + lhs: lhs2, + rhs: rhs2, + }, ) if lop == rop => { self.unify_tp(lhs, lhs2, bounds, allow_divergence)?; self.unify_tp(rhs, rhs2, bounds, allow_divergence) - }, + } (l, r) => panic!("type-parameter unification failed:\nl:{l}\nr: {r}"), } } - fn reunify_tp(&self, before: &TyParam, after: &TyParam, bounds: Option<&Set>) -> TyCheckResult<()> { + fn reunify_tp( + &self, + before: &TyParam, + after: &TyParam, + bounds: Option<&Set>, + ) -> TyCheckResult<()> { match (before, after) { - (TyParam::ConstObj(ConstObj::MutValue(l)),TyParam::ConstObj(ConstObj::Value(r))) => { + (TyParam::ConstObj(ConstObj::MutValue(l)), TyParam::ConstObj(ConstObj::Value(r))) => { *l.borrow_mut() = r.clone(); Ok(()) - }, - (TyParam::ConstObj(ConstObj::MutValue(l)),TyParam::ConstObj(ConstObj::MutValue(r))) => { + } + ( + TyParam::ConstObj(ConstObj::MutValue(l)), + TyParam::ConstObj(ConstObj::MutValue(r)), + ) => { *l.borrow_mut() = r.borrow().clone(); Ok(()) - }, - (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 => { + } + (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 => + { self.reunify_tp(lval, rval, bounds) - }, + } ( - TyParam::BinOp{ op: lop, lhs, rhs }, - TyParam::BinOp{ op: rop, lhs: lhs2, rhs: rhs2 } + TyParam::BinOp { op: lop, lhs, rhs }, + TyParam::BinOp { + op: rop, + lhs: lhs2, + rhs: rhs2, + }, ) if lop == rop => { self.reunify_tp(lhs, lhs2, bounds)?; self.reunify_tp(rhs, rhs2, bounds) - }, + } (l, r) if self.eq_tp(l, r, None) => Ok(()), (l, r) => panic!("type-parameter re-unification failed:\nl: {l}\nr: {r}"), } @@ -1308,77 +1694,117 @@ impl Context { /// predは正規化されているとする fn unify_pred(&self, l_pred: &Predicate, r_pred: &Predicate) -> TyCheckResult<()> { match (l_pred, r_pred) { - (Pred::Value(_), Pred::Value(_)) - | (Pred::Const(_), Pred::Const(_)) => Ok(()), - (Pred::Equal{ rhs, .. }, Pred::Equal{ rhs: rhs2, .. }) - | (Pred::GreaterEqual{ rhs, .. }, Pred::GreaterEqual{ rhs: rhs2, .. }) - | (Pred::LessEqual{ rhs, .. }, Pred::LessEqual{ rhs: rhs2, .. }) - | (Pred::NotEqual{ rhs, .. }, Pred::NotEqual{ rhs: rhs2, .. }) => - self.unify_tp(rhs, rhs2, None, false), + (Pred::Value(_), Pred::Value(_)) | (Pred::Const(_), Pred::Const(_)) => Ok(()), + (Pred::Equal { rhs, .. }, Pred::Equal { rhs: rhs2, .. }) + | (Pred::GreaterEqual { rhs, .. }, Pred::GreaterEqual { rhs: rhs2, .. }) + | (Pred::LessEqual { rhs, .. }, Pred::LessEqual { rhs: rhs2, .. }) + | (Pred::NotEqual { rhs, .. }, Pred::NotEqual { rhs: rhs2, .. }) => { + self.unify_tp(rhs, rhs2, None, false) + } (Pred::And(l1, r1), Pred::And(l2, r2)) | (Pred::Or(l1, r1), Pred::Or(l2, r2)) - | (Pred::Not(l1, r1), Pred::Not(l2, r2)) => + | (Pred::Not(l1, r1), Pred::Not(l2, r2)) => { match (self.unify_pred(l1, l2), self.unify_pred(r1, r2)) { (Ok(()), Ok(())) => Ok(()), - (Ok(()), Err(e)) | (Err(e), Ok(())) - | (Err(e), Err(_)) => Err(e), + (Ok(()), Err(e)) | (Err(e), Ok(())) | (Err(e), Err(_)) => Err(e), } + } // unify({I >= 0}, {I >= ?M and I <= ?N}): ?M => 0, ?N => Inf - (Pred::GreaterEqual{ rhs, .. }, Pred::And(l , r)) - | (Predicate::And(l, r), Pred::GreaterEqual{ rhs, .. }) => match (l.as_ref(), r.as_ref()) { - (Pred::GreaterEqual{ rhs: ge_rhs, .. }, Pred::LessEqual{ rhs: le_rhs, .. }) - | (Pred::LessEqual{ rhs: le_rhs, .. }, Pred::GreaterEqual{ rhs: ge_rhs, .. }) => { - self.unify_tp(rhs, ge_rhs, None, false)?; - self.unify_tp(le_rhs, &TyParam::value(Inf), None, true) - }, - _ => Err(TyCheckError::pred_unification_error(l_pred, r_pred, self.caused_by())), - }, - (Pred::LessEqual{ rhs, .. }, Pred::And(l , r)) - | (Pred::And(l, r), Pred::LessEqual{ rhs, .. }) => match (l.as_ref(), r.as_ref()) { - (Pred::GreaterEqual{ rhs: ge_rhs, .. }, Pred::LessEqual{ rhs: le_rhs, .. }) - | (Pred::LessEqual{ rhs: le_rhs, .. }, Pred::GreaterEqual{ rhs: ge_rhs, .. }) => { + (Pred::GreaterEqual { rhs, .. }, Pred::And(l, r)) + | (Predicate::And(l, r), Pred::GreaterEqual { rhs, .. }) => { + match (l.as_ref(), r.as_ref()) { + ( + Pred::GreaterEqual { rhs: ge_rhs, .. }, + Pred::LessEqual { rhs: le_rhs, .. }, + ) + | ( + Pred::LessEqual { rhs: le_rhs, .. }, + Pred::GreaterEqual { rhs: ge_rhs, .. }, + ) => { + self.unify_tp(rhs, ge_rhs, None, false)?; + self.unify_tp(le_rhs, &TyParam::value(Inf), None, true) + } + _ => Err(TyCheckError::pred_unification_error( + l_pred, + r_pred, + self.caused_by(), + )), + } + } + (Pred::LessEqual { rhs, .. }, Pred::And(l, r)) + | (Pred::And(l, r), Pred::LessEqual { rhs, .. }) => match (l.as_ref(), r.as_ref()) { + (Pred::GreaterEqual { rhs: ge_rhs, .. }, Pred::LessEqual { rhs: le_rhs, .. }) + | (Pred::LessEqual { rhs: le_rhs, .. }, Pred::GreaterEqual { rhs: ge_rhs, .. }) => { self.unify_tp(rhs, le_rhs, None, false)?; self.unify_tp(ge_rhs, &TyParam::value(NegInf), None, true) - }, - _ => Err(TyCheckError::pred_unification_error(l_pred, r_pred, self.caused_by())), + } + _ => Err(TyCheckError::pred_unification_error( + l_pred, + r_pred, + self.caused_by(), + )), }, - (Pred::Equal{ rhs, .. }, Pred::And(l , r)) - | (Pred::And(l, r), Pred::Equal{ rhs, .. }) => match (l.as_ref(), r.as_ref()) { - (Pred::GreaterEqual{ rhs: ge_rhs, .. }, Pred::LessEqual{ rhs: le_rhs, .. }) - | (Pred::LessEqual{ rhs: le_rhs, .. }, Pred::GreaterEqual{ rhs: ge_rhs, .. }) => { + (Pred::Equal { rhs, .. }, Pred::And(l, r)) + | (Pred::And(l, r), Pred::Equal { rhs, .. }) => match (l.as_ref(), r.as_ref()) { + (Pred::GreaterEqual { rhs: ge_rhs, .. }, Pred::LessEqual { rhs: le_rhs, .. }) + | (Pred::LessEqual { rhs: le_rhs, .. }, Pred::GreaterEqual { rhs: ge_rhs, .. }) => { self.unify_tp(rhs, le_rhs, None, false)?; self.unify_tp(rhs, ge_rhs, None, false) - }, - _ => Err(TyCheckError::pred_unification_error(l_pred, r_pred, self.caused_by())), + } + _ => Err(TyCheckError::pred_unification_error( + l_pred, + r_pred, + self.caused_by(), + )), }, - _ => Err(TyCheckError::pred_unification_error(l_pred, r_pred, self.caused_by())), + _ => Err(TyCheckError::pred_unification_error( + l_pred, + r_pred, + self.caused_by(), + )), } } /// By default, all type variables are instances of Class ('T: Nominal) /// So `unify(?T, Int); unify(?T, Bool)` will causes an error /// To bypass the constraint, you need to specify `'T: Structural` in the type bounds - pub(crate) fn unify(&self, lhs_t: &Type, rhs_t: &Type, lhs_loc: Option, rhs_loc: Option) -> TyCheckResult<()> { + pub(crate) fn unify( + &self, + lhs_t: &Type, + rhs_t: &Type, + lhs_loc: Option, + rhs_loc: Option, + ) -> TyCheckResult<()> { if lhs_t.has_no_unbound_var() - && rhs_t.has_no_unbound_var() - && self.rec_supertype_of(lhs_t, rhs_t) { return Ok(()) } + && rhs_t.has_no_unbound_var() + && self.rec_supertype_of(lhs_t, rhs_t) + { + return Ok(()); + } match (lhs_t, rhs_t) { // unify(?T[2], ?U[3]): ?U[3] => ?T[2] // bind the higher level var to lower one (lt @ Type::FreeVar(lfv), rt @ Type::FreeVar(rfv)) - if lfv.is_unbound() && rfv.is_unbound() => { - if lfv.level().unwrap() > rfv.level().unwrap() { lfv.link(rt); } - else { rfv.link(lt); } + if lfv.is_unbound() && rfv.is_unbound() => + { + if lfv.level().unwrap() > rfv.level().unwrap() { + lfv.link(rt); + } else { + rfv.link(lt); + } Ok(()) - }, + } // unify(?L(<: Add(?R, ?O)), Nat): (?R => Nat, ?O => Nat, ?L => Nat) // unify(?A(<: Mutate), [?T; 0]): (?A => [?T; 0]) - (Type::FreeVar(fv), t) - | (t, Type::FreeVar(fv)) => { + (Type::FreeVar(fv), t) | (t, Type::FreeVar(fv)) => { match &mut *fv.borrow_mut() { - FreeKind::Linked(l) => { return self.unify(l, t, lhs_loc, rhs_loc) }, - FreeKind::Unbound{ lev, constraint, .. } - | FreeKind::NamedUnbound{ lev, constraint, .. } => { + FreeKind::Linked(l) => return self.unify(l, t, lhs_loc, rhs_loc), + FreeKind::Unbound { + lev, constraint, .. + } + | FreeKind::NamedUnbound { + lev, constraint, .. + } => { t.update_level(*lev); // TODO: constraint.type_of() if let Some(sup) = constraint.super_type_mut() { @@ -1390,24 +1816,31 @@ impl Context { self.sub_unify(t, sup, rhs_loc, lhs_loc)?; } } - }, + } } // &fv is dropped let new_constraint = Constraint::SubtypeOf(t.clone()); // 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md) // fv == ?T(: Type)の場合は?T(<: U)にする if fv.level() < Some(self.level) { if self.is_sub_constraint_of(fv.borrow().constraint().unwrap(), &new_constraint) - || fv.borrow().constraint().unwrap().typ() == Some(&Type) { + || fv.borrow().constraint().unwrap().typ() == Some(&Type) + { fv.update_constraint(new_constraint); } } else { fv.link(t); } Ok(()) - }, + } (Type::Refinement(l), Type::Refinement(r)) => { if !self.supertype_of(&l.t, &r.t, None) && !self.supertype_of(&r.t, &l.t, None) { - return Err(TyCheckError::unification_error(lhs_t, rhs_t, lhs_loc, rhs_loc, self.caused_by())) + return Err(TyCheckError::unification_error( + lhs_t, + rhs_t, + lhs_loc, + rhs_loc, + self.caused_by(), + )); } // FIXME: 正規化する for l_pred in l.preds.iter() { @@ -1416,24 +1849,28 @@ impl Context { } } Ok(()) - }, + } (Type::Refinement(_), r) => { let rhs_t = self.into_refinement(r.clone()); self.unify(lhs_t, &Type::Refinement(rhs_t), lhs_loc, rhs_loc) - }, + } (l, Type::Refinement(_)) => { let lhs_t = self.into_refinement(l.clone()); self.unify(&Type::Refinement(lhs_t), rhs_t, lhs_loc, rhs_loc) - }, + } (Type::Subr(ls), Type::Subr(rs)) if ls.kind.same_kind_as(&rs.kind) => { if let (Some(l), Some(r)) = (ls.kind.self_t(), rs.kind.self_t()) { self.unify(l, r, lhs_loc, rhs_loc)?; } - for (l, r) in ls.non_default_params.iter().zip(rs.non_default_params.iter()) { + for (l, r) in ls + .non_default_params + .iter() + .zip(rs.non_default_params.iter()) + { self.unify(&l.ty, &r.ty, lhs_loc, rhs_loc)?; } self.unify(&ls.return_t, &rs.return_t, lhs_loc, rhs_loc) - }, + } (Range(l), Range(r)) | (Iter(l), Iter(r)) | (Type::Ref(l), Type::Ref(r)) @@ -1442,34 +1879,62 @@ impl Context { | (OptionMut(l), OptionMut(r)) | (VarArgs(l), VarArgs(r)) => self.unify(l, r, lhs_loc, rhs_loc), // REVIEW: - (Type::Ref(l), r) - | (Type::RefMut(l), r) => self.unify(l, r, lhs_loc, rhs_loc), - (l, Type::Ref(r)) - | (l, Type::RefMut(r)) => self.unify(l, r, lhs_loc, rhs_loc), - (Type::Poly{ name: ln, params: lps }, Type::Poly{ name: rn, params: rps }) => { - if ln != rn { return Err(TyCheckError::unification_error(lhs_t, rhs_t, lhs_loc, rhs_loc, self.caused_by())) } + (Type::Ref(l), r) | (Type::RefMut(l), r) => self.unify(l, r, lhs_loc, rhs_loc), + (l, Type::Ref(r)) | (l, Type::RefMut(r)) => self.unify(l, r, lhs_loc, rhs_loc), + ( + Type::Poly { + name: ln, + params: lps, + }, + Type::Poly { + name: rn, + params: rps, + }, + ) => { + if ln != rn { + return Err(TyCheckError::unification_error( + lhs_t, + rhs_t, + lhs_loc, + rhs_loc, + self.caused_by(), + )); + } for (l, r) in lps.iter().zip(rps.iter()) { self.unify_tp(l, r, None, false)?; } Ok(()) - }, - (Type::Poly{ name: _, params: _ }, _r) => { + } + (Type::Poly { name: _, params: _ }, _r) => { todo!() - }, - (l, r) => - Err(TyCheckError::unification_error(l, r, lhs_loc, rhs_loc, self.caused_by())), + } + (l, r) => Err(TyCheckError::unification_error( + l, + r, + lhs_loc, + rhs_loc, + self.caused_by(), + )), } } /// T: Array(Int, !0), U: Array(Int, !1) /// reunify(T, U): /// T: Array(Int, !1), U: Array(Int, !1) - pub(crate) fn reunify(&self, before_t: &Type, after_t: &Type, bef_loc: Option, aft_loc: Option) -> TyCheckResult<()> { + pub(crate) fn reunify( + &self, + before_t: &Type, + after_t: &Type, + bef_loc: Option, + aft_loc: Option, + ) -> TyCheckResult<()> { match (before_t, after_t) { - (Type::FreeVar(fv), r) if fv.is_linked() => - self.reunify(&fv.crack(), r, bef_loc, aft_loc), - (l, Type::FreeVar(fv)) if fv.is_linked() => - self.reunify(l, &fv.crack(), bef_loc, aft_loc), + (Type::FreeVar(fv), r) if fv.is_linked() => { + self.reunify(&fv.crack(), r, bef_loc, aft_loc) + } + (l, Type::FreeVar(fv)) if fv.is_linked() => { + self.reunify(l, &fv.crack(), bef_loc, aft_loc) + } (Type::Range(l), Type::Range(r)) | (Type::Iter(l), Type::Iter(r)) | (Type::Ref(l), Type::Ref(r)) @@ -1478,23 +1943,41 @@ impl Context { | (Type::OptionMut(l), Type::OptionMut(r)) | (Type::VarArgs(l), Type::VarArgs(r)) => self.reunify(l, r, bef_loc, aft_loc), // REVIEW: - (Type::Ref(l), r) - | (Type::RefMut(l), r) => self.reunify(l, r, bef_loc, aft_loc), - (l, Type::Ref(r)) - | (l, Type::RefMut(r)) => self.reunify(l, r, bef_loc, aft_loc), - (Type::Poly{ name: ln, params: lps }, Type::Poly{ name: rn, params: rps }) => { + (Type::Ref(l), r) | (Type::RefMut(l), r) => self.reunify(l, r, bef_loc, aft_loc), + (l, Type::Ref(r)) | (l, Type::RefMut(r)) => self.reunify(l, r, bef_loc, aft_loc), + ( + Type::Poly { + name: ln, + params: lps, + }, + Type::Poly { + name: rn, + params: rps, + }, + ) => { if ln != rn { let before_t = Type::poly(ln.clone(), lps.clone()); - return Err(TyCheckError::re_unification_error(&before_t, after_t, bef_loc, aft_loc, self.caused_by())) + return Err(TyCheckError::re_unification_error( + &before_t, + after_t, + bef_loc, + aft_loc, + self.caused_by(), + )); } for (l, r) in lps.iter().zip(rps.iter()) { self.reunify_tp(l, r, None)?; } Ok(()) - }, + } (l, r) if self.same_type_of(l, r, None) => Ok(()), - (l, r) => - Err(TyCheckError::re_unification_error(l, r, bef_loc, aft_loc, self.caused_by())), + (l, r) => Err(TyCheckError::re_unification_error( + l, + r, + bef_loc, + aft_loc, + self.caused_by(), + )), } } @@ -1506,12 +1989,18 @@ impl Context { /// sub_unify(Nat, Add(?R, ?O)): (?R => Nat, ?O => Nat) /// sub_unify([?T; 0], Mutate): (/* OK */) /// ``` - fn sub_unify(&self, maybe_sub: &Type, maybe_sup: &Type, sub_loc: Option, sup_loc: Option) -> TyCheckResult<()> { + fn sub_unify( + &self, + maybe_sub: &Type, + maybe_sup: &Type, + sub_loc: Option, + sup_loc: Option, + ) -> TyCheckResult<()> { erg_common::fmt_dbg!(maybe_sub, maybe_sup,); let maybe_sub_is_sub = self.rec_subtype_of(maybe_sub, maybe_sup); - if maybe_sub.has_no_unbound_var() - && maybe_sup.has_no_unbound_var() - && maybe_sub_is_sub { return Ok(()) } + if maybe_sub.has_no_unbound_var() && maybe_sup.has_no_unbound_var() && maybe_sub_is_sub { + return Ok(()); + } if !maybe_sub_is_sub { let loc = sub_loc.or(sup_loc).unwrap_or(Location::Unknown); return Err(TyCheckError::type_mismatch_error( @@ -1520,63 +2009,80 @@ impl Context { "", maybe_sup, maybe_sub, - )) + )); } match (maybe_sub, maybe_sup) { (l, Type::FreeVar(fv)) if fv.is_unbound() => { match &mut *fv.borrow_mut() { - FreeKind::NamedUnbound{ constraint, .. } - | FreeKind::Unbound{ constraint, .. } => match constraint { + FreeKind::NamedUnbound { constraint, .. } + | FreeKind::Unbound { constraint, .. } => match constraint { // sub_unify(Nat, ?T(:> Int)): (/* OK */) // sub_unify(Int, ?T(:> Nat)): (?T :> Int) Constraint::SupertypeOf(sub) if self.rec_supertype_of(l, sub) => { *constraint = Constraint::SupertypeOf(l.clone()); - }, + } // sub_unify(Nat, ?T(<: Int)): (/* OK */) // sub_unify(Int, ?T(<: Nat)): Error! Constraint::SubtypeOf(sup) if self.rec_supertype_of(l, sup) => { - return Err(TyCheckError::subtyping_error(l, sup, sub_loc, sup_loc, self.caused_by())) - }, + return Err(TyCheckError::subtyping_error( + l, + sup, + sub_loc, + sup_loc, + self.caused_by(), + )) + } // sub_unify(Nat, (Ratio :> ?T :> Int)): (/* OK */) // sub_unify(Int, (Ratio :> ?T :> Nat)): (Ratio :> ?T :> Int) - Constraint::Sandwiched{ sub, sup } if self.rec_supertype_of(l, sub) => { - *constraint = Constraint::Sandwiched{ sub: l.clone(), sup: mem::take(sup) }; - }, + Constraint::Sandwiched { sub, sup } if self.rec_supertype_of(l, sub) => { + *constraint = Constraint::Sandwiched { + sub: l.clone(), + sup: mem::take(sup), + }; + } _ => {} }, - _ => {}, + _ => {} } - return Ok(()) - }, + return Ok(()); + } (Type::FreeVar(fv), _r) if fv.is_linked() => todo!(), - (l @ Refinement(_), r @ Refinement(_)) => { - return self.unify(l ,r, sub_loc, sup_loc) - }, + (l @ Refinement(_), r @ Refinement(_)) => return self.unify(l, r, sub_loc, sup_loc), _ => {} } let mut opt_smallest = None; for ctx in self.get_sorted_supertypes(maybe_sub) { - let instances = ctx.super_classes.iter() + let instances = ctx + .super_classes + .iter() .chain(ctx.super_traits.iter()) .filter(|t| self.supertype_of(maybe_sup, t, None)); // instanceが複数ある場合、経験的に最も小さい型を選ぶのが良い // これでうまくいかない場合は型指定してもらう(REVIEW: もっと良い方法があるか?) if let Some(t) = self.smallest_ref_t(instances) { - opt_smallest = if let Some(small) = opt_smallest { self.min(small, t) } else { Some(t) }; + opt_smallest = if let Some(small) = opt_smallest { + self.min(small, t) + } else { + Some(t) + }; } } let glue_patch_and_types = self.rec_get_glue_patch_and_types(); - let patch_instances = glue_patch_and_types.iter() + let patch_instances = glue_patch_and_types + .iter() .filter_map(|(patch_name, l, r)| { let patch = self.rec_get_patch(patch_name).unwrap(); let bounds = patch.bounds(); if self.supertype_of(l, maybe_sub, Some(&bounds)) - && self.supertype_of(r, maybe_sup, Some(&bounds)) { + && self.supertype_of(r, maybe_sup, Some(&bounds)) + { let tv_ctx = TyVarContext::new(self.level, bounds); let (l, _) = Self::instantiate_t(l.clone(), tv_ctx.clone()); let (r, _) = Self::instantiate_t(r.clone(), tv_ctx); Some((l, r)) - } else { None } + } else { + None + } }); let opt_smallest_pair = self.smallest_pair(patch_instances); match (opt_smallest, opt_smallest_pair) { @@ -1587,15 +2093,13 @@ impl Context { } else { self.unify(maybe_sup, smallest, sup_loc, None) } - }, - (Some(smallest), None) => { - self.unify(maybe_sup, smallest, sup_loc, None) - }, + } + (Some(smallest), None) => self.unify(maybe_sup, smallest, sup_loc, None), (None, Some((l, r))) => { self.unify(maybe_sub, &l, sub_loc, None)?; self.unify(maybe_sup, &r, sup_loc, None)?; Ok(()) - }, + } (None, None) => { log!("{maybe_sub}, {maybe_sup}"); todo!() @@ -1606,71 +2110,124 @@ impl Context { // (type) getters & validators impl Context { - fn validate_var_sig_t(&self, sig: &ast::VarSignature, body_t: &Type, mode: RegistrationMode) -> TyCheckResult<()> { + fn validate_var_sig_t( + &self, + sig: &ast::VarSignature, + body_t: &Type, + mode: RegistrationMode, + ) -> TyCheckResult<()> { let spec_t = self.instantiate_var_sig_t(sig, None, mode)?; match &sig.pat { ast::VarPattern::Discard(token) => { if self.unify(&spec_t, body_t, None, Some(sig.loc())).is_err() { return Err(TyCheckError::type_mismatch_error( - token.loc(), self.caused_by(), "_", &spec_t, body_t, - )) + token.loc(), + self.caused_by(), + "_", + &spec_t, + body_t, + )); } - }, + } ast::VarPattern::VarName(n) => { if self.unify(&spec_t, body_t, None, Some(sig.loc())).is_err() { return Err(TyCheckError::type_mismatch_error( - n.loc(), self.caused_by(), n.inspect(), &spec_t, body_t, - )) + n.loc(), + self.caused_by(), + n.inspect(), + &spec_t, + body_t, + )); } } ast::VarPattern::Array(a) => { for (elem, inf_elem_t) in a.iter().zip(body_t.inner_ts().iter()) { self.validate_var_sig_t(elem, inf_elem_t, mode)?; } - }, + } _ => todo!(), } Ok(()) } - pub(crate) fn instantiate_var_sig_t(&self, sig: &ast::VarSignature, opt_t: Option, mode: RegistrationMode) -> TyCheckResult { + pub(crate) fn instantiate_var_sig_t( + &self, + sig: &ast::VarSignature, + opt_t: Option, + mode: RegistrationMode, + ) -> TyCheckResult { let ty = if let Some(s) = sig.t_spec.as_ref() { self.instantiate_typespec(s, mode)? - } else { Type::free_var(self.level, Constraint::TypeOf(Type)) }; + } else { + Type::free_var(self.level, Constraint::TypeOf(Type)) + }; if let Some(t) = opt_t { self.unify(&ty, &t, sig.t_spec.as_ref().map(|s| s.loc()), None)?; } Ok(ty) } - pub(crate) fn instantiate_sub_sig_t(&self, sig: &ast::SubrSignature, opt_ret_t: Option, mode: RegistrationMode) -> TyCheckResult { - let non_defaults = sig.params.non_defaults.iter() - .map(|p| ParamTy::new( - p.inspect().cloned(), - self.instantiate_param_sig_t(p, None, mode).unwrap() - )).collect::>(); - let defaults = sig.params.defaults.iter() - .map(|p| ParamTy::new( - p.inspect().cloned(), self.instantiate_param_sig_t(p, None, mode).unwrap() - )).collect::>(); + pub(crate) fn instantiate_sub_sig_t( + &self, + sig: &ast::SubrSignature, + opt_ret_t: Option, + mode: RegistrationMode, + ) -> TyCheckResult { + let non_defaults = sig + .params + .non_defaults + .iter() + .map(|p| { + ParamTy::new( + p.inspect().cloned(), + self.instantiate_param_sig_t(p, None, mode).unwrap(), + ) + }) + .collect::>(); + let defaults = sig + .params + .defaults + .iter() + .map(|p| { + ParamTy::new( + p.inspect().cloned(), + self.instantiate_param_sig_t(p, None, mode).unwrap(), + ) + }) + .collect::>(); let return_t = if let Some(s) = sig.return_t_spec.as_ref() { self.instantiate_typespec(s, mode)? } else { // preregisterならouter scopeで型宣言(see inference.md) - let level = if mode == PreRegister { self.level } else { self.level+1 }; + let level = if mode == PreRegister { + self.level + } else { + self.level + 1 + }; Type::free_var(level, Constraint::TypeOf(Type)) }; if let Some(ret_t) = opt_ret_t { - self.unify(&return_t, &ret_t, sig.return_t_spec.as_ref().map(|s| s.loc()), None)?; + self.unify( + &return_t, + &ret_t, + sig.return_t_spec.as_ref().map(|s| s.loc()), + None, + )?; } - Ok( - if sig.name.is_procedural() { Type::proc(non_defaults, defaults, return_t) } - else { Type::func(non_defaults, defaults, return_t) } - ) + Ok(if sig.name.is_procedural() { + Type::proc(non_defaults, defaults, return_t) + } else { + Type::func(non_defaults, defaults, return_t) + }) } /// spec_t == Noneかつリテラル推論が不可能なら型変数を発行する - pub(crate) fn instantiate_param_sig_t(&self, sig: impl ParamSig, opt_decl_t: Option<&ParamTy>, mode: RegistrationMode) -> TyCheckResult { + pub(crate) fn instantiate_param_sig_t( + &self, + sig: impl ParamSig, + opt_decl_t: Option<&ParamTy>, + mode: RegistrationMode, + ) -> TyCheckResult { let t = if let Some(spec) = sig.t_spec() { self.instantiate_typespec(spec, mode)? } else { @@ -1678,9 +2235,13 @@ impl Context { ast::ParamPattern::Lit(lit) => Type::enum_t(set![self.eval.eval_const_lit(lit)]), // TODO: Array _ => { - let level = if mode == PreRegister { self.level } else { self.level+1 }; + let level = if mode == PreRegister { + self.level + } else { + self.level + 1 + }; Type::free_var(level, Constraint::TypeOf(Type)) - }, + } } }; if let Some(decl_t) = opt_decl_t { @@ -1731,58 +2292,95 @@ impl Context { other if simple.args.is_empty() => Ok(Type::mono(Str::rc(other))), other => { // FIXME: kw args - let params = simple.args.pos_args().map(|arg| { - match &arg.expr { - ast::ConstExpr::Lit(lit) => TyParam::ConstObj(ConstObj::Value(ValueObj::from(lit))), - _ => { todo!() } + let params = simple.args.pos_args().map(|arg| match &arg.expr { + ast::ConstExpr::Lit(lit) => { + TyParam::ConstObj(ConstObj::Value(ValueObj::from(lit))) + } + _ => { + todo!() } }); Ok(Type::poly(Str::rc(other), params.collect())) - }, + } } } pub(crate) fn instantiate_const_expr(&self, expr: &ast::ConstExpr) -> TyParam { match expr { - ast::ConstExpr::Lit(lit) => TyParam::ConstObj(ConstObj::Value(ValueObj::from(&lit.token))), - ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => TyParam::Mono(name.inspect().clone()), + ast::ConstExpr::Lit(lit) => { + TyParam::ConstObj(ConstObj::Value(ValueObj::from(&lit.token))) + } + ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => { + TyParam::Mono(name.inspect().clone()) + } _ => todo!(), } } - pub(crate) fn instantiate_const_expr_as_type(&self, expr: &ast::ConstExpr) -> TyCheckResult { + pub(crate) fn instantiate_const_expr_as_type( + &self, + expr: &ast::ConstExpr, + ) -> TyCheckResult { match expr { - ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => Ok(Type::mono(name.inspect())), + ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => { + Ok(Type::mono(name.inspect())) + } _ => todo!(), } } - fn instantiate_func_param_spec(&self, p: &ParamTySpec, mode: RegistrationMode) -> TyCheckResult { + fn instantiate_func_param_spec( + &self, + p: &ParamTySpec, + mode: RegistrationMode, + ) -> TyCheckResult { let t = self.instantiate_typespec(&p.ty, mode)?; - Ok(ParamTy::new(p.name.as_ref().map(|t| t.inspect().to_owned()), t)) + Ok(ParamTy::new( + p.name.as_ref().map(|t| t.inspect().to_owned()), + t, + )) } - pub(crate) fn instantiate_typespec(&self, spec: &TypeSpec, mode: RegistrationMode) -> TyCheckResult { + pub(crate) fn instantiate_typespec( + &self, + spec: &TypeSpec, + mode: RegistrationMode, + ) -> TyCheckResult { match spec { TypeSpec::PreDeclTy(predecl) => self.instantiate_predecl_t(predecl), // TODO: Flatten - TypeSpec::And(lhs, rhs) => - Ok(Type::And(vec![self.instantiate_typespec(lhs, mode)?, self.instantiate_typespec(rhs, mode)?])), - TypeSpec::Not(lhs, rhs) => - Ok(Type::Not(vec![self.instantiate_typespec(lhs, mode)?, self.instantiate_typespec(rhs, mode)?])), - TypeSpec::Or(lhs, rhs) => - Ok(Type::Or(vec![self.instantiate_typespec(lhs, mode)?, self.instantiate_typespec(rhs, mode)?])), + TypeSpec::And(lhs, rhs) => Ok(Type::And(vec![ + self.instantiate_typespec(lhs, mode)?, + self.instantiate_typespec(rhs, mode)?, + ])), + TypeSpec::Not(lhs, rhs) => Ok(Type::Not(vec![ + self.instantiate_typespec(lhs, mode)?, + self.instantiate_typespec(rhs, mode)?, + ])), + TypeSpec::Or(lhs, rhs) => Ok(Type::Or(vec![ + self.instantiate_typespec(lhs, mode)?, + self.instantiate_typespec(rhs, mode)?, + ])), TypeSpec::Array { .. } => todo!(), // FIXME: unwrap - TypeSpec::Tuple(tys) => - Ok(Type::Tuple(tys.iter().map(|spec| self.instantiate_typespec(spec, mode).unwrap()).collect())), + TypeSpec::Tuple(tys) => Ok(Type::Tuple( + tys.iter() + .map(|spec| self.instantiate_typespec(spec, mode).unwrap()) + .collect(), + )), // TODO: エラー処理(リテラルでない、ダブりがある)はパーサーにやらせる TypeSpec::Enum(set) => Ok(Type::enum_t( - set.pos_args().map(|arg| if let ast::ConstExpr::Lit(lit) = &arg.expr { - ValueObj::from(lit) - } else { todo!() }).collect::>() + set.pos_args() + .map(|arg| { + if let ast::ConstExpr::Lit(lit) = &arg.expr { + ValueObj::from(lit) + } else { + todo!() + } + }) + .collect::>(), )), - TypeSpec::Interval{ op, lhs, rhs } => { + TypeSpec::Interval { op, lhs, rhs } => { let op = match op.kind { TokenKind::Closed => IntervalOp::Closed, TokenKind::LeftOpen => IntervalOp::LeftOpen, @@ -1798,29 +2396,50 @@ impl Context { panic!("{l}..{r} is not a valid interval type (should be lhs <= rhs)") } Ok(Type::int_interval(op, l, r)) - }, + } TypeSpec::Subr(subr) => { - let non_defaults = try_map(subr.non_defaults.iter(), |p| self.instantiate_func_param_spec(p, mode))?; - let defaults = try_map(subr.defaults.iter(), |p| self.instantiate_func_param_spec(p, mode))?; + let non_defaults = try_map(subr.non_defaults.iter(), |p| { + self.instantiate_func_param_spec(p, mode) + })?; + let defaults = try_map(subr.defaults.iter(), |p| { + self.instantiate_func_param_spec(p, mode) + })?; let return_t = self.instantiate_typespec(&subr.return_t, mode)?; - Ok(Type::subr(subr.kind.clone(), non_defaults, defaults, return_t)) - }, + Ok(Type::subr( + subr.kind.clone(), + non_defaults, + defaults, + return_t, + )) + } } } - pub(crate) fn instantiate_ty_bound(&self, bound: &TypeBoundSpec, mode: RegistrationMode) -> TyCheckResult { + pub(crate) fn instantiate_ty_bound( + &self, + bound: &TypeBoundSpec, + mode: RegistrationMode, + ) -> TyCheckResult { // REVIEW: 型境界の左辺に来れるのは型変数だけか? // TODO: 高階型変数 match bound { - TypeBoundSpec::Subtype{ sub, sup } => - Ok(TyBound::subtype(Type::mono_q(sub.inspect().clone()), self.instantiate_typespec(sup, mode)?)), - TypeBoundSpec::Instance{ name, ty } => - Ok(TyBound::instance(name.inspect().clone(), self.instantiate_typespec(ty, mode)?)), + TypeBoundSpec::Subtype { sub, sup } => Ok(TyBound::subtype( + Type::mono_q(sub.inspect().clone()), + self.instantiate_typespec(sup, mode)?, + )), + TypeBoundSpec::Instance { name, ty } => Ok(TyBound::instance( + name.inspect().clone(), + self.instantiate_typespec(ty, mode)?, + )), } } - pub(crate) fn instantiate_ty_bounds(&self, bounds: &TypeBoundSpecs, mode: RegistrationMode) -> TyCheckResult> { - let mut new_bounds = set!{}; + pub(crate) fn instantiate_ty_bounds( + &self, + bounds: &TypeBoundSpecs, + mode: RegistrationMode, + ) -> TyCheckResult> { + let mut new_bounds = set! {}; for bound in bounds.iter() { new_bounds.insert(self.instantiate_ty_bound(bound, mode)?); } @@ -1831,7 +2450,12 @@ impl Context { self.impls.get(name).or_else(|| self.decls.get(name)) } - fn get_context(&self, obj: &hir::Expr, kind: Option, namespace: &Str) -> TyCheckResult<&Context> { + fn get_context( + &self, + obj: &hir::Expr, + kind: Option, + namespace: &Str, + ) -> TyCheckResult<&Context> { match obj { hir::Expr::Accessor(hir::Accessor::Local(name)) => { if kind == Some(ContextKind::Module) { @@ -1845,14 +2469,22 @@ impl Context { self.get_similar_name(name.inspect()), )) } - } else { todo!() } - }, + } else { + todo!() + } + } _ => todo!(), } } - fn get_match_call_t(&self, pos_args: &[hir::PosArg], kw_args: &[hir::KwArg]) -> TyCheckResult { - if !kw_args.is_empty() { todo!() } + fn get_match_call_t( + &self, + pos_args: &[hir::PosArg], + kw_args: &[hir::KwArg], + ) -> TyCheckResult { + if !kw_args.is_empty() { + todo!() + } for pos_arg in pos_args.iter().skip(1) { let t = pos_arg.expr.ref_t(); if !matches!(&pos_arg.expr, hir::Expr::Lambda(_)) { @@ -1862,7 +2494,7 @@ impl Context { "match", &Type::mono("LambdaFunc"), &t, - )) + )); } } let expr_t = pos_args[0].expr.ref_t(); @@ -1870,14 +2502,16 @@ impl Context { let mut union_pat_t = Type::Never; for (i, a) in pos_args.iter().skip(1).enumerate() { let lambda = erg_common::enum_unwrap!(&a.expr, hir::Expr::Lambda); - if !lambda.params.defaults.is_empty() { todo!() } + if !lambda.params.defaults.is_empty() { + todo!() + } if lambda.params.len() != 1 { return Err(TyCheckError::argument_error( - pos_args[i+1].loc(), + pos_args[i + 1].loc(), self.caused_by(), 1, - pos_args[i+1].expr.ref_t().typaram_len(), - )) + pos_args[i + 1].expr.ref_t().typaram_len(), + )); } let rhs = self.instantiate_param_sig_t(&lambda.params.non_defaults[0], None, Normal)?; union_pat_t = self.union(&union_pat_t, &rhs); @@ -1886,24 +2520,33 @@ impl Context { // OK: expr_t: Int, union_pat_t: {1} | 'T if expr_t.has_no_unbound_var() && self.supertype_of(&expr_t, &union_pat_t, None) - && !self.supertype_of(&union_pat_t, &expr_t, None) { + && !self.supertype_of(&union_pat_t, &expr_t, None) + { return Err(TyCheckError::match_error( pos_args[0].loc(), self.caused_by(), &expr_t, - )) + )); } - let branch_ts = pos_args.iter().skip(1) - .map(|a| ParamTy::anonymous(a.expr.ref_t().clone())).collect::>(); + let branch_ts = pos_args + .iter() + .skip(1) + .map(|a| ParamTy::anonymous(a.expr.ref_t().clone())) + .collect::>(); let mut return_t = branch_ts[0].ty.return_t().unwrap().clone(); for arg_t in branch_ts.iter().skip(1) { return_t = self.union(&return_t, arg_t.ty.return_t().unwrap()); } - let expr_t = if expr_t.has_unbound_var() { union_pat_t } else { expr_t.clone() }; + let expr_t = if expr_t.has_unbound_var() { + union_pat_t + } else { + expr_t.clone() + }; let param_ts = [ vec![ParamTy::anonymous(expr_t)], - branch_ts.iter().map(|pt| pt.clone()).collect() - ].concat(); + branch_ts.iter().map(|pt| pt.clone()).collect(), + ] + .concat(); let t = Type::func(param_ts, vec![], return_t); Ok(t) } @@ -1911,18 +2554,21 @@ impl Context { pub(crate) fn get_local_uniq_obj_name(&self, name: &Token) -> Option { // TODO: types, functions, patches if let Some(ctx) = self.rec_get_mod(name.inspect()) { - return Some(ctx.name.clone()) + return Some(ctx.name.clone()); } None } pub(crate) fn get_local_t(&self, name: &Token, namespace: &Str) -> TyCheckResult { - if let Some(vi) = self.impls.get(name.inspect()) - .or_else(|| self.decls.get(name.inspect())) { - Ok(vi.t()) + if let Some(vi) = self + .impls + .get(name.inspect()) + .or_else(|| self.decls.get(name.inspect())) + { + Ok(vi.t()) } else { if let Some(parent) = self.outer.as_ref() { - return parent.get_local_t(name, namespace) + return parent.get_local_t(name, namespace); } Err(TyCheckError::no_var_error( name.loc(), @@ -1933,7 +2579,12 @@ impl Context { } } - pub(crate) fn get_attr_t(&self, obj: &hir::Expr, name: &Token, namespace: &Str) -> TyCheckResult { + pub(crate) fn get_attr_t( + &self, + obj: &hir::Expr, + name: &Token, + namespace: &Str, + ) -> TyCheckResult { let self_t = obj.t(); match self_t { ASTOmitted => panic!(), @@ -1942,13 +2593,13 @@ impl Context { Module => { let mod_ctx = self.get_context(obj, Some(ContextKind::Module), namespace)?; let t = mod_ctx.get_local_t(name, namespace)?; - return Ok(t) - }, + return Ok(t); + } _ => {} } for ctx in self.get_sorted_supertypes(&self_t) { if let Ok(t) = ctx.get_local_t(name, namespace) { - return Ok(t) + return Ok(t); } } // TODO: dependent type widening @@ -1972,7 +2623,7 @@ impl Context { match callee { hir::Expr::Accessor(hir::Accessor::Local(local)) => { self.get_local_t(&local.name, namespace) - }, + } hir::Expr::Accessor(hir::Accessor::Attr(attr)) => { self.get_attr_t(&attr.obj, &attr.name, namespace) } @@ -1980,23 +2631,45 @@ impl Context { } } - pub(crate) fn get_binop_t(&self, op: &Token, args: &[hir::PosArg], namespace: &Str) -> TyCheckResult { + pub(crate) fn get_binop_t( + &self, + op: &Token, + args: &[hir::PosArg], + namespace: &Str, + ) -> TyCheckResult { 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| { // HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする - let core = ErrorCore::new(e.core.errno, e.core.kind, op.loc(), e.core.desc, e.core.hint); + let core = ErrorCore::new( + e.core.errno, + e.core.kind, + op.loc(), + e.core.desc, + e.core.hint, + ); TyCheckError::new(core, e.caused_by) }) } - pub(crate) fn get_unaryop_t(&self, op: &Token, args: &[hir::PosArg], namespace: &Str) -> TyCheckResult { + pub(crate) fn get_unaryop_t( + &self, + op: &Token, + args: &[hir::PosArg], + namespace: &Str, + ) -> TyCheckResult { 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 core = ErrorCore::new(e.core.errno, e.core.kind, op.loc(), e.core.desc, e.core.hint); + let core = ErrorCore::new( + e.core.errno, + e.core.kind, + op.loc(), + e.core.desc, + e.core.hint, + ); TyCheckError::new(core, e.caused_by) }) } @@ -2006,7 +2679,7 @@ impl Context { callee: &hir::Expr, pos_args: &[hir::PosArg], kw_args: &[hir::KwArg], - namespace: &Str + namespace: &Str, ) -> TyCheckResult { match callee { hir::Expr::Accessor(hir::Accessor::Local(local)) if &local.inspect()[..] == "match" => { @@ -2017,7 +2690,11 @@ impl Context { let found = self.search_call_t(callee, namespace)?; log!("Found:\ncallee: {callee}\nfound: {found}"); let instance = self.instantiate(found, callee)?; - log!("Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})", fmt_slice(pos_args), fmt_slice(kw_args)); + log!( + "Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})", + fmt_slice(pos_args), + fmt_slice(kw_args) + ); self.substitute_call(callee, &instance, pos_args, kw_args)?; log!("Substituted:\ninstance: {instance}"); let res = self.eval.eval_t(instance, &self, self.level)?; @@ -2030,20 +2707,36 @@ impl Context { } pub(crate) fn rec_supertype_of(&self, lhs: &Type, rhs: &Type) -> bool { - if self.supertype_of(lhs, rhs, None) { return true } + if self.supertype_of(lhs, rhs, None) { + return true; + } for sup_rhs in self.get_sorted_supertypes(rhs) { let bounds = sup_rhs.bounds(); - if sup_rhs.super_classes.iter().any(|sup| self.supertype_of(lhs, sup, Some(&bounds))) - || sup_rhs.super_traits.iter().any(|sup| self.supertype_of(lhs, sup, Some(&bounds))) { return true } + if sup_rhs + .super_classes + .iter() + .any(|sup| self.supertype_of(lhs, sup, Some(&bounds))) + || sup_rhs + .super_traits + .iter() + .any(|sup| self.supertype_of(lhs, sup, Some(&bounds))) + { + return true; + } } for (patch_name, sub, sup) in self.glue_patch_and_types.iter() { let patch = self.rec_get_patch(patch_name).unwrap(); let bounds = patch.bounds(); if self.supertype_of(sub, rhs, Some(&bounds)) - && self.supertype_of(sup, lhs, Some(&bounds)) { return true } + && self.supertype_of(sup, lhs, Some(&bounds)) + { + return true; + } } if let Some(outer) = &self.outer { - if outer.rec_supertype_of(lhs, rhs) { return true } + if outer.rec_supertype_of(lhs, rhs) { + return true; + } } false } @@ -2058,44 +2751,53 @@ impl Context { fn eq_tp(&self, lhs: &TyParam, rhs: &TyParam, bounds: Option<&Set>) -> bool { match (lhs, rhs) { - (TyParam::Type(lhs), TyParam::Type(rhs)) => { return self.same_type_of(lhs, rhs, bounds) }, + (TyParam::Type(lhs), TyParam::Type(rhs)) => return self.same_type_of(lhs, rhs, bounds), (TyParam::Mono(l), TyParam::Mono(r)) => { if let (Some((l, _)), Some((r, _))) = ( self.types.iter().find(|(t, _)| t.name() == &l[..]), self.types.iter().find(|(t, _)| t.name() == &r[..]), - ) { return self.supertype_of(l, r, None) || self.subtype_of(l, r, None) } - }, - (TyParam::MonoQVar(name), other) - | (other, TyParam::MonoQVar(name)) => { + ) { + return self.supertype_of(l, r, None) || self.subtype_of(l, r, None); + } + } + (TyParam::MonoQVar(name), other) | (other, TyParam::MonoQVar(name)) => { if let Some(bs) = bounds { if let Some(bound) = bs.iter().find(|b| b.mentions_as_instance(name)) { let other_t = self.type_of(other, bounds); - return self.supertype_of(bound.t(), &other_t, bounds) - } else { todo!() } // subtyping + return self.supertype_of(bound.t(), &other_t, bounds); + } else { + todo!() + } // subtyping } - }, + } ( - TyParam::App{ name: ln, args: largs }, - TyParam::App{ name: rn, args: rargs }, + TyParam::App { + name: ln, + args: largs, + }, + TyParam::App { + name: rn, + args: rargs, + }, ) => { return ln == rn && largs.len() == rargs.len() - && largs.iter().zip(rargs.iter()).all(|(l, r)| self.eq_tp(l, r, bounds)) - }, - (TyParam::FreeVar(fv), other) - | (other, TyParam::FreeVar(fv)) => { - match &*fv.borrow() { - FreeKind::Linked(tp) => { return self.eq_tp(tp, other, bounds) }, - FreeKind::Unbound{ constraint, .. } - | FreeKind::NamedUnbound{ constraint, .. }=> { - let t = constraint.typ().unwrap(); - let other_t = self.type_of(other, bounds); - return self.supertype_of(&t, &other_t, bounds) - } + && largs + .iter() + .zip(rargs.iter()) + .all(|(l, r)| self.eq_tp(l, r, bounds)) + } + (TyParam::FreeVar(fv), other) | (other, TyParam::FreeVar(fv)) => match &*fv.borrow() { + FreeKind::Linked(tp) => return self.eq_tp(tp, other, bounds), + FreeKind::Unbound { constraint, .. } + | FreeKind::NamedUnbound { constraint, .. } => { + let t = constraint.typ().unwrap(); + let other_t = self.type_of(other, bounds); + return self.supertype_of(&t, &other_t, bounds); } }, - (l, r) if l == r => { return true }, - _ => {}, + (l, r) if l == r => return true, + _ => {} } self.eval.shallow_eq_tp(lhs, rhs, &self) } @@ -2108,8 +2810,15 @@ impl Context { /// TODO: Inputs/Outputs trait /// 単一化、評価等はここでは行わない、スーパータイプになる可能性があるかだけ判定する /// ので、lhsが(未連携)型変数の場合は単一化せずにtrueを返す - pub(crate) fn supertype_of(&self, lhs: &Type, rhs: &Type, bounds: Option<&Set>) -> bool { - if lhs.rec_eq(rhs) { return true } + pub(crate) fn supertype_of( + &self, + lhs: &Type, + rhs: &Type, + bounds: Option<&Set>, + ) -> bool { + if lhs.rec_eq(rhs) { + return true; + } match (lhs, rhs) { // FIXME: Obj/Neverはクラス、Top/Bottomは構造型 (Obj, _) | (_, Never) => true, @@ -2119,16 +2828,44 @@ impl Context { | (Float | Ratio | Int, Int) | (Float | Ratio, Ratio) | (Float, Float) => true, - (FuncCommon, Subr(SubrType{ kind: SubrKind::Func, .. })) - | (ProcCommon, Subr(SubrType{ kind: SubrKind::Proc, .. })) - | (FuncMethodCommon, Subr(SubrType{ kind: SubrKind::FuncMethod(_), .. })) - | (ProcMethodCommon, Subr(SubrType{ kind: SubrKind::ProcMethod{ .. }, .. })) - | (ArrayCommon, Type::Array{ .. }) - | (DictCommon, Type::Dict{ .. }) => true, - (CallableCommon, Subr(_) | FuncCommon | ProcCommon | FuncMethodCommon | ProcMethodCommon) => true, + ( + FuncCommon, + Subr(SubrType { + kind: SubrKind::Func, + .. + }), + ) + | ( + ProcCommon, + Subr(SubrType { + kind: SubrKind::Proc, + .. + }), + ) + | ( + FuncMethodCommon, + Subr(SubrType { + kind: SubrKind::FuncMethod(_), + .. + }), + ) + | ( + ProcMethodCommon, + Subr(SubrType { + kind: SubrKind::ProcMethod { .. }, + .. + }), + ) + | (ArrayCommon, Type::Array { .. }) + | (DictCommon, Type::Dict { .. }) => true, + ( + CallableCommon, + Subr(_) | FuncCommon | ProcCommon | FuncMethodCommon | ProcMethodCommon, + ) => true, (Subr(ls), Subr(rs)) if ls.kind.same_kind_as(&rs.kind) - && (ls.kind == SubrKind::Func || ls.kind == SubrKind::Proc) => { + && (ls.kind == SubrKind::Func || ls.kind == SubrKind::Proc) => + { // () -> Never <: () -> Int <: () -> Object // (Object) -> Int <: (Int) -> Int <: (Never) -> Int ls.non_default_params.len() == rs.non_default_params.len() @@ -2141,15 +2878,15 @@ impl Context { .zip(rs.default_params.iter()) .all(|(l, r)| self.subtype_of(&l.ty, &r.ty, bounds)) // contravariant } - (Type::Array{ t: lhs, len: llen }, Type::Array{ t: rhs, len: rlen }) => { - self.eq_tp(llen, rlen, bounds) - && self.supertype_of(lhs, rhs, bounds) + (Type::Array { t: lhs, len: llen }, Type::Array { t: rhs, len: rlen }) => { + self.eq_tp(llen, rlen, bounds) && self.supertype_of(lhs, rhs, bounds) } (Tuple(lhs), Tuple(rhs)) => { lhs.len() == rhs.len() - && lhs.iter() - .zip(rhs.iter()) - .all(|(l, r)| self.supertype_of(l, r, bounds)) + && lhs + .iter() + .zip(rhs.iter()) + .all(|(l, r)| self.supertype_of(l, r, bounds)) } // RefMut, OptionMutは非変 (Range(lhs), Range(rhs)) @@ -2163,18 +2900,23 @@ impl Context { match &*v.borrow() { FreeKind::Linked(t) => self.supertype_of(t, rhs, bounds), FreeKind::Unbound { constraint, .. } - | FreeKind::NamedUnbound{ constraint, .. } => match constraint { + | FreeKind::NamedUnbound { constraint, .. } => match constraint { // `(?T <: Int) :> Nat` can be true, `(?T <: Nat) :> Int` is false Constraint::SubtypeOf(sup) => self.supertype_of(sup, rhs, bounds), // `(?T :> X) :> Y` is true, Constraint::SupertypeOf(_) => true, // `(Nat <: ?T <: Ratio) :> Nat` can be true - Constraint::Sandwiched{ sup, .. } => self.supertype_of(sup, rhs, bounds), + Constraint::Sandwiched { sup, .. } => self.supertype_of(sup, rhs, bounds), // (?v: Type, rhs): OK // (?v: Nat, rhs): Something wrong // Class <: Type, but Nat - if self.supertype_of(&Type, t, bounds) { true } else { panic!() }, + Constraint::TypeOf(t) => { + if self.supertype_of(&Type, t, bounds) { + true + } else { + panic!() + } + } }, } } @@ -2182,15 +2924,20 @@ impl Context { match &*v.borrow() { FreeKind::Linked(t) => self.supertype_of(lhs, t, bounds), FreeKind::Unbound { constraint, .. } - | FreeKind::NamedUnbound{ constraint, .. } => match constraint { + | FreeKind::NamedUnbound { constraint, .. } => match constraint { // `Nat :> (?T <: Int)` can be true => `X :> (?T <: Y)` can be true Constraint::SubtypeOf(_sup) => true, // `Int :> (?T :> Nat)` can be true, `Nat :> (?T :> Int)` is false Constraint::SupertypeOf(sub) => self.supertype_of(lhs, sub, bounds), // `Int :> (Nat <: ?T <: Ratio)` can be true, `Nat :> (Int <: ?T <: Ratio)` is false - Constraint::Sandwiched{ sub, .. } => self.supertype_of(lhs, sub, bounds), - Constraint::TypeOf(t) => - if self.supertype_of(&Type, t, bounds) { true } else { panic!() }, + Constraint::Sandwiched { sub, .. } => self.supertype_of(lhs, sub, bounds), + Constraint::TypeOf(t) => { + if self.supertype_of(&Type, t, bounds) { + true + } else { + panic!() + } + } }, } } @@ -2201,19 +2948,22 @@ impl Context { // ({I: Int | I >= 0} :> {N: Nat | N >= 1}) == true, // ({I: Int | I > 1 or I < -1} :> {I: Int | I >= 0}) == false, (Refinement(l), Refinement(r)) => { - if !self.supertype_of(&l.t, &r.t, bounds) { return false } + if !self.supertype_of(&l.t, &r.t, bounds) { + return false; + } let mut r_preds_clone = r.preds.clone(); for l_pred in l.preds.iter() { for r_pred in r.preds.iter() { if l_pred.subject().unwrap_or("") == &l.var[..] - && r_pred.subject().unwrap_or("") == &r.var[..] - && self.is_super_pred_of(l_pred, r_pred, bounds) { + && r_pred.subject().unwrap_or("") == &r.var[..] + && self.is_super_pred_of(l_pred, r_pred, bounds) + { r_preds_clone.remove(r_pred); } } } r_preds_clone.is_empty() - }, + } (Nat, re @ Refinement(_)) => { let nat = Type::Refinement(self.into_refinement(Nat)); self.supertype_of(&nat, re, bounds) @@ -2223,55 +2973,81 @@ impl Context { self.supertype_of(re, &nat, bounds) } // Int :> {I: Int | ...} == true, Real :> {I: Int | ...} == false, Int :> {I: Str| ...} == false - (l, Refinement(r)) => { - self.supertype_of(l, &r.t, bounds) - }, + (l, Refinement(r)) => self.supertype_of(l, &r.t, bounds), // ({I: Int | True} :> Int) == true, ({N: Nat | ...} :> Int) == false, ({I: Int | I >= 0} :> Int) == false (Refinement(l), r) => { - if l.preds.iter().any(|p| p.mentions(&l.var) && p.can_be_false()) { - return false + if l.preds + .iter() + .any(|p| p.mentions(&l.var) && p.can_be_false()) + { + return false; } self.supertype_of(&l.t, r, bounds) - }, + } (Quantified(l), Quantified(r)) => { // REVIEW: maybe this should be `unreachable` - if bounds.is_some() { panic!("Nested quantification") } - else { + if bounds.is_some() { + panic!("Nested quantification") + } else { // TODO: bounds同士の評価 - self.supertype_of(l.unbound_callable.as_ref(), r.unbound_callable.as_ref(), Some(&l.bounds)) + self.supertype_of( + l.unbound_callable.as_ref(), + r.unbound_callable.as_ref(), + Some(&l.bounds), + ) } - }, + } (Quantified(q), r) => { // REVIEW: maybe this should be `unreachable` - if bounds.is_some() { panic!("Nested quantification") } - else { self.supertype_of(q.unbound_callable.as_ref(), r, Some(&q.bounds)) } - }, + if bounds.is_some() { + panic!("Nested quantification") + } else { + self.supertype_of(q.unbound_callable.as_ref(), r, Some(&q.bounds)) + } + } (lhs, Or(tys)) => tys.iter().all(|t| self.supertype_of(lhs, t, bounds)), (And(tys), rhs) => tys.iter().all(|t| self.supertype_of(t, rhs, bounds)), (VarArgs(lhs), rhs) => self.supertype_of(lhs, rhs, bounds), // TはすべてのRef(T)のメソッドを持つので、Ref(T)のサブタイプ - (Ref(lhs), rhs) - | (RefMut(lhs), rhs) => self.supertype_of(lhs, rhs, bounds), + (Ref(lhs), rhs) | (RefMut(lhs), rhs) => self.supertype_of(lhs, rhs, bounds), // TODO: Consider variance - (Poly{ name: ln, params: lp }, Poly{ name: rn, params: rp }) => { + ( + Poly { + name: ln, + params: lp, + }, + Poly { + name: rn, + params: rp, + }, + ) => { ln == rn - && lp.len() == rp.len() - && lp.iter() - .zip(rp.iter()) - .all(|(l, r)| self.eq_tp(l, r, bounds)) - }, + && lp.len() == rp.len() + && lp + .iter() + .zip(rp.iter()) + .all(|(l, r)| self.eq_tp(l, r, bounds)) + } (MonoQVar(name), r) => { if let Some(bs) = bounds { if let Some(bound) = bs.iter().find(|b| b.mentions_as_subtype(name)) { self.supertype_of(bound.t(), r, bounds) } else if let Some(bound) = bs.iter().find(|b| b.mentions_as_instance(name)) { - if self.same_type_of(bound.t(), &Type::Type, bounds) { true } else { todo!()} - } else { panic!("Unbound type variable: {name}") } - } else { panic!("No quantification") } - }, + if self.same_type_of(bound.t(), &Type::Type, bounds) { + true + } else { + todo!() + } + } else { + panic!("Unbound type variable: {name}") + } + } else { + panic!("No quantification") + } + } (_l, MonoQVar(_name)) => todo!(), - (PolyQVar{ .. }, _r) => todo!(), - (_l, PolyQVar{ .. }) => todo!(), + (PolyQVar { .. }, _r) => todo!(), + (_l, PolyQVar { .. }) => todo!(), (_l, _r) => false, } } @@ -2281,11 +3057,21 @@ impl Context { self.supertype_of(rhs, lhs, bounds) } - pub(crate) fn same_type_of(&self, lhs: &Type, rhs: &Type, bounds: Option<&Set>) -> bool { + pub(crate) fn same_type_of( + &self, + lhs: &Type, + rhs: &Type, + bounds: Option<&Set>, + ) -> bool { self.supertype_of(lhs, rhs, bounds) && self.subtype_of(lhs, rhs, bounds) } - fn try_cmp(&self, l: &TyParam, r: &TyParam, bounds: Option<&Set>) -> Option { + fn try_cmp( + &self, + l: &TyParam, + r: &TyParam, + bounds: Option<&Set>, + ) -> Option { match (l, r) { (TyParam::ConstObj(l), TyParam::ConstObj(r)) => l.try_cmp(r).map(Into::into), @@ -2371,35 +3157,39 @@ impl Context { match t { Nat => { let var = Str::from(fresh_varname()); - RefinementType::new(var.clone(), Int, set!{Predicate::ge(var, TyParam::value(0))}) + RefinementType::new( + var.clone(), + Int, + set! {Predicate::ge(var, TyParam::value(0))}, + ) } Refinement(r) => r, t => { let var = Str::from(fresh_varname()); - RefinementType::new(var.clone(), t, set!{}) + RefinementType::new(var.clone(), t, set! {}) } } } /// 和集合(A or B)を返す fn union(&self, lhs: &Type, rhs: &Type) -> Type { - match (self.rec_supertype_of(lhs, rhs), self.rec_subtype_of(lhs, rhs)) { - (true, true) => return lhs.clone(), // lhs = rhs + match ( + self.rec_supertype_of(lhs, rhs), + self.rec_subtype_of(lhs, rhs), + ) { + (true, true) => return lhs.clone(), // lhs = rhs (true, false) => return lhs.clone(), // lhs :> rhs (false, true) => return rhs.clone(), - (false, false) => {}, + (false, false) => {} } match (lhs, rhs) { - (Refinement(l), Refinement(r)) => - Type::Refinement(self.union_refinement(l, r)), - (Or(ts), t) - | (t, Or(ts)) => Or([vec![t.clone()], ts.clone()].concat()), + (Refinement(l), Refinement(r)) => Type::Refinement(self.union_refinement(l, r)), + (Or(ts), t) | (t, Or(ts)) => Or([vec![t.clone()], ts.clone()].concat()), (t, Type::Never) | (Type::Never, t) => t.clone(), - (t, Refinement(r)) - | (Refinement(r), t) => { + (t, Refinement(r)) | (Refinement(r), t) => { let t = self.into_refinement(t.clone()); Type::Refinement(self.union_refinement(&t, r)) - }, + } (l, r) => Type::Or(vec![l.clone(), r.clone()]), } } @@ -2410,7 +3200,11 @@ impl Context { todo!() } else { let name = lhs.var.clone(); - let rhs_preds = rhs.preds.iter().map(|p| p.clone().change_subject_name(name.clone())).collect(); + let rhs_preds = rhs + .preds + .iter() + .map(|p| p.clone().change_subject_name(name.clone())) + .collect(); // FIXME: predの包含関係も考慮する RefinementType::new( lhs.var.clone(), @@ -2426,37 +3220,47 @@ impl Context { /// assert is_super_pred({T >= 0}, {I == 0}) /// assert !is_super_pred({I < 0}, {I == 0}) /// ``` - fn is_super_pred_of(&self, lhs: &Predicate, rhs: &Predicate, bounds: Option<&Set>) -> bool { + fn is_super_pred_of( + &self, + lhs: &Predicate, + rhs: &Predicate, + bounds: Option<&Set>, + ) -> bool { match (lhs, rhs) { - (Pred::LessEqual{ rhs, .. }, _) if !rhs.has_upper_bound() => true, - (Pred::GreaterEqual{ rhs, .. }, _) if !rhs.has_lower_bound() => true, + (Pred::LessEqual { rhs, .. }, _) if !rhs.has_upper_bound() => true, + (Pred::GreaterEqual { rhs, .. }, _) if !rhs.has_lower_bound() => true, ( - Pred::Equal{ .. }, - Pred::GreaterEqual{ .. } | Pred::LessEqual{ .. } | Pred::NotEqual{ .. } + Pred::Equal { .. }, + Pred::GreaterEqual { .. } | Pred::LessEqual { .. } | Pred::NotEqual { .. }, ) - | (Pred::LessEqual{ .. }, Pred::GreaterEqual{ .. }) - | (Pred::GreaterEqual{ .. }, Pred::LessEqual{ .. }) - | (Pred::NotEqual{ .. }, Pred::Equal{ .. }) => false, - (Pred::Equal{ rhs, .. }, Pred::Equal{ rhs: rhs2, .. }) - | (Pred::NotEqual{ rhs, .. }, Pred::NotEqual{ rhs: rhs2, .. }) => - self.try_cmp(rhs, rhs2, bounds).unwrap().is_eq(), + | (Pred::LessEqual { .. }, Pred::GreaterEqual { .. }) + | (Pred::GreaterEqual { .. }, Pred::LessEqual { .. }) + | (Pred::NotEqual { .. }, Pred::Equal { .. }) => false, + (Pred::Equal { rhs, .. }, Pred::Equal { rhs: rhs2, .. }) + | (Pred::NotEqual { rhs, .. }, Pred::NotEqual { rhs: rhs2, .. }) => { + self.try_cmp(rhs, rhs2, bounds).unwrap().is_eq() + } // {T >= 0} :> {T >= 1}, {T >= 0} :> {T == 1} ( - Pred::GreaterEqual{ rhs, .. }, - Pred::GreaterEqual{ rhs: rhs2, .. } | Pred::Equal{ rhs: rhs2, .. }, + Pred::GreaterEqual { rhs, .. }, + Pred::GreaterEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. }, ) => self.try_cmp(rhs, rhs2, bounds).unwrap().is_le(), ( - Pred::LessEqual{ rhs, .. }, - Pred::LessEqual{ rhs: rhs2, .. } | Pred::Equal{ rhs: rhs2, .. }, + Pred::LessEqual { rhs, .. }, + Pred::LessEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. }, ) => self.try_cmp(rhs, rhs2, bounds).unwrap().is_ge(), - (lhs @ (Pred::GreaterEqual{ .. } | Pred::LessEqual { .. }), Pred::And(l, r)) => - self.is_super_pred_of(lhs, l, bounds) || self.is_super_pred_of(lhs, r, bounds), - (lhs, Pred::Or(l, r)) => - self.is_super_pred_of(lhs, l, bounds) && self.is_super_pred_of(lhs, r, bounds), - (Pred::Or(l, r), rhs @ (Pred::GreaterEqual{ .. } | Pred::LessEqual{ .. })) => - self.is_super_pred_of(l, rhs, bounds) || self.is_super_pred_of(r, rhs, bounds), - (Pred::And(l, r), rhs) => - self.is_super_pred_of(l, rhs, bounds) && self.is_super_pred_of(r, rhs, bounds), + (lhs @ (Pred::GreaterEqual { .. } | Pred::LessEqual { .. }), Pred::And(l, r)) => { + self.is_super_pred_of(lhs, l, bounds) || self.is_super_pred_of(lhs, r, bounds) + } + (lhs, Pred::Or(l, r)) => { + self.is_super_pred_of(lhs, l, bounds) && self.is_super_pred_of(lhs, r, bounds) + } + (Pred::Or(l, r), rhs @ (Pred::GreaterEqual { .. } | Pred::LessEqual { .. })) => { + self.is_super_pred_of(l, rhs, bounds) || self.is_super_pred_of(r, rhs, bounds) + } + (Pred::And(l, r), rhs) => { + self.is_super_pred_of(l, rhs, bounds) && self.is_super_pred_of(r, rhs, bounds) + } (lhs, rhs) => todo!("{lhs}/{rhs}"), } } @@ -2466,16 +3270,22 @@ impl Context { // |T <: Nat| <: |T <: Int| // |I: Nat| <: |I: Int| (Constraint::SubtypeOf(lhs), Constraint::SubtypeOf(rhs)) - | (Constraint::TypeOf(lhs), Constraint::TypeOf(rhs)) => - self.rec_subtype_of(lhs, rhs), + | (Constraint::TypeOf(lhs), Constraint::TypeOf(rhs)) => self.rec_subtype_of(lhs, rhs), // |Int <: T| <: |Nat <: T| - (Constraint::SupertypeOf(lhs), Constraint::SupertypeOf(rhs)) => - self.rec_supertype_of(lhs, rhs), + (Constraint::SupertypeOf(lhs), Constraint::SupertypeOf(rhs)) => { + self.rec_supertype_of(lhs, rhs) + } (Constraint::SubtypeOf(_), Constraint::TypeOf(Type)) => true, // |Int <: T <: Ratio| <: |Nat <: T <: Complex| ( - Constraint::Sandwiched{ sub: lsub, sup: lsup }, - Constraint::Sandwiched{ sub: rsub, sup: rsup }, + Constraint::Sandwiched { + sub: lsub, + sup: lsup, + }, + Constraint::Sandwiched { + sub: rsub, + sup: rsup, + }, ) => self.rec_supertype_of(lsub, rsub) && self.rec_subtype_of(lsup, rsup), _ => false, } @@ -2494,8 +3304,9 @@ impl Context { let mut maybe_max = None; for pred in refine.preds.iter() { match pred { - Pred::LessEqual{ lhs, rhs } | - Pred::Equal{ lhs, rhs } if lhs == &refine.var => { + Pred::LessEqual { lhs, rhs } | Pred::Equal { lhs, rhs } + if lhs == &refine.var => + { if let Some(max) = &maybe_max { if self.try_cmp(rhs, &max, None).unwrap() == Greater { maybe_max = Some(rhs.clone()); @@ -2503,12 +3314,12 @@ impl Context { } else { maybe_max = Some(rhs.clone()); } - }, + } _ => {} } } maybe_max - }, + } _other => None, } } @@ -2521,8 +3332,9 @@ impl Context { let mut maybe_min = None; for pred in refine.preds.iter() { match pred { - Predicate::GreaterEqual{ lhs, rhs } | - Predicate::Equal{ lhs, rhs } if lhs == &refine.var => { + Predicate::GreaterEqual { lhs, rhs } | Predicate::Equal { lhs, rhs } + if lhs == &refine.var => + { if let Some(min) = &maybe_min { if self.try_cmp(rhs, &min, None).unwrap() == Less { maybe_min = Some(rhs.clone()); @@ -2530,12 +3342,12 @@ impl Context { } else { maybe_min = Some(rhs.clone()); } - }, + } _ => {} } } maybe_min - }, + } _other => None, } } @@ -2544,7 +3356,10 @@ impl Context { /// 関係なければNoneを返す fn min<'t>(&self, lhs: &'t Type, rhs: &'t Type) -> Option<&'t Type> { // 同じならどちらを返しても良い - match (self.rec_supertype_of(lhs, rhs), self.rec_subtype_of(lhs, rhs)) { + match ( + self.rec_supertype_of(lhs, rhs), + self.rec_subtype_of(lhs, rhs), + ) { (true, true) | (true, false) => Some(rhs), (false, true) => Some(lhs), _ => None, @@ -2560,20 +3375,20 @@ impl Context { } // TODO: - fn smallest_pair>(&self, ts: I) -> Option<(Type, Type)> { + fn smallest_pair>(&self, ts: I) -> Option<(Type, Type)> { ts.min_by(|(_, lhs), (_, rhs)| self.cmp_t(lhs, rhs).try_into().unwrap()) } - fn smallest_ref_t<'t, I: Iterator>(&self, ts: I) -> Option<&'t Type> { + fn smallest_ref_t<'t, I: Iterator>(&self, ts: I) -> Option<&'t Type> { ts.min_by(|lhs, rhs| self.cmp_t(lhs, rhs).try_into().unwrap()) } pub(crate) fn get_local(&self, name: &Token, namespace: &Str) -> TyCheckResult { if let Some(obj) = self.consts.get(name.inspect()) { - Ok(obj.clone()) + Ok(obj.clone()) } else { if let Some(parent) = self.outer.as_ref() { - return parent.get_local(name, namespace) + return parent.get_local(name, namespace); } Err(TyCheckError::no_var_error( name.loc(), @@ -2584,11 +3399,16 @@ impl Context { } } - pub(crate) fn _get_attr(&self, obj: &hir::Expr, name: &Token, namespace: &Str) -> TyCheckResult { + pub(crate) fn _get_attr( + &self, + obj: &hir::Expr, + name: &Token, + namespace: &Str, + ) -> TyCheckResult { let self_t = obj.t(); for ctx in self.get_sorted_supertypes(&self_t) { if let Ok(t) = ctx.get_local(name, namespace) { - return Ok(t) + return Ok(t); } } // TODO: dependent type widening @@ -2606,29 +3426,45 @@ impl Context { } pub(crate) fn get_similar_name(&self, name: &str) -> Option<&Str> { - if name.len() <= 1 { return None } - let most_similar_name = self.impls.keys().min_by_key(|v| levenshtein(v.inspect(), name))?.inspect(); + if name.len() <= 1 { + return None; + } + let most_similar_name = self + .impls + .keys() + .min_by_key(|v| levenshtein(v.inspect(), name))? + .inspect(); let len = most_similar_name.len(); - if levenshtein(most_similar_name, name) >= len/2 { + if levenshtein(most_similar_name, name) >= len / 2 { let outer = self.outer.as_ref()?; outer.get_similar_name(name) + } else { + Some(most_similar_name) } - else { Some(most_similar_name) } } pub(crate) fn get_similar_attr<'a>(&'a self, self_t: &'a Type, name: &str) -> Option<&'a Str> { for ctx in self.get_sorted_supertypes(self_t) { - if let Some(name) = ctx.get_similar_name(name) { return Some(name) } + if let Some(name) = ctx.get_similar_name(name) { + return Some(name); + } } None } } impl Context { - pub(crate) fn grow(&mut self, name: &str, kind: ContextKind, vis: Visibility) -> TyCheckResult<()> { + pub(crate) fn grow( + &mut self, + name: &str, + kind: ContextKind, + vis: Visibility, + ) -> TyCheckResult<()> { let name = if vis.is_public() { format!("{parent}.{name}", parent = self.name) - } else { format!("{parent}::{name}", parent = self.name) }; + } else { + format!("{parent}::{name}", parent = self.name) + }; log!("{}: current namespace: {name}", fn_name!()); self.outer = Some(Box::new(mem::take(self))); self.name = name.into(); @@ -2649,42 +3485,63 @@ impl Context { if let Some(parent) = &mut self.outer { *self = mem::take(parent); log!("{}: current namespace: {}", fn_name!(), self.name); - if !uninited_errs.is_empty() { Err(uninited_errs) } - else { Ok(()) } + if !uninited_errs.is_empty() { + Err(uninited_errs) + } else { + Ok(()) + } } else { - Err(TyCheckErrors::from(TyCheckError::checker_bug(0, Location::Unknown, fn_name!(), line!()))) + Err(TyCheckErrors::from(TyCheckError::checker_bug( + 0, + Location::Unknown, + fn_name!(), + line!(), + ))) } } - pub(crate) fn get_sorted_supertypes<'a>(&'a self, t: &'a Type) -> impl Iterator { + pub(crate) fn get_sorted_supertypes<'a>( + &'a self, + t: &'a Type, + ) -> impl Iterator { let mut ctxs = self._rec_get_supertypes(t).collect::>(); ctxs.sort_by(|(lhs, _), (rhs, _)| self.cmp_t(lhs, rhs).try_into().unwrap()); ctxs.into_iter().map(|(_, ctx)| ctx) } /// this method is for `get_sorted_supertypes` only - fn _rec_get_supertypes<'a>(&'a self, t: &'a Type) -> impl Iterator { + fn _rec_get_supertypes<'a>( + &'a self, + t: &'a Type, + ) -> impl Iterator { let i = self._get_supertypes(t); if i.size_hint().1 == Some(0) { if let Some(outer) = &self.outer { - return outer._rec_get_supertypes(t) + return outer._rec_get_supertypes(t); } } i } /// this method is for `rec_get_supertypes` only - fn _get_supertypes<'a>(&'a self, t: &'a Type) -> impl Iterator { - self.types.iter() - .filter_map(|(maybe_sup, ctx)| { - let bounds = ctx.bounds(); - if self.supertype_of(maybe_sup, t, Some(&bounds)) { Some((maybe_sup, ctx)) } else { None } - }) + fn _get_supertypes<'a>(&'a self, t: &'a Type) -> impl Iterator { + self.types.iter().filter_map(|(maybe_sup, ctx)| { + let bounds = ctx.bounds(); + if self.supertype_of(maybe_sup, t, Some(&bounds)) { + Some((maybe_sup, ctx)) + } else { + None + } + }) } fn rec_get_glue_patch_and_types(&self) -> Vec<(VarName, Type, Type)> { if let Some(outer) = &self.outer { - [&self.glue_patch_and_types[..], &outer.rec_get_glue_patch_and_types()].concat() + [ + &self.glue_patch_and_types[..], + &outer.rec_get_glue_patch_and_types(), + ] + .concat() } else { self.glue_patch_and_types.clone() } @@ -2692,10 +3549,10 @@ impl Context { fn rec_get_patch(&self, name: &VarName) -> Option<&Context> { if let Some(patch) = self.patches.get(name) { - return Some(patch) + return Some(patch); } else { if let Some(outer) = &self.outer { - return outer.rec_get_patch(name) + return outer.rec_get_patch(name); } } None @@ -2703,10 +3560,10 @@ impl Context { fn rec_get_mod(&self, name: &str) -> Option<&Context> { if let Some(mod_) = self.mods.get(name) { - return Some(mod_) + return Some(mod_); } else { if let Some(outer) = &self.outer { - return outer.rec_get_mod(name) + return outer.rec_get_mod(name); } } None @@ -2719,26 +3576,31 @@ impl Context { ast::Expr::Def(def) => { let id = Some(def.body.id); let eval_body_t = || { - self.eval.eval_const_block(&def.body.block, &self) + 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() }; + } 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() }; + } else { + eval_body_t() + }; self.declare_var(&sig, t, id)?; } _ => {} } - }, - _ => {}, + } + _ => {} } } Ok(()) diff --git a/compiler/erg_compiler/effectcheck.rs b/compiler/erg_compiler/effectcheck.rs index 63c7bfba..4f9a134a 100644 --- a/compiler/erg_compiler/effectcheck.rs +++ b/compiler/erg_compiler/effectcheck.rs @@ -2,13 +2,13 @@ //! SideEffectCheckerを実装 //! 関数や不変型に副作用がないかチェックする -use erg_common::Str; use erg_common::color::{GREEN, RESET}; use erg_common::log; use erg_common::traits::Stream; +use erg_common::Str; use crate::error::{EffectError, EffectErrors, EffectResult}; -use crate::hir::{HIR, Expr, Def, Accessor, Signature}; +use crate::hir::{Accessor, Def, Expr, Signature, HIR}; use crate::varinfo::Visibility; use Visibility::*; @@ -19,12 +19,23 @@ pub struct SideEffectChecker { } impl SideEffectChecker { - pub fn new() -> Self { Self { path_stack: vec![], errs: EffectErrors::empty() } } + pub fn new() -> Self { + Self { + path_stack: vec![], + errs: EffectErrors::empty(), + } + } fn full_path(&self) -> String { - self.path_stack.iter().fold(String::new(), |acc, (path, vis)| { - if vis.is_public() { acc + "." + &path[..] } else { acc + "::" + &path[..] } - }) + self.path_stack + .iter() + .fold(String::new(), |acc, (path, vis)| { + if vis.is_public() { + acc + "." + &path[..] + } else { + acc + "::" + &path[..] + } + }) } pub fn check(mut self, hir: HIR) -> EffectResult { @@ -33,7 +44,9 @@ impl SideEffectChecker { // トップレベルでは副作用があっても問題なく、純粋性違反がないかのみチェックする for expr in hir.module.iter() { match expr { - Expr::Def(def) => { self.check_def(def, true); }, + Expr::Def(def) => { + self.check_def(def, true); + } Expr::Call(call) => { for parg in call.args.pos_args().iter() { self.check_expr(&parg.expr, true); @@ -41,7 +54,7 @@ impl SideEffectChecker { for kwarg in call.args.kw_args().iter() { self.check_expr(&kwarg.expr, true); } - }, + } other => todo!("{other}"), } } @@ -56,9 +69,14 @@ impl SideEffectChecker { fn check_def(&mut self, def: &Def, allow_inner_effect: bool) { let name_and_vis = match &def.sig { Signature::Var(var) => - // TODO: visibility - if let Some(name) = var.inspect() { (name.clone(), Private) } - else { (Str::ever("::"), Private) }, + // TODO: visibility + { + if let Some(name) = var.inspect() { + (name.clone(), Private) + } else { + (Str::ever("::"), Private) + } + } Signature::Subr(subr) => (subr.name.inspect().clone(), Private), }; self.path_stack.push(name_and_vis); @@ -71,23 +89,28 @@ impl SideEffectChecker { (true, _) => { if !allow_inner_effect { let expr = Expr::Def(def.clone()); - self.errs.push( - EffectError::has_effect(&expr, self.full_path()) - ); + self.errs + .push(EffectError::has_effect(&expr, self.full_path())); } for chunk in def.body.block.iter() { self.check_expr(chunk, allow_inner_effect); } - }, + } (false, false) => { for chunk in def.body.block.iter() { self.check_expr(chunk, allow_inner_effect); } - }, - (false, true) => { self.check_func(def); }, + } + (false, true) => { + self.check_func(def); + } + } + if is_const { + self.check_const(def); + } + if !is_procedural && is_type { + self.check_immut_type(def); } - if is_const { self.check_const(def); } - if !is_procedural && is_type { self.check_immut_type(def); } self.path_stack.pop(); } @@ -128,30 +151,31 @@ impl SideEffectChecker { /// ``` fn check_expr(&mut self, expr: &Expr, allow_self_effect: bool) { match expr { - Expr::Def(def) => { self.check_def(def, allow_self_effect); }, + Expr::Def(def) => { + self.check_def(def, allow_self_effect); + } // 引数がproceduralでも関数呼び出しなら副作用なし Expr::Call(call) => { if self.is_procedural(&call.obj) && !allow_self_effect { - self.errs.push( - EffectError::has_effect(expr, self.full_path()) - ); + self.errs + .push(EffectError::has_effect(expr, self.full_path())); } call.args .pos_args() .iter() - .for_each(|parg|self.check_expr(&parg.expr, allow_self_effect)); + .for_each(|parg| self.check_expr(&parg.expr, allow_self_effect)); call.args .kw_args() .iter() .for_each(|kwarg| self.check_expr(&kwarg.expr, allow_self_effect)); - }, + } Expr::UnaryOp(unary) => { self.check_expr(&unary.expr, allow_self_effect); - }, + } Expr::BinOp(bin) => { self.check_expr(&bin.lhs, allow_self_effect); self.check_expr(&bin.rhs, allow_self_effect); - }, + } Expr::Lambda(lambda) => { let is_proc = lambda.is_procedural(); if is_proc { @@ -160,14 +184,16 @@ impl SideEffectChecker { self.path_stack.push((Str::ever(""), Private)); } if !allow_self_effect && is_proc { - self.errs.push(EffectError::has_effect(expr, self.full_path())); + self.errs + .push(EffectError::has_effect(expr, self.full_path())); } - lambda.body + lambda + .body .iter() .for_each(|chunk| self.check_expr(chunk, allow_self_effect && is_proc)); self.path_stack.pop(); - }, - _ => {}, + } + _ => {} } } diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 75843905..581cd53a 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -1,12 +1,12 @@ use std::fmt::Display; use std::ops::Add; -use erg_common::color::{GREEN, RED, YELLOW, RESET}; +use erg_common::color::{GREEN, RED, RESET, YELLOW}; use erg_common::config::Input; -use erg_common::error::{ErrorCore, ErrorKind::*, ErrorDisplay, MultiErrorDisplay, Location}; -use erg_common::traits::{Stream, Locational}; -use erg_common::ty::{Type, Predicate}; -use erg_common::{Str, fmt_iter}; +use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay}; +use erg_common::traits::{Locational, Stream}; +use erg_common::ty::{Predicate, Type}; +use erg_common::{fmt_iter, Str}; use erg_common::{impl_stream_for_wrapper, switch_lang}; use erg_parser::error::{ParserRunnerError, ParserRunnerErrors}; @@ -99,28 +99,58 @@ pub struct CompileError { impl From for CompileError { fn from(err: ParserRunnerError) -> Self { - Self { core: err.core, input: err.input, caused_by: "".into() } + Self { + core: err.core, + input: err.input, + caused_by: "".into(), + } } } impl ErrorDisplay for CompileError { - fn core(&self) -> &ErrorCore { &self.core } - fn input(&self) -> &Input { &self.input } - fn caused_by(&self) -> &str { &self.caused_by } - fn ref_inner(&self) -> Option<&Box> { None } + fn core(&self) -> &ErrorCore { + &self.core + } + fn input(&self) -> &Input { + &self.input + } + fn caused_by(&self) -> &str { + &self.caused_by + } + fn ref_inner(&self) -> Option<&Box> { + None + } } impl CompileError { - pub const fn new(core: ErrorCore, input: Input, caused_by: Str) -> Self { Self{ core, input, caused_by } } + pub const fn new(core: ErrorCore, input: Input, caused_by: Str) -> Self { + Self { + core, + input, + caused_by, + } + } - pub fn compiler_bug(errno: usize, input: Input, loc: Location, fn_name: &str, line: u32) -> Self { + pub fn compiler_bug( + errno: usize, + input: Input, + loc: Location, + fn_name: &str, + line: u32, + ) -> Self { Self::new(ErrorCore::new(errno, CompilerSystemError, loc, switch_lang!( format!("this is a bug of the Erg compiler, please report it to https://github.com/...\ncaused from: {fn_name}:{line}"), format!("これはErg compilerのバグです、開発者に報告して下さい (https://github.com/...)\n{fn_name}:{line}より発生") ), None), input, "".into()) } - pub fn stack_bug(input: Input, loc: Location, stack_len: u32, block_id: usize, fn_name: &str) -> Self { + pub fn stack_bug( + input: Input, + loc: Location, + stack_len: u32, + block_id: usize, + fn_name: &str, + ) -> Self { Self::new(ErrorCore::new(0, CompilerSystemError, loc, switch_lang!( format!("the number of elements in the stack is invalid (num of elems: {stack_len}, block id: {block_id})\n\ this is a bug of the Erg compiler, please report it (https://github.com/...)\n\ @@ -132,10 +162,20 @@ impl CompileError { } pub fn feature_error(input: Input, loc: Location, name: &str, caused_by: Str) -> Self { - Self::new(ErrorCore::new(0, FeatureError, loc, switch_lang!( - format!("this feature({name}) is not implemented yet"), - format!("この機能({name})はまだ正式に提供されていません") - ), None), input, caused_by) + Self::new( + ErrorCore::new( + 0, + FeatureError, + loc, + switch_lang!( + format!("this feature({name}) is not implemented yet"), + format!("この機能({name})はまだ正式に提供されていません") + ), + None, + ), + input, + caused_by, + ) } } @@ -146,9 +186,13 @@ pub struct TyCheckError { } impl TyCheckError { - pub const fn new(core: ErrorCore, caused_by: Str) -> Self { Self{ core, caused_by } } + pub const fn new(core: ErrorCore, caused_by: Str) -> Self { + Self { core, caused_by } + } - pub fn unreachable(fn_name: &str, line: u32) -> Self { Self::new(ErrorCore::unreachable(fn_name, line), "".into()) } + pub fn unreachable(fn_name: &str, line: u32) -> Self { + Self::new(ErrorCore::unreachable(fn_name, line), "".into()) + } pub fn checker_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self { Self::new(ErrorCore::new(errno, CompilerSystemError, loc, switch_lang!( @@ -158,28 +202,58 @@ impl TyCheckError { } pub fn feature_error(loc: Location, name: &str, caused_by: Str) -> Self { - Self::new(ErrorCore::new(0, FeatureError, loc, switch_lang!( - format!("this feature({name}) is not implemented yet"), - format!("この機能({name})はまだ正式に提供されていません") - ), None), caused_by) + Self::new( + ErrorCore::new( + 0, + FeatureError, + loc, + switch_lang!( + format!("this feature({name}) is not implemented yet"), + format!("この機能({name})はまだ正式に提供されていません") + ), + None, + ), + caused_by, + ) } - pub fn syntax_error>(errno: usize, loc: Location, caused_by: Str, desc: S, hint: Option) -> Self { - Self::new(ErrorCore::new(errno, SyntaxError, loc, desc, hint), caused_by) + pub fn syntax_error>( + errno: usize, + loc: Location, + caused_by: Str, + desc: S, + hint: Option, + ) -> Self { + Self::new( + ErrorCore::new(errno, SyntaxError, loc, desc, hint), + caused_by, + ) } pub fn duplicate_decl_error(loc: Location, caused_by: Str, name: &str) -> Self { let name = readable_name(name); - Self::new(ErrorCore::new(0, NameError, loc, - switch_lang!( - format!("{name} is already declared"), - format!("{name}は既に宣言されています") - ), Option::::None), - caused_by + Self::new( + ErrorCore::new( + 0, + NameError, + loc, + switch_lang!( + format!("{name} is already declared"), + format!("{name}は既に宣言されています") + ), + Option::::None, + ), + caused_by, ) } - pub fn violate_decl_error(loc: Location, caused_by: Str, name: &str, spec_t: &Type, found_t: &Type) -> Self { + pub fn violate_decl_error( + loc: Location, + caused_by: Str, + name: &str, + spec_t: &Type, + found_t: &Type, + ) -> Self { let name = readable_name(name); Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!( @@ -192,28 +266,49 @@ impl TyCheckError { pub fn no_type_spec_error(loc: Location, caused_by: Str, name: &str) -> Self { let name = readable_name(name); - Self::new(ErrorCore::new(0, TypeError, loc, - switch_lang!( - format!("the type of {name} is not specified"), - format!("{name}の型が指定されていません") - ), None), - caused_by + Self::new( + ErrorCore::new( + 0, + TypeError, + loc, + switch_lang!( + format!("the type of {name} is not specified"), + format!("{name}の型が指定されていません") + ), + None, + ), + caused_by, ) } - pub fn no_var_error(loc: Location, caused_by: Str, name: &str, similar_name: Option<&Str>) -> Self { + pub fn no_var_error( + loc: Location, + caused_by: Str, + name: &str, + similar_name: Option<&Str>, + ) -> Self { let name = readable_name(name); let hint = similar_name.map(|n| { let n = readable_name(n); switch_lang!( format!("exists a similar name variable: {n}"), format!("似た名前の変数があります: {n}") - ).into() + ) + .into() }); - Self::new(ErrorCore::new(0, NameError, loc, switch_lang!( - format!("{RED}{name}{RESET} is not defined"), - format!("{RED}{name}{RESET}という変数は定義されていません") - ), hint), caused_by) + Self::new( + ErrorCore::new( + 0, + NameError, + loc, + switch_lang!( + format!("{RED}{name}{RESET} is not defined"), + format!("{RED}{name}{RESET}という変数は定義されていません") + ), + hint, + ), + caused_by, + ) } pub fn no_attr_error( @@ -228,22 +323,47 @@ impl TyCheckError { switch_lang!( format!("has a similar name attribute: {n}"), format!("似た名前の属性があります: {n}") - ).into() + ) + .into() }); - Self::new(ErrorCore::new( 0, AttributeError, loc, switch_lang!( - format!("{obj_t} object has no attribute {RED}{name}{RESET}"), - format!("{obj_t}型オブジェクトに{RED}{name}{RESET}という属性はありません") - ), hint), + Self::new( + ErrorCore::new( + 0, + AttributeError, + loc, + switch_lang!( + format!("{obj_t} object has no attribute {RED}{name}{RESET}"), + format!("{obj_t}型オブジェクトに{RED}{name}{RESET}という属性はありません") + ), + hint, + ), caused_by, ) } - pub fn callable_impl_error<'a, C: Locational + Display>(callee: &C, param_ts: impl Iterator, caused_by: Str) -> Self { - let param_ts = fmt_iter(param_ts); - Self::new(ErrorCore::new(0, NotImplementedError, callee.loc(), switch_lang!( - format!("{callee} is not a Callable object that takes {param_ts} as an argument"), - format!("{callee}は{param_ts}を引数に取る呼び出し可能オブジェクトではありません") - ), None), caused_by) + pub fn callable_impl_error<'a, C: Locational + Display>( + callee: &C, + param_ts: impl Iterator, + caused_by: Str, + ) -> Self { + let param_ts = fmt_iter(param_ts); + Self::new( + ErrorCore::new( + 0, + NotImplementedError, + callee.loc(), + switch_lang!( + format!( + "{callee} is not a Callable object that takes {param_ts} as an argument" + ), + format!( + "{callee}は{param_ts}を引数に取る呼び出し可能オブジェクトではありません" + ) + ), + None, + ), + caused_by, + ) } pub fn type_mismatch_error( @@ -276,10 +396,19 @@ impl TyCheckError { pub fn uninitialized_error(loc: Location, caused_by: Str, name: &str, t: &Type) -> Self { let name = readable_name(name); - Self::new(ErrorCore::new(0, NameError, loc, switch_lang!( - format!("{name}: {t} is not initialized"), - format!("{name}: {t}は初期化されていません") - ), None), caused_by) + Self::new( + ErrorCore::new( + 0, + NameError, + loc, + switch_lang!( + format!("{name}: {t} is not initialized"), + format!("{name}: {t}は初期化されていません") + ), + None, + ), + caused_by, + ) } pub fn argument_error(loc: Location, caused_by: Str, expect: usize, found: usize) -> Self { @@ -290,25 +419,52 @@ impl TyCheckError { } pub fn match_error(loc: Location, caused_by: Str, expr_t: &Type) -> Self { - Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!( - format!("not all patterns of type {expr_t} are covered"), - format!("{expr_t}型の全パターンを網羅していません") - ), None), caused_by) + Self::new( + ErrorCore::new( + 0, + TypeError, + loc, + switch_lang!( + format!("not all patterns of type {expr_t} are covered"), + format!("{expr_t}型の全パターンを網羅していません") + ), + None, + ), + caused_by, + ) } pub fn infer_error(loc: Location, caused_by: Str, expr: &str) -> Self { - Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!( - format!("failed to infer the type of {expr}"), - format!("{expr}の型が推論できません") - ), None), caused_by) + Self::new( + ErrorCore::new( + 0, + TypeError, + loc, + switch_lang!( + format!("failed to infer the type of {expr}"), + format!("{expr}の型が推論できません") + ), + None, + ), + caused_by, + ) } pub fn reassign_error(loc: Location, caused_by: Str, name: &str) -> Self { let name = readable_name(name); - Self::new(ErrorCore::new(0, AssignError, loc, switch_lang!( - format!("cannot assign twice to the immutable variable {name}"), - format!("定数{name}には再代入できません") - ), None), caused_by) + Self::new( + ErrorCore::new( + 0, + AssignError, + loc, + switch_lang!( + format!("cannot assign twice to the immutable variable {name}"), + format!("定数{name}には再代入できません") + ), + None, + ), + caused_by, + ) } pub fn too_many_args_error( @@ -317,19 +473,32 @@ impl TyCheckError { caused_by: Str, params_len: usize, pos_args_len: usize, - kw_args_len: usize + kw_args_len: usize, ) -> Self { let name = readable_name(callee_name); - Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!( - format!("too many arguments for {name}: + Self::new( + ErrorCore::new( + 0, + TypeError, + loc, + switch_lang!( + format!( + "too many arguments for {name}: total expected params: {GREEN}{params_len}{RESET} passed positional args: {RED}{pos_args_len}{RESET} -passed keyword args: {RED}{kw_args_len}{RESET}"), - format!("{name}に渡された引数の数が多すぎます。 +passed keyword args: {RED}{kw_args_len}{RESET}" + ), + format!( + "{name}に渡された引数の数が多すぎます。 必要な引数の合計数: {GREEN}{params_len}{RESET}個 渡された引数の数: {RED}{pos_args_len}{RESET}個 -キーワード引数の数: {RED}{kw_args_len}{RESET}個") - ), None), caused_by) +キーワード引数の数: {RED}{kw_args_len}{RESET}個" + ) + ), + None, + ), + caused_by, + ) } pub fn multiple_args_error( @@ -339,10 +508,19 @@ passed keyword args: {RED}{kw_args_len}{RESET}"), arg_name: &str, ) -> Self { let name = readable_name(callee_name); - Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!( - format!("{name}'s argument {RED}{arg_name}{RESET} is passed multiple times"), - format!("{name}の引数{RED}{arg_name}{RESET}が複数回渡されています") - ), None), caused_by) + Self::new( + ErrorCore::new( + 0, + TypeError, + loc, + switch_lang!( + format!("{name}'s argument {RED}{arg_name}{RESET} is passed multiple times"), + format!("{name}の引数{RED}{arg_name}{RESET}が複数回渡されています") + ), + None, + ), + caused_by, + ) } pub fn unexpected_kw_arg_error( @@ -352,21 +530,45 @@ passed keyword args: {RED}{kw_args_len}{RESET}"), param_name: &str, ) -> Self { let name = readable_name(callee_name); - Self::new(ErrorCore::new(0, TypeError, loc, switch_lang!( + Self::new( + ErrorCore::new( + 0, + TypeError, + loc, + switch_lang!( format!("{name} got unexpected keyword argument {RED}{param_name}{RESET}"), format!("{name}には予期しないキーワード引数{RED}{param_name}{RESET}が渡されています") - ), None), caused_by) + ), + None, + ), + caused_by, + ) } pub fn unused_warning(loc: Location, name: &str, caused_by: Str) -> Self { let name = readable_name(name); - Self::new(ErrorCore::new(0, UnusedWarning, loc, switch_lang!( - format!("{YELLOW}{name}{RESET} is not used"), - format!("{YELLOW}{name}{RESET}は使用されていません") - ), None), caused_by) + Self::new( + ErrorCore::new( + 0, + UnusedWarning, + loc, + switch_lang!( + format!("{YELLOW}{name}{RESET} is not used"), + format!("{YELLOW}{name}{RESET}は使用されていません") + ), + None, + ), + caused_by, + ) } - pub fn unification_error(lhs_t: &Type, rhs_t: &Type, lhs_loc: Option, rhs_loc: Option, caused_by: Str) -> Self { + pub fn unification_error( + lhs_t: &Type, + rhs_t: &Type, + lhs_loc: Option, + rhs_loc: Option, + caused_by: Str, + ) -> Self { let loc = match (lhs_loc, rhs_loc) { (Some(l), Some(r)) => Location::pair(l, r), (Some(l), None) => l, @@ -379,7 +581,13 @@ passed keyword args: {RED}{kw_args_len}{RESET}"), ), None), caused_by) } - pub fn re_unification_error(lhs_t: &Type, rhs_t: &Type, lhs_loc: Option, rhs_loc: Option, caused_by: Str) -> Self { + pub fn re_unification_error( + lhs_t: &Type, + rhs_t: &Type, + lhs_loc: Option, + rhs_loc: Option, + caused_by: Str, + ) -> Self { let loc = match (lhs_loc, rhs_loc) { (Some(l), Some(r)) => Location::pair(l, r), (Some(l), None) => l, @@ -392,7 +600,13 @@ passed keyword args: {RED}{kw_args_len}{RESET}"), ), None), caused_by) } - pub fn subtyping_error(sub_t: &Type, sup_t: &Type, sub_loc: Option, sup_loc: Option, caused_by: Str) -> Self { + pub fn subtyping_error( + sub_t: &Type, + sup_t: &Type, + sub_loc: Option, + sup_loc: Option, + caused_by: Str, + ) -> Self { let loc = match (sub_loc, sup_loc) { (Some(l), Some(r)) => Location::pair(l, r), (Some(l), None) => l, @@ -413,17 +627,46 @@ passed keyword args: {RED}{kw_args_len}{RESET}"), } pub fn has_effect>(expr: &Expr, caused_by: S) -> Self { - Self::new(ErrorCore::new(0, HasEffect, expr.loc(), switch_lang!( - format!("this expression causes a side-effect"), - format!("この式には副作用があります") - ), None), caused_by.into()) + Self::new( + ErrorCore::new( + 0, + HasEffect, + expr.loc(), + switch_lang!( + format!("this expression causes a side-effect"), + format!("この式には副作用があります") + ), + None, + ), + caused_by.into(), + ) } - pub fn move_error>(name: &str, name_loc: Location, moved_loc: Location, caused_by: S) -> Self { - Self::new(ErrorCore::new(0, MoveError, name_loc, switch_lang!( - format!("{RED}{name}{RESET} was moved in line {}", moved_loc.ln_begin().unwrap()), - format!("{RED}{name}{RESET}は{}行目ですでに移動されています", moved_loc.ln_begin().unwrap()) - ), None), caused_by.into()) + pub fn move_error>( + name: &str, + name_loc: Location, + moved_loc: Location, + caused_by: S, + ) -> Self { + Self::new( + ErrorCore::new( + 0, + MoveError, + name_loc, + switch_lang!( + format!( + "{RED}{name}{RESET} was moved in line {}", + moved_loc.ln_begin().unwrap() + ), + format!( + "{RED}{name}{RESET}は{}行目ですでに移動されています", + moved_loc.ln_begin().unwrap() + ) + ), + None, + ), + caused_by.into(), + ) } } @@ -433,7 +676,9 @@ pub struct TyCheckErrors(Vec); impl_stream_for_wrapper!(TyCheckErrors, TyCheckError); impl From> for TyCheckErrors { - fn from(errs: Vec) -> Self { Self(errs) } + fn from(errs: Vec) -> Self { + Self(errs) + } } impl Add for TyCheckErrors { @@ -444,7 +689,9 @@ impl Add for TyCheckErrors { } impl From for TyCheckErrors { - fn from(err: TyCheckError) -> Self { Self(vec![err]) } + fn from(err: TyCheckError) -> Self { + Self(vec![err]) + } } pub type TyCheckResult = Result; @@ -481,11 +728,15 @@ impl From for CompileErrors { } impl From> for CompileErrors { - fn from(errs: Vec) -> Self { Self(errs) } + fn from(errs: Vec) -> Self { + Self(errs) + } } impl From for CompileErrors { - fn from(err: CompileError) -> Self { Self(vec![err]) } + fn from(err: CompileError) -> Self { + Self(vec![err]) + } } impl MultiErrorDisplay for CompileErrors {} diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index 0d95086f..5dcda2ee 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -1,13 +1,13 @@ use std::mem; -use erg_common::Str; -use erg_common::{fn_name, set}; -use erg_common::value::ValueObj; use erg_common::dict::Dict; use erg_common::rccell::RcCell; -use erg_common::set::{Set}; +use erg_common::set::Set; use erg_common::traits::Stream; -use erg_common::ty::{OpKind, TyParam, Type, Predicate, TyBound, ConstObj, SubrKind}; +use erg_common::ty::{ConstObj, OpKind, Predicate, SubrKind, TyBound, TyParam, Type}; +use erg_common::value::ValueObj; +use erg_common::Str; +use erg_common::{fn_name, set}; use OpKind::*; use erg_parser::ast::*; @@ -25,11 +25,15 @@ struct SubstContext { impl SubstContext { pub fn new(substituted: &Type, ty_ctx: &Context) -> Self { - let param_names = ty_ctx.impls.iter() + let param_names = ty_ctx + .impls + .iter() .filter(|(_, vi)| vi.kind.is_parameter()) .map(|(name, _)| name.inspect().clone()); - let self_ = SubstContext{ - params: param_names.zip(substituted.typarams().into_iter()).collect(), + let self_ = SubstContext { + params: param_names + .zip(substituted.typarams().into_iter()) + .collect(), }; // REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は? self_ @@ -53,26 +57,30 @@ impl SubstContext { ty_ctx.unify_tp(param, v, None, false)?; } } else { - if fv.is_unbound() { panic!() } + if fv.is_unbound() { + panic!() + } } } - TyParam::BinOp{ lhs, rhs, .. } => { + TyParam::BinOp { lhs, rhs, .. } => { self.substitute_tp(lhs, ty_ctx)?; self.substitute_tp(rhs, ty_ctx)?; } - TyParam::UnaryOp{ val, .. } => { + TyParam::UnaryOp { val, .. } => { self.substitute_tp(val, ty_ctx)?; } TyParam::Array(args) | TyParam::Tuple(args) - | TyParam::App{ args, .. } - | TyParam::PolyQVar{ args, .. } => { + | TyParam::App { args, .. } + | TyParam::PolyQVar { args, .. } => { for arg in args.iter() { self.substitute_tp(arg, ty_ctx)?; } } - TyParam::Type(t) => { self.substitute_t(t, ty_ctx)?; }, - TyParam::MonoProj{ obj, attr } => todo!("{obj}.{attr}"), + TyParam::Type(t) => { + self.substitute_t(t, ty_ctx)?; + } + TyParam::MonoProj { obj, attr } => todo!("{obj}.{attr}"), _ => {} } Ok(()) @@ -98,15 +106,18 @@ impl SubstContext { } #[derive(Debug, Default)] -pub struct Evaluator { -} +pub struct Evaluator {} impl Evaluator { #[inline] - pub fn new() -> Self { Self::default() } + pub fn new() -> Self { + Self::default() + } #[inline] - pub(crate) fn eval_const_lit(&self, lit: &Literal) -> ValueObj { ValueObj::from(lit) } + pub(crate) fn eval_const_lit(&self, lit: &Literal) -> ValueObj { + ValueObj::from(lit) + } fn eval_const_acc(&self, _acc: &Accessor) -> Option { todo!() @@ -142,7 +153,9 @@ impl Evaluator { Accessor::SelfDot(_name) => todo!(), Accessor::Subscr(_subscr) => todo!(), } - } else { None } + } else { + None + } } fn eval_const_def(&self, def: &Def) -> Option { @@ -175,42 +188,66 @@ impl Evaluator { fn eval_bin_lit(&self, op: OpKind, lhs: ValueObj, rhs: ValueObj) -> EvalResult { match op { - Add => lhs.try_add(rhs).ok_or(EvalError::unreachable(fn_name!(), line!())), - Sub => lhs.try_sub(rhs).ok_or(EvalError::unreachable(fn_name!(), line!())), - Mul => lhs.try_mul(rhs).ok_or(EvalError::unreachable(fn_name!(), line!())), - Div => lhs.try_div(rhs).ok_or(EvalError::unreachable(fn_name!(), line!())), - Gt => lhs.try_gt(rhs).ok_or(EvalError::unreachable(fn_name!(), line!())), - Ge => lhs.try_ge(rhs).ok_or(EvalError::unreachable(fn_name!(), line!())), - Eq => lhs.try_eq(rhs).ok_or(EvalError::unreachable(fn_name!(), line!())), - Ne => lhs.try_ne(rhs).ok_or(EvalError::unreachable(fn_name!(), line!())), + Add => lhs + .try_add(rhs) + .ok_or(EvalError::unreachable(fn_name!(), line!())), + Sub => lhs + .try_sub(rhs) + .ok_or(EvalError::unreachable(fn_name!(), line!())), + Mul => lhs + .try_mul(rhs) + .ok_or(EvalError::unreachable(fn_name!(), line!())), + Div => lhs + .try_div(rhs) + .ok_or(EvalError::unreachable(fn_name!(), line!())), + Gt => lhs + .try_gt(rhs) + .ok_or(EvalError::unreachable(fn_name!(), line!())), + Ge => lhs + .try_ge(rhs) + .ok_or(EvalError::unreachable(fn_name!(), line!())), + Eq => lhs + .try_eq(rhs) + .ok_or(EvalError::unreachable(fn_name!(), line!())), + Ne => lhs + .try_ne(rhs) + .ok_or(EvalError::unreachable(fn_name!(), line!())), other => todo!("{other}"), } } - pub(crate) fn eval_bin_tp(&self, op: OpKind, lhs: &TyParam, rhs: &TyParam) -> EvalResult { + pub(crate) fn eval_bin_tp( + &self, + op: OpKind, + lhs: &TyParam, + rhs: &TyParam, + ) -> EvalResult { 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()) - .map(|v| TyParam::value(v)), - (TyParam::ConstObj(ConstObj::MutValue(lhs)), TyParam::ConstObj(ConstObj::Value(rhs))) => - self.eval_bin_lit(op, lhs.borrow().clone(), rhs.clone()) - .map(|v| TyParam::ConstObj(ConstObj::MutValue(RcCell::new(v)))), + .map(|v| TyParam::value(v)) + } + ( + TyParam::ConstObj(ConstObj::MutValue(lhs)), + TyParam::ConstObj(ConstObj::Value(rhs)), + ) => self + .eval_bin_lit(op, lhs.borrow().clone(), rhs.clone()) + .map(|v| TyParam::ConstObj(ConstObj::MutValue(RcCell::new(v)))), (TyParam::FreeVar(fv), r) => { if fv.is_linked() { self.eval_bin_tp(op, &*fv.crack(), r) } else { Err(EvalError::unreachable(fn_name!(), line!())) } - }, + } (l, TyParam::FreeVar(fv)) => { if fv.is_linked() { self.eval_bin_tp(op, l, &*fv.crack()) } else { Err(EvalError::unreachable(fn_name!(), line!())) } - }, - (e @ TyParam::Erased(_), _) - | (_, e @ TyParam::Erased(_)) => Ok(e.clone()), + } + (e @ TyParam::Erased(_), _) | (_, e @ TyParam::Erased(_)) => Ok(e.clone()), (l, r) => todo!("{l} {op} {r}"), } } @@ -220,20 +257,21 @@ impl Evaluator { Pos => todo!(), Neg => todo!(), Invert => todo!(), - Mutate => if let ConstObj::Value(v) = val { - Ok(ConstObj::MutValue(RcCell::new(v))) - } else { todo!() }, + Mutate => { + if let ConstObj::Value(v) = val { + Ok(ConstObj::MutValue(RcCell::new(v))) + } else { + todo!() + } + } other => todo!("{other}"), } } - fn eval_unary_tp(&self, op: OpKind, val: &TyParam) -> EvalResult { + fn eval_unary_tp(&self, op: OpKind, val: &TyParam) -> EvalResult { match val { - TyParam::ConstObj(c) => - self.eval_unary_lit(op, c.clone()).map(|c| TyParam::cons(c)), - TyParam::FreeVar(fv) if fv.is_linked() => { - self.eval_unary_tp(op, &*fv.crack()) - }, + TyParam::ConstObj(c) => self.eval_unary_lit(op, c.clone()).map(|c| TyParam::cons(c)), + TyParam::FreeVar(fv) if fv.is_linked() => self.eval_unary_tp(op, &*fv.crack()), e @ TyParam::Erased(_) => Ok(e.clone()), other => todo!("{op} {other}"), } @@ -246,37 +284,41 @@ impl Evaluator { /// 量化変数などはそのまま返す pub(crate) fn eval_tp(&self, p: &TyParam, ctx: &Context) -> EvalResult { match p { - TyParam::FreeVar(fv) if fv.is_linked() => - self.eval_tp(&fv.crack(), ctx), - TyParam::Mono(name) => - ctx.consts.get(name) - .and_then(|c| match c { - ConstObj::Value(v) => Some(TyParam::value(v.clone())), - _ => None, - }).ok_or(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), - p @ ( - TyParam::Type(_) | TyParam::Erased(_) | TyParam::ConstObj(_) | TyParam::FreeVar(_) | TyParam::MonoQVar(_) - ) => Ok(p.clone()), + TyParam::FreeVar(fv) if fv.is_linked() => self.eval_tp(&fv.crack(), ctx), + TyParam::Mono(name) => ctx + .consts + .get(name) + .and_then(|c| match c { + ConstObj::Value(v) => Some(TyParam::value(v.clone())), + _ => None, + }) + .ok_or(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), + p @ (TyParam::Type(_) + | TyParam::Erased(_) + | TyParam::ConstObj(_) + | TyParam::FreeVar(_) + | TyParam::MonoQVar(_)) => Ok(p.clone()), other => todo!("{other}"), } } - pub(crate) fn eval_t(&self, substituted: Type, ctx: &Context, level: usize) -> EvalResult { + pub(crate) fn eval_t( + &self, + substituted: Type, + ctx: &Context, + level: usize, + ) -> EvalResult { match substituted { - Type::FreeVar(fv) if fv.is_linked() => - self.eval_t(fv.crack().clone(), ctx, level), + Type::FreeVar(fv) if fv.is_linked() => self.eval_t(fv.crack().clone(), ctx, level), Type::Subr(mut subr) => { let kind = match subr.kind { SubrKind::FuncMethod(self_t) => { SubrKind::fn_met(self.eval_t(*self_t, ctx, level)?) } - SubrKind::ProcMethod{ before, after } => { + SubrKind::ProcMethod { before, after } => { let before = self.eval_t(*before, ctx, level)?; if let Some(after) = after { let after = self.eval_t(*after, ctx, level)?; @@ -294,34 +336,41 @@ impl Evaluator { p.ty = self.eval_t(mem::take(&mut p.ty), ctx, level)?; } let return_t = self.eval_t(*subr.return_t, ctx, level)?; - Ok(Type::subr(kind, subr.non_default_params, subr.default_params, return_t)) - }, - Type::Array{ t, len } => { + Ok(Type::subr( + kind, + subr.non_default_params, + subr.default_params, + return_t, + )) + } + Type::Array { t, len } => { let t = self.eval_t(*t, ctx, level)?; let len = self.eval_tp(&len, ctx)?; Ok(Type::array(t, len)) - }, + } Type::Refinement(refine) => { let mut preds = Set::with_capacity(refine.preds.len()); for pred in refine.preds.into_iter() { preds.insert(self.eval_pred(pred, ctx)?); } Ok(Type::refinement(refine.var, *refine.t, preds)) - }, + } // [?T; 0].MutType! == [?T; !0] - Type::MonoProj{ lhs, rhs } => { + Type::MonoProj { lhs, rhs } => { for ty_ctx in ctx.get_sorted_supertypes(&lhs) { if let Ok(obj) = ty_ctx.get_local(&Token::symbol(&rhs), &ctx.name) { if let ConstObj::Type(quant_t) = obj { let subst_ctx = SubstContext::new(&lhs, ty_ctx); let t = subst_ctx.substitute(*quant_t, ty_ctx, level)?; let t = self.eval_t(t, ctx, level)?; - return Ok(t) - } else { todo!() } + return Ok(t); + } else { + todo!() + } } } todo!() - }, + } Type::Range(l) => Ok(Type::range(self.eval_t(*l, ctx, level)?)), Type::Iter(l) => Ok(Type::iter(self.eval_t(*l, ctx, level)?)), Type::Ref(l) => Ok(Type::refer(self.eval_t(*l, ctx, level)?)), @@ -329,87 +378,109 @@ impl Evaluator { Type::Option(l) => Ok(Type::option_mut(self.eval_t(*l, ctx, level)?)), Type::OptionMut(l) => Ok(Type::option_mut(self.eval_t(*l, ctx, level)?)), Type::VarArgs(l) => Ok(Type::var_args(self.eval_t(*l, ctx, level)?)), - Type::Poly{ name, mut params } => { + Type::Poly { name, mut params } => { for p in params.iter_mut() { *p = self.eval_tp(&mem::take(p), ctx)?; } Ok(Type::poly(name, params)) - }, + } other if other.is_monomorphic() => Ok(other), other => todo!("{other}"), } } - pub(crate) fn _eval_bound(&self, bound: TyBound, ctx: &Context, level: usize) -> EvalResult { + pub(crate) fn _eval_bound( + &self, + bound: TyBound, + ctx: &Context, + level: usize, + ) -> EvalResult { match bound { - TyBound::Subtype{ sub, sup } => - Ok(TyBound::subtype( - self.eval_t(sub, ctx, level)?, - self.eval_t(sup, ctx, level)? - )), - TyBound::Supertype{ sup, sub } => - Ok(TyBound::supertype( - self.eval_t(sup, ctx, level)?, - self.eval_t(sub, ctx, level)? - )), + TyBound::Subtype { sub, sup } => Ok(TyBound::subtype( + self.eval_t(sub, ctx, level)?, + self.eval_t(sup, ctx, level)?, + )), + TyBound::Supertype { sup, sub } => Ok(TyBound::supertype( + self.eval_t(sup, ctx, level)?, + self.eval_t(sub, ctx, level)?, + )), TyBound::Sandwiched { sub, mid, sup } => { let sub = self.eval_t(sub, ctx, level)?; let mid = self.eval_t(mid, ctx, level)?; let sup = self.eval_t(sup, ctx, level)?; Ok(TyBound::sandwiched(sub, mid, sup)) - }, - TyBound::Instance{ name: inst, t } => - Ok(TyBound::instance(inst, self.eval_t(t, ctx, level)?)), + } + TyBound::Instance { name: inst, t } => { + Ok(TyBound::instance(inst, self.eval_t(t, ctx, level)?)) + } } } pub(crate) fn eval_pred(&self, p: Predicate, ctx: &Context) -> EvalResult { match p { Predicate::Value(_) | Predicate::Const(_) => Ok(p), - Predicate::Equal{ lhs, rhs } => - Ok(Predicate::eq(lhs, self.eval_tp(&rhs, ctx)?)), - Predicate::NotEqual{ lhs, rhs } => - Ok(Predicate::ne(lhs, self.eval_tp(&rhs, ctx)?)), - Predicate::LessEqual{ lhs, rhs } => - Ok(Predicate::le(lhs, self.eval_tp(&rhs, ctx)?)), - Predicate::GreaterEqual{ lhs, rhs } => - Ok(Predicate::ge(lhs, self.eval_tp(&rhs, ctx)?)), - Predicate::And(l, r) => - Ok(Predicate::and(self.eval_pred(*l, ctx)?, self.eval_pred(*r, ctx)?)), - Predicate::Or(l, r) => - Ok(Predicate::or(self.eval_pred(*l, ctx)?, self.eval_pred(*r, ctx)?)), - Predicate::Not(l, r) => - Ok(Predicate::not(self.eval_pred(*l, ctx)?, self.eval_pred(*r, ctx)?)), + Predicate::Equal { lhs, rhs } => Ok(Predicate::eq(lhs, self.eval_tp(&rhs, ctx)?)), + Predicate::NotEqual { lhs, rhs } => Ok(Predicate::ne(lhs, self.eval_tp(&rhs, ctx)?)), + Predicate::LessEqual { lhs, rhs } => Ok(Predicate::le(lhs, self.eval_tp(&rhs, ctx)?)), + Predicate::GreaterEqual { lhs, rhs } => { + Ok(Predicate::ge(lhs, self.eval_tp(&rhs, ctx)?)) + } + Predicate::And(l, r) => Ok(Predicate::and( + self.eval_pred(*l, ctx)?, + self.eval_pred(*r, ctx)?, + )), + Predicate::Or(l, r) => Ok(Predicate::or( + self.eval_pred(*l, ctx)?, + self.eval_pred(*r, ctx)?, + )), + Predicate::Not(l, r) => Ok(Predicate::not( + self.eval_pred(*l, ctx)?, + self.eval_pred(*r, ctx)?, + )), } } - pub(crate) fn get_tp_t(&self, p: &TyParam, bounds: Option<&Set>, ctx: &Context) -> EvalResult { + pub(crate) fn get_tp_t( + &self, + p: &TyParam, + bounds: Option<&Set>, + ctx: &Context, + ) -> EvalResult { let p = self.eval_tp(p, ctx)?; 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::FreeVar(fv) => - if let Some(t) = fv.type_of() { Ok(t) } else { todo!() }, + TyParam::FreeVar(fv) => { + if let Some(t) = fv.type_of() { + Ok(t) + } else { + todo!() + } + } TyParam::Type(_) => Ok(Type::Type), - TyParam::Mono(name) => - ctx.consts.get(&name) - .and_then(|c| match c { - ConstObj::Value(v) => Some(Type::enum_t(set![v.clone()])), - _ => None, - }).ok_or(EvalError::unreachable(fn_name!(), line!())), + TyParam::Mono(name) => ctx + .consts + .get(&name) + .and_then(|c| match c { + ConstObj::Value(v) => Some(Type::enum_t(set![v.clone()])), + _ => None, + }) + .ok_or(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)) { Ok(bound.t().clone()) - } else { todo!() } - } else { todo!() } - }, - TyParam::UnaryOp{ op, val } => { - match op { - OpKind::Mutate => Ok(self.get_tp_t(&val, bounds, ctx)?.mutate()), - _ => todo!(), + } else { + todo!() + } + } else { + todo!() } + } + TyParam::UnaryOp { op, val } => match op { + OpKind::Mutate => Ok(self.get_tp_t(&val, bounds, ctx)?.mutate()), + _ => todo!(), }, other => todo!("{other}"), } @@ -420,15 +491,22 @@ impl Evaluator { match p { TyParam::ConstObj(ConstObj::Value(v)) => Ok(v.class()), TyParam::Erased(t) => Ok((&*t).clone()), - | TyParam::FreeVar(fv) => - if let Some(t) = fv.type_of() { Ok(t) } else { todo!() }, + TyParam::FreeVar(fv) => { + if let Some(t) = fv.type_of() { + Ok(t) + } else { + todo!() + } + } TyParam::Type(_) => Ok(Type::Type), - TyParam::Mono(name) => - ctx.consts.get(&name) - .and_then(|c| match c { - ConstObj::Value(v) => Some(v.class()), - _ => None, - }).ok_or(EvalError::unreachable(fn_name!(), line!())), + TyParam::Mono(name) => ctx + .consts + .get(&name) + .and_then(|c| match c { + ConstObj::Value(v) => Some(v.class()), + _ => None, + }) + .ok_or(EvalError::unreachable(fn_name!(), line!())), other => todo!("{other}"), } } @@ -439,21 +517,27 @@ impl Evaluator { (TyParam::Type(l), TyParam::Type(r)) => l == r, (TyParam::ConstObj(l), TyParam::ConstObj(r)) => l == r, (TyParam::Erased(l), TyParam::Erased(r)) => l == r, - (TyParam::FreeVar{ .. }, TyParam::FreeVar{ .. }) => true, + (TyParam::FreeVar { .. }, TyParam::FreeVar { .. }) => true, (TyParam::Mono(l), TyParam::Mono(r)) => { - if l == r { true } - else if let (Some(l), Some(r)) = (ctx.consts.get(l), ctx.consts.get(r)) { l == r } - else { + if l == r { + true + } else if let (Some(l), Some(r)) = (ctx.consts.get(l), ctx.consts.get(r)) { + l == r + } else { // lとrが型の場合は... false } - }, - (TyParam::BinOp{ .. }, TyParam::BinOp{ .. }) => todo!(), - (TyParam::UnaryOp{ .. }, TyParam::UnaryOp{ .. }) => todo!(), - (TyParam::App{ .. }, TyParam::App{ .. }) => todo!(), - (TyParam::Mono(m), TyParam::ConstObj(l)) - | (TyParam::ConstObj(l), TyParam::Mono(m)) => - if let Some(o) = ctx.consts.get(m) { o == l } else { true }, + } + (TyParam::BinOp { .. }, TyParam::BinOp { .. }) => todo!(), + (TyParam::UnaryOp { .. }, TyParam::UnaryOp { .. }) => todo!(), + (TyParam::App { .. }, TyParam::App { .. }) => todo!(), + (TyParam::Mono(m), TyParam::ConstObj(l)) | (TyParam::ConstObj(l), TyParam::Mono(m)) => { + if let Some(o) = ctx.consts.get(m) { + o == l + } else { + true + } + } (TyParam::MonoQVar(_), _) | (_, TyParam::MonoQVar(_)) => false, (l, r) => todo!("l: {l}, r: {r}"), } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 731f27ac..4207e3e5 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -1,32 +1,35 @@ /// defines High-level Intermediate Representation use std::fmt; -use erg_common::{Str}; -use erg_common::value::ValueObj; use erg_common::error::Location; -use erg_common::traits::{HasType, Locational, Stream, NestedDisplay}; -use erg_common::ty::{Type, TyParam, Constraint}; +use erg_common::traits::{HasType, Locational, NestedDisplay, Stream}; +use erg_common::ty::{Constraint, TyParam, Type}; +use erg_common::value::ValueObj; +use erg_common::Str; use erg_common::{ - impl_locational, impl_locational_for_enum, - impl_stream_for_wrapper, impl_display_for_enum, - impl_nested_display_for_enum, impl_display_from_nested, + impl_display_for_enum, impl_display_from_nested, impl_locational, impl_locational_for_enum, + impl_nested_display_for_enum, impl_stream_for_wrapper, }; +use erg_parser::ast::{fmt_lines, DefId, Params, VarName, VarPattern}; use erg_parser::token::{Token, TokenKind}; -use erg_parser::ast::{VarName, VarPattern, Params, DefId, fmt_lines}; #[derive(Debug, Clone)] pub struct Literal { pub data: ValueObj, // for constant folding - pub token: Token, // for Locational + pub token: Token, // for Locational t: Type, } impl HasType for Literal { #[inline] - fn ref_t(&self) -> &Type { &self.t } + fn ref_t(&self) -> &Type { + &self.t + } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl NestedDisplay for Literal { @@ -39,13 +42,19 @@ impl_display_from_nested!(Literal); impl Locational for Literal { #[inline] - fn loc(&self) -> Location { self.token.loc() } + fn loc(&self) -> Location { + self.token.loc() + } } impl From for Literal { fn from(token: Token) -> Self { let data = ValueObj::from_str(Type::from(token.kind), token.content.clone()); - Self { t: data.t(), data, token } + Self { + t: data.t(), + data, + token, + } } } @@ -53,7 +62,11 @@ impl Literal { pub fn new(c: ValueObj, lineno: usize, col: usize) -> Self { let kind = TokenKind::from(&c); let token = Token::new(kind, c.to_string(), lineno, col); - Self { t: c.t(), data: c, token } + Self { + t: c.t(), + data: c, + token, + } } #[inline] @@ -76,11 +89,15 @@ impl NestedDisplay for PosArg { impl_display_from_nested!(PosArg); impl Locational for PosArg { - fn loc(&self) -> Location { self.expr.loc() } + fn loc(&self) -> Location { + self.expr.loc() + } } impl PosArg { - pub const fn new(expr: Expr) -> Self { Self { expr } } + pub const fn new(expr: Expr) -> Self { + Self { expr } + } } #[derive(Debug, Clone)] @@ -105,7 +122,9 @@ impl Locational for KwArg { } impl KwArg { - pub const fn new(keyword: Token, expr: Expr) -> Self { Self { keyword, expr } } + pub const fn new(keyword: Token, expr: Expr) -> Self { + Self { keyword, expr } + } } #[derive(Debug, Clone)] @@ -117,8 +136,12 @@ pub struct Args { impl NestedDisplay for Args { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { - if !self.pos_args.is_empty() { fmt_lines(self.pos_args.iter(), f, level)?; } - if !self.kw_args.is_empty() { fmt_lines(self.kw_args.iter(), f, level)?; } + if !self.pos_args.is_empty() { + fmt_lines(self.pos_args.iter(), f, level)?; + } + if !self.kw_args.is_empty() { + fmt_lines(self.kw_args.iter(), f, level)?; + } Ok(()) } } @@ -132,7 +155,10 @@ impl Locational for Args { } else if !self.kw_args.is_empty() { Location::concat(self.kw_args.first().unwrap(), self.kw_args.last().unwrap()) } else if !self.pos_args.is_empty() { - Location::concat(self.pos_args.first().unwrap(), self.pos_args.last().unwrap()) + Location::concat( + self.pos_args.first().unwrap(), + self.pos_args.last().unwrap(), + ) } else { Location::Unknown } @@ -142,8 +168,16 @@ impl Locational for Args { // impl_stream!(Args, KwArg, kw_args); impl Args { - pub const fn new(pos_args: Vec, kw_args: Vec, paren: Option<(Token, Token)>) -> Self { - Self { pos_args, kw_args, paren } + pub const fn new( + pos_args: Vec, + kw_args: Vec, + paren: Option<(Token, Token)>, + ) -> Self { + Self { + pos_args, + kw_args, + paren, + } } pub const fn empty() -> Self { @@ -156,11 +190,17 @@ impl Args { } #[inline] - pub fn kw_len(&self) -> usize { self.kw_args.len() } + pub fn kw_len(&self) -> usize { + self.kw_args.len() + } - pub fn pos_args(&self) -> &[PosArg] { &self.pos_args[..] } + pub fn pos_args(&self) -> &[PosArg] { + &self.pos_args[..] + } - pub fn kw_args(&self) -> &[KwArg] { &self.kw_args[..] } + pub fn kw_args(&self) -> &[KwArg] { + &self.kw_args[..] + } pub fn push_pos(&mut self, pos: PosArg) { self.pos_args.push(pos); @@ -174,7 +214,7 @@ impl Args { if self.pos_args.get(index).is_some() { self.pos_args.remove(index).expr } else { - self.kw_args.remove(index-self.pos_args.len()).expr + self.kw_args.remove(index - self.pos_args.len()).expr } } @@ -183,8 +223,8 @@ impl Args { if self.pos_args.get(index).is_some() { Some(self.pos_args.remove(index).expr) } else { - self.kw_args.get(index-self.pos_args.len())?; - Some(self.kw_args.remove(index-self.pos_args.len()).expr) + self.kw_args.get(index - self.pos_args.len())?; + Some(self.kw_args.remove(index - self.pos_args.len()).expr) } } @@ -202,7 +242,9 @@ impl Args { if self.pos_args.get(index).is_some() { self.pos_args.get(index).map(|a| &a.expr) } else { - self.kw_args.get(index-self.pos_args.len()).map(|a| &a.expr) + self.kw_args + .get(index - self.pos_args.len()) + .map(|a| &a.expr) } } } @@ -220,7 +262,9 @@ impl fmt::Display for Local { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let __name__ = if let Some(__name__) = self.__name__() { format!("(__name__ = {__name__})") - } else { "".to_string() }; + } else { + "".to_string() + }; if self.t != Type::ASTOmitted { write!(f, "{} (: {}){}", self.name.content, self.t, __name__) } else { @@ -231,31 +275,43 @@ impl fmt::Display for Local { impl HasType for Local { #[inline] - fn ref_t(&self) -> &Type { &self.t } + fn ref_t(&self) -> &Type { + &self.t + } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl Locational for Local { #[inline] - fn loc(&self) -> Location { self.name.loc() } + fn loc(&self) -> Location { + self.name.loc() + } } impl Local { - pub const fn new(name: Token, __name__: Option, t: Type) -> Self { Self{ name, __name__, t } } + pub const fn new(name: Token, __name__: Option, t: Type) -> Self { + Self { name, __name__, t } + } // &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで #[inline] - pub fn inspect(&self) -> &Str { &self.name.content } + pub fn inspect(&self) -> &Str { + &self.name.content + } - pub const fn __name__(&self) -> Option<&Str> { self.__name__.as_ref() } + pub const fn __name__(&self) -> Option<&Str> { + self.__name__.as_ref() + } } #[derive(Debug, Clone)] pub struct Attribute { pub obj: Box, pub name: Token, - t: Type + t: Type, } impl fmt::Display for Attribute { @@ -268,14 +324,22 @@ impl_locational!(Attribute, obj, name); impl HasType for Attribute { #[inline] - fn ref_t(&self) -> &Type { &self.t } + fn ref_t(&self) -> &Type { + &self.t + } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl Attribute { pub fn new(obj: Expr, name: Token, t: Type) -> Self { - Self { obj: Box::new(obj), name, t } + Self { + obj: Box::new(obj), + name, + t, + } } } @@ -283,7 +347,7 @@ impl Attribute { pub struct Subscript { obj: Box, index: Box, - t: Type + t: Type, } impl fmt::Display for Subscript { @@ -296,14 +360,22 @@ impl_locational!(Subscript, obj, index); impl HasType for Subscript { #[inline] - fn ref_t(&self) -> &Type { &self.t } + fn ref_t(&self) -> &Type { + &self.t + } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl Subscript { pub fn new(obj: Expr, index: Expr, t: Type) -> Self { - Self { obj: Box::new(obj), index: Box::new(index), t } + Self { + obj: Box::new(obj), + index: Box::new(index), + t, + } } } @@ -339,13 +411,19 @@ impl HasType for Accessor { } } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl Accessor { - pub const fn local(symbol: Token, t: Type) -> Self { Self::Local(Local::new(symbol, None, t)) } + pub const fn local(symbol: Token, t: Type) -> Self { + Self::Local(Local::new(symbol, None, t)) + } - pub const fn self_dot(name: Token, t: Type) -> Self { Self::SelfDot(Local::new(name, None, t)) } + pub const fn self_dot(name: Token, t: Type) -> Self { + Self::SelfDot(Local::new(name, None, t)) + } pub fn attr(obj: Expr, name: Token, t: Type) -> Self { Self::Attr(Attribute::new(obj, name, t)) @@ -358,18 +436,18 @@ impl Accessor { pub fn var_full_name(&self) -> Option { match self { Self::Local(local) => Some(local.inspect().to_string()), - Self::Attr(attr) => - attr.obj.var_full_name().map(|n| n + "." + attr.name.inspect()), - Self::Subscr(_) - | Self::SelfDot(_) => todo!(), + Self::Attr(attr) => attr + .obj + .var_full_name() + .map(|n| n + "." + attr.name.inspect()), + Self::Subscr(_) | Self::SelfDot(_) => todo!(), } } // 参照するオブジェクト自体が持っている固有の名前 pub fn __name__(&self) -> Option<&str> { match self { - Self::Local(local) - | Self::SelfDot(local) => local.__name__().map(|s| &s[..]), + Self::Local(local) | Self::SelfDot(local) => local.__name__().map(|s| &s[..]), _ => None, } } @@ -386,9 +464,13 @@ pub struct Array { impl HasType for Array { #[inline] - fn ref_t(&self) -> &Type { &self.t } + fn ref_t(&self) -> &Type { + &self.t + } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl NestedDisplay for Array { @@ -405,12 +487,26 @@ impl_display_from_nested!(Array); impl_locational!(Array, l_sqbr, r_sqbr); impl Array { - pub fn new(l_sqbr: Token, r_sqbr: Token, level: usize, elems: Args, guard: Option) -> Self { - let elem_t = elems.pos_args().first() + pub fn new( + l_sqbr: Token, + r_sqbr: Token, + level: usize, + elems: Args, + guard: Option, + ) -> Self { + let elem_t = elems + .pos_args() + .first() .map(|a| a.expr.t()) .unwrap_or_else(|| Type::free_var(level, Constraint::TypeOf(Type::Type))); let t = Type::array(elem_t, TyParam::value(elems.len())); - Self { l_sqbr, r_sqbr, t, elems, guard: guard.map(Box::new) } + Self { + l_sqbr, + r_sqbr, + t, + elems, + guard: guard.map(Box::new), + } } pub fn push(&mut self, elem: Expr) { @@ -426,10 +522,16 @@ pub struct Dict { } impl HasType for Dict { - fn ref_t(&self) -> &Type { todo!() } - fn t(&self) -> Type { todo!() } + fn ref_t(&self) -> &Type { + todo!() + } + fn t(&self) -> Type { + todo!() + } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl NestedDisplay for Dict { @@ -443,7 +545,11 @@ impl_locational!(Dict, l_brace, r_brace); impl Dict { pub const fn new(l_brace: Token, r_brace: Token, attrs: Args) -> Self { - Self { l_brace, r_brace, attrs } + Self { + l_brace, + r_brace, + attrs, + } } } @@ -466,13 +572,21 @@ impl NestedDisplay for BinOp { impl HasType for BinOp { #[inline] - fn ref_t(&self) -> &Type { &self.sig_t.return_t().unwrap() } + fn ref_t(&self) -> &Type { + &self.sig_t.return_t().unwrap() + } #[inline] - fn lhs_t(&self) -> &Type { &self.sig_t.lhs_t() } + fn lhs_t(&self) -> &Type { + &self.sig_t.lhs_t() + } #[inline] - fn rhs_t(&self) -> &Type { &self.sig_t.rhs_t() } + fn rhs_t(&self) -> &Type { + &self.sig_t.rhs_t() + } #[inline] - fn signature_t(&self) -> Option<&Type> { Some(&self.sig_t) } + fn signature_t(&self) -> Option<&Type> { + Some(&self.sig_t) + } } impl_display_from_nested!(BinOp); @@ -480,7 +594,12 @@ impl_locational!(BinOp, lhs, rhs); impl BinOp { pub fn new(op: Token, lhs: Expr, rhs: Expr, sig_t: Type) -> Self { - Self { op, lhs: Box::new(lhs), rhs: Box::new(rhs), sig_t } + Self { + op, + lhs: Box::new(lhs), + rhs: Box::new(rhs), + sig_t, + } } } @@ -493,13 +612,21 @@ pub struct UnaryOp { impl HasType for UnaryOp { #[inline] - fn ref_t(&self) -> &Type { &self.sig_t.return_t().unwrap() } + fn ref_t(&self) -> &Type { + &self.sig_t.return_t().unwrap() + } #[inline] - fn lhs_t(&self) -> &Type { self.expr.ref_t() } + fn lhs_t(&self) -> &Type { + self.expr.ref_t() + } #[inline] - fn rhs_t(&self) -> &Type { panic!("invalid operation") } + fn rhs_t(&self) -> &Type { + panic!("invalid operation") + } #[inline] - fn signature_t(&self) -> Option<&Type> { Some(&self.sig_t) } + fn signature_t(&self) -> Option<&Type> { + Some(&self.sig_t) + } } impl NestedDisplay for UnaryOp { @@ -514,7 +641,11 @@ impl_locational!(UnaryOp, op, expr); impl UnaryOp { pub fn new(op: Token, expr: Expr, sig_t: Type) -> Self { - Self { op, expr: Box::new(expr), sig_t } + Self { + op, + expr: Box::new(expr), + sig_t, + } } } @@ -538,13 +669,21 @@ impl_display_from_nested!(Call); impl HasType for Call { #[inline] - fn ref_t(&self) -> &Type { &self.sig_t.return_t().unwrap() } + fn ref_t(&self) -> &Type { + &self.sig_t.return_t().unwrap() + } #[inline] - fn lhs_t(&self) -> &Type { self.sig_t.lhs_t() } + fn lhs_t(&self) -> &Type { + self.sig_t.lhs_t() + } #[inline] - fn rhs_t(&self) -> &Type { self.sig_t.rhs_t() } + fn rhs_t(&self) -> &Type { + self.sig_t.rhs_t() + } #[inline] - fn signature_t(&self) -> Option<&Type> { Some(&self.sig_t) } + fn signature_t(&self) -> Option<&Type> { + Some(&self.sig_t) + } } impl Locational for Call { @@ -555,11 +694,16 @@ impl Locational for Call { impl Call { pub fn new(obj: Expr, args: Args, sig_t: Type) -> Self { - Self { obj: Box::new(obj), args, sig_t } + Self { + obj: Box::new(obj), + args, + sig_t, + } } pub fn is_import_call(&self) -> bool { - self.obj.var_full_name() + self.obj + .var_full_name() .map(|s| &s[..] == "import" || &s[..] == "pyimport") .unwrap_or(false) } @@ -570,11 +714,17 @@ pub struct Block(Vec); impl HasType for Block { #[inline] - fn ref_t(&self) -> &Type { self.last().unwrap().ref_t() } + fn ref_t(&self) -> &Type { + self.last().unwrap().ref_t() + } #[inline] - fn t(&self) -> Type { self.last().unwrap().t() } + fn t(&self) -> Type { + self.last().unwrap().t() + } #[inline] - fn signature_t(&self) -> Option<&Type> { self.last().unwrap().signature_t() } + fn signature_t(&self) -> Option<&Type> { + self.last().unwrap().signature_t() + } } impl NestedDisplay for Block { @@ -605,13 +755,19 @@ impl fmt::Display for VarSignature { } impl Locational for VarSignature { - fn loc(&self) -> Location { self.pat.loc() } + fn loc(&self) -> Location { + self.pat.loc() + } } impl VarSignature { - pub const fn new(pat: VarPattern, t: Type) -> Self { Self{ pat, t } } + pub const fn new(pat: VarPattern, t: Type) -> Self { + Self { pat, t } + } - pub fn inspect(&self) -> Option<&Str> { self.pat.inspect() } + pub fn inspect(&self) -> Option<&Str> { + self.pat.inspect() + } } #[derive(Debug, Clone)] @@ -635,10 +791,12 @@ impl Locational for SubrSignature { impl SubrSignature { pub const fn new(name: VarName, params: Params, t: Type) -> Self { - Self{ name, params, t } + Self { name, params, t } } - pub fn is_procedural(&self) -> bool { self.name.is_procedural() } + pub fn is_procedural(&self) -> bool { + self.name.is_procedural() + } } #[derive(Debug, Clone)] @@ -647,14 +805,18 @@ pub struct Lambda { op: Token, pub body: Block, pub id: usize, - t: Type + t: Type, } impl HasType for Lambda { #[inline] - fn ref_t(&self) -> &Type { &self.t } + fn ref_t(&self) -> &Type { + &self.t + } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl NestedDisplay for Lambda { @@ -669,10 +831,18 @@ impl_locational!(Lambda, params, body); impl Lambda { pub const fn new(id: usize, params: Params, op: Token, body: Block, t: Type) -> Self { - Self { id, params, op, body, t } + Self { + id, + params, + op, + body, + t, + } } - pub fn is_procedural(&self) -> bool { self.op.is(TokenKind::ProcArrow) } + pub fn is_procedural(&self) -> bool { + self.op.is(TokenKind::ProcArrow) + } } #[derive(Debug, Clone)] @@ -685,7 +855,9 @@ impl_display_for_enum!(Signature; Var, Subr,); impl_locational_for_enum!(Signature; Var, Subr,); impl Signature { - pub const fn is_subr(&self) -> bool { matches!(self, Self::Subr(_)) } + pub const fn is_subr(&self) -> bool { + matches!(self, Self::Subr(_)) + } pub fn is_const(&self) -> bool { match self { @@ -720,34 +892,44 @@ impl_display_from_nested!(Decl); impl Locational for Decl { #[inline] - fn loc(&self) -> Location { self.sig.loc() } + fn loc(&self) -> Location { + self.sig.loc() + } } impl Decl { - pub const fn spec_t(&self) -> &Type { &self.t } + pub const fn spec_t(&self) -> &Type { + &self.t + } - pub const fn is_sub(&self) -> bool { self.sig.is_subr() } + pub const fn is_sub(&self) -> bool { + self.sig.is_subr() + } } #[derive(Clone, Debug)] pub struct DefBody { pub op: Token, pub block: Block, - pub id : DefId, + pub id: DefId, } impl_locational!(DefBody, op, block); impl DefBody { - pub const fn new(op: Token, block: Block, id: DefId) -> Self { Self { op, block, id } } + pub const fn new(op: Token, block: Block, id: DefId) -> Self { + Self { op, block, id } + } pub fn is_type(&self) -> bool { match self.block.first().unwrap() { Expr::Call(call) => { if let Expr::Accessor(Accessor::Local(local)) = call.obj.as_ref() { &local.inspect()[..] == "Type" - } else { false } - }, + } else { + false + } + } _ => false, } } @@ -770,7 +952,9 @@ impl_display_from_nested!(Def); impl_locational!(Def, sig, body); impl Def { - pub const fn new(sig: Signature, body: DefBody) -> Self { Self { sig, body } } + pub const fn new(sig: Signature, body: DefBody) -> Self { + Self { sig, body } + } } #[derive(Debug, Clone)] @@ -872,5 +1056,7 @@ impl std::fmt::Display for HIR { } impl HIR { - pub const fn new(name: Str, module: Module) -> Self { Self { name, module } } + pub const fn new(name: Str, module: Module) -> Self { + Self { name, module } + } } diff --git a/compiler/erg_compiler/initialize.rs b/compiler/erg_compiler/initialize.rs index b5af1ead..fb50faae 100644 --- a/compiler/erg_compiler/initialize.rs +++ b/compiler/erg_compiler/initialize.rs @@ -1,21 +1,21 @@ //! defines type information for builtin objects (in `Context`) //! //! 組み込みオブジェクトの型情報を(Contextに)定義 -use erg_common::{Str}; -use erg_common::{set, debug_power_assert}; -use erg_common::ty::{Type, TyParam, ConstObj}; -use Type::*; use erg_common::ty::type_constrs::*; +use erg_common::ty::{ConstObj, TyParam, Type}; +use erg_common::Str; +use erg_common::{debug_power_assert, set}; use ParamSpec as PS; +use Type::*; -use erg_parser::ast::{VarName}; +use erg_parser::ast::VarName; -use crate::varinfo::{Mutability, Visibility, VarInfo, VarKind}; -use crate::context::{Context, ParamSpec, DefaultInfo}; -use Visibility::*; +use crate::context::{Context, DefaultInfo, ParamSpec}; +use crate::varinfo::{Mutability, VarInfo, VarKind, Visibility}; +use DefaultInfo::*; use Mutability::*; use VarKind::*; -use DefaultInfo::*; +use Visibility::*; // NOTE: TyParam::MonoQuantVarは生成時に型を指定する必要があるが、逆にそちらがあれば型境界を指定しなくてもよい impl Context { @@ -24,7 +24,8 @@ impl Context { if self.decls.get(&name).is_some() { panic!("already registered: {name}"); } else { - self.decls.insert(name, VarInfo::new(t, Immutable, vis, Builtin)); + self.decls + .insert(name, VarInfo::new(t, Immutable, vis, Builtin)); } } @@ -50,7 +51,8 @@ impl Context { panic!("{} has already been registered", t.name()); } else { let name = VarName::from_str(Str::rc(t.name())); - self.impls.insert(name, VarInfo::new(Type, muty, Private, Builtin)); + self.impls + .insert(name, VarInfo::new(Type, muty, Private, Builtin)); self.types.insert(t, ctx); } } @@ -60,20 +62,24 @@ impl Context { panic!("{} has already been registered", name); } else { let name = VarName::from_static(name); - self.impls.insert(name.clone(), VarInfo::new(Type, muty, Private, Builtin)); + self.impls + .insert(name.clone(), VarInfo::new(Type, muty, Private, Builtin)); for method_name in ctx.impls.keys() { if let Some(patches) = self._method_impl_patches.get_mut(method_name) { patches.push(name.clone()); } else { - self._method_impl_patches.insert(method_name.clone(), vec![name.clone()]); + self._method_impl_patches + .insert(method_name.clone(), vec![name.clone()]); } } debug_power_assert!(ctx.super_classes.len(), ==, 1); if let Some(target_type) = ctx.super_classes.first() { for impl_trait in ctx.super_traits.iter() { - self.glue_patch_and_types.push( - (VarName::from_str(ctx.name.clone()), target_type.clone(), impl_trait.clone()) - ); + self.glue_patch_and_types.push(( + VarName::from_str(ctx.name.clone()), + target_type.clone(), + impl_trait.clone(), + )); } } self.patches.insert(name, ctx); @@ -87,33 +93,54 @@ impl Context { let mut eq = Self::poly_trait("Eq", vec![PS::t("R", WithDefault)], vec![], Self::TOP_LEVEL); // __eq__: |Self <: Eq; R <: Eq()| Self(R).(R) -> Bool let op_t = fn1_met(poly("Self", vec![mono_q_tp("R")]), mono_q("R"), Bool); - let op_t = quant(op_t, set!{subtype(mono_q("Self"), mono("Eq")), subtype(mono_q("R"), poly("Eq", vec![]))}); + let op_t = quant( + op_t, + set! {subtype(mono_q("Self"), mono("Eq")), subtype(mono_q("R"), poly("Eq", vec![]))}, + ); eq.register_decl("__eq__", op_t.clone(), Public); - let mut ord = Self::poly_trait("Ord", vec![PS::t("R", WithDefault)], vec![mono("Eq")], Self::TOP_LEVEL); + let mut ord = Self::poly_trait( + "Ord", + vec![PS::t("R", WithDefault)], + vec![mono("Eq")], + Self::TOP_LEVEL, + ); let op_t = fn1_met(poly("Self", vec![mono_q_tp("R")]), mono_q("R"), Bool); - let op_t = quant(op_t, set!{subtype(mono_q("Self"), mono("Ord")), subtype(mono_q("R"), poly("Ord", vec![]))}); + let op_t = quant( + op_t, + set! {subtype(mono_q("Self"), mono("Ord")), subtype(mono_q("R"), poly("Ord", vec![]))}, + ); ord.register_decl("__lt__", op_t.clone(), Public); - let mut seq = Self::poly_trait("Seq", vec![PS::t("T", NonDefault)], vec![], Self::TOP_LEVEL); + let mut seq = + Self::poly_trait("Seq", vec![PS::t("T", NonDefault)], vec![], Self::TOP_LEVEL); let self_t = poly_q("Self", vec![TyParam::t(mono_q("T"))]); let t = fn0_met(self_t.clone(), Nat); - let t = quant(t, set!{subtype(self_t.clone(), mono("Seq"))}); + let t = quant(t, set! {subtype(self_t.clone(), mono("Seq"))}); seq.register_decl("__len__", t, Public); let t = Type::fn1_met(self_t.clone(), Nat, mono_q("T")); - let t = quant(t, set!{subtype(self_t, mono("Seq")), static_instance("T", Type)}); + let t = quant( + t, + set! {subtype(self_t, mono("Seq")), static_instance("T", Type)}, + ); seq.register_decl("get", t, Public); 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)]; let ty_params = vec![mono_q_tp("R"), mono_q_tp("O")]; let mut add_ro = Self::poly_trait("Add", params.clone(), vec![], Self::TOP_LEVEL); - let self_bound = subtype(poly_q("Self", ty_params.clone()), poly("Add", ty_params.clone())); + let self_bound = subtype( + poly_q("Self", ty_params.clone()), + poly("Add", 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.clone(), o_bound.clone(), self_bound}); add_ro.register_decl("__add__", op_t, Public); let mut sub_ro = Self::poly_trait("Sub", params.clone(), vec![], Self::TOP_LEVEL); - let self_bound = subtype(poly_q("Self", ty_params.clone()), poly("Sub", ty_params.clone())); + let self_bound = subtype( + poly_q("Self", 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 = quant(op_t, set!{r_bound.clone(), o_bound.clone(), self_bound}); + let op_t = quant(op_t, set! {r_bound.clone(), o_bound.clone(), self_bound}); sub_ro.register_decl("__sub__", op_t, Public); let mut mul_ro = Self::poly_trait("Mul", params.clone(), vec![], Self::TOP_LEVEL); let op_t = fn1_met(poly("Mul", ty_params.clone()), r.clone(), o.clone()); @@ -121,36 +148,61 @@ impl Context { let mut div_ro = Self::poly_trait("Div", params.clone(), vec![], Self::TOP_LEVEL); let op_t = fn1_met(poly("Div", ty_params.clone()), r, o); div_ro.register_decl("__div__", op_t, Public); - let sup = poly("Add", vec![mono_q_tp("Self"), TyParam::mono_proj(mono_q_tp("Self"), "AddO")]); + let sup = poly( + "Add", + vec![ + mono_q_tp("Self"), + TyParam::mono_proj(mono_q_tp("Self"), "AddO"), + ], + ); let mut add = Self::mono_trait("Add", vec![sup], Self::TOP_LEVEL); add.register_decl("AddO", Type, Public); - let sup = poly("Sub", vec![mono_q_tp("Self"), TyParam::mono_proj(mono_q_tp("Self"), "SubO")]); + let sup = poly( + "Sub", + vec![ + mono_q_tp("Self"), + TyParam::mono_proj(mono_q_tp("Self"), "SubO"), + ], + ); let mut sub = Self::mono_trait("Sub", vec![sup], Self::TOP_LEVEL); sub.register_decl("SubO", Type, Public); - let sup = poly("Mul", vec![mono_q_tp("Self"), TyParam::mono_proj(mono_q_tp("Self"), "MulO")]); + let sup = poly( + "Mul", + vec![ + mono_q_tp("Self"), + TyParam::mono_proj(mono_q_tp("Self"), "MulO"), + ], + ); let mut mul = Self::mono_trait("Mul", vec![sup], Self::TOP_LEVEL); mul.register_decl("MulO", Type, Public); - let sup = Type::poly("Div", vec![mono_q_tp("Self"), TyParam::mono_proj(mono_q_tp("Self"), "DivO")]); + let sup = Type::poly( + "Div", + vec![ + mono_q_tp("Self"), + TyParam::mono_proj(mono_q_tp("Self"), "DivO"), + ], + ); let mut div = Self::mono_trait("Div", vec![sup], Self::TOP_LEVEL); div.register_decl("DivO", Type, Public); - let num = Self::mono_trait("Num", vec![ - mono("Eq"), - mono("Add"), mono("Sub"), mono("Mul"), - ], Self::TOP_LEVEL); + let num = Self::mono_trait( + "Num", + vec![mono("Eq"), mono("Add"), mono("Sub"), mono("Mul")], + Self::TOP_LEVEL, + ); self.register_type(mono("Eq"), eq, Const); self.register_type(mono("Ord"), ord, Const); self.register_type(mono("Seq"), seq, Const); self.register_type(poly("Add", ty_params.clone()), add_ro, Const); self.register_type(poly("Sub", ty_params.clone()), sub_ro, Const); self.register_type(poly("Mul", ty_params.clone()), mul_ro, Const); - self.register_type(poly("Div", ty_params), div_ro, Const); + self.register_type(poly("Div", ty_params), div_ro, Const); self.register_type(mono("Num"), num, Const); } fn init_builtin_classes(&mut self) { let mut obj = Self::mono_class("Obj", vec![], vec![], Self::TOP_LEVEL); let t = fn0_met(mono_q("Self"), mono_q("Self")); - let t = quant(t, set!{subtype(mono_q("Self"), mono("Obj"))}); + let t = quant(t, set! {subtype(mono_q("Self"), mono("Obj"))}); obj.register_impl("clone", t, Const, Public); obj.register_impl("__module__", Str, Const, Public); obj.register_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public); @@ -170,101 +222,179 @@ impl Context { ); // let mut record = Self::mono_trait("Record", vec![Obj], Self::TOP_LEVEL); // let mut class = Self::mono_class("Class", vec![Type, Obj], Self::TOP_LEVEL); - let mut float = Self::mono_class("Float", vec![Obj], vec![ - mono("Num"), - mono("Ord"), mono("Eq"), - mono("Add"), mono("Sub"), mono("Mul"), mono("Div"), - mono("Mutate"), - ], Self::TOP_LEVEL); + let mut float = Self::mono_class( + "Float", + vec![Obj], + vec![ + mono("Num"), + mono("Ord"), + mono("Eq"), + mono("Add"), + mono("Sub"), + mono("Mul"), + mono("Div"), + mono("Mutate"), + ], + Self::TOP_LEVEL, + ); let op_t = fn1_met(Float, Float, Float); float.register_impl("__add__", op_t.clone(), Const, Public); float.register_impl("__sub__", op_t.clone(), Const, Public); float.register_impl("__mul__", op_t.clone(), Const, Public); - float.register_impl("__div__", op_t , Const, Public); + float.register_impl("__div__", op_t, Const, Public); float.register_impl("Real", Float, Const, Public); float.register_impl("Imag", Float, Const, Public); - let mut ratio = Self::mono_class("Ratio", vec![Obj], vec![ - mono("Num"), - mono("Ord"), mono("Eq"), - mono("Add"), mono("Sub"), mono("Mul"), mono("Div"), - mono("Mutate"), - ], Self::TOP_LEVEL); + let mut ratio = Self::mono_class( + "Ratio", + vec![Obj], + vec![ + mono("Num"), + mono("Ord"), + mono("Eq"), + mono("Add"), + mono("Sub"), + mono("Mul"), + mono("Div"), + mono("Mutate"), + ], + Self::TOP_LEVEL, + ); let op_t = fn1_met(Ratio, Ratio, Ratio); ratio.register_impl("__add__", op_t.clone(), Const, Public); ratio.register_impl("__sub__", op_t.clone(), Const, Public); ratio.register_impl("__mul__", op_t.clone(), Const, Public); - ratio.register_impl("__div__", op_t , Const, Public); + ratio.register_impl("__div__", op_t, Const, Public); ratio.register_impl("Real", Ratio, Const, Public); ratio.register_impl("Imag", Ratio, Const, Public); - let mut int = Self::mono_class("Int", vec![Obj], vec![ - mono("Num"), - mono("Rational"), mono("Integral"), - mono("Ord"), mono("Eq"), - mono("Add"), mono("Sub"), mono("Mul"), mono("Div"), - mono("Mutate"), - ], Self::TOP_LEVEL); + let mut int = Self::mono_class( + "Int", + vec![Obj], + vec![ + mono("Num"), + mono("Rational"), + mono("Integral"), + mono("Ord"), + mono("Eq"), + mono("Add"), + mono("Sub"), + mono("Mul"), + mono("Div"), + mono("Mutate"), + ], + Self::TOP_LEVEL, + ); int.register_impl("abs", fn0_met(Int, Nat), Immutable, Public); // __div__ is not included in Int (cast to Float) let op_t = fn1_met(Int, Int, Int); int.register_impl("__add__", op_t.clone(), Const, Public); int.register_impl("__sub__", op_t.clone(), Const, Public); - int.register_impl("__mul__", op_t, Const, Public); + int.register_impl("__mul__", op_t, Const, Public); int.register_impl("Real", Int, Const, Public); int.register_impl("Imag", Int, Const, Public); - int.super_traits.push(poly("Add", vec![ty_tp(Int), ty_tp(Int)])); - int.super_traits.push(poly("Sub", vec![ty_tp(Int), ty_tp(Int)])); - int.super_traits.push(poly("Mul", vec![ty_tp(Int), ty_tp(Int)])); - int.super_traits.push(poly("Div", vec![ty_tp(Int), ty_tp(Ratio)])); - let mut nat = Self::mono_class("Nat", vec![Int, Obj], vec![ - mono("Num"), - mono("Rational"), mono("Integral"), - mono("Ord"), mono("Eq"), - mono("Add"), mono("Sub"), mono("Mul"), mono("Div"), - mono("Mutate"), - Obj, - ], Self::TOP_LEVEL); + int.super_traits + .push(poly("Add", vec![ty_tp(Int), ty_tp(Int)])); + int.super_traits + .push(poly("Sub", vec![ty_tp(Int), ty_tp(Int)])); + int.super_traits + .push(poly("Mul", vec![ty_tp(Int), ty_tp(Int)])); + int.super_traits + .push(poly("Div", vec![ty_tp(Int), ty_tp(Ratio)])); + let mut nat = Self::mono_class( + "Nat", + vec![Int, Obj], + vec![ + mono("Num"), + mono("Rational"), + mono("Integral"), + mono("Ord"), + mono("Eq"), + mono("Add"), + mono("Sub"), + mono("Mul"), + mono("Div"), + mono("Mutate"), + Obj, + ], + Self::TOP_LEVEL, + ); // __sub__, __div__ is not included in Nat (cast to Int) let op_t = fn1_met(Nat, Nat, Nat); nat.register_impl("__add__", op_t.clone(), Const, Public); - nat.register_impl("__mul__", op_t, Const, Public); + nat.register_impl("__mul__", op_t, Const, Public); nat.register_impl( "times!", - Type::pr_met(Nat, None, vec![param_t("p", nd_proc(vec![], NoneType))], vec![], NoneType), + Type::pr_met( + Nat, + None, + vec![param_t("p", nd_proc(vec![], NoneType))], + vec![], + NoneType, + ), Immutable, - Public + Public, ); nat.register_impl("Real", Nat, Const, Public); nat.register_impl("Imag", Nat, Const, Public); - nat.super_traits.push(poly("Add", vec![ty_tp(Nat), ty_tp(Nat)])); - nat.super_traits.push(poly("Sub", vec![ty_tp(Nat), ty_tp(Nat)])); - nat.super_traits.push(poly("Mul", vec![ty_tp(Nat), ty_tp(Nat)])); - nat.super_traits.push(poly("Div", vec![ty_tp(Nat), ty_tp(Ratio)])); - let mut bool_ = Self::mono_class("Bool", vec![Nat, Int, Obj], vec![ - mono("Num"), - mono("Rational"), mono("Integral"), - mono("Ord"), mono("Eq"), - mono("Add"), mono("Sub"), mono("Mul"), mono("Div"), - mono("Mutate"), - Obj, - ], Self::TOP_LEVEL); - bool_.register_impl("__and__", fn1_met(Bool, Bool, Bool), Const, Public); - bool_.register_impl("__or__", fn1_met(Bool, Bool, Bool), Const, Public); - let mut str_ = Self::mono_class("Str", vec![Obj], vec![ - mono("Eq"), mono("Mutate"), poly("Seq", vec![ty_tp(Str)]), - ], Self::TOP_LEVEL); - str_.register_impl("__add__", fn1_met(Str, Str, Str), Const, Public); - str_.register_impl("replace", Type::fn_met( - Str, - vec![param_t("pat", Str), param_t("into", Str)], - vec![], Str), - Immutable, - Public + nat.super_traits + .push(poly("Add", vec![ty_tp(Nat), ty_tp(Nat)])); + nat.super_traits + .push(poly("Sub", vec![ty_tp(Nat), ty_tp(Nat)])); + nat.super_traits + .push(poly("Mul", vec![ty_tp(Nat), ty_tp(Nat)])); + nat.super_traits + .push(poly("Div", vec![ty_tp(Nat), ty_tp(Ratio)])); + let mut bool_ = Self::mono_class( + "Bool", + vec![Nat, Int, Obj], + vec![ + mono("Num"), + mono("Rational"), + mono("Integral"), + mono("Ord"), + mono("Eq"), + mono("Add"), + mono("Sub"), + mono("Mul"), + mono("Div"), + mono("Mutate"), + Obj, + ], + Self::TOP_LEVEL, + ); + bool_.register_impl("__and__", fn1_met(Bool, Bool, Bool), Const, Public); + bool_.register_impl("__or__", fn1_met(Bool, Bool, Bool), Const, Public); + let mut str_ = Self::mono_class( + "Str", + vec![Obj], + vec![mono("Eq"), mono("Mutate"), poly("Seq", vec![ty_tp(Str)])], + Self::TOP_LEVEL, + ); + str_.register_impl("__add__", fn1_met(Str, Str, Str), Const, Public); + str_.register_impl( + "replace", + Type::fn_met( + Str, + vec![param_t("pat", Str), param_t("into", Str)], + vec![], + Str, + ), + Immutable, + Public, + ); + str_.super_traits + .push(poly("Add", vec![ty_tp(Str), ty_tp(Str)])); + let mut array = Self::poly_class( + "Array", + vec![PS::t_nd("T"), PS::named_nd("N", Nat)], + vec![Obj], + vec![ + mono("Eq"), + mono("Mutate"), + poly("Seq", vec![ty_tp(mono_q("T"))]), + poly("Output", vec![ty_tp(mono_q("T"))]), + ], + Self::TOP_LEVEL, ); - str_.super_traits.push(poly("Add", vec![ty_tp(Str), ty_tp(Str)])); - let mut array = Self::poly_class("Array", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], vec![Obj], vec![ - mono("Eq"), mono("Mutate"), - poly("Seq", vec![ty_tp(mono_q("T"))]), poly("Output", vec![ty_tp(mono_q("T"))]) - ], Self::TOP_LEVEL); let n = mono_q_tp("N"); let m = mono_q_tp("M"); let array_t = Type::array(mono_q("T"), n.clone()); @@ -272,37 +402,77 @@ impl Context { array_t.clone(), vec![param_t("rhs", Type::array(mono_q("T"), m.clone()))], vec![], - Type::array(mono_q("T"), n + m) + Type::array(mono_q("T"), n + m), + ); + let t = quant( + t, + set! {static_instance("N", Nat), static_instance("M", Nat)}, ); - let t = quant(t, set!{static_instance("N", Nat), static_instance("M", Nat)}); array.register_impl("concat", t, Immutable, Public); - let mut_type = ConstObj::t(Type::poly("Array!", vec![ - TyParam::t(mono_q("T")), - TyParam::mono_q("N").mutate(), - ])); + let mut_type = ConstObj::t(Type::poly( + "Array!", + vec![TyParam::t(mono_q("T")), TyParam::mono_q("N").mutate()], + )); // [T; N].MutType! = [T; !N] (neither [T!; N] nor [T; N]!) array.register_const("MutType!", mut_type); - let mut type_ = Self::mono_class("Type", vec![Obj], vec![mono("Eq"), mono("Named")], Self::TOP_LEVEL); - type_.register_impl("mro", Type::array(Type, TyParam::erased(Nat)), Immutable, Public); - let module = Self::mono_class("Module", vec![Obj], vec![mono("Eq"), mono("Named")], Self::TOP_LEVEL); + let mut type_ = Self::mono_class( + "Type", + vec![Obj], + vec![mono("Eq"), mono("Named")], + Self::TOP_LEVEL, + ); + type_.register_impl( + "mro", + Type::array(Type, TyParam::erased(Nat)), + Immutable, + Public, + ); + let module = Self::mono_class( + "Module", + vec![Obj], + vec![mono("Eq"), mono("Named")], + Self::TOP_LEVEL, + ); let array_mut_t = Type::poly("Array!", vec![TyParam::t(mono_q("T")), mono_q_tp("N")]); - let mut array_mut = Self::poly_class("Array!", vec![PS::t_nd("T"), PS::named_nd("N", NatMut)], vec![Obj], vec![ - mono("Eq"), mono("Mutate"), poly("Seq", vec![ty_tp(mono_q("T"))]) - ], Self::TOP_LEVEL); + let mut array_mut = Self::poly_class( + "Array!", + vec![PS::t_nd("T"), PS::named_nd("N", NatMut)], + vec![Obj], + vec![ + mono("Eq"), + mono("Mutate"), + poly("Seq", vec![ty_tp(mono_q("T"))]), + ], + Self::TOP_LEVEL, + ); let t = Type::pr_met( Type::ref_mut(array_mut_t.clone()), - Some(Type::ref_mut(poly("Array!", vec![TyParam::t(mono_q("T")), mono_q_tp("N") + value(1)]))), + Some(Type::ref_mut(poly( + "Array!", + vec![TyParam::t(mono_q("T")), mono_q_tp("N") + value(1)], + ))), vec![param_t("elem", mono_q("T"))], vec![], Type::NoneType, ); - let t = quant(t, set!{static_instance("T", Type), static_instance("N", NatMut)}); + let t = quant( + t, + set! {static_instance("T", Type), static_instance("N", NatMut)}, + ); array_mut.register_impl("push!", t, Immutable, Public); let range_t = Type::poly("Range", vec![TyParam::t(mono_q("T"))]); - let range = Self::poly_class("Range", vec![PS::t_nd("T")], vec![Obj], vec![ - mono("Eq"), mono("Mutate"), - poly("Seq", vec![ty_tp(mono_q("T"))]), poly("Output", vec![ty_tp(mono_q("T"))]) - ], Self::TOP_LEVEL); + let range = Self::poly_class( + "Range", + vec![PS::t_nd("T")], + vec![Obj], + vec![ + mono("Eq"), + mono("Mutate"), + poly("Seq", vec![ty_tp(mono_q("T"))]), + poly("Output", vec![ty_tp(mono_q("T"))]), + ], + Self::TOP_LEVEL, + ); self.register_type(Obj, obj, Const); // self.register_type(Type::mono("Record"), vec![], record, Const); // self.register_type(Type::mono("Class"), vec![], class, Const); @@ -321,23 +491,34 @@ impl Context { fn init_builtin_funcs(&mut self) { let t_abs = nd_func(vec![param_t("n", mono("Num"))], Nat); - let t_assert = func(vec![param_t("condition", Bool)], vec![param_t("err_message", Str)], NoneType); + let t_assert = func( + vec![param_t("condition", Bool)], + vec![param_t("err_message", Str)], + NoneType, + ); let t_classof = nd_func(vec![param_t("o", Obj)], Type::option(Class)); let t_compile = nd_func(vec![param_t("src", Str)], Code); let t_cond = nd_func( - vec![param_t("condition", Bool), param_t("then", mono_q("T")), param_t("else", mono_q("T"))], + vec![ + param_t("condition", Bool), + param_t("then", mono_q("T")), + param_t("else", mono_q("T")), + ], mono_q("T"), ); - let t_cond = quant(t_cond, set!{static_instance("T", Type)}); + let t_cond = quant(t_cond, set! {static_instance("T", Type)}); let t_discard = nd_func(vec![param_t("o", Obj)], NoneType); let t_id = nd_func(vec![param_t("o", Obj)], Nat); // FIXME: quantify let t_if = func( - vec![param_t("cond", Bool), param_t("then", nd_func(vec![], mono_q("T")))], + vec![ + param_t("cond", Bool), + param_t("then", nd_func(vec![], mono_q("T"))), + ], vec![param_t("else", nd_func(vec![], mono_q("T")))], Type::option(mono_q("T")), ); - let t_if = quant(t_if, set!{static_instance("T", Type)}); + let t_if = quant(t_if, set! {static_instance("T", Type)}); let t_import = nd_func(vec![param_t("path", Str)], Module); let t_log = nd_func(vec![param_t("objs", Type::var_args(Obj))], NoneType); let t_pyimport = nd_func(vec![param_t("path", Str)], Module); @@ -348,7 +529,7 @@ impl Context { self.register_impl("compile", t_compile, Const, Private); self.register_impl("cond", t_cond, Const, Private); self.register_impl("discard", t_discard, Const, Private); - self.register_impl("id" , t_id, Const, Private); + self.register_impl("id", t_id, Const, Private); self.register_impl("if", t_if, Const, Private); self.register_impl("log", t_log, Const, Private); self.register_impl("import", t_import, Const, Private); @@ -357,17 +538,35 @@ impl Context { } fn init_builtin_procs(&mut self) { - let t_print = nd_proc(vec![param_t("objs", Type::var_args(Type::refer(Obj)))], NoneType); + let t_print = nd_proc( + vec![param_t("objs", Type::var_args(Type::refer(Obj)))], + NoneType, + ); let t_input = nd_proc(vec![param_t("msg", Str)], Str); let t_if = proc( - vec![param_t("cond", Bool), param_t("then", nd_proc(vec![], mono_q("T")))], + vec![ + param_t("cond", Bool), + param_t("then", nd_proc(vec![], mono_q("T"))), + ], vec![param_t("else", nd_proc(vec![], mono_q("T")))], - Type::option(mono_q("T")) + Type::option(mono_q("T")), + ); + let t_if = quant(t_if, set! {static_instance("T", Type)}); + let t_for = nd_proc( + vec![ + param_t("iter", Type::iter(mono_q("T"))), + param_t("p", nd_proc(vec![anon(mono_q("T"))], NoneType)), + ], + NoneType, + ); + let t_for = quant(t_for, set! {static_instance("T", Type)}); + let t_while = nd_proc( + vec![ + param_t("cond", BoolMut), + param_t("p", nd_proc(vec![], NoneType)), + ], + NoneType, ); - let t_if = quant(t_if, set!{static_instance("T", Type)}); - let t_for = nd_proc(vec![param_t("iter", Type::iter(mono_q("T"))), param_t("p", nd_proc(vec![anon(mono_q("T"))], NoneType))], NoneType); - let t_for = quant(t_for, set!{static_instance("T", Type)}); - let t_while = nd_proc(vec![param_t("cond", BoolMut), param_t("p", nd_proc(vec![], NoneType))], NoneType); self.register_impl("print!", t_print, Const, Private); self.register_impl("input!", t_input, Const, Private); self.register_impl("if!", t_if, Const, Private); @@ -382,63 +581,69 @@ impl Context { let o = mono_q("O"); let params = vec![mono_q_tp("R"), mono_q_tp("O")]; let op_t = Type::func2(l.clone(), r.clone(), o.clone()); - let op_t = quant(op_t, set!{ - static_instance("R", Type), - static_instance("O", Type), - subtype(l.clone(), poly("Add", params.clone())) - }); + let op_t = quant( + op_t, + set! { + static_instance("R", Type), + static_instance("O", Type), + subtype(l.clone(), poly("Add", params.clone())) + }, + ); self.register_impl("__add__", op_t, Const, Private); let op_t = Type::func2(l.clone(), r.clone(), o.clone()); - let op_t = quant(op_t, set!{ - static_instance("R", Type), - static_instance("O", Type), - subtype(l.clone(), poly("Sub", params.clone())) - }); + let op_t = quant( + op_t, + set! { + static_instance("R", Type), + static_instance("O", Type), + subtype(l.clone(), poly("Sub", params.clone())) + }, + ); self.register_impl("__sub__", op_t, Const, Private); 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); 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 = quant(op_t, set! {subtype(l, poly("Mul", params.clone()))}); self.register_impl("__div__", op_t, Const, Private); let m = mono_q("M"); let op_t = Type::func2(m.clone(), m.clone(), m.clone()); - let op_t = quant(op_t, set!{subtype(m, poly("Mul", vec![]))}); + let op_t = quant(op_t, set! {subtype(m, poly("Mul", vec![]))}); self.register_impl("__pow__", op_t, Const, Private); let d = mono_q("D"); let op_t = Type::func2(d.clone(), d.clone(), d.clone()); - let op_t = quant(op_t, set!{subtype(d, poly("Div", vec![]))}); + let op_t = quant(op_t, set! {subtype(d, poly("Div", vec![]))}); self.register_impl("__mod__", op_t, Const, Private); let e = mono_q("E"); let op_t = Type::func2(e.clone(), e.clone(), Bool); - let op_t = quant(op_t, set!{subtype(e, poly("Eq", vec![]))}); + let op_t = quant(op_t, set! {subtype(e, poly("Eq", vec![]))}); self.register_impl("__eq__", op_t.clone(), Const, Private); - self.register_impl("__ne__", op_t, Const, Private); + self.register_impl("__ne__", op_t, Const, Private); let o = mono_q("O"); let op_t = Type::func2(o.clone(), o.clone(), Bool); - let op_t = quant(op_t, set!{subtype(o, poly("Ord", vec![]))}); - self.register_impl("__lt__", op_t.clone(), Const, Private); - self.register_impl("__le__", op_t.clone(), Const, Private); - self.register_impl("__gt__", op_t.clone(), Const, Private); - self.register_impl("__ge__", op_t, Const, Private); + let op_t = quant(op_t, set! {subtype(o, poly("Ord", vec![]))}); + self.register_impl("__lt__", op_t.clone(), Const, Private); + self.register_impl("__le__", op_t.clone(), Const, Private); + self.register_impl("__gt__", op_t.clone(), Const, Private); + self.register_impl("__ge__", op_t, Const, Private); self.register_impl("__and__", Type::func2(Bool, Bool, Bool), Const, Private); - self.register_impl("__or__", Type::func2(Bool, Bool, Bool), Const, Private); + self.register_impl("__or__", Type::func2(Bool, Bool, Bool), Const, Private); /* unary */ // TODO: Boolの+/-は警告を出したい let n = mono_q("N"); let op_t = fn0_met(n.clone(), n.clone()); - let op_t = quant(op_t, set!{subtype(n, mono("Num"))}); + let op_t = quant(op_t, set! {subtype(n, mono("Num"))}); self.register_decl("__pos__", op_t.clone(), Private); - self.register_decl("__neg__", op_t, Private); + self.register_decl("__neg__", op_t, Private); let t = mono_q("T"); let op_t = Type::func2(t.clone(), t.clone(), Type::range(t.clone())); - let op_t = quant(op_t, set!{subtype(t, mono("Ord"))}); + let op_t = quant(op_t, set! {subtype(t, mono("Ord"))}); self.register_decl("__rng__", op_t.clone(), Private); self.register_decl("__lorng__", op_t.clone(), Private); self.register_decl("__rorng__", op_t.clone(), Private); self.register_decl("__orng__", op_t, Private); let op_t = Type::func1(mono_q("T"), Type::mono_proj(mono_q("T"), "MutType!")); - let op_t = quant(op_t, set!{subtype(mono_q("T"), mono("Mutate"))}); + let op_t = quant(op_t, set! {subtype(mono_q("T"), mono("Mutate"))}); self.register_impl("__mutate__", op_t, Const, Private); } @@ -448,24 +653,44 @@ impl Context { let o = mono_q_tp("O"); let p = mono_q_tp("P"); let params = vec![ - PS::named_nd("M", Int), PS::named_nd("N", Int), - PS::named_nd("O", Int), PS::named_nd("P", Int), + PS::named_nd("M", Int), + PS::named_nd("N", Int), + PS::named_nd("O", Int), + PS::named_nd("P", Int), ]; // Interval is a bounding patch connecting M..N and (Add(O..P, M+O..N..P), Sub(O..P, M-P..N-O)) - let mut interval = Self::poly_patch("Interval", params, vec![Type::from(&m..=&n)], vec![ - poly("Add", vec![TyParam::from(&o..=&p), TyParam::from(m.clone() + o.clone() ..= n.clone() + p.clone())]), - poly("Sub", vec![TyParam::from(&o..=&p), TyParam::from(m.clone() - p.clone() ..= n.clone() - o.clone())]), - ], Self::TOP_LEVEL); + let mut interval = Self::poly_patch( + "Interval", + params, + vec![Type::from(&m..=&n)], + vec![ + poly( + "Add", + vec![ + TyParam::from(&o..=&p), + TyParam::from(m.clone() + o.clone()..=n.clone() + p.clone()), + ], + ), + poly( + "Sub", + vec![ + TyParam::from(&o..=&p), + TyParam::from(m.clone() - p.clone()..=n.clone() - o.clone()), + ], + ), + ], + Self::TOP_LEVEL, + ); let op_t = fn1_met( Type::from(&m..=&n), Type::from(&o..=&p), - Type::from(m.clone() + o.clone() ..= n.clone() + p.clone()), + Type::from(m.clone() + o.clone()..=n.clone() + p.clone()), ); interval.register_impl("__add__", op_t, Const, Public); let op_t = fn1_met( Type::from(&m..=&n), Type::from(&o..=&p), - Type::from(m - p ..= n - o), + Type::from(m - p..=n - o), ); interval.register_impl("__sub__", op_t, Const, Public); self.register_patch("Interval", interval, Const); @@ -488,13 +713,30 @@ impl Context { pub(crate) fn init_py_random_mod() -> Self { let mut random = Context::module("random".into(), 10); - random.register_impl("seed!", Type::proc(vec![], vec![ - param_t("a", Type::mono("Num")), // TODO: NoneType, int, float, str, bytes, bytearray - param_t("version", Type::Int), - ], NoneType), Immutable, Public); - random.register_impl("randint!", nd_proc(vec![param_t("a", Int), param_t("b", Int)], Int), Immutable, Public); - let t = nd_proc(vec![param_t("seq", Type::poly("Seq", vec![ty_tp(mono_q("T"))]))], mono_q("T")); - let t = quant(t, set!{static_instance("T", Type)}); + random.register_impl( + "seed!", + Type::proc( + vec![], + vec![ + param_t("a", Type::mono("Num")), // TODO: NoneType, int, float, str, bytes, bytearray + param_t("version", Type::Int), + ], + NoneType, + ), + Immutable, + Public, + ); + random.register_impl( + "randint!", + nd_proc(vec![param_t("a", Int), param_t("b", Int)], Int), + Immutable, + Public, + ); + let t = nd_proc( + vec![param_t("seq", Type::poly("Seq", vec![ty_tp(mono_q("T"))]))], + mono_q("T"), + ); + let t = quant(t, set! {static_instance("T", Type)}); random.register_impl("choice!", t, Immutable, Public); random } diff --git a/compiler/erg_compiler/lib.rs b/compiler/erg_compiler/lib.rs index 7b94146b..52b4182c 100644 --- a/compiler/erg_compiler/lib.rs +++ b/compiler/erg_compiler/lib.rs @@ -12,7 +12,7 @@ pub mod hir; pub mod initialize; pub mod lower; pub use lower::ASTLowerer; +pub mod context; pub mod optimize; pub mod ownercheck; -pub mod context; pub mod varinfo; diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 988273e8..9a4e9698 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -1,21 +1,21 @@ //! implements `ASTLowerer`. //! //! ASTLowerer(ASTからHIRへの変換器)を実装 -use erg_common::{switch_lang, log, fn_name}; use erg_common::color::{GREEN, RED, RESET}; use erg_common::error::Location; -use erg_common::traits::{Locational, Stream, HasType}; -use erg_common::ty::{Type, ParamTy}; use erg_common::get_hash; +use erg_common::traits::{HasType, Locational, Stream}; +use erg_common::ty::{ParamTy, Type}; +use erg_common::{fn_name, log, switch_lang}; use erg_parser::ast; -use erg_parser::ast::{AST}; +use erg_parser::ast::AST; -use crate::hir; -use crate::hir::{HIR}; -use crate::error::{LowerError, LowerErrors, LowerResult, LowerWarnings}; use crate::context::{Context, ContextKind, RegistrationMode}; -use crate::varinfo::{Visibility}; +use crate::error::{LowerError, LowerErrors, LowerResult, LowerWarnings}; +use crate::hir; +use crate::hir::HIR; +use crate::varinfo::Visibility; use Visibility::*; /// Singleton that checks types of an AST, and convert (lower) it into a HIR @@ -36,23 +36,31 @@ impl ASTLowerer { Some(Context::init_builtins()), vec![], vec![], - 0 + 0, ), errs: LowerErrors::empty(), warns: LowerWarnings::empty(), } } - fn return_t_check(&self, loc: Location, name: &str, expect: &Type, found: &Type) -> LowerResult<()> { + fn return_t_check( + &self, + loc: Location, + name: &str, + expect: &Type, + found: &Type, + ) -> LowerResult<()> { self.mod_ctx .unify(expect, found, Some(loc), None) - .or_else(|_| Err(LowerError::type_mismatch_error( - loc, - self.mod_ctx.caused_by(), - name, - expect, - found, - ))) + .or_else(|_| { + Err(LowerError::type_mismatch_error( + loc, + self.mod_ctx.caused_by(), + name, + expect, + found, + )) + }) } fn use_check(&self, expr: hir::Expr, mode: &str) -> LowerResult { @@ -65,10 +73,13 @@ impl ASTLowerer { "the evaluation result of the expression is not used", "式の評価結果が使われていません", ), - Some(switch_lang!( - "if you don't use the value, use `discard` function", - "値を使わない場合は、discard関数を使用してください", - ).into()) + Some( + switch_lang!( + "if you don't use the value, use `discard` function", + "値を使わない場合は、discard関数を使用してください", + ) + .into(), + ), )) } else { Ok(expr) @@ -83,7 +94,13 @@ impl ASTLowerer { fn lower_array(&mut self, array: ast::Array, check: bool) -> LowerResult { log!("[DEBUG] entered {}({array})", fn_name!()); - let mut hir_array = hir::Array::new(array.l_sqbr, array.r_sqbr, self.mod_ctx.level, hir::Args::empty(), None); + let mut hir_array = hir::Array::new( + array.l_sqbr, + array.r_sqbr, + self.mod_ctx.level, + hir::Args::empty(), + None, + ); for elem in array.elems.into_iters().0 { hir_array.push(self.lower_expr(elem.expr, check)?); } @@ -100,19 +117,24 @@ impl ASTLowerer { self.mod_ctx.get_local_t(&n.symbol, &self.mod_ctx.name)?, self.mod_ctx.get_local_uniq_obj_name(&n.symbol), ) - } else { (Type::ASTOmitted, None) }; + } else { + (Type::ASTOmitted, None) + }; let acc = hir::Accessor::Local(hir::Local::new(n.symbol, __name__, t)); Ok(acc) } ast::Accessor::Attr(a) => { let obj = self.lower_expr(*a.obj, true)?; let t = if check { - self.mod_ctx.get_attr_t(&obj, &a.name.symbol, &self.mod_ctx.name)? - } else { Type::ASTOmitted }; + self.mod_ctx + .get_attr_t(&obj, &a.name.symbol, &self.mod_ctx.name)? + } else { + Type::ASTOmitted + }; let acc = hir::Accessor::Attr(hir::Attribute::new(obj, a.name.symbol, t)); Ok(acc) } - _ => todo!() + _ => todo!(), } } @@ -122,7 +144,9 @@ impl ASTLowerer { let lhs = hir::PosArg::new(self.lower_expr(*args.next().unwrap(), true)?); let rhs = hir::PosArg::new(self.lower_expr(*args.next().unwrap(), true)?); let args = [lhs, rhs]; - let t = self.mod_ctx.get_binop_t(&bin.op, &args, &self.mod_ctx.name)?; + let t = self + .mod_ctx + .get_binop_t(&bin.op, &args, &self.mod_ctx.name)?; let mut args = args.into_iter(); let lhs = args.next().unwrap().expr; let rhs = args.next().unwrap().expr; @@ -134,7 +158,9 @@ impl ASTLowerer { let mut args = unary.args.into_iter(); let arg = hir::PosArg::new(self.lower_expr(*args.next().unwrap(), true)?); let args = [arg]; - let t = self.mod_ctx.get_unaryop_t(&unary.op, &args, &self.mod_ctx.name)?; + let t = self + .mod_ctx + .get_unaryop_t(&unary.op, &args, &self.mod_ctx.name)?; let mut args = args.into_iter(); let expr = args.next().unwrap().expr; Ok(hir::UnaryOp::new(unary.op, expr, t)) @@ -143,15 +169,27 @@ impl ASTLowerer { fn lower_call(&mut self, call: ast::Call) -> LowerResult { log!("[DEBUG] entered {}({}(...))", fn_name!(), call.obj); let (pos_args, kw_args, paren) = call.args.deconstruct(); - let mut hir_args = hir::Args::new(Vec::with_capacity(pos_args.len()), Vec::with_capacity(kw_args.len()), paren); + let mut hir_args = hir::Args::new( + Vec::with_capacity(pos_args.len()), + Vec::with_capacity(kw_args.len()), + paren, + ); for arg in pos_args.into_iter() { hir_args.push_pos(hir::PosArg::new(self.lower_expr(arg.expr, true)?)); } for arg in kw_args.into_iter() { - hir_args.push_kw(hir::KwArg::new(arg.keyword, self.lower_expr(arg.expr, true)?)); + hir_args.push_kw(hir::KwArg::new( + arg.keyword, + self.lower_expr(arg.expr, true)?, + )); } let mut obj = self.lower_expr(*call.obj, false)?; - let t = self.mod_ctx.get_call_t(&mut obj, hir_args.pos_args(), hir_args.kw_args(), &self.mod_ctx.name)?; + let t = self.mod_ctx.get_call_t( + &mut obj, + hir_args.pos_args(), + hir_args.kw_args(), + &self.mod_ctx.name, + )?; Ok(hir::Call::new(obj, hir_args, t)) } @@ -160,42 +198,80 @@ impl ASTLowerer { let is_procedural = lambda.is_procedural(); let id = get_hash(&lambda.sig); let name = format!(""); - let kind = if is_procedural { ContextKind::Proc } else { ContextKind::Func }; + let kind = if is_procedural { + ContextKind::Proc + } else { + ContextKind::Func + }; self.mod_ctx.grow(&name, kind, Private)?; - self.mod_ctx.assign_params(&lambda.sig.params, None) - .map_err(|e| { self.pop_append_errs(); e })?; - self.mod_ctx.preregister(lambda.body.ref_payload()) - .map_err(|e| { self.pop_append_errs(); e })?; - let body = self.lower_block(lambda.body) - .map_err(|e| { self.pop_append_errs(); e })?; + self.mod_ctx + .assign_params(&lambda.sig.params, None) + .map_err(|e| { + self.pop_append_errs(); + e + })?; + self.mod_ctx + .preregister(lambda.body.ref_payload()) + .map_err(|e| { + self.pop_append_errs(); + e + })?; + let body = self.lower_block(lambda.body).map_err(|e| { + self.pop_append_errs(); + e + })?; // impls => named non-default params + named default params + embedded params (will be discarded) // unnnamed_params => unnamed non-default params + unnamed default params // non default params = [unnamed non-default params + unnamed default params].sorted() // sort by pos // default params = [unnamed default params, named default params].sorted() let (named_non_default_params, named_default_params) = { - let (named_default_params, named_non_default_params_and_embeddeds): (Vec<_>, Vec<_>) = self.mod_ctx.impls.iter() + let (named_default_params, named_non_default_params_and_embeddeds): (Vec<_>, Vec<_>) = + self.mod_ctx + .impls + .iter() .filter(|(_, v)| v.kind.is_parameter()) .partition(|(_, v)| v.kind.has_default()); - let (_, named_non_default_params): (Vec<_>, Vec<_>)= named_non_default_params_and_embeddeds.into_iter() + let (_, named_non_default_params): (Vec<_>, Vec<_>) = + named_non_default_params_and_embeddeds + .into_iter() .partition(|(_, v)| v.kind.is_embedded_param()); - ( - named_non_default_params.into_iter() - .map(|(n, v)| (v.kind.pos_as_param().unwrap(), ParamTy::new(Some(n.inspect().clone()), v.t()))) - .collect::>(), - named_default_params.into_iter() - .map(|(n, v)| (v.kind.pos_as_param().unwrap(), ParamTy::new(Some(n.inspect().clone()), v.t()))) - .collect::>() - ) + ( + named_non_default_params + .into_iter() + .map(|(n, v)| { + ( + v.kind.pos_as_param().unwrap(), + ParamTy::new(Some(n.inspect().clone()), v.t()), + ) + }) + .collect::>(), + named_default_params + .into_iter() + .map(|(n, v)| { + ( + v.kind.pos_as_param().unwrap(), + ParamTy::new(Some(n.inspect().clone()), v.t()), + ) + }) + .collect::>(), + ) }; let (unnamed_non_default_params, unnamed_default_params) = { - let (unnamed_default_params, unnamed_non_default_params): (Vec<_>, Vec<_>) = self.mod_ctx.unnamed_params.iter() + let (unnamed_default_params, unnamed_non_default_params): (Vec<_>, Vec<_>) = self + .mod_ctx + .unnamed_params + .iter() .map(|v| (v, ParamTy::anonymous(v.t()))) .partition(|(v, _)| v.kind.has_default()); ( - unnamed_non_default_params.into_iter() - .map(|(v, pt)| (v.kind.pos_as_param().unwrap(), pt)).collect(), - unnamed_default_params.into_iter() - .map(|(v, pt)| (v.kind.pos_as_param().unwrap(), pt)).collect(), + unnamed_non_default_params + .into_iter() + .map(|(v, pt)| (v.kind.pos_as_param().unwrap(), pt)) + .collect(), + unnamed_default_params + .into_iter() + .map(|(v, pt)| (v.kind.pos_as_param().unwrap(), pt)) + .collect(), ) }; let non_default_params = { @@ -208,22 +284,32 @@ impl ASTLowerer { a.sort_by(|(l, _), (r, _)| l.cmp(r)); a.into_iter().map(|(_, p)| p).collect::>() }; - let bounds = self.mod_ctx.instantiate_ty_bounds(&lambda.sig.bounds, RegistrationMode::Normal) - .map_err(|e| { self.pop_append_errs(); e })?; + let bounds = self + .mod_ctx + .instantiate_ty_bounds(&lambda.sig.bounds, RegistrationMode::Normal) + .map_err(|e| { + self.pop_append_errs(); + e + })?; self.pop_append_errs(); let t = if is_procedural { Type::proc(non_default_params, default_params, body.t()) } else { Type::func(non_default_params, default_params, body.t()) }; - let t = if bounds.is_empty() { t } else { Type::quantified(t, bounds) }; + let t = if bounds.is_empty() { + t + } else { + Type::quantified(t, bounds) + }; Ok(hir::Lambda::new(id, lambda.sig.params, lambda.op, body, t)) } fn lower_def(&mut self, def: ast::Def) -> LowerResult { log!("[DEBUG] entered {}({})", fn_name!(), def.sig); // FIXME: Instant - self.mod_ctx.grow(def.sig.name_as_str(), ContextKind::Instant, Private)?; + self.mod_ctx + .grow(def.sig.name_as_str(), ContextKind::Instant, Private)?; let res = match def.sig { ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body), ast::Signature::Var(sig) => self.lower_var_def(sig, def.body), @@ -233,13 +319,20 @@ impl ASTLowerer { res } - fn lower_var_def(&mut self, sig: ast::VarSignature, body: ast::DefBody) -> LowerResult { + fn lower_var_def( + &mut self, + sig: ast::VarSignature, + body: ast::DefBody, + ) -> LowerResult { log!("[DEBUG] entered {}({sig})", fn_name!()); self.mod_ctx.preregister(body.block.ref_payload())?; let block = self.lower_block(body.block)?; let found_body_t = block.ref_t(); - let opt_expect_body_t = self.mod_ctx - .outer.as_ref().unwrap() + let opt_expect_body_t = self + .mod_ctx + .outer + .as_ref() + .unwrap() .get_current_scope_local_var(sig.inspect().unwrap()) .map(|vi| vi.t.clone()); let name = sig.pat.inspect().unwrap(); @@ -250,17 +343,25 @@ impl ASTLowerer { } let id = body.id; // TODO: cover all VarPatterns - self.mod_ctx.outer.as_mut().unwrap().assign_var(&sig, id, found_body_t)?; + self.mod_ctx + .outer + .as_mut() + .unwrap() + .assign_var(&sig, id, found_body_t)?; match block.first().unwrap() { hir::Expr::Call(call) => { if let ast::VarPattern::VarName(name) = &sig.pat { if call.is_import_call() { - self.mod_ctx.outer.as_mut() + self.mod_ctx + .outer + .as_mut() .unwrap() .import_mod(name, &call.args.pos_args().first().unwrap().expr)?; } - } else { todo!() } - }, + } else { + todo!() + } + } _other => {} } let sig = hir::VarSignature::new(sig.pat, found_body_t.clone()); @@ -269,27 +370,41 @@ impl ASTLowerer { } // NOTE: 呼ばれている間はinner scopeなので注意 - fn lower_subr_def(&mut self, sig: ast::SubrSignature, body: ast::DefBody) -> LowerResult { + fn lower_subr_def( + &mut self, + sig: ast::SubrSignature, + body: ast::DefBody, + ) -> LowerResult { log!("[DEBUG] entered {}({sig})", fn_name!()); - let t = self.mod_ctx - .outer.as_ref().unwrap() + let t = self + .mod_ctx + .outer + .as_ref() + .unwrap() .get_current_scope_local_var(sig.name.inspect()) .unwrap_or_else(|| { log!("{}\n", sig.name.inspect()); log!("{}\n", self.mod_ctx.outer.as_ref().unwrap()); panic!() }) // FIXME: or instantiate - .t.clone(); + .t + .clone(); self.mod_ctx.assign_params(&sig.params, None)?; self.mod_ctx.preregister(body.block.ref_payload())?; let block = self.lower_block(body.block)?; let found_body_t = block.ref_t(); let expect_body_t = t.return_t().unwrap(); - if let Err(e) = self.return_t_check(sig.loc(), sig.name.inspect(), expect_body_t, found_body_t) { + if let Err(e) = + self.return_t_check(sig.loc(), sig.name.inspect(), expect_body_t, found_body_t) + { self.errs.push(e); } let id = body.id; - self.mod_ctx.outer.as_mut().unwrap().assign_subr(&sig, id, found_body_t)?; + self.mod_ctx + .outer + .as_mut() + .unwrap() + .assign_subr(&sig, id, found_body_t)?; let sig = hir::SubrSignature::new(sig.name, sig.params, t); let body = hir::DefBody::new(body.op, block, body.id); Ok(hir::Def::new(hir::Signature::Subr(sig), body)) @@ -300,30 +415,14 @@ impl ASTLowerer { fn lower_expr(&mut self, expr: ast::Expr, check: bool) -> LowerResult { log!("[DEBUG] entered {}", fn_name!()); match expr { - ast::Expr::Lit(lit) => { - Ok(hir::Expr::Lit(hir::Literal::from(lit.token))) - }, - ast::Expr::Array(arr) => { - Ok(hir::Expr::Array(self.lower_array(arr, check)?)) - } - ast::Expr::Accessor(acc) => { - Ok(hir::Expr::Accessor(self.lower_acc(acc, check)?)) - } - ast::Expr::BinOp(bin) => { - Ok(hir::Expr::BinOp(self.lower_bin(bin)?)) - } - ast::Expr::UnaryOp(unary) => { - Ok(hir::Expr::UnaryOp(self.lower_unary(unary)?)) - } - ast::Expr::Call(call) => { - Ok(hir::Expr::Call(self.lower_call(call)?)) - } - ast::Expr::Lambda(lambda) => { - Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)) - } - ast::Expr::Def(def) => { - Ok(hir::Expr::Def(self.lower_def(def)?)) - } + ast::Expr::Lit(lit) => Ok(hir::Expr::Lit(hir::Literal::from(lit.token))), + ast::Expr::Array(arr) => Ok(hir::Expr::Array(self.lower_array(arr, check)?)), + ast::Expr::Accessor(acc) => Ok(hir::Expr::Accessor(self.lower_acc(acc, check)?)), + ast::Expr::BinOp(bin) => Ok(hir::Expr::BinOp(self.lower_bin(bin)?)), + ast::Expr::UnaryOp(unary) => Ok(hir::Expr::UnaryOp(self.lower_unary(unary)?)), + ast::Expr::Call(call) => Ok(hir::Expr::Call(self.lower_call(call)?)), + ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)), + ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)), other => todo!("{other}"), } } @@ -343,14 +442,24 @@ impl ASTLowerer { let mut module = hir::Module::with_capacity(ast.module.len()); self.mod_ctx.preregister(ast.module.ref_payload())?; for expr in ast.module.into_iter() { - match self.lower_expr(expr, true) - .and_then(|e| self.use_check(e, mode)) { - Ok(expr) => { module.push(expr); } - Err(e) => { self.errs.push(e); }, + match self + .lower_expr(expr, true) + .and_then(|e| self.use_check(e, mode)) + { + Ok(expr) => { + module.push(expr); + } + Err(e) => { + self.errs.push(e); + } } } let hir = HIR::new(ast.name, module); - log!("[DEBUG] {}() has completed, found errors: {}", fn_name!(), self.errs.len()); + log!( + "[DEBUG] {}() has completed, found errors: {}", + fn_name!(), + self.errs.len() + ); if self.errs.is_empty() { log!("HIR:\n{hir}"); log!("[DEBUG] the type-checking process has completed.{RESET}"); diff --git a/compiler/erg_compiler/main.rs b/compiler/erg_compiler/main.rs index a71614df..5d180b0e 100644 --- a/compiler/erg_compiler/main.rs +++ b/compiler/erg_compiler/main.rs @@ -4,8 +4,8 @@ extern crate erg_parser; use std::process; +use erg_common::config::ErgConfig; use erg_common::deserialize::Deserializer; -use erg_common::config::{ErgConfig}; use erg_common::traits::Runnable; use erg_compiler::Compiler; @@ -16,10 +16,18 @@ use erg_parser::ParserRunner; fn main() { let cfg = ErgConfig::parse(); match cfg.mode { - "lex" => { LexerRunner::run(cfg); } - "parse" => { ParserRunner::run(cfg); } - "compile" | "exec" => { Compiler::run(cfg); } - "read" => { Deserializer::run(cfg); } + "lex" => { + LexerRunner::run(cfg); + } + "parse" => { + ParserRunner::run(cfg); + } + "compile" | "exec" => { + Compiler::run(cfg); + } + "read" => { + Deserializer::run(cfg); + } other => { println!("invalid mode: {other}"); process::exit(1); diff --git a/compiler/erg_compiler/optimize.rs b/compiler/erg_compiler/optimize.rs index 6f421d6e..32619fc2 100644 --- a/compiler/erg_compiler/optimize.rs +++ b/compiler/erg_compiler/optimize.rs @@ -1,15 +1,17 @@ +use crate::error::CompileWarnings; use crate::hir::HIR; -use crate::error::{CompileWarnings}; #[derive(Debug)] -pub struct HIROptimizer { - -} +pub struct HIROptimizer {} impl HIROptimizer { - pub fn fold_constants(&mut self, mut _hir: HIR) -> HIR { todo!() } + pub fn fold_constants(&mut self, mut _hir: HIR) -> HIR { + todo!() + } - pub fn eliminate_unused_variables(&mut self, mut _hir: HIR) -> (HIR, CompileWarnings) { todo!() } + pub fn eliminate_unused_variables(&mut self, mut _hir: HIR) -> (HIR, CompileWarnings) { + todo!() + } pub fn eliminate_dead_code(&mut self, mut _hir: HIR) -> (HIR, CompileWarnings) { todo!() diff --git a/compiler/erg_compiler/ownercheck.rs b/compiler/erg_compiler/ownercheck.rs index f77dc730..2d6a2a43 100644 --- a/compiler/erg_compiler/ownercheck.rs +++ b/compiler/erg_compiler/ownercheck.rs @@ -1,14 +1,14 @@ -use erg_common::Str; -use erg_common::{log}; use erg_common::color::{GREEN, RESET}; use erg_common::dict::Dict; use erg_common::error::Location; +use erg_common::log; use erg_common::set::Set; -use erg_common::traits::{Stream, Locational, HasType}; +use erg_common::traits::{HasType, Locational, Stream}; use erg_common::ty::{ArgsOwnership, Ownership}; +use erg_common::Str; use crate::error::{OwnershipError, OwnershipErrors, OwnershipResult}; -use crate::hir::{HIR, Def, Signature, Accessor, Block, Expr}; +use crate::hir::{Accessor, Block, Def, Expr, Signature, HIR}; use crate::varinfo::Visibility; use Visibility::*; @@ -42,9 +42,15 @@ impl OwnershipChecker { } fn full_path(&self) -> String { - self.path_stack.iter().fold(String::new(), |acc, (path, vis)| { - if vis.is_public() { acc + "." + &path[..] } else { acc + "::" + &path[..] } - }) + self.path_stack + .iter() + .fold(String::new(), |acc, (path, vis)| { + if vis.is_public() { + acc + "." + &path[..] + } else { + acc + "::" + &path[..] + } + }) } // moveされた後の変数が使用されていないかチェックする @@ -52,11 +58,15 @@ impl OwnershipChecker { pub fn check(mut self, hir: HIR) -> OwnershipResult { log!("{GREEN}[DEBUG] the ownership checking process has started.{RESET}"); self.path_stack.push((hir.name.clone(), Private)); - self.dict.insert(Str::from(self.full_path()), LocalVars::default()); + self.dict + .insert(Str::from(self.full_path()), LocalVars::default()); for chunk in hir.module.iter() { self.check_expr(chunk, Ownership::Owned); } - log!("{GREEN}[DEBUG] the ownership checking process has completed, found errors: {}{RESET}", self.errs.len()); + log!( + "{GREEN}[DEBUG] the ownership checking process has completed, found errors: {}{RESET}", + self.errs.len() + ); if self.errs.is_empty() { Ok(hir) } else { @@ -76,19 +86,27 @@ impl OwnershipChecker { self.define(&def); let name_and_vis = match &def.sig { Signature::Var(var) => - // TODO: visibility - if let Some(name) = var.inspect() { (name.clone(), Private) } - else { (Str::ever("::"), Private) }, + // TODO: visibility + { + if let Some(name) = var.inspect() { + (name.clone(), Private) + } else { + (Str::ever("::"), Private) + } + } Signature::Subr(subr) => (subr.name.inspect().clone(), Private), }; self.path_stack.push(name_and_vis); - self.dict.insert(Str::from(self.full_path()), LocalVars::default()); + self.dict + .insert(Str::from(self.full_path()), LocalVars::default()); self.check_block(&def.body.block); self.path_stack.pop(); - }, + } Expr::Accessor(Accessor::Local(local)) => { for n in 0..self.path_stack.len() { - if let Some(moved_loc) = self.nth_outer_scope(n).dropped_vars.get(local.inspect()) { + if let Some(moved_loc) = + self.nth_outer_scope(n).dropped_vars.get(local.inspect()) + { let moved_loc = *moved_loc; self.errs.push(OwnershipError::move_error( local.inspect(), @@ -102,34 +120,44 @@ impl OwnershipChecker { log!("dropped: {}", local.inspect()); self.drop(local.inspect(), expr.loc()); } - }, + } Expr::Accessor(Accessor::Attr(a)) => { - if a.ref_t().is_mut() { todo!("ownership checking {a}") } - }, + if a.ref_t().is_mut() { + todo!("ownership checking {a}") + } + } Expr::Accessor(_a) => todo!(), // TODO: referenced Expr::Call(call) => { self.check_expr(&call.obj, ownership); let args_ownership = call.signature_t().unwrap().args_ownership(); match args_ownership { - ArgsOwnership::Args{ self_, non_defaults, defaults } => { + ArgsOwnership::Args { + self_, + non_defaults, + defaults, + } => { if let Some(ownership) = self_ { self.check_expr(&call.obj, ownership); } - let (nd_ownerships, d_ownerships): (Vec<_>, Vec<_>) = non_defaults.iter() + let (nd_ownerships, d_ownerships): (Vec<_>, Vec<_>) = non_defaults + .iter() .enumerate() .partition(|(i, _)| *i == call.args.pos_args().len()); - for (parg, (_, ownership)) in call.args.pos_args() - .iter() - .zip(nd_ownerships.into_iter()) { - self.check_expr(&parg.expr, *ownership); + for (parg, (_, ownership)) in + call.args.pos_args().iter().zip(nd_ownerships.into_iter()) + { + self.check_expr(&parg.expr, *ownership); } - for (kwarg, (_, ownership)) in call.args.kw_args() + for (kwarg, (_, ownership)) in call + .args + .kw_args() .iter() - .zip(d_ownerships.into_iter().chain(defaults.iter().enumerate())) { - self.check_expr(&kwarg.expr, *ownership); + .zip(d_ownerships.into_iter().chain(defaults.iter().enumerate())) + { + self.check_expr(&kwarg.expr, *ownership); } - }, + } ArgsOwnership::VarArgs(ownership) => { for parg in call.args.pos_args().iter() { self.check_expr(&parg.expr, ownership); @@ -137,38 +165,39 @@ impl OwnershipChecker { for kwarg in call.args.kw_args().iter() { self.check_expr(&kwarg.expr, ownership); } - }, + } other => todo!("{other:?}"), } - }, + } // TODO: referenced Expr::BinOp(binop) => { self.check_expr(&binop.lhs, ownership); self.check_expr(&binop.rhs, ownership); - }, + } Expr::UnaryOp(unary) => { self.check_expr(&unary.expr, ownership); - }, + } Expr::Array(arr) => { for a in arr.elems.pos_args().iter() { self.check_expr(&a.expr, ownership); } - }, + } Expr::Dict(dict) => { for a in dict.attrs.kw_args().iter() { // self.check_expr(&a.key); self.check_expr(&a.expr, ownership); } - }, + } // TODO: capturing Expr::Lambda(lambda) => { let name_and_vis = (Str::from(format!("", lambda.id)), Private); self.path_stack.push(name_and_vis); - self.dict.insert(Str::from(self.full_path()), LocalVars::default()); + self.dict + .insert(Str::from(self.full_path()), LocalVars::default()); self.check_block(&lambda.body); self.path_stack.pop(); - }, - _ => {}, + } + _ => {} } } @@ -180,11 +209,16 @@ impl OwnershipChecker { #[inline] fn nth_outer_scope(&mut self, n: usize) -> &mut LocalVars { - let path = self.path_stack.iter() - .take(self.path_stack.len() - n) - .fold(String::new(), |acc, (path, vis)| { - if vis.is_public() { acc + "." + &path[..] } else { acc + "::" + &path[..] } - }); + let path = self.path_stack.iter().take(self.path_stack.len() - n).fold( + String::new(), + |acc, (path, vis)| { + if vis.is_public() { + acc + "." + &path[..] + } else { + acc + "::" + &path[..] + } + }, + ); self.dict.get_mut(&path[..]).unwrap() } @@ -194,18 +228,22 @@ impl OwnershipChecker { for name in sig.pat.inspects() { self.current_scope().alive_vars.insert(name.clone()); } - }, + } Signature::Subr(sig) => { - self.current_scope().alive_vars.insert(sig.name.inspect().clone()); - }, + self.current_scope() + .alive_vars + .insert(sig.name.inspect().clone()); + } } } fn drop(&mut self, name: &Str, moved_loc: Location) { for n in 0..self.path_stack.len() { if self.nth_outer_scope(n).alive_vars.remove(name) { - self.nth_outer_scope(n).dropped_vars.insert(name.clone(), moved_loc); - return + self.nth_outer_scope(n) + .dropped_vars + .insert(name.clone(), moved_loc); + return; } } panic!("variable not found: {name}"); diff --git a/compiler/erg_compiler/varinfo.rs b/compiler/erg_compiler/varinfo.rs index 21560763..4cbb6a93 100644 --- a/compiler/erg_compiler/varinfo.rs +++ b/compiler/erg_compiler/varinfo.rs @@ -1,8 +1,8 @@ use std::fmt; -use erg_common::Str; -use erg_common::ty::{Type}; use erg_common::traits::HasType; +use erg_common::ty::Type; +use erg_common::Str; use erg_parser::ast::DefId; @@ -17,12 +17,16 @@ impl From<&str> for Mutability { fn from(item: &str) -> Self { if item.chars().next().unwrap().is_uppercase() { Self::Const - } else { Self::Immutable } + } else { + Self::Immutable + } } } impl Mutability { - pub const fn is_const(&self) -> bool { matches!(self, Self::Const) } + pub const fn is_const(&self) -> bool { + matches!(self, Self::Const) + } } use Mutability::*; @@ -35,8 +39,12 @@ pub enum Visibility { } impl Visibility { - pub const fn is_public(&self) -> bool { matches!(self, Self::Public) } - pub const fn is_private(&self) -> bool { matches!(self, Self::Private) } + pub const fn is_public(&self) -> bool { + matches!(self, Self::Public) + } + pub const fn is_private(&self) -> bool { + matches!(self, Self::Private) + } } use Visibility::*; @@ -50,9 +58,9 @@ pub enum ParamId { PatWithDefault(usize), /// 変数パターン /// e.g. `z` of `f [x, y], z = ...` - VarNonDefault{ keyword: Str, pos: usize }, + VarNonDefault { keyword: Str, pos: usize }, /// e.g. `z` of `f [x, y], z |= 0 = ...` - VarWithDefault{ keyword: Str, pos: usize }, + VarWithDefault { keyword: Str, pos: usize }, /// パターンに埋め込まれた変数パターン /// この場合デフォルト値はない /// e.g. `x` or `y` of `f [x, y], z = ...` @@ -60,31 +68,37 @@ pub enum ParamId { } impl ParamId { - pub const fn var_default(keyword: Str, pos: usize) -> Self { Self::VarWithDefault{ keyword, pos } } - pub const fn var_non_default(keyword: Str, pos: usize) -> Self { Self::VarNonDefault{ keyword, pos } } + pub const fn var_default(keyword: Str, pos: usize) -> Self { + Self::VarWithDefault { keyword, pos } + } + pub const fn var_non_default(keyword: Str, pos: usize) -> Self { + Self::VarNonDefault { keyword, pos } + } pub const fn pos(&self) -> Option { match self { Self::PatNonDefault(pos) | Self::PatWithDefault(pos) - | Self::VarNonDefault{ pos, .. } - | Self::VarWithDefault{ pos, .. } => Some(*pos), + | Self::VarNonDefault { pos, .. } + | Self::VarWithDefault { pos, .. } => Some(*pos), _ => None, } } pub const fn has_default(&self) -> bool { - matches!(self, Self::PatWithDefault(_) | Self::VarWithDefault{ .. }) + matches!(self, Self::PatWithDefault(_) | Self::VarWithDefault { .. }) } - pub const fn is_embedded(&self) -> bool { matches!(self, Self::Embedded(_)) } + pub const fn is_embedded(&self) -> bool { + matches!(self, Self::Embedded(_)) + } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum VarKind { Defined(DefId), Declared, - Parameter{ def_id: DefId, param_id: ParamId }, + Parameter { def_id: DefId, param_id: ParamId }, Generated, DoesNotExist, Builtin, @@ -92,25 +106,25 @@ pub enum VarKind { impl VarKind { pub const fn parameter(def_id: DefId, param_id: ParamId) -> Self { - Self::Parameter{ def_id, param_id } + Self::Parameter { def_id, param_id } } pub const fn pos_as_param(&self) -> Option { match self { - Self::Parameter{ param_id, .. } => param_id.pos(), + Self::Parameter { param_id, .. } => param_id.pos(), _ => None, } } pub const fn has_default(&self) -> bool { match self { - Self::Parameter{ param_id, .. } => param_id.has_default(), + Self::Parameter { param_id, .. } => param_id.has_default(), _ => false, } } pub const fn is_parameter(&self) -> bool { - matches!(self, Self::Parameter{ .. }) + matches!(self, Self::Parameter { .. }) } pub const fn is_embedded_param(&self) -> bool { @@ -128,19 +142,28 @@ pub struct VarInfo { impl fmt::Display for VarInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "VarInfo{{t: {}, muty: {:?}, vis: {:?} kind: {:?}}}", self.t, self.muty, self.vis, self.kind) + write!( + f, + "VarInfo{{t: {}, muty: {:?}, vis: {:?} kind: {:?}}}", + self.t, self.muty, self.vis, self.kind + ) } } impl HasType for VarInfo { #[inline] - fn ref_t(&self) -> &Type { &self.t } + fn ref_t(&self) -> &Type { + &self.t + } #[inline] - fn signature_t(&self) -> Option<&Type> { None } + fn signature_t(&self) -> Option<&Type> { + None + } } impl VarInfo { - pub const ILLEGAL: &'static Self = &VarInfo::new(Type::Failure, Immutable, Private, VarKind::DoesNotExist); + pub const ILLEGAL: &'static Self = + &VarInfo::new(Type::Failure, Immutable, Private, VarKind::DoesNotExist); pub const fn new(t: Type, muty: Mutability, vis: Visibility, kind: VarKind) -> Self { Self { t, muty, vis, kind } @@ -148,7 +171,7 @@ impl VarInfo { pub fn same_id_as(&self, id: DefId) -> bool { match self.kind { - VarKind::Defined(i) | VarKind::Parameter{ def_id: i, .. } => id == i, + VarKind::Defined(i) | VarKind::Parameter { def_id: i, .. } => id == i, _ => false, } } diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 535508b3..28e1d899 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -2,25 +2,24 @@ use std::borrow::Borrow; use std::fmt; -use erg_common::{Str}; -use erg_common::{ - impl_display_for_single_struct, - impl_locational, impl_locational_for_enum, - impl_displayable_stream_for_wrapper, - impl_stream, impl_stream_for_wrapper, - fmt_vec, fmt_option, impl_display_for_enum, - impl_display_from_nested, impl_nested_display_for_enum -}; -use erg_common::value::ValueObj; use erg_common::error::Location; use erg_common::set::Set; -use erg_common::traits::{Locational, Stream, NestedDisplay}; +use erg_common::traits::{Locational, NestedDisplay, Stream}; use erg_common::ty::SubrKind; +use erg_common::value::ValueObj; +use erg_common::Str; +use erg_common::{ + fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct, + impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_locational, + impl_locational_for_enum, impl_nested_display_for_enum, impl_stream, impl_stream_for_wrapper, +}; use crate::token::{Token, TokenKind}; pub fn fmt_lines<'a, T: NestedDisplay + 'a>( - mut iter: impl Iterator, f: &mut fmt::Formatter<'_>, level: usize + mut iter: impl Iterator, + f: &mut fmt::Formatter<'_>, + level: usize, ) -> fmt::Result { if let Some(line) = iter.next() { line.fmt_nest(f, level)?; @@ -49,22 +48,30 @@ impl_display_from_nested!(Literal); impl Locational for Literal { #[inline] - fn loc(&self) -> Location { self.token.loc() } + fn loc(&self) -> Location { + self.token.loc() + } } impl From for Literal { #[inline] - fn from(token: Token) -> Self { Self { token } } + fn from(token: Token) -> Self { + Self { token } + } } impl From<&Literal> for ValueObj { #[inline] - fn from(lit: &Literal) -> ValueObj { ValueObj::from(&lit.token) } + fn from(lit: &Literal) -> ValueObj { + ValueObj::from(&lit.token) + } } impl Literal { #[inline] - pub fn is(&self, kind: TokenKind) -> bool { self.token.is(kind) } + pub fn is(&self, kind: TokenKind) -> bool { + self.token.is(kind) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -81,11 +88,15 @@ impl NestedDisplay for PosArg { impl_display_from_nested!(PosArg); impl Locational for PosArg { - fn loc(&self) -> Location { self.expr.loc() } + fn loc(&self) -> Location { + self.expr.loc() + } } impl PosArg { - pub const fn new(expr: Expr) -> Self { Self { expr } } + pub const fn new(expr: Expr) -> Self { + Self { expr } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -110,7 +121,9 @@ impl Locational for KwArg { } impl KwArg { - pub const fn new(keyword: Token, expr: Expr) -> Self { Self { keyword, expr } } + pub const fn new(keyword: Token, expr: Expr) -> Self { + Self { keyword, expr } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -130,19 +143,32 @@ impl_display_from_nested!(Args); impl Locational for Args { fn loc(&self) -> Location { - if let Some((l, r)) = &self.paren { Location::concat(l, r) } - else { Location::concat(&self.pos_args[0], self.pos_args.last().unwrap()) } + if let Some((l, r)) = &self.paren { + Location::concat(l, r) + } else { + Location::concat(&self.pos_args[0], self.pos_args.last().unwrap()) + } } } // impl_stream!(Args, Arg, args); impl Args { - pub const fn new(pos_args: Vec, kw_args: Vec, paren: Option<(Token, Token)>) -> Self { - Self { pos_args, kw_args, paren } + pub const fn new( + pos_args: Vec, + kw_args: Vec, + paren: Option<(Token, Token)>, + ) -> Self { + Self { + pos_args, + kw_args, + paren, + } } - pub const fn empty() -> Self { Self::new(vec![], vec![], None) } + pub const fn empty() -> Self { + Self::new(vec![], vec![], None) + } // for replacing to hir::Args pub fn deconstruct(self) -> (Vec, Vec, Option<(Token, Token)>) { @@ -157,11 +183,20 @@ impl Args { self.kw_args.is_empty() } - pub fn pos_args(&self) -> &[PosArg] { &self.pos_args[..] } + pub fn pos_args(&self) -> &[PosArg] { + &self.pos_args[..] + } - pub fn kw_args(&self) -> &[KwArg] { &self.kw_args[..] } + pub fn kw_args(&self) -> &[KwArg] { + &self.kw_args[..] + } - pub fn into_iters(self) -> (impl IntoIterator, impl IntoIterator) { + pub fn into_iters( + self, + ) -> ( + impl IntoIterator, + impl IntoIterator, + ) { (self.pos_args.into_iter(), self.kw_args.into_iter()) } @@ -192,20 +227,28 @@ impl_display_for_single_struct!(Local, symbol.content); impl Locational for Local { #[inline] - fn loc(&self) -> Location { self.symbol.loc() } + fn loc(&self) -> Location { + self.symbol.loc() + } } impl Local { - pub const fn new(symbol: Token) -> Self { Self{ symbol } } + pub const fn new(symbol: Token) -> Self { + Self { symbol } + } pub fn dummy(name: &'static str) -> Self { Self::new(Token::from_str(TokenKind::Symbol, name)) } // &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで - pub const fn inspect(&self) -> &Str { &self.symbol.content } + pub const fn inspect(&self) -> &Str { + &self.symbol.content + } - pub fn is_const(&self) -> bool { self.symbol.inspect().chars().next().unwrap().is_uppercase() } + pub fn is_const(&self) -> bool { + self.symbol.inspect().chars().next().unwrap().is_uppercase() + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -223,7 +266,12 @@ impl fmt::Display for Attribute { impl_locational!(Attribute, obj, name); impl Attribute { - pub fn new(obj: Expr, name: Local) -> Self { Self { obj: Box::new(obj), name } } + pub fn new(obj: Expr, name: Local) -> Self { + Self { + obj: Box::new(obj), + name, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -241,7 +289,12 @@ impl fmt::Display for TupleAttribute { impl_locational!(TupleAttribute, obj, index); impl TupleAttribute { - pub fn new(obj: Expr, index: Literal) -> Self { Self { obj: Box::new(obj), index } } + pub fn new(obj: Expr, index: Literal) -> Self { + Self { + obj: Box::new(obj), + index, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -260,7 +313,10 @@ impl_locational!(Subscript, obj, index); impl Subscript { pub fn new(obj: Expr, index: Expr) -> Self { - Self { obj: Box::new(obj), index: Box::new(index) } + Self { + obj: Box::new(obj), + index: Box::new(index), + } } } @@ -289,11 +345,17 @@ impl_display_from_nested!(Accessor); impl_locational_for_enum!(Accessor; Local, SelfDot, Attr, TupleAttr, Subscr); impl Accessor { - pub const fn local(symbol: Token) -> Self { Self::Local(Local::new(symbol)) } + pub const fn local(symbol: Token) -> Self { + Self::Local(Local::new(symbol)) + } - pub const fn self_dot(attr: Token) -> Self { Self::SelfDot(Local::new(attr)) } + pub const fn self_dot(attr: Token) -> Self { + Self::SelfDot(Local::new(attr)) + } - pub fn attr(obj: Expr, name: Local) -> Self { Self::Attr(Attribute::new(obj, name)) } + pub fn attr(obj: Expr, name: Local) -> Self { + Self::Attr(Attribute::new(obj, name)) + } pub fn subscr(obj: Expr, index: Expr) -> Self { Self::Subscr(Subscript::new(obj, index)) @@ -309,8 +371,7 @@ impl Accessor { pub fn is_const(&self) -> bool { match self { - Self::Local(local) - | Self::SelfDot(local) => local.is_const(), + Self::Local(local) | Self::SelfDot(local) => local.is_const(), Self::Subscr(subscr) => subscr.obj.is_const_acc(), Self::TupleAttr(attr) => attr.obj.is_const_acc(), Self::Attr(attr) => attr.obj.is_const_acc() && attr.name.is_const(), @@ -342,7 +403,12 @@ impl_locational!(Array, l_sqbr, r_sqbr); impl Array { pub fn new(l_sqbr: Token, r_sqbr: Token, elems: Args, guard: Option) -> Self { - Self { l_sqbr, r_sqbr, elems, guard: guard.map(Box::new) } + Self { + l_sqbr, + r_sqbr, + elems, + guard: guard.map(Box::new), + } } } @@ -370,7 +436,12 @@ impl_locational!(Dict, l_brace, r_brace); impl Dict { pub fn new(l_brace: Token, r_brace: Token, attrs: Args, guard: Option) -> Self { - Self { l_brace, r_brace, attrs, guard: guard.map(Box::new) } + Self { + l_brace, + r_brace, + attrs, + guard: guard.map(Box::new), + } } } @@ -399,7 +470,10 @@ impl Locational for BinOp { impl BinOp { pub fn new(op: Token, lhs: Expr, rhs: Expr) -> Self { - Self { op, args: [Box::new(lhs), Box::new(rhs)] } + Self { + op, + args: [Box::new(lhs), Box::new(rhs)], + } } } @@ -425,7 +499,12 @@ impl Locational for UnaryOp { } impl UnaryOp { - pub fn new(op: Token, expr: Expr) -> Self { Self { op, args: [Box::new(expr)] } } + pub fn new(op: Token, expr: Expr) -> Self { + Self { + op, + args: [Box::new(expr)], + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -445,13 +524,21 @@ impl_display_from_nested!(Call); impl Locational for Call { fn loc(&self) -> Location { - if self.args.is_empty() { self.obj.loc() } - else { Location::concat(self.obj.as_ref(), &self.args) } + if self.args.is_empty() { + self.obj.loc() + } else { + Location::concat(self.obj.as_ref(), &self.args) + } } } impl Call { - pub fn new(obj: Expr, args: Args) -> Self { Self { obj: Box::new(obj), args } } + pub fn new(obj: Expr, args: Args) -> Self { + Self { + obj: Box::new(obj), + args, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -488,18 +575,24 @@ impl_display_from_nested!(ConstLocal); impl Locational for ConstLocal { #[inline] - fn loc(&self) -> Location { self.symbol.loc() } + fn loc(&self) -> Location { + self.symbol.loc() + } } impl ConstLocal { - pub const fn new(symbol: Token) -> Self { Self{ symbol } } + pub const fn new(symbol: Token) -> Self { + Self { symbol } + } pub fn dummy(name: &'static str) -> Self { Self::new(Token::from_str(TokenKind::Symbol, name)) } // &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで - pub const fn inspect(&self) -> &Str { &self.symbol.content } + pub const fn inspect(&self) -> &Str { + &self.symbol.content + } } /// type variables @@ -521,7 +614,12 @@ impl_display_from_nested!(ConstAttribute); impl_locational!(ConstAttribute, obj, name); impl ConstAttribute { - pub fn new(expr: ConstExpr, name: ConstLocal) -> Self { Self { obj: Box::new(expr), name } } + pub fn new(expr: ConstExpr, name: ConstLocal) -> Self { + Self { + obj: Box::new(expr), + name, + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -541,7 +639,10 @@ impl_locational!(ConstSubscript, obj, index); impl ConstSubscript { pub fn new(obj: ConstExpr, index: ConstExpr) -> Self { - Self { obj: Box::new(obj), index: Box::new(index) } + Self { + obj: Box::new(obj), + index: Box::new(index), + } } } @@ -558,9 +659,13 @@ impl_display_from_nested!(ConstAccessor); impl_locational_for_enum!(ConstAccessor; Local, SelfDot, Attr, Subscr); impl ConstAccessor { - pub const fn local(symbol: Token) -> Self { Self::Local(ConstLocal::new(symbol)) } + pub const fn local(symbol: Token) -> Self { + Self::Local(ConstLocal::new(symbol)) + } - pub const fn dot_self(attr: Token) -> Self { Self::SelfDot(ConstLocal::new(attr)) } + pub const fn dot_self(attr: Token) -> Self { + Self::SelfDot(ConstLocal::new(attr)) + } pub fn attr(obj: ConstExpr, name: ConstLocal) -> Self { Self::Attr(ConstAttribute::new(obj, name)) @@ -595,7 +700,12 @@ impl_locational!(ConstArray, l_sqbr, r_sqbr); impl ConstArray { pub fn new(l_sqbr: Token, r_sqbr: Token, elems: ConstArgs, guard: Option) -> Self { - Self { l_sqbr, r_sqbr, elems, guard: guard.map(Box::new) } + Self { + l_sqbr, + r_sqbr, + elems, + guard: guard.map(Box::new), + } } } @@ -617,7 +727,11 @@ impl_locational!(ConstDict, l_brace, r_brace); impl ConstDict { pub fn new(l_brace: Token, r_brace: Token, attrs: ConstArgs) -> Self { - Self { l_brace, r_brace, attrs } + Self { + l_brace, + r_brace, + attrs, + } } } @@ -639,7 +753,11 @@ impl_locational!(ConstBinOp, lhs, rhs); impl ConstBinOp { pub fn new(op: Token, lhs: ConstExpr, rhs: ConstExpr) -> Self { - Self { op, lhs: Box::new(lhs), rhs: Box::new(rhs) } + Self { + op, + lhs: Box::new(lhs), + rhs: Box::new(rhs), + } } } @@ -660,7 +778,10 @@ impl_locational!(ConstUnaryOp, op, expr); impl ConstUnaryOp { pub fn new(op: Token, expr: ConstExpr) -> Self { - Self { op, expr: Box::new(expr) } + Self { + op, + expr: Box::new(expr), + } } } @@ -681,13 +802,18 @@ impl NestedDisplay for ConstApp { impl Locational for ConstApp { fn loc(&self) -> Location { - if self.args.is_empty() { self.acc.loc() } - else { Location::concat(&self.acc, &self.args) } + if self.args.is_empty() { + self.acc.loc() + } else { + Location::concat(&self.acc, &self.args) + } } } impl ConstApp { - pub const fn new(acc: ConstAccessor, args: ConstArgs) -> Self { Self { acc, args } } + pub const fn new(acc: ConstAccessor, args: ConstArgs) -> Self { + Self { acc, args } + } } /// valid expression for an argument of polymorphic types @@ -722,11 +848,15 @@ impl NestedDisplay for ConstPosArg { } impl Locational for ConstPosArg { - fn loc(&self) -> Location { self.expr.loc() } + fn loc(&self) -> Location { + self.expr.loc() + } } impl ConstPosArg { - pub const fn new(expr: ConstExpr) -> Self { Self { expr } } + pub const fn new(expr: ConstExpr) -> Self { + Self { expr } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -749,7 +879,9 @@ impl Locational for ConstKwArg { } impl ConstKwArg { - pub const fn new(keyword: Token, expr: ConstExpr) -> Self { Self { keyword, expr } } + pub const fn new(keyword: Token, expr: ConstExpr) -> Self { + Self { keyword, expr } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -784,15 +916,25 @@ impl Locational for ConstArgs { Location::concat(self.pos_args.first().unwrap(), last) } else if let Some(last) = self.pos_args.last() { Location::concat(self.pos_args.first().unwrap(), last) - } else { unreachable!() } + } else { + unreachable!() + } } } // impl_stream!(ConstArgs, ConstKwArg, pos_args); impl ConstArgs { - pub const fn new(pos_args: Vec, kw_args: Vec, paren: Option<(Token, Token)>) -> Self { - Self { pos_args, kw_args, paren } + pub const fn new( + pos_args: Vec, + kw_args: Vec, + paren: Option<(Token, Token)>, + ) -> Self { + Self { + pos_args, + kw_args, + paren, + } } pub const fn empty() -> Self { @@ -803,15 +945,20 @@ impl ConstArgs { self.pos_args.is_empty() && self.kw_args.is_empty() } - pub fn pos_args(&self) -> impl Iterator { + pub fn pos_args(&self) -> impl Iterator { self.pos_args.iter() } - pub fn kw_args(&self) -> impl Iterator { + pub fn kw_args(&self) -> impl Iterator { self.kw_args.iter() } - pub fn into_iters(self) -> (impl IntoIterator, impl IntoIterator) { + pub fn into_iters( + self, + ) -> ( + impl IntoIterator, + impl IntoIterator, + ) { (self.pos_args.into_iter(), self.kw_args.into_iter()) } @@ -853,7 +1000,9 @@ impl Locational for SimpleTypeSpec { } impl SimpleTypeSpec { - pub const fn new(name: VarName, args: ConstArgs) -> Self { Self { name, args } } + pub const fn new(name: VarName, args: ConstArgs) -> Self { + Self { name, args } + } } // OK: @@ -867,18 +1016,29 @@ impl SimpleTypeSpec { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum PreDeclTypeSpec { Simple(SimpleTypeSpec), - Attr{ namespace: Vec, t: SimpleTypeSpec }, - Subscr{ namespace: Vec, name: VarName, index: Token }, + Attr { + namespace: Vec, + t: SimpleTypeSpec, + }, + Subscr { + namespace: Vec, + name: VarName, + index: Token, + }, } impl fmt::Display for PreDeclTypeSpec { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { PreDeclTypeSpec::Simple(ts) => write!(f, "{}", ts), - PreDeclTypeSpec::Attr{ namespace, t } => { + PreDeclTypeSpec::Attr { namespace, t } => { write!(f, "{}.{}", namespace.join("."), t) } - PreDeclTypeSpec::Subscr{ namespace, name, index } => { + PreDeclTypeSpec::Subscr { + namespace, + name, + index, + } => { write!(f, "{}.{}[{}]", namespace.join("."), name, index) } } @@ -889,14 +1049,10 @@ impl Locational for PreDeclTypeSpec { fn loc(&self) -> Location { match self { Self::Simple(s) => s.loc(), - Self::Attr{ namespace, t } => Location::concat( - &namespace[0], - t, - ), - Self::Subscr{ namespace, index, .. } => Location::concat( - &namespace[0], - index, - ), + Self::Attr { namespace, t } => Location::concat(&namespace[0], t), + Self::Subscr { + namespace, index, .. + } => Location::concat(&namespace[0], index), } } } @@ -928,9 +1084,13 @@ impl Locational for ParamTySpec { } impl ParamTySpec { - pub const fn new(name: Option, ty: TypeSpec) -> Self { Self { name, ty } } + pub const fn new(name: Option, ty: TypeSpec) -> Self { + Self { name, ty } + } - pub const fn anonymous(ty: TypeSpec) -> Self { Self::new(None, ty) } + pub const fn anonymous(ty: TypeSpec) -> Self { + Self::new(None, ty) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -944,7 +1104,14 @@ pub struct SubrTySpec { impl fmt::Display for SubrTySpec { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "({}, ? {}) {} {}", fmt_vec(&self.non_defaults), fmt_vec(&self.defaults), self.kind.arrow(), self.return_t) + write!( + f, + "({}, ? {}) {} {}", + fmt_vec(&self.non_defaults), + fmt_vec(&self.defaults), + self.kind.arrow(), + self.return_t + ) } } @@ -960,8 +1127,20 @@ impl Locational for SubrTySpec { } impl SubrTySpec { - pub fn new(kind: SubrKind, lparen: Option, non_defaults: Vec, defaults: Vec, return_t: TypeSpec) -> Self { - Self { kind, lparen, non_defaults, defaults, return_t: Box::new(return_t) } + pub fn new( + kind: SubrKind, + lparen: Option, + non_defaults: Vec, + defaults: Vec, + return_t: TypeSpec, + ) -> Self { + Self { + kind, + lparen, + non_defaults, + defaults, + return_t: Box::new(return_t), + } } } @@ -979,7 +1158,10 @@ impl SubrTySpec { pub enum TypeSpec { PreDeclTy(PreDeclTypeSpec), /* Composite types */ - Array{ t: PreDeclTypeSpec, len: ConstExpr }, + Array { + t: PreDeclTypeSpec, + len: ConstExpr, + }, Tuple(Vec), // Dict(), // Option(), @@ -987,7 +1169,11 @@ pub enum TypeSpec { Not(Box, Box), Or(Box, Box), Enum(ConstArgs), - Interval{ op: Token, lhs: ConstExpr, rhs: ConstExpr }, + Interval { + op: Token, + lhs: ConstExpr, + rhs: ConstExpr, + }, // Record(), Subr(SubrTySpec), } @@ -999,10 +1185,10 @@ impl fmt::Display for TypeSpec { Self::And(lhs, rhs) => write!(f, "{lhs} and {rhs}"), 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::Array { t, len } => write!(f, "[{t}; {len}]"), 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::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()), Self::Subr(s) => write!(f, "{s}"), } } @@ -1012,14 +1198,14 @@ impl Locational for TypeSpec { fn loc(&self) -> Location { match self { Self::PreDeclTy(sig) => sig.loc(), - Self::And(lhs, rhs) - | Self::Not(lhs, rhs) - | Self::Or(lhs, rhs) => Location::concat(lhs.as_ref(), rhs.as_ref()), - Self::Array{ t, len } => Location::concat(t, len), + Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { + Location::concat(lhs.as_ref(), rhs.as_ref()) + } + Self::Array { t, len } => Location::concat(t, len), // TODO: ユニット Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()), Self::Enum(set) => set.loc(), - Self::Interval{ lhs, rhs, .. } => Location::concat(lhs, rhs), + Self::Interval { lhs, rhs, .. } => Location::concat(lhs, rhs), Self::Subr(s) => s.loc(), } } @@ -1039,30 +1225,52 @@ impl TypeSpec { } pub const fn interval(op: Token, lhs: ConstExpr, rhs: ConstExpr) -> Self { - Self::Interval{ op, lhs, rhs } + Self::Interval { op, lhs, rhs } } - pub fn func(lparen: Option, non_defaults: Vec, defaults: Vec, return_t: TypeSpec) -> Self { - Self::Subr(SubrTySpec::new(SubrKind::Func, lparen, non_defaults, defaults, return_t)) + pub fn func( + lparen: Option, + non_defaults: Vec, + defaults: Vec, + return_t: TypeSpec, + ) -> Self { + Self::Subr(SubrTySpec::new( + SubrKind::Func, + lparen, + non_defaults, + defaults, + return_t, + )) } - pub fn proc(lparen: Option, non_defaults: Vec, defaults: Vec, return_t: TypeSpec) -> Self { - Self::Subr(SubrTySpec::new(SubrKind::Proc, lparen, non_defaults, defaults, return_t)) + pub fn proc( + lparen: Option, + non_defaults: Vec, + defaults: Vec, + return_t: TypeSpec, + ) -> Self { + Self::Subr(SubrTySpec::new( + SubrKind::Proc, + lparen, + non_defaults, + defaults, + return_t, + )) } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum TypeBoundSpec { - Subtype{ sub: VarName, sup: TypeSpec }, // e.g. S <: Show - Instance{ name: VarName, ty: TypeSpec }, // e.g. N: Nat - // Predicate, // TODO: e.g. N > 5 + Subtype { sub: VarName, sup: TypeSpec }, // e.g. S <: Show + Instance { name: VarName, ty: TypeSpec }, // e.g. N: Nat + // Predicate, // TODO: e.g. N > 5 } impl NestedDisplay for TypeBoundSpec { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { match self { - Self::Subtype{ sub, sup } => write!(f, "{} <: {}", sub, sup), - Self::Instance{ name, ty } => write!(f, "{} : {}", name, ty), + Self::Subtype { sub, sup } => write!(f, "{} <: {}", sub, sup), + Self::Instance { name, ty } => write!(f, "{} : {}", name, ty), } } } @@ -1072,8 +1280,9 @@ impl_display_from_nested!(TypeBoundSpec); impl Locational for TypeBoundSpec { fn loc(&self) -> Location { match self { - Self::Subtype { sub: l, sup: r } - | Self::Instance { name: l, ty: r } => Location::concat(l, r), + Self::Subtype { sub: l, sup: r } | Self::Instance { name: l, ty: r } => { + Location::concat(l, r) + } } } } @@ -1095,7 +1304,9 @@ impl Locational for TypeBoundSpecs { pub struct Decorator(Expr); impl Decorator { - pub const fn new(expr: Expr) -> Self { Self(expr) } + pub const fn new(expr: Expr) -> Self { + Self(expr) + } } /// symbol as a left value @@ -1104,17 +1315,23 @@ pub struct VarName(Token); impl Borrow for VarName { #[inline] - fn borrow(&self) -> &str { &self.0.content[..] } + fn borrow(&self) -> &str { + &self.0.content[..] + } } impl Borrow for VarName { #[inline] - fn borrow(&self) -> &Str { &self.0.content } + fn borrow(&self) -> &Str { + &self.0.content + } } impl Locational for VarName { #[inline] - fn loc(&self) -> Location { self.0.loc() } + fn loc(&self) -> Location { + self.0.loc() + } } impl fmt::Display for VarName { @@ -1124,27 +1341,49 @@ impl fmt::Display for VarName { } impl VarName { - pub const fn new(symbol: Token) -> Self { Self(symbol) } + pub const fn new(symbol: Token) -> Self { + Self(symbol) + } - pub const fn from_static(symbol: &'static str) -> Self { Self(Token::static_symbol(symbol)) } + pub const fn from_static(symbol: &'static str) -> Self { + Self(Token::static_symbol(symbol)) + } - pub fn from_str(symbol: Str) -> Self { Self(Token::from_str(TokenKind::Symbol, &symbol)) } + pub fn from_str(symbol: Str) -> Self { + Self(Token::from_str(TokenKind::Symbol, &symbol)) + } #[inline] pub fn is_const(&self) -> bool { - self.0.content.chars().next().map(|c| c.is_uppercase()).unwrap_or(false) + self.0 + .content + .chars() + .next() + .map(|c| c.is_uppercase()) + .unwrap_or(false) } #[inline] pub fn is_procedural(&self) -> bool { - self.0.content.chars().last().map(|c| c == '!').unwrap_or(false) + self.0 + .content + .chars() + .last() + .map(|c| c == '!') + .unwrap_or(false) } - pub const fn token(&self) -> &Token { &self.0 } + pub const fn token(&self) -> &Token { + &self.0 + } - pub fn into_token(self) -> Token { self.0 } + pub fn into_token(self) -> Token { + self.0 + } - pub const fn inspect(&self) -> &Str { &self.0.content } + pub const fn inspect(&self) -> &Str { + &self.0.content + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1164,16 +1403,26 @@ impl_locational!(VarArrayPattern, l_sqbr, r_sqbr); impl Stream for VarArrayPattern { #[inline] - fn payload(self) -> Vec { self.elems.payload() } + fn payload(self) -> Vec { + self.elems.payload() + } #[inline] - fn ref_payload(&self) -> &Vec { self.elems.ref_payload() } + fn ref_payload(&self) -> &Vec { + self.elems.ref_payload() + } #[inline] - fn ref_mut_payload(&mut self) -> &mut Vec { self.elems.ref_mut_payload() } + fn ref_mut_payload(&mut self) -> &mut Vec { + self.elems.ref_mut_payload() + } } impl VarArrayPattern { pub const fn new(l_sqbr: Token, elems: Vars, r_sqbr: Token) -> Self { - Self{ l_sqbr, elems, r_sqbr } + Self { + l_sqbr, + elems, + r_sqbr, + } } } @@ -1200,16 +1449,22 @@ impl Locational for VarTuplePattern { impl Stream for VarTuplePattern { #[inline] - fn payload(self) -> Vec { self.elems.payload() } + fn payload(self) -> Vec { + self.elems.payload() + } #[inline] - fn ref_payload(&self) -> &Vec { self.elems.ref_payload() } + fn ref_payload(&self) -> &Vec { + self.elems.ref_payload() + } #[inline] - fn ref_mut_payload(&mut self) -> &mut Vec { self.elems.ref_mut_payload() } + fn ref_mut_payload(&mut self) -> &mut Vec { + self.elems.ref_mut_payload() + } } impl VarTuplePattern { pub const fn new(paren: Option<(Token, Token)>, elems: Vars) -> Self { - Self{ paren, elems } + Self { paren, elems } } } @@ -1231,7 +1486,11 @@ impl_locational!(VarRecordPattern, l_brace, r_brace); impl VarRecordPattern { pub const fn new(l_brace: Token, elems: Vars, r_brace: Token) -> Self { - Self{ l_brace, elems, r_brace } + Self { + l_brace, + elems, + r_brace, + } } } @@ -1275,9 +1534,9 @@ impl VarPattern { pub fn inspects(&self) -> Vec<&Str> { match self { Self::VarName(n) | Self::SelfDot(n) => vec![n.inspect()], - Self::Array(VarArrayPattern{ elems, .. }) - | Self::Tuple(VarTuplePattern{ elems, .. }) - | Self::Record(VarRecordPattern{ elems, .. }) => { + Self::Array(VarArrayPattern { elems, .. }) + | Self::Tuple(VarTuplePattern { elems, .. }) + | Self::Record(VarRecordPattern { elems, .. }) => { elems.iter().map(|s| s.pat.inspects()).flatten().collect() } _ => vec![], @@ -1326,11 +1585,17 @@ impl Locational for VarSignature { } impl VarSignature { - pub const fn new(pat: VarPattern, t_spec: Option) -> Self { Self{ pat, t_spec } } + pub const fn new(pat: VarPattern, t_spec: Option) -> Self { + Self { pat, t_spec } + } - pub const fn inspect(&self) -> Option<&Str> { self.pat.inspect() } + pub const fn inspect(&self) -> Option<&Str> { + self.pat.inspect() + } - pub fn is_const(&self) -> bool { self.pat.is_const() } + pub fn is_const(&self) -> bool { + self.pat.is_const() + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1348,9 +1613,13 @@ impl_display_from_nested!(Vars); impl_stream!(Vars, VarSignature, elems); impl Vars { - pub const fn new(elems: Vec) -> Self { Self { elems } } + pub const fn new(elems: Vec) -> Self { + Self { elems } + } - pub const fn empty() -> Self { Self::new(vec![]) } + pub const fn empty() -> Self { + Self::new(vec![]) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1371,11 +1640,19 @@ impl_locational!(ParamArrayPattern, l_sqbr, r_sqbr); impl ParamArrayPattern { pub const fn new(l_sqbr: Token, elems: Params, r_sqbr: Token) -> Self { - Self{ l_sqbr, elems, r_sqbr } + Self { + l_sqbr, + elems, + r_sqbr, + } } - pub fn is_empty(&self) -> bool { self.elems.is_empty() } - pub fn len(&self) -> usize { self.elems.len() } + pub fn is_empty(&self) -> bool { + self.elems.is_empty() + } + pub fn len(&self) -> usize { + self.elems.len() + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1396,7 +1673,11 @@ impl_locational!(ParamRecordPattern, l_brace, r_brace); impl ParamRecordPattern { pub const fn new(l_brace: Token, elems: Params, r_brace: Token) -> Self { - Self{ l_brace, elems, r_brace } + Self { + l_brace, + elems, + r_brace, + } } } @@ -1420,19 +1701,19 @@ impl_locational_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Arra impl ParamPattern { pub const fn inspect(&self) -> Option<&Str> { match self { - Self::VarName(n) - | Self::VarArgsName(n) => Some(n.inspect()), + Self::VarName(n) | Self::VarArgsName(n) => Some(n.inspect()), _ => None, } } - pub const fn is_lit(&self) -> bool { matches!(self, Self::Lit(_)) } + pub const fn is_lit(&self) -> bool { + matches!(self, Self::Lit(_)) + } pub fn is_procedural(&self) -> bool { match self { Self::Discard(_) => true, - Self::VarName(n) - | Self::VarArgsName(n) => n.is_procedural(), + Self::VarName(n) | Self::VarArgsName(n) => n.is_procedural(), _ => false, } } @@ -1440,8 +1721,7 @@ impl ParamPattern { pub fn is_const(&self) -> bool { match self { Self::Discard(_) => true, - Self::VarName(n) - | Self::VarArgsName(n) => n.is_const(), + Self::VarName(n) | Self::VarArgsName(n) => n.is_const(), _ => false, } } @@ -1463,17 +1743,22 @@ impl_display_from_nested!(NonDefaultParamSignature); impl Locational for NonDefaultParamSignature { fn loc(&self) -> Location { - if let Some(t_spec) = &self.t_spec { Location::concat(&self.pat, t_spec) } - else { self.pat.loc() } + if let Some(t_spec) = &self.t_spec { + Location::concat(&self.pat, t_spec) + } else { + self.pat.loc() + } } } impl NonDefaultParamSignature { pub const fn new(pat: ParamPattern, t_spec: Option) -> Self { - Self{ pat, t_spec } + Self { pat, t_spec } } - pub const fn inspect(&self) -> Option<&Str> { self.pat.inspect() } + pub const fn inspect(&self) -> Option<&Str> { + self.pat.inspect() + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1485,7 +1770,13 @@ pub struct DefaultParamSignature { impl NestedDisplay for DefaultParamSignature { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { - write!(f, "{}{} |= {}", self.pat, fmt_option!(pre ": ", &self.t_spec), self.val) + write!( + f, + "{}{} |= {}", + self.pat, + fmt_option!(pre ": ", &self.t_spec), + self.val + ) } } @@ -1499,10 +1790,12 @@ impl Locational for DefaultParamSignature { impl DefaultParamSignature { pub const fn new(pat: ParamPattern, t_spec: Option, val: ConstExpr) -> Self { - Self{ pat, t_spec, val } + Self { pat, t_spec, val } } - pub const fn inspect(&self) -> Option<&Str> { self.pat.inspect() } + pub const fn inspect(&self) -> Option<&Str> { + self.pat.inspect() + } } pub trait ParamSig { @@ -1511,23 +1804,39 @@ pub trait ParamSig { } impl ParamSig for NonDefaultParamSignature { - fn pat(&self) -> &ParamPattern { &self.pat } - fn t_spec(&self) -> Option<&TypeSpec> { self.t_spec.as_ref() } + fn pat(&self) -> &ParamPattern { + &self.pat + } + fn t_spec(&self) -> Option<&TypeSpec> { + self.t_spec.as_ref() + } } impl ParamSig for DefaultParamSignature { - fn pat(&self) -> &ParamPattern { &self.pat } - fn t_spec(&self) -> Option<&TypeSpec> { self.t_spec.as_ref() } + fn pat(&self) -> &ParamPattern { + &self.pat + } + fn t_spec(&self) -> Option<&TypeSpec> { + self.t_spec.as_ref() + } } impl ParamSig for &NonDefaultParamSignature { - fn pat(&self) -> &ParamPattern { &self.pat } - fn t_spec(&self) -> Option<&TypeSpec> { self.t_spec.as_ref() } + fn pat(&self) -> &ParamPattern { + &self.pat + } + fn t_spec(&self) -> Option<&TypeSpec> { + self.t_spec.as_ref() + } } impl ParamSig for &DefaultParamSignature { - fn pat(&self) -> &ParamPattern { &self.pat } - fn t_spec(&self) -> Option<&TypeSpec> { self.t_spec.as_ref() } + fn pat(&self) -> &ParamPattern { + &self.pat + } + fn t_spec(&self) -> Option<&TypeSpec> { + self.t_spec.as_ref() + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1539,7 +1848,12 @@ pub struct Params { impl fmt::Display for Params { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "({}, {})", fmt_vec(&self.non_defaults), fmt_vec(&self.defaults)) + write!( + f, + "({}, {})", + fmt_vec(&self.non_defaults), + fmt_vec(&self.defaults) + ) } } @@ -1558,19 +1872,37 @@ impl Locational for Params { } impl Params { - pub const fn new(non_defaults: Vec, defaults: Vec, parens: Option<(Token, Token)>) -> Self { - Self { non_defaults, defaults, parens } + pub const fn new( + non_defaults: Vec, + defaults: Vec, + parens: Option<(Token, Token)>, + ) -> Self { + Self { + non_defaults, + defaults, + parens, + } } - pub fn deconstruct(self) -> (Vec, Vec, Option<(Token, Token)>) { + pub fn deconstruct( + self, + ) -> ( + Vec, + Vec, + Option<(Token, Token)>, + ) { (self.non_defaults, self.defaults, self.parens) } #[inline] - pub fn len(&self) -> usize { self.non_defaults.len() + self.defaults.len() } + pub fn len(&self) -> usize { + self.non_defaults.len() + self.defaults.len() + } #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } /// 引数を取るならTypeでもSubr扱い @@ -1586,9 +1918,22 @@ pub struct SubrSignature { impl NestedDisplay for SubrSignature { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { if self.bounds.is_empty() { - write!(f, "{}{}{}", self.name, self.params, fmt_option!(pre ": ", &self.return_t_spec)) + write!( + f, + "{}{}{}", + self.name, + self.params, + fmt_option!(pre ": ", &self.return_t_spec) + ) } else { - write!(f, "{}|{}|{}{}", self.name, self.bounds, self.params, fmt_option!(pre ": ", &self.return_t_spec)) + write!( + f, + "{}|{}|{}{}", + self.name, + self.bounds, + self.params, + fmt_option!(pre ": ", &self.return_t_spec) + ) } } } @@ -1613,11 +1958,20 @@ impl SubrSignature { name: VarName, params: Params, return_t: Option, - bounds: TypeBoundSpecs) -> Self { - Self{ decorators, name, params, return_t_spec: return_t, bounds } + bounds: TypeBoundSpecs, + ) -> Self { + Self { + decorators, + name, + params, + return_t_spec: return_t, + bounds, + } } - pub fn is_const(&self) -> bool { self.name.is_const() } + pub fn is_const(&self) -> bool { + self.name.is_const() + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1630,9 +1984,20 @@ pub struct LambdaSignature { impl fmt::Display for LambdaSignature { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.bounds.is_empty() { - write!(f, "{}{}", self.params, fmt_option!(pre ": ", &self.return_t_spec)) + write!( + f, + "{}{}", + self.params, + fmt_option!(pre ": ", &self.return_t_spec) + ) } else { - write!(f, "|{}|{}{}", self.bounds, self.params, fmt_option!(pre ": ", &self.return_t_spec)) + write!( + f, + "|{}|{}{}", + self.bounds, + self.params, + fmt_option!(pre ": ", &self.return_t_spec) + ) } } } @@ -1653,7 +2018,11 @@ impl Locational for LambdaSignature { impl LambdaSignature { pub const fn new(params: Params, return_t: Option, bounds: TypeBoundSpecs) -> Self { - Self { params, return_t_spec: return_t, bounds } + Self { + params, + return_t_spec: return_t, + bounds, + } } } @@ -1661,7 +2030,9 @@ impl LambdaSignature { pub struct DefId(pub usize); impl DefId { - pub fn inc(&mut self) { self.0 += 1; } + pub fn inc(&mut self) { + self.0 += 1; + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -1683,11 +2054,13 @@ impl NestedDisplay for Lambda { impl_display_from_nested!(Lambda); impl Lambda { - pub const fn new(sig: LambdaSignature, op: Token, body: Block, id : DefId) -> Self { + pub const fn new(sig: LambdaSignature, op: Token, body: Block, id: DefId) -> Self { Self { sig, op, body, id } } - pub fn is_procedural(&self) -> bool { self.op.is(TokenKind::ProcArrow) } + pub fn is_procedural(&self) -> bool { + self.op.is(TokenKind::ProcArrow) + } } impl_locational!(Lambda, sig, body); @@ -1713,7 +2086,13 @@ impl Signature { pub fn name(&self) -> Option<&VarName> { match self { - Self::Var(v) => if let VarPattern::VarName(v) = &v.pat { Some(v) } else { None }, + Self::Var(v) => { + if let VarPattern::VarName(v) = &v.pat { + Some(v) + } else { + None + } + } Self::Subr(s) => Some(&s.name), } } @@ -1739,13 +2118,15 @@ pub type Decl = Signature; pub struct DefBody { pub op: Token, pub block: Block, - pub id : DefId, + pub id: DefId, } impl_locational!(DefBody, op, block); impl DefBody { - pub const fn new(op: Token, block: Block, id: DefId) -> Self { Self { op, block, id } } + pub const fn new(op: Token, block: Block, id: DefId) -> Self { + Self { op, block, id } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -1765,9 +2146,13 @@ impl_display_from_nested!(Def); impl_locational!(Def, sig, body); impl Def { - pub const fn new(sig: Signature, body: DefBody) -> Self { Self { sig, body } } + pub const fn new(sig: Signature, body: DefBody) -> Self { + Self { sig, body } + } - pub fn is_const(&self) -> bool { self.sig.is_const() } + pub fn is_const(&self) -> bool { + self.sig.is_const() + } pub const fn is_subr(&self) -> bool { matches!(&self.sig, Signature::Subr(_)) @@ -1812,7 +2197,12 @@ impl Expr { } pub fn local(name: &str, lineno: usize, col_begin: usize) -> Self { - Self::Accessor(Accessor::local(Token::new(TokenKind::Symbol, Str::rc(name), lineno, col_begin))) + Self::Accessor(Accessor::local(Token::new( + TokenKind::Symbol, + Str::rc(name), + lineno, + col_begin, + ))) } pub fn dummy_local(name: &str) -> Self { @@ -1850,7 +2240,11 @@ pub struct AST { impl_display_for_single_struct!(AST, module); impl AST { - pub const fn new(name: Str, module: Module) -> Self { Self { name, module } } + pub const fn new(name: Str, module: Module) -> Self { + Self { name, module } + } - pub fn is_empty(&self) -> bool { self.module.is_empty() } + pub fn is_empty(&self) -> bool { + self.module.is_empty() + } } diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 8485aa97..aa95451b 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -5,18 +5,17 @@ //! 型チェックなどによる検証は行わない #![allow(dead_code)] +use erg_common::set::Set; +use erg_common::traits::{Locational, Stream}; +use erg_common::Str; use erg_common::{enum_unwrap, set}; -use erg_common::{Str}; -use erg_common::set::{Set}; -use erg_common::traits::{Stream, Locational}; -use crate::token::{Token, TokenKind}; use crate::ast::{ - Module, Expr, Lambda, Call, Def, Accessor, - LambdaSignature, PosArg, Signature, SubrSignature, Args, - ParamPattern, NonDefaultParamSignature, Params, VarName, - TypeBoundSpecs, DefBody, Block, VarPattern + Accessor, Args, Block, Call, Def, DefBody, Expr, Lambda, LambdaSignature, Module, + NonDefaultParamSignature, ParamPattern, Params, PosArg, Signature, SubrSignature, + TypeBoundSpecs, VarName, VarPattern, }; +use crate::token::{Token, TokenKind}; #[derive(Debug)] pub struct Desugarer { @@ -24,7 +23,11 @@ pub struct Desugarer { } impl Desugarer { - pub fn new() -> Desugarer { Self { desugared: Set::default() } } + pub fn new() -> Desugarer { + Self { + desugared: Set::default(), + } + } pub fn desugar(&mut self, module: Module) -> Module { self.desugar_multiple_pattern_def(module) @@ -42,40 +45,66 @@ impl Desugarer { match chunk { Expr::Def(def) if def.is_subr() => { if let Some(Expr::Def(previous)) = new.last() { - if previous.is_subr() && previous.sig.name_as_str() == def.sig.name_as_str() { + if previous.is_subr() && previous.sig.name_as_str() == def.sig.name_as_str() + { let mut previous = enum_unwrap!(new.pop().unwrap(), Expr::Def); let name = def.sig.name().unwrap().clone(); let op = Token::from_str(TokenKind::FuncArrow, "->"); let (call, return_t_spec) = if previous.body.block.len() == 1 - && previous.body.block.first().unwrap().is_match_call() { - let mut call = enum_unwrap!(previous.body.block.remove(0), Expr::Call); + && previous.body.block.first().unwrap().is_match_call() + { + let mut call = + enum_unwrap!(previous.body.block.remove(0), Expr::Call); let sig = enum_unwrap!(def.sig, Signature::Subr); let return_t_spec = sig.return_t_spec; let first_arg = sig.params.non_defaults.first().unwrap(); // 最後の定義の引数名を関数全体の引数名にする if let Some(name) = first_arg.inspect() { call.args.remove_pos(0); - let arg = PosArg::new(Expr::local(name, first_arg.ln_begin().unwrap(), first_arg.col_begin().unwrap())); + let arg = PosArg::new(Expr::local( + name, + first_arg.ln_begin().unwrap(), + first_arg.col_begin().unwrap(), + )); call.args.insert_pos(0, arg); } - let sig = LambdaSignature::new(sig.params, return_t_spec.clone(), sig.bounds); + let sig = LambdaSignature::new( + sig.params, + return_t_spec.clone(), + sig.bounds, + ); let new_branch = Lambda::new(sig, op, def.body.block, def.body.id); call.args.push_pos(PosArg::new(Expr::Lambda(new_branch))); (call, return_t_spec) } else { let sig = enum_unwrap!(previous.sig, Signature::Subr); let match_symbol = Expr::static_local("match"); - let sig = LambdaSignature::new(sig.params, sig.return_t_spec, sig.bounds); - let first_branch = Lambda::new(sig, op.clone(), previous.body.block, previous.body.id); + let sig = + LambdaSignature::new(sig.params, sig.return_t_spec, sig.bounds); + let first_branch = Lambda::new( + sig, + op.clone(), + previous.body.block, + previous.body.id, + ); let sig = enum_unwrap!(def.sig, Signature::Subr); let return_t_spec = sig.return_t_spec; - let sig = LambdaSignature::new(sig.params, return_t_spec.clone(), sig.bounds); - let second_branch = Lambda::new(sig, op, def.body.block, def.body.id); - let args = Args::new(vec![ - PosArg::new(Expr::dummy_local("_")), // dummy argument, will be removed in line 56 - PosArg::new(Expr::Lambda(first_branch)), - PosArg::new(Expr::Lambda(second_branch)) - ], vec![], None); + let sig = LambdaSignature::new( + sig.params, + return_t_spec.clone(), + sig.bounds, + ); + let second_branch = + Lambda::new(sig, op, def.body.block, def.body.id); + let args = Args::new( + vec![ + PosArg::new(Expr::dummy_local("_")), // dummy argument, will be removed in line 56 + PosArg::new(Expr::Lambda(first_branch)), + PosArg::new(Expr::Lambda(second_branch)), + ], + vec![], + None, + ); let call = Call::new(match_symbol, args); (call, return_t_spec) }; @@ -85,12 +114,23 @@ impl Desugarer { TokenKind::Symbol, param_name, name.ln_begin().unwrap(), - name.col_end().unwrap() + 1 // HACK: `(name) %x = ...`という形を想定 + name.col_end().unwrap() + 1, // HACK: `(name) %x = ...`という形を想定 )); - let param = NonDefaultParamSignature::new(ParamPattern::VarName(param), None); + let param = + NonDefaultParamSignature::new(ParamPattern::VarName(param), None); let params = Params::new(vec![param], vec![], None); - let sig = Signature::Subr(SubrSignature::new(set!{}, name, params, return_t_spec, TypeBoundSpecs::empty())); - let body = DefBody::new(def.body.op, Block::new(vec![Expr::Call(call)]), def.body.id); + let sig = Signature::Subr(SubrSignature::new( + set! {}, + name, + params, + return_t_spec, + TypeBoundSpecs::empty(), + )); + let body = DefBody::new( + def.body.op, + Block::new(vec![Expr::Call(call)]), + def.body.id, + ); let def = Def::new(sig, body); new.push(Expr::Def(def)); } else { @@ -99,8 +139,10 @@ impl Desugarer { } else { new.push(Expr::Def(def)); } - }, - other => { new.push(other); }, + } + other => { + new.push(other); + } } } new @@ -123,13 +165,15 @@ impl Desugarer { if let Signature::Var(v) = &def.sig { match &v.pat { VarPattern::Array(_a) => {} - VarPattern::Record(_r) => {}, + VarPattern::Record(_r) => {} _ => {} } } new.push(Expr::Def(def)); - }, - other => { new.push(other); }, + } + other => { + new.push(other); + } } } new diff --git a/compiler/erg_parser/error.rs b/compiler/erg_parser/error.rs index 120a67f4..694beeb9 100644 --- a/compiler/erg_parser/error.rs +++ b/compiler/erg_parser/error.rs @@ -1,11 +1,11 @@ //! defines `ParseError` and others. //! //! パーサーが出すエラーを定義 -use erg_common::{impl_stream_for_wrapper, switch_lang}; -use erg_common::Str; use erg_common::config::Input; -use erg_common::error::{ErrorCore, ErrorDisplay, MultiErrorDisplay, Location, ErrorKind::*}; +use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay}; use erg_common::traits::Stream; +use erg_common::Str; +use erg_common::{impl_stream_for_wrapper, switch_lang}; #[derive(Debug)] pub struct LexError(ErrorCore); @@ -16,7 +16,9 @@ pub struct LexErrors(Vec); impl_stream_for_wrapper!(LexErrors, LexError); impl LexError { - pub const fn new(core: ErrorCore) -> Self { Self(core) } + pub const fn new(core: ErrorCore) -> Self { + Self(core) + } pub fn compiler_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self { Self::new(ErrorCore::new(errno, CompilerSystemError, loc, switch_lang!( @@ -26,21 +28,43 @@ impl LexError { } pub fn feature_error(errno: usize, loc: Location, name: &str) -> Self { - Self::new(ErrorCore::new(errno, FeatureError, loc, switch_lang!( - format!("this feature({name}) is not implemented yet"), - format!("この機能({name})はまだ正式に提供されていません") - ), None)) + Self::new(ErrorCore::new( + errno, + FeatureError, + loc, + switch_lang!( + format!("this feature({name}) is not implemented yet"), + format!("この機能({name})はまだ正式に提供されていません") + ), + None, + )) } pub fn simple_syntax_error(errno: usize, loc: Location) -> Self { - Self::new(ErrorCore::new(errno, SyntaxError, loc, switch_lang!("invalid syntax", "不正な構文です"), None)) + Self::new(ErrorCore::new( + errno, + SyntaxError, + loc, + switch_lang!("invalid syntax", "不正な構文です"), + None, + )) } - pub fn syntax_error>(errno: usize, loc: Location, desc: S, hint: Option) -> Self { + pub fn syntax_error>( + errno: usize, + loc: Location, + desc: S, + hint: Option, + ) -> Self { Self::new(ErrorCore::new(errno, SyntaxError, loc, desc, hint)) } - pub fn syntax_warning>(errno: usize,loc: Location, desc: S, hint: Option) -> Self { + pub fn syntax_warning>( + errno: usize, + loc: Location, + desc: S, + hint: Option, + ) -> Self { Self::new(ErrorCore::new(errno, SyntaxWarning, loc, desc, hint)) } } @@ -57,7 +81,9 @@ pub struct DesugaringError { } impl DesugaringError { - pub const fn new(core: ErrorCore) -> Self { Self{ core }} + pub const fn new(core: ErrorCore) -> Self { + Self { core } + } } #[derive(Debug)] @@ -74,14 +100,24 @@ pub struct ParserRunnerError { } impl ErrorDisplay for ParserRunnerError { - fn core(&self) -> &ErrorCore { &self.core } - fn input(&self) -> &Input { &self.input } - fn caused_by(&self) -> &str { "" } - fn ref_inner(&self) -> Option<&Box> { None } + fn core(&self) -> &ErrorCore { + &self.core + } + fn input(&self) -> &Input { + &self.input + } + fn caused_by(&self) -> &str { + "" + } + fn ref_inner(&self) -> Option<&Box> { + None + } } impl ParserRunnerError { - pub const fn new(core: ErrorCore, input: Input) -> Self { Self{ core, input } } + pub const fn new(core: ErrorCore, input: Input) -> Self { + Self { core, input } + } } #[derive(Debug)] @@ -93,7 +129,11 @@ impl MultiErrorDisplay for ParserRunnerErrors {} impl ParserRunnerErrors { pub fn convert(input: &Input, errs: ParseErrors) -> Self { - Self(errs.into_iter().map(|err| ParserRunnerError::new(err.0, input.clone())).collect()) + Self( + errs.into_iter() + .map(|err| ParserRunnerError::new(err.0, input.clone())) + .collect(), + ) } } diff --git a/compiler/erg_parser/lex.rs b/compiler/erg_parser/lex.rs index 70c12906..36818e02 100644 --- a/compiler/erg_parser/lex.rs +++ b/compiler/erg_parser/lex.rs @@ -1,12 +1,12 @@ //! defines and implements `Lexer` (Tokenizer). use erg_common::cache::Cache; -use erg_common::Str; -use erg_common::{fn_name_full, switch_lang, debug_power_assert, normalize_newline}; -use erg_common::config::Input; use erg_common::config::ErgConfig; +use erg_common::config::Input; use erg_common::traits::{Locational, Runnable, Stream}; +use erg_common::Str; +use erg_common::{debug_power_assert, fn_name_full, normalize_newline, switch_lang}; -use crate::error::{LexerRunnerError, LexerRunnerErrors, LexError, LexErrors, LexResult}; +use crate::error::{LexError, LexErrors, LexResult, LexerRunnerError, LexerRunnerErrors}; use crate::token::{Token, TokenCategory, TokenKind, TokenStream}; use TokenKind::*; @@ -20,13 +20,19 @@ impl Runnable for LexerRunner { type Errs = LexerRunnerErrors; #[inline] - fn new(cfg: ErgConfig) -> Self { Self { cfg } } + fn new(cfg: ErgConfig) -> Self { + Self { cfg } + } #[inline] - fn input(&self) -> &Input { &self.cfg.input } + fn input(&self) -> &Input { + &self.cfg.input + } #[inline] - fn start_message(&self) -> String { "Erg lexer\n".to_string() } + fn start_message(&self) -> String { + "Erg lexer\n".to_string() + } #[inline] fn finish(&mut self) {} @@ -37,11 +43,16 @@ impl Runnable for LexerRunner { fn eval(&mut self, src: Str) -> Result { let lexer = Lexer::from_str(src); if cfg!(feature = "debug") { - let ts = lexer.lex().map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?; + let ts = lexer + .lex() + .map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?; println!("{ts}"); Ok(ts.to_string()) } else { - Ok(lexer.lex().map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?.to_string()) + Ok(lexer + .lex() + .map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))? + .to_string()) } } } @@ -96,18 +107,29 @@ impl Lexer /*<'a>*/ { let mut errs = LexErrors::empty(); for i in self.into_iter() { match i { - Ok(token) => { result.push(token) } - Err(err) => { errs.push(err); } + Ok(token) => result.push(token), + Err(err) => { + errs.push(err); + } } } - if errs.is_empty() { Ok(result) } else { Err(errs) } + if errs.is_empty() { + Ok(result) + } else { + Err(errs) + } } fn emit_token(&mut self, kind: TokenKind, cont: &str) -> Token { let cont = self.str_cache.get(cont); // cannot use String::len() for multi-byte characters let cont_len = cont.chars().count(); - let token = Token::new(kind, cont, self.lineno_token_starts + 1, self.col_token_starts); + let token = Token::new( + kind, + cont, + self.lineno_token_starts + 1, + self.col_token_starts, + ); self.prev_token = token.clone(); self.col_token_starts += cont_len; token @@ -160,8 +182,7 @@ impl Lexer /*<'a>*/ { fn is_definable_operator(s: &str) -> bool { match s { "+" | "-" | "*" | "/" | "//" | "**" | "%" | ".." | "..=" | "~" | "&&" | "||" | "^^" - | ">>" | "<<" | "==" | "!=" | ">" | "<" | ">=" | "<=" - | "dot" | "cross" => true, + | ">>" | "<<" | "==" | "!=" | ">" | "<" | ">=" | "<=" | "dot" | "cross" => true, _ => false, } } @@ -187,7 +208,9 @@ impl Lexer /*<'a>*/ { } } - fn is_zero(s: &str) -> bool { s.replace("-0", "").replace("0", "").is_empty() } + fn is_zero(s: &str) -> bool { + s.replace("-0", "").replace("0", "").is_empty() + } /// emit_tokenで一気にcol_token_startsを移動させるのでここでは移動させない fn consume(&mut self) -> Option { @@ -220,10 +243,15 @@ impl Lexer /*<'a>*/ { while self.peek_cur_ch().map(|cur| cur != '\n').unwrap_or(false) { if Self::is_bidi(self.peek_cur_ch().unwrap()) { let comment = self.emit_token(Illegal, &s); - return Err(LexError::syntax_error(0, comment.loc(), switch_lang!( - "invalid unicode character (bi-directional override) in comments", - "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています" - ), None)) + return Err(LexError::syntax_error( + 0, + comment.loc(), + switch_lang!( + "invalid unicode character (bi-directional override) in comments", + "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています" + ), + None, + )); } s.push(self.consume().unwrap()); } @@ -239,7 +267,7 @@ impl Lexer /*<'a>*/ { let dedent = self.emit_token(Dedent, ""); self.indent_stack.pop(); self.col_token_starts = 0; - return Some(Ok(dedent)) + return Some(Ok(dedent)); } let mut spaces = "".to_string(); while let Some(' ') = self.peek_cur_ch() { @@ -248,10 +276,12 @@ impl Lexer /*<'a>*/ { // indent in the first line: error if !spaces.is_empty() && self.cursor == 0 { let space = self.emit_token(Illegal, &spaces); - Some(Err(LexError::syntax_error(0, space.loc(), switch_lang!( - "invalid indent", - "インデントが不正です" - ), None))) + Some(Err(LexError::syntax_error( + 0, + space.loc(), + switch_lang!("invalid indent", "インデントが不正です"), + None, + ))) } else if self.prev_token.is(Newline) { self.lex_indent_dedent(spaces) } else { @@ -265,21 +295,30 @@ impl Lexer /*<'a>*/ { // same as the CPython's limit if spaces.len() > 100 { let token = self.emit_token(Indent, &spaces); - return Some(Err(LexError::syntax_error(0, token.loc(), switch_lang!( - "indentation is too deep", - "インデントが深すぎます" - ), Some(switch_lang!( - "The code is too complicated. Please split the process.", - "コードが複雑すぎます。処理を分割してください" - ).into())))) + return Some(Err(LexError::syntax_error( + 0, + token.loc(), + switch_lang!("indentation is too deep", "インデントが深すぎます"), + Some( + switch_lang!( + "The code is too complicated. Please split the process.", + "コードが複雑すぎます。処理を分割してください" + ) + .into(), + ), + ))); } // ignore indents if the current line is a comment if let Some('#') = self.peek_cur_ch() { - if let Err(e) = self.lex_comment() { return Some(Err(e)) } + if let Err(e) = self.lex_comment() { + return Some(Err(e)); + } } let mut is_valid_dedent = false; let calc_indent_and_validate = |sum: usize, x: &usize| { - if sum + *x == spaces.len() { is_valid_dedent = true; } + if sum + *x == spaces.len() { + is_valid_dedent = true; + } sum + *x }; let sum_indent = self.indent_stack.iter().fold(0, calc_indent_and_validate); @@ -296,12 +335,16 @@ impl Lexer /*<'a>*/ { 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))) + Some(Err(LexError::syntax_error( + 0, + invalid_dedent.loc(), + switch_lang!("invalid indent", "インデントが不正です"), + None, + ))) } - } else /* if indent_sum == space.len() */ { + } else + /* if indent_sum == space.len() */ + { self.col_token_starts += spaces.len(); None } @@ -328,19 +371,20 @@ impl Lexer /*<'a>*/ { while let Some(ch) = self.peek_cur_ch() { match ch { // `.` may be a dot operator, don't consume - '.' => { return self.lex_num_dot(num) }, + '.' => return self.lex_num_dot(num), n if n.is_ascii_digit() || n == '_' => { num.push(self.consume().unwrap()); } c if Self::is_valid_symbol_ch(c) => { // exponent (e.g. 10e+3) if c == 'e' - && (self.peek_next_ch() == Some('+') || self.peek_next_ch() == Some('-')) { - return self.lex_exponent(num) + && (self.peek_next_ch() == Some('+') || self.peek_next_ch() == Some('-')) + { + return self.lex_exponent(num); } else { // IntLit * Symbol(e.g. 3x + 1) let token = self.emit_token(Illegal, &(num + &c.to_string())); - return Err(LexError::feature_error(0, token.loc(), "*-less multiply")) + return Err(LexError::feature_error(0, token.loc(), "*-less multiply")); } } _ => { @@ -348,7 +392,11 @@ impl Lexer /*<'a>*/ { } } } - let kind = if num.starts_with('-') && !Self::is_zero(&num) { IntLit } else { NatLit }; + let kind = if num.starts_with('-') && !Self::is_zero(&num) { + IntLit + } else { + NatLit + }; Ok(self.emit_token(kind, &num)) } @@ -364,10 +412,14 @@ impl Lexer /*<'a>*/ { // method call of IntLit // or range operator (e.g. 1..) Some(c) if Self::is_valid_symbol_ch(c) || c == '.' => { - let kind = if num.starts_with('-') && !Self::is_zero(&num) { IntLit } else { NatLit }; + let kind = if num.starts_with('-') && !Self::is_zero(&num) { + IntLit + } else { + NatLit + }; Ok(self.emit_token(kind, &num)) - }, - Some('_') => { + } + Some('_') => { self.consume(); let token = self.emit_token(Illegal, &(num + "_")); Err(LexError::simple_syntax_error(0, token.loc())) @@ -387,7 +439,7 @@ impl Lexer /*<'a>*/ { if cur.is_ascii_digit() || cur == '_' { num.push(self.consume().unwrap()); } else if cur == 'e' { - return self.lex_exponent(num) + return self.lex_exponent(num); } else { break; } @@ -409,7 +461,12 @@ impl Lexer /*<'a>*/ { } if cont.is_empty() { let token = self.emit_token(Illegal, &self.peek_cur_ch().unwrap().to_string()); - return Err(LexError::compiler_bug(0, token.loc(), fn_name_full!(), line!())) + return Err(LexError::compiler_bug( + 0, + token.loc(), + fn_name_full!(), + line!(), + )); } // dot: scalar product, cross: vector product // An alphabetical operator can also declare as a function, so checking is necessary @@ -441,24 +498,34 @@ impl Lexer /*<'a>*/ { if c == '\"' && s.chars().last() != Some('\\') { s.push(self.consume().unwrap()); let token = self.emit_token(StrLit, &s); - return Ok(token) + return Ok(token); } else { let c = self.consume().unwrap(); s.push(c); if Self::is_bidi(c) { let token = self.emit_token(Illegal, &s); - return Err(LexError::syntax_error(0, token.loc(), switch_lang!( + return Err(LexError::syntax_error( + 0, + token.loc(), + switch_lang!( "invalid unicode character (bi-directional override) in string literal", "不正なユニコード文字(双方向オーバーライド)が文字列中に使用されています" - ), None)) + ), + None, + )); } } } let token = self.emit_token(Illegal, &s); - Err(LexError::syntax_error(0, token.loc(), switch_lang!( - "the string is not closed by \"", - "文字列が\"によって閉じられていません" - ), None)) + Err(LexError::syntax_error( + 0, + token.loc(), + switch_lang!( + "the string is not closed by \"", + "文字列が\"によって閉じられていません" + ), + None, + )) } } @@ -467,14 +534,16 @@ impl Iterator for Lexer /*<'a>*/ { fn next(&mut self) -> Option { if self.prev_token.is(TokenKind::EOF) { - return None + return None; } let indent_dedent = self.lex_space_indent_dedent(); if indent_dedent.is_some() { - return indent_dedent + return indent_dedent; } if let Some('#') = self.peek_cur_ch() { - if let Err(e) = self.lex_comment() { return Some(Err(e)) } + if let Err(e) = self.lex_comment() { + return Some(Err(e)); + } } match self.consume() { Some('(') => self.accept(LParen, "("), @@ -497,10 +566,12 @@ impl Iterator for Lexer /*<'a>*/ { } } else { let token = self.emit_token(Illegal, "<."); - Some(Err(LexError::syntax_error(0, token.loc(), switch_lang!( - "no such operator: <.", - "<.という演算子はありません" - ), None))) + Some(Err(LexError::syntax_error( + 0, + token.loc(), + switch_lang!("no such operator: <.", "<.という演算子はありません"), + None, + ))) } } Some('=') => { @@ -524,30 +595,24 @@ impl Iterator for Lexer /*<'a>*/ { } _ => self.accept(Gre, ">"), }, - Some('.') => { - match self.peek_cur_ch() { - Some('.') => { - self.consume(); - match self.peek_cur_ch() { - Some('<') => { - self.consume(); - self.accept(RightOpen, "..<") - }, - Some('.') => { - self.consume(); - self.accept(EllipsisLit, "...") - }, - _ => { - self.accept(Closed, "..") - } + Some('.') => match self.peek_cur_ch() { + Some('.') => { + self.consume(); + match self.peek_cur_ch() { + Some('<') => { + self.consume(); + self.accept(RightOpen, "..<") } + Some('.') => { + self.consume(); + self.accept(EllipsisLit, "...") + } + _ => self.accept(Closed, ".."), } - Some(c) if c.is_ascii_digit() => { - Some(self.lex_ratio(".".into())) - } - _ => self.accept(Dot, ".") } - } + Some(c) if c.is_ascii_digit() => Some(self.lex_ratio(".".into())), + _ => self.accept(Dot, "."), + }, Some(',') => self.accept(Comma, ","), Some(':') => match self.peek_cur_ch() { Some(':') => { @@ -570,21 +635,17 @@ impl Iterator for Lexer /*<'a>*/ { self.accept(Amper, "&") } } - Some('|') => { - match self.peek_cur_ch() { - Some('|') => { - self.consume(); - self.accept(BitOr, "||") - } - Some('=') => { - self.consume(); - self.accept(OrEqual, "|=") - } - _ => { - self.accept(VBar, "|") - } + Some('|') => match self.peek_cur_ch() { + Some('|') => { + self.consume(); + self.accept(BitOr, "||") } - } + Some('=') => { + self.consume(); + self.accept(OrEqual, "|=") + } + _ => self.accept(VBar, "|"), + }, Some('^') => { if let Some('^') = self.peek_cur_ch() { self.consume(); @@ -596,7 +657,7 @@ impl Iterator for Lexer /*<'a>*/ { Some('~') => self.accept(PreBitNot, "~"), // TODO: Some('$') => self.deny_feature("$", "shared variables"), - Some('@') => self.accept(AtSign, "@"), + Some('@') => self.accept(AtSign, "@"), Some('=') => match self.peek_cur_ch() { Some('=') => { self.consume(); @@ -635,7 +696,11 @@ impl Iterator for Lexer /*<'a>*/ { self.accept(Minus, "-") } else { // IntLit (negative number) - if self.peek_cur_ch().map(|t| t.is_ascii_digit()).unwrap_or(false) { + if self + .peek_cur_ch() + .map(|t| t.is_ascii_digit()) + .unwrap_or(false) + { Some(self.lex_num('-')) } else { self.accept(Minus, "-") @@ -675,10 +740,12 @@ impl Iterator for Lexer /*<'a>*/ { } Some('\t') => { let token = self.emit_token(Illegal, "\t"); - Some(Err(LexError::syntax_error(0, token.loc(), switch_lang!( - "cannot use a tab as a space", - "タブ文字は使用できません" - ), Some(switch_lang!("use spaces", "スペースを使用してください").into())))) + Some(Err(LexError::syntax_error( + 0, + token.loc(), + switch_lang!("cannot use a tab as a space", "タブ文字は使用できません"), + Some(switch_lang!("use spaces", "スペースを使用してください").into()), + ))) } // TODO: Some('\\') => self.deny_feature("\\", "ignoring line break"), @@ -693,22 +760,32 @@ impl Iterator for Lexer /*<'a>*/ { while let Some(c) = self.consume() { if c == '`' { if Self::is_definable_operator(&op[..]) { - return self.accept(Symbol, &op) + return self.accept(Symbol, &op); } else { let token = self.emit_token(Illegal, &op); - return Some(Err(LexError::syntax_error(0, token.loc(), switch_lang!( - format!("`{}` cannot be defined by user", &token.content), - format!("`{}`はユーザー定義できません", &token.content) - ), None))) + return Some(Err(LexError::syntax_error( + 0, + token.loc(), + switch_lang!( + format!("`{}` cannot be defined by user", &token.content), + format!("`{}`はユーザー定義できません", &token.content) + ), + None, + ))); } } op.push(c); } let token = self.emit_token(Illegal, &op); - Some(Err(LexError::syntax_error(0, token.loc(), switch_lang!( - format!("back quotes (`) not closed"), - format!("バッククォート(`)が閉じられていません") - ), None))) + Some(Err(LexError::syntax_error( + 0, + token.loc(), + switch_lang!( + format!("back quotes (`) not closed"), + format!("バッククォート(`)が閉じられていません") + ), + None, + ))) } // IntLit or RatioLit Some(n) if n.is_ascii_digit() => Some(self.lex_num(n)), @@ -717,10 +794,15 @@ impl Iterator for Lexer /*<'a>*/ { // Invalid character (e.g. space-like character) Some(invalid) => { let token = self.emit_token(Illegal, &invalid.to_string()); - Some(Err(LexError::syntax_error(0, token.loc(), switch_lang!( - format!("invalid character: '{invalid}'"), - format!("この文字は使用できません: '{invalid}'") - ), None))) + Some(Err(LexError::syntax_error( + 0, + token.loc(), + switch_lang!( + format!("invalid character: '{invalid}'"), + format!("この文字は使用できません: '{invalid}'") + ), + None, + ))) } None => { if self.indent_stack.len() == 0 { diff --git a/compiler/erg_parser/lib.rs b/compiler/erg_parser/lib.rs index a666f748..bb437b75 100644 --- a/compiler/erg_parser/lib.rs +++ b/compiler/erg_parser/lib.rs @@ -2,9 +2,9 @@ //! and performs type checking and other optimizations if necessary. extern crate erg_common; +pub mod ast; pub mod desugar; pub mod error; -pub mod ast; pub mod lex; pub mod parse; pub mod token; diff --git a/compiler/erg_parser/main.rs b/compiler/erg_parser/main.rs index ada8c198..f214e2b3 100644 --- a/compiler/erg_parser/main.rs +++ b/compiler/erg_parser/main.rs @@ -12,8 +12,12 @@ use erg_parser::ParserRunner; fn main() { let cfg = ErgConfig::parse(); match cfg.mode { - "lex" => { LexerRunner::run(cfg); } - "parse" | "exec" => { ParserRunner::run(cfg); } + "lex" => { + LexerRunner::run(cfg); + } + "parse" | "exec" => { + ParserRunner::run(cfg); + } other => { println!("invalid mode: {other}"); process::exit(1); diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 4bb2077a..364fb947 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -5,21 +5,23 @@ use std::fmt::Debug; use std::mem; -use erg_common::Str; -use erg_common::{debug_power_assert, enum_unwrap, fn_name, caused_by, switch_lang, switch_unreachable, log, set}; use erg_common::color::{GREEN, RED, RESET}; -use erg_common::config::{Input, SEMVER, BUILD_INFO}; use erg_common::config::ErgConfig; -use erg_common::error::{Location}; +use erg_common::config::{Input, BUILD_INFO, SEMVER}; +use erg_common::error::Location; use erg_common::set::Set; use erg_common::traits::Runnable; use erg_common::traits::{Locational, Stream}; +use erg_common::Str; +use erg_common::{ + caused_by, debug_power_assert, enum_unwrap, fn_name, log, set, switch_lang, switch_unreachable, +}; -use crate::error::{ParseError, ParseErrors, ParseResult, ParserRunnerError, ParserRunnerErrors}; use crate::ast::*; -use crate::lex::Lexer; -use crate::token::{TokenCategory, TokenKind, TokenStream, Token}; use crate::desugar::Desugarer; +use crate::error::{ParseError, ParseErrors, ParseResult, ParserRunnerError, ParserRunnerErrors}; +use crate::lex::Lexer; +use crate::token::{Token, TokenCategory, TokenKind, TokenStream}; use TokenCategory as TC; use TokenKind::*; @@ -29,7 +31,11 @@ use TokenKind::*; /// So it is not possible to lower the level macro_rules! debug_call_info { ($self: ident) => { - log!("[DEBUG] entered {}, cur: {}", fn_name!(), $self.peek().unwrap()); + log!( + "[DEBUG] entered {}, cur: {}", + fn_name!(), + $self.peek().unwrap() + ); }; } @@ -65,20 +71,33 @@ pub struct Parser { impl Parser { const fn new(ts: TokenStream) -> Self { - Self { counter: DefId(0), tokens: ts, warns: ParseErrors::empty(), errs: ParseErrors::empty() } + Self { + counter: DefId(0), + tokens: ts, + warns: ParseErrors::empty(), + errs: ParseErrors::empty(), + } } #[inline] - fn peek(&self) -> Option<&Token> { self.tokens.get(0) } + fn peek(&self) -> Option<&Token> { + self.tokens.get(0) + } #[inline] - fn nth(&self, idx: usize) -> Option<&Token> { self.tokens.get(idx) } + fn nth(&self, idx: usize) -> Option<&Token> { + self.tokens.get(idx) + } #[inline] - fn skip(&mut self) { self.tokens.remove(0); } + fn skip(&mut self) { + self.tokens.remove(0); + } #[inline] - fn lpop(&mut self) -> Token { self.tokens.remove(0) } + fn lpop(&mut self) -> Token { + self.tokens.remove(0) + } fn cur_category_is(&self, category: TokenCategory) -> bool { self.peek() @@ -87,15 +106,11 @@ impl Parser { } fn cur_is(&self, kind: TokenKind) -> bool { - self.peek() - .map(|t| t.is(kind)) - .unwrap_or(false) + self.peek().map(|t| t.is(kind)).unwrap_or(false) } fn nth_is(&self, idx: usize, kind: TokenKind) -> bool { - self.nth(idx) - .map(|t| t.is(kind)) - .unwrap_or(false) + self.nth(idx).map(|t| t.is(kind)).unwrap_or(false) } fn nth_category(&self, idx: usize) -> Option { @@ -124,20 +139,29 @@ impl Parser { /// `(Rhs) (LhsLambda) -> (Rhs);` fn cur_side(&self) -> Side { // 以降に=, ->などがないならすべて右辺値 - let opt_equal_pos = self.tokens.iter().skip(1) - .position(|t| t.is(Equal)); - let opt_arrow_pos = self.tokens.iter().skip(1) + let opt_equal_pos = self.tokens.iter().skip(1).position(|t| t.is(Equal)); + let opt_arrow_pos = self + .tokens + .iter() + .skip(1) .position(|t| t.category_is(TC::LambdaOp)); - let opt_sep_pos = self.tokens.iter().skip(1) + let opt_sep_pos = self + .tokens + .iter() + .skip(1) .position(|t| t.category_is(TC::Separator)); match (opt_equal_pos, opt_arrow_pos, opt_sep_pos) { (Some(equal), Some(arrow), Some(sep)) => { let min = [equal, arrow, sep].into_iter().min().unwrap(); - if min == sep { Side::Rhs } - else if min == equal { Side::LhsAssign } - else { + if min == sep { + Side::Rhs + } else if min == equal { + Side::LhsAssign + } else { // (cur) -> ... = ... ; - if equal < sep { Side::LhsAssign } + if equal < sep { + Side::LhsAssign + } // (cur) -> ... ; ... = else { if self.arrow_distance(0, 0) == 1 { @@ -153,21 +177,35 @@ impl Parser { (Some(_eq), Some(_arrow), None) => Side::LhsAssign, // (cur) = ... ; // (cur) ; ... = - (Some(equal), None, Some(sep)) => - if equal < sep { Side::LhsAssign } else { Side::Rhs }, + (Some(equal), None, Some(sep)) => { + if equal < sep { + Side::LhsAssign + } else { + Side::Rhs + } + } (None, Some(arrow), Some(sep)) => { // (cur) -> ... ; if arrow < sep { - if self.arrow_distance(0, 0) == 1 { Side::LhsLambda } - else { Side::Rhs } + if self.arrow_distance(0, 0) == 1 { + Side::LhsLambda + } else { + Side::Rhs + } } // (cur) ; ... -> - else { Side::Rhs } + else { + Side::Rhs + } } (Some(_eq), None, None) => Side::LhsAssign, - (None, Some(_arrow), None) => - if self.arrow_distance(0, 0) == 1 { Side::LhsLambda } - else { Side::Rhs }, + (None, Some(_arrow), None) => { + if self.arrow_distance(0, 0) == 1 { + Side::LhsLambda + } else { + Side::Rhs + } + } (None, None, Some(_)) | (None, None, None) => Side::Rhs, } } @@ -184,28 +222,20 @@ impl Parser { match self.nth_category(cur).unwrap() { TC::LambdaOp => 0, TC::LEnclosure => { - if self.nth_category(cur+1).unwrap() == TC::REnclosure { - 1 + self.arrow_distance(cur+2, enc_nest_level) + if self.nth_category(cur + 1).unwrap() == TC::REnclosure { + 1 + self.arrow_distance(cur + 2, enc_nest_level) } else { - self.arrow_distance(cur+1, enc_nest_level+1) + self.arrow_distance(cur + 1, enc_nest_level + 1) } - }, - TC::REnclosure => { - self.arrow_distance(cur+1, enc_nest_level-1) } - _ => { - match self.nth_category(cur+1).unwrap() { - TC::SpecialBinOp => self.arrow_distance(cur+1, enc_nest_level), - TC::LEnclosure if self.cur_is_in_contact_with_next() => { - self.arrow_distance(cur+2, enc_nest_level+1) - }, - _ if enc_nest_level == 0 => { - 1 + self.arrow_distance(cur+1, enc_nest_level) - }, - _ => { - self.arrow_distance(cur+1, enc_nest_level) - }, + TC::REnclosure => self.arrow_distance(cur + 1, enc_nest_level - 1), + _ => match self.nth_category(cur + 1).unwrap() { + TC::SpecialBinOp => self.arrow_distance(cur + 1, enc_nest_level), + TC::LEnclosure if self.cur_is_in_contact_with_next() => { + self.arrow_distance(cur + 2, enc_nest_level + 1) } + _ if enc_nest_level == 0 => 1 + self.arrow_distance(cur + 1, enc_nest_level), + _ => self.arrow_distance(cur + 1, enc_nest_level), }, } } @@ -218,8 +248,12 @@ impl Parser { self.skip(); return; } - TC::EOF => { return; } - _ => { self.skip(); } + TC::EOF => { + return; + } + _ => { + self.skip(); + } } } } @@ -232,7 +266,9 @@ impl Parser { } #[inline] - fn restore(&mut self, token: Token) { self.tokens.insert(0, token); } + fn restore(&mut self, token: Token) { + self.tokens.insert(0, token); + } } #[derive(Debug)] @@ -245,13 +281,19 @@ impl Runnable for ParserRunner { type Errs = ParserRunnerErrors; #[inline] - fn new(cfg: ErgConfig) -> Self { Self { cfg } } + fn new(cfg: ErgConfig) -> Self { + Self { cfg } + } #[inline] - fn input(&self) -> &Input { &self.cfg.input } + fn input(&self) -> &Input { + &self.cfg.input + } #[inline] - fn start_message(&self) -> String { format!("Erg parser {} {}\n", SEMVER, &*BUILD_INFO) } + fn start_message(&self) -> String { + format!("Erg parser {} {}\n", SEMVER, &*BUILD_INFO) + } #[inline] fn finish(&mut self) {} @@ -267,12 +309,14 @@ impl Runnable for ParserRunner { impl ParserRunner { pub fn parse(&mut self, ts: TokenStream) -> Result { - Parser::new(ts).parse(Str::ever(self.cfg.module)) + Parser::new(ts) + .parse(Str::ever(self.cfg.module)) .map_err(|errs| ParserRunnerErrors::convert(self.input(), errs)) } pub fn parse_from_str(&mut self, src: Str) -> Result { - let ts = Lexer::from_str(src).lex() + let ts = Lexer::from_str(src) + .lex() .map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?; self.parse(ts) } @@ -280,20 +324,23 @@ impl ParserRunner { impl Parser { pub fn parse(&mut self, mod_name: Str) -> Result { - if self.tokens.is_empty() { return Ok(AST::new(mod_name, Module::empty())) } + if self.tokens.is_empty() { + return Ok(AST::new(mod_name, Module::empty())); + } log!("{GREEN}[DEBUG] the parsing process has started."); log!("token stream: {}", self.tokens); let module = match self.try_reduce_module() { Ok(module) => module, Err(e) => { self.errs.push(e); - return Err(mem::take(&mut self.errs)) - }, + return Err(mem::take(&mut self.errs)); + } }; if !self.cur_is(EOF) { let loc = self.peek().unwrap().loc(); - self.errs.push(ParseError::compiler_bug(0, loc, fn_name!(), line!())); - return Err(mem::take(&mut self.errs)) + self.errs + .push(ParseError::compiler_bug(0, loc, fn_name!(), line!())); + return Err(mem::take(&mut self.errs)); } log!("[DEBUG] the parsing process has completed."); log!("AST:\n{module}"); @@ -317,18 +364,24 @@ impl Parser { let mut chunks = Module::empty(); loop { match self.peek() { - Some(t) if t.category_is(TC::Separator) => { self.skip(); } - Some(t) if t.is(EOF) => { break; } + Some(t) if t.category_is(TC::Separator) => { + self.skip(); + } + Some(t) if t.is(EOF) => { + break; + } Some(t) if t.is(Indent) || t.is(Dedent) => { switch_unreachable!() } - Some(_) => { - match self.try_reduce_expr() { - Ok(expr) => { chunks.push(expr); } - Err(e) => { self.errs.push(e); } + Some(_) => match self.try_reduce_expr() { + Ok(expr) => { + chunks.push(expr); } - } - _ => switch_unreachable!() + Err(e) => { + self.errs.push(e); + } + }, + _ => switch_unreachable!(), } } Ok(chunks) @@ -340,11 +393,13 @@ impl Parser { // single line block if !self.cur_is(Newline) { block.push(self.try_reduce_expr()?); - return Ok(block) + return Ok(block); } loop { match self.peek() { - Some(t) if t.category_is(TC::Separator) => { self.skip(); } + Some(t) if t.category_is(TC::Separator) => { + self.skip(); + } Some(t) => { if t.is(Indent) { self.skip(); @@ -354,7 +409,9 @@ impl Parser { } else if self.cur_is(Dedent) { self.skip(); break; - } else if t.is(EOF) { break; } + } else if t.is(EOF) { + break; + } match self.try_reduce_expr() { Ok(expr) => { block.push(expr); @@ -363,18 +420,26 @@ impl Parser { break; } } - Err(e) => { self.errs.push(e); } + Err(e) => { + self.errs.push(e); + } } } - _ => switch_unreachable!() + _ => switch_unreachable!(), } } if block.is_empty() { - let loc = if let Some(u) = self.peek() { u.loc() } else { Location::Unknown }; - let err = ParseError::syntax_error(0, loc, switch_lang!( - "failed to parse a block", - "ブロックの解析に失敗しました" - ), None); + let loc = if let Some(u) = self.peek() { + u.loc() + } else { + Location::Unknown + }; + let err = ParseError::syntax_error( + 0, + loc, + switch_lang!("failed to parse a block", "ブロックの解析に失敗しました"), + None, + ); Err(err) } else { Ok(block) @@ -386,7 +451,9 @@ impl Parser { if self.cur_is(TokenKind::AtSign) { self.lpop(); Ok(Some(Decorator::new(self.try_reduce_expr()?))) - } else { Ok(None) } + } else { + Ok(None) + } } #[inline] @@ -394,8 +461,12 @@ impl Parser { let mut decs = set![]; loop { match self.opt_reduce_decorator()? { - Some(deco) => { decs.insert(deco); } - None => { break; } + Some(deco) => { + decs.insert(deco); + } + None => { + break; + } } } Ok(decs) @@ -405,7 +476,7 @@ impl Parser { fn try_reduce_decl(&mut self) -> ParseResult { debug_call_info!(self); if self.peek().unwrap().category_is(TC::LEnclosure) { - return Ok(Signature::Var(self.try_reduce_var_sig()?)) + return Ok(Signature::Var(self.try_reduce_var_sig()?)); } let decorators = self.opt_reduce_decorators()?; let name = self.try_reduce_name()?; @@ -418,16 +489,25 @@ impl Parser { let t_spec = if self.cur_is(Colon) { self.skip(); Some(self.try_reduce_type_spec()?) - } else { None }; - Ok(Signature::Subr(SubrSignature::new(decorators, name, params, t_spec, bounds))) + } else { + None + }; + Ok(Signature::Subr(SubrSignature::new( + decorators, name, params, t_spec, bounds, + ))) } else { if !bounds.is_empty() { - let err = ParseError::syntax_error(0, self.peek().unwrap().loc(), switch_lang!( - "Cannot use type bounds in a declaration of a variable", - "変数宣言で型制約は使えません" - ), None); + let err = ParseError::syntax_error( + 0, + self.peek().unwrap().loc(), + switch_lang!( + "Cannot use type bounds in a declaration of a variable", + "変数宣言で型制約は使えません" + ), + None, + ); self.next_expr(); - return Err(err) + return Err(err); } let t_spec = if name.is_const() { if self.cur_is(SubtypeOf) { @@ -450,9 +530,14 @@ impl Parser { if self.cur_is(Colon) { self.skip(); Some(self.try_reduce_type_spec()?) - } else { None } + } else { + None + } }; - Ok(Signature::Var(VarSignature::new(VarPattern::VarName(name), t_spec))) + Ok(Signature::Var(VarSignature::new( + VarPattern::VarName(name), + t_spec, + ))) } } @@ -463,7 +548,9 @@ impl Parser { let t_spec = if self.cur_is(Colon) { self.skip(); Some(self.try_reduce_type_spec()?) - } else { None }; + } else { + None + }; if self.cur_is(VBar) { todo!() } @@ -477,7 +564,9 @@ impl Parser { if self.cur_is(OrEqual) { self.skip(); let val = self.try_reduce_const_expr()?; - Ok(ParamSig::Default(DefaultParamSignature::new(lhs.pat, lhs.t_spec, val))) + Ok(ParamSig::Default(DefaultParamSignature::new( + lhs.pat, lhs.t_spec, val, + ))) } else { Ok(ParamSig::NonDefault(lhs)) } @@ -490,7 +579,9 @@ impl Parser { let t_spec = if self.cur_is(Colon) { self.skip(); Some(self.try_reduce_type_spec()?) - } else { None }; + } else { + None + }; Ok(NonDefaultParamSignature::new(pat, t_spec)) } @@ -503,7 +594,12 @@ impl Parser { let val = self.try_reduce_const_expr()?; Ok(DefaultParamSignature::new(lhs.pat, lhs.t_spec, val)) } else { - Err(ParseError::syntax_error(0, lhs.loc(), "non-default argument follows default argument", None)) + Err(ParseError::syntax_error( + 0, + lhs.loc(), + "non-default argument follows default argument", + None, + )) } } @@ -532,13 +628,9 @@ impl Parser { fn try_reduce_acc(&mut self) -> ParseResult { debug_call_info!(self); let mut acc = match self.peek() { - Some(t) if t.is(Symbol) => { - Accessor::local(self.lpop()) - } + Some(t) if t.is(Symbol) => Accessor::local(self.lpop()), // TODO: SelfDot - _ => { - return Err(self.skip_and_throw_syntax_err(caused_by!())) - } + _ => return Err(self.skip_and_throw_syntax_err(caused_by!())), }; loop { match self.peek() { @@ -552,17 +644,22 @@ impl Parser { Some(t) if t.is(LSqBr) => { self.skip(); let index = self.try_reduce_expr()?; - if self.cur_is(RSqBr) { self.skip(); } - else { return Err(self.skip_and_throw_syntax_err(caused_by!())) } + if self.cur_is(RSqBr) { + self.skip(); + } else { + return Err(self.skip_and_throw_syntax_err(caused_by!())); + } acc = Accessor::subscr(Expr::Accessor(acc), index); if self.cur_is(RSqBr) { self.lpop(); } else { // TODO: error report: RSqBr not found - return Err(self.skip_and_throw_syntax_err(caused_by!())) + return Err(self.skip_and_throw_syntax_err(caused_by!())); } } - _ => { break; } + _ => { + break; + } } } Ok(acc) @@ -572,16 +669,12 @@ impl Parser { debug_call_info!(self); let mut elems = Vars::empty(); match self.peek() { - Some(t) if t.is_block_op() => { - return Ok(Vars::empty()) - } + Some(t) if t.is_block_op() => return Ok(Vars::empty()), Some(_) => { let elem = self.try_reduce_var_sig()?; elems.push(elem); } - _ => { - return Err(self.skip_and_throw_syntax_err(caused_by!())) - } + _ => return Err(self.skip_and_throw_syntax_err(caused_by!())), } loop { match self.peek() { @@ -592,14 +685,21 @@ impl Parser { } Some(t) if t.category_is(TC::BinOp) => { log!("[DEBUG] error caused by: {}", fn_name!()); - let err = ParseError::syntax_error(0, t.loc(), switch_lang!( - "Binary operators cannot be used in left-values", - "左辺値の中で中置演算子は使えません" - ), None); + let err = ParseError::syntax_error( + 0, + t.loc(), + switch_lang!( + "Binary operators cannot be used in left-values", + "左辺値の中で中置演算子は使えません" + ), + None, + ); self.next_expr(); - return Err(err) + return Err(err); + } + _ => { + break; } - _ => { break; } } } Ok(elems) @@ -608,10 +708,16 @@ impl Parser { fn opt_reduce_params(&mut self) -> Option> { debug_call_info!(self); match self.peek() { - Some(t) if - t.category_is(TC::Literal) || t.is(Symbol) - || t.category_is(TC::UnaryOp) || t.is(Dot) || t.category_is(TC::Caret) - || t.is(LParen) || t.is(LSqBr) || t.is(LBrace) => { + Some(t) + if t.category_is(TC::Literal) + || t.is(Symbol) + || t.category_is(TC::UnaryOp) + || t.is(Dot) + || t.category_is(TC::Caret) + || t.is(LParen) + || t.is(LSqBr) + || t.is(LBrace) => + { Some(self.try_reduce_params()) } _ => None, @@ -622,32 +728,38 @@ impl Parser { debug_call_info!(self); let lp = if self.cur_is(TokenKind::LParen) { Some(self.lpop()) - } else { None }; + } else { + None + }; let mut non_default_params = vec![]; let mut default_params = vec![]; match self.peek() { Some(t) if t.is(RParen) => { let parens = (lp.unwrap(), self.lpop()); - return Ok(Params::new(non_default_params, default_params, Some(parens))) - }, - Some(t) if t.is_block_op() => { - if lp.is_none() { return Ok(Params::new(non_default_params, default_params, None)) } - // TODO: RParen not found - else { return Err(self.skip_and_throw_syntax_err(caused_by!())) } + return Ok(Params::new( + non_default_params, + default_params, + Some(parens), + )); } - Some(_) => { - match self.try_reduce_param_sig()? { - ParamSig::NonDefault(non_default) => { - non_default_params.push(non_default); - } - ParamSig::Default(default) => { - default_params.push(default); - } + Some(t) if t.is_block_op() => { + if lp.is_none() { + return Ok(Params::new(non_default_params, default_params, None)); + } + // TODO: RParen not found + else { + return Err(self.skip_and_throw_syntax_err(caused_by!())); } } - _ => { - return Err(self.skip_and_throw_syntax_err(caused_by!())) - } + Some(_) => match self.try_reduce_param_sig()? { + ParamSig::NonDefault(non_default) => { + non_default_params.push(non_default); + } + ParamSig::Default(default) => { + default_params.push(default); + } + }, + _ => return Err(self.skip_and_throw_syntax_err(caused_by!())), } loop { match self.peek() { @@ -668,20 +780,29 @@ impl Parser { } } Some(t) if t.category_is(TC::BinOp) => { - let err = ParseError::syntax_error(0, t.loc(), switch_lang!( - "Binary operators cannot be used in parameters", - "仮引数の中で中置演算子は使えません" - ), None); + let err = ParseError::syntax_error( + 0, + t.loc(), + switch_lang!( + "Binary operators cannot be used in parameters", + "仮引数の中で中置演算子は使えません" + ), + None, + ); self.next_expr(); - return Err(err) + return Err(err); } Some(t) if t.is(TokenKind::RParen) => { let rp = self.lpop(); if let Some(lp) = lp { - return Ok(Params::new(non_default_params, default_params, Some((lp, rp)))) + return Ok(Params::new( + non_default_params, + default_params, + Some((lp, rp)), + )); } else { // LParen not found - return Err(self.skip_and_throw_syntax_err(caused_by!())) + return Err(self.skip_and_throw_syntax_err(caused_by!())); } } _ if lp.is_none() => { @@ -689,7 +810,7 @@ impl Parser { } _ => { // TODO: RParen not found - return Err(self.skip_and_throw_syntax_err(caused_by!())) + return Err(self.skip_and_throw_syntax_err(caused_by!())); } } } @@ -698,18 +819,16 @@ impl Parser { fn try_reduce_var_pattern(&mut self) -> ParseResult { debug_call_info!(self); match self.peek() { - Some(t) if t.is(Symbol) => { - Ok(VarPattern::VarName(self.try_reduce_name()?)) - } - Some(t) if t.is(UBar) => { - Ok(VarPattern::Discard(self.lpop())) - } + Some(t) if t.is(Symbol) => Ok(VarPattern::VarName(self.try_reduce_name()?)), + Some(t) if t.is(UBar) => Ok(VarPattern::Discard(self.lpop())), Some(t) if t.is(LSqBr) => { let l_sqbr = self.lpop(); let elems = self.try_reduce_elems()?; if self.cur_is(RSqBr) { let r_sqbr = self.lpop(); - Ok(VarPattern::Array(VarArrayPattern::new(l_sqbr, elems, r_sqbr))) + Ok(VarPattern::Array(VarArrayPattern::new( + l_sqbr, elems, r_sqbr, + ))) } else { // TODO: error report: RSqBr not found Err(self.skip_and_throw_syntax_err(caused_by!())) @@ -733,12 +852,8 @@ impl Parser { fn try_reduce_param_pattern(&mut self) -> ParseResult { debug_call_info!(self); match self.peek() { - Some(t) if t.is(Symbol) => { - Ok(ParamPattern::VarName(self.try_reduce_name()?)) - } - Some(t) if t.is(UBar) => { - Ok(ParamPattern::Discard(self.lpop())) - } + Some(t) if t.is(Symbol) => Ok(ParamPattern::VarName(self.try_reduce_name()?)), + Some(t) if t.is(UBar) => Ok(ParamPattern::Discard(self.lpop())), Some(t) if t.category_is(TC::Literal) => { // TODO: range pattern Ok(ParamPattern::Lit(self.try_reduce_lit()?)) @@ -752,7 +867,9 @@ impl Parser { let elems = self.try_reduce_params()?; if self.cur_is(RSqBr) { let r_sqbr = self.lpop(); - Ok(ParamPattern::Array(ParamArrayPattern::new(l_sqbr, elems, r_sqbr))) + Ok(ParamPattern::Array(ParamArrayPattern::new( + l_sqbr, elems, r_sqbr, + ))) } else { // TODO: error report: RSqBr not found Err(self.skip_and_throw_syntax_err(caused_by!())) @@ -783,18 +900,20 @@ impl Parser { Some(t) if t.category_is(TC::Literal) => { let lhs = ConstExpr::Lit(self.try_reduce_lit()?); let maybe_op = self.lpop(); - let op = if - maybe_op.is(Closed) || maybe_op.is(LeftOpen) - || maybe_op.is(RightOpen) || maybe_op.is(Open) { maybe_op } else { - return Err(self.skip_and_throw_syntax_err(caused_by!())) + let op = if maybe_op.is(Closed) + || maybe_op.is(LeftOpen) + || maybe_op.is(RightOpen) + || maybe_op.is(Open) + { + maybe_op + } else { + return Err(self.skip_and_throw_syntax_err(caused_by!())); }; // TODO: maybe Name let rhs = ConstExpr::Lit(self.try_reduce_lit()?); TypeSpec::interval(op, lhs, rhs) } - Some(t) if t.is(LParen) => { - self.try_reduce_func_type()? - } + Some(t) if t.is(LParen) => self.try_reduce_func_type()?, Some(t) if t.is(LSqBr) => { self.skip(); let mut tys = vec![self.try_reduce_type_spec()?]; @@ -809,16 +928,12 @@ impl Parser { self.skip(); break; } - _ => { - return Err(self.skip_and_throw_syntax_err(caused_by!())) - } + _ => return Err(self.skip_and_throw_syntax_err(caused_by!())), } } TypeSpec::Tuple(tys) } - _ => { - return Err(self.skip_and_throw_syntax_err(caused_by!())) - } + _ => return Err(self.skip_and_throw_syntax_err(caused_by!())), }; loop { match self.peek() { @@ -840,7 +955,9 @@ impl Parser { TypeSpec::proc(None, vec![ParamTySpec::anonymous(typ)], vec![], rhs) }; } - _ => { break; } + _ => { + break; + } } } Ok(typ) @@ -873,9 +990,7 @@ impl Parser { self.skip(); break; } - _ => { - return Err(self.skip_and_throw_syntax_err(caused_by!())) - } + _ => return Err(self.skip_and_throw_syntax_err(caused_by!())), } } match self.peek() { @@ -889,7 +1004,7 @@ impl Parser { Ok(TypeSpec::proc(lparen, non_defaults, vec![], rhs)) } } - _ => { Err(self.skip_and_throw_syntax_err(caused_by!())) } + _ => Err(self.skip_and_throw_syntax_err(caused_by!())), } } @@ -950,7 +1065,7 @@ impl Parser { Ok(arg) => { const_args.push_pos(arg); } - Err(e) => { return Err(e) } + Err(e) => return Err(e), } } for arg in kw.into_iter() { @@ -958,7 +1073,7 @@ impl Parser { Ok(arg) => { const_args.push_kw(arg); } - Err(e) => { return Err(e) } + Err(e) => return Err(e), } } Ok(const_args) @@ -967,11 +1082,17 @@ impl Parser { fn opt_reduce_args(&mut self) -> Option> { debug_call_info!(self); match self.peek() { - Some(t) if t.category_is(TC::Literal) - || t.is(Symbol) || t.category_is(TC::UnaryOp) - || t.is(Dot) || t.category_is(TC::Caret) - || t.is(LParen) || t.is(LSqBr) || t.is(LBrace) - || t.is(Colon) => { + Some(t) + if t.category_is(TC::Literal) + || t.is(Symbol) + || t.category_is(TC::UnaryOp) + || t.is(Dot) + || t.category_is(TC::Caret) + || t.is(LParen) + || t.is(LSqBr) + || t.is(LBrace) + || t.is(Colon) => + { Some(self.try_reduce_args()) } _ => None, @@ -1009,7 +1130,7 @@ impl Parser { match self.peek() { Some(t) if t.is(Colon) && colon_style => { self.skip(); - return Err(self.skip_and_throw_syntax_err(caused_by!())) + return Err(self.skip_and_throw_syntax_err(caused_by!())); } Some(t) if t.is(Colon) => { self.skip(); @@ -1023,22 +1144,30 @@ impl Parser { args.push_kw(self.try_reduce_kw_arg()?); } else { match self.try_reduce_arg()? { - PosOrKwArg::Pos(arg) => { args.push_pos(arg); }, - PosOrKwArg::Kw(arg) => { args.push_kw(arg); }, + PosOrKwArg::Pos(arg) => { + args.push_pos(arg); + } + PosOrKwArg::Kw(arg) => { + args.push_kw(arg); + } } } } Some(t) if t.is(Comma) => { self.skip(); if colon_style || self.cur_is(Comma) { - return Err(self.skip_and_throw_syntax_err(caused_by!())) + return Err(self.skip_and_throw_syntax_err(caused_by!())); } if !args.kw_is_empty() { args.push_kw(self.try_reduce_kw_arg()?); } else { match self.try_reduce_arg()? { - PosOrKwArg::Pos(arg) => { args.push_pos(arg); }, - PosOrKwArg::Kw(arg) => { args.push_kw(arg); }, + PosOrKwArg::Pos(arg) => { + args.push_pos(arg); + } + PosOrKwArg::Kw(arg) => { + args.push_kw(arg); + } } } } @@ -1054,8 +1183,12 @@ impl Parser { args.push_kw(self.try_reduce_kw_arg()?); } else { match self.try_reduce_arg()? { - PosOrKwArg::Pos(arg) => { args.push_pos(arg); }, - PosOrKwArg::Kw(arg) => { args.push_kw(arg); }, + PosOrKwArg::Pos(arg) => { + args.push_pos(arg); + } + PosOrKwArg::Kw(arg) => { + args.push_kw(arg); + } } } } @@ -1065,7 +1198,9 @@ impl Parser { args = Args::new(pos_args, kw_args, Some((lp.unwrap(), rp.unwrap()))); break; } - _ => { break; } + _ => { + break; + } } } Ok(args) @@ -1078,7 +1213,8 @@ impl Parser { if self.nth_is(1, Colon) { let acc = self.try_reduce_acc()?; debug_power_assert!(self.cur_is(Colon)); - if self.nth_is(1, Newline) { // colon style call + if self.nth_is(1, Newline) { + // colon style call Ok(PosOrKwArg::Pos(PosArg::new(Expr::Accessor(acc)))) } else { self.skip(); @@ -1086,7 +1222,7 @@ impl Parser { n.symbol } else { self.next_expr(); - return Err(ParseError::simple_syntax_error(0, acc.loc())) + return Err(ParseError::simple_syntax_error(0, acc.loc())); }; Ok(PosOrKwArg::Kw(KwArg::new(kw, self.try_reduce_expr()?))) } @@ -1094,9 +1230,7 @@ impl Parser { Ok(PosOrKwArg::Pos(PosArg::new(self.try_reduce_expr()?))) } } - Some(_) => { - Ok(PosOrKwArg::Pos(PosArg::new(self.try_reduce_expr()?))) - } + Some(_) => Ok(PosOrKwArg::Pos(PosArg::new(self.try_reduce_expr()?))), None => switch_unreachable!(), } } @@ -1113,16 +1247,14 @@ impl Parser { n.symbol } else { self.next_expr(); - return Err(ParseError::simple_syntax_error(0, acc.loc())) + return Err(ParseError::simple_syntax_error(0, acc.loc())); }; Ok(KwArg::new(keyword, self.try_reduce_expr()?)) } else { - return Err(ParseError::simple_syntax_error(0, t.loc())) + return 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())), None => switch_unreachable!(), } } @@ -1145,12 +1277,10 @@ impl Parser { self.counter.inc(); let body = DefBody::new(op, self.try_reduce_block()?, self.counter); Ok(Expr::Def(Def::new(sig, body))) - }, - _other => { - Err(self.skip_and_throw_syntax_err(caused_by!())) } + _other => Err(self.skip_and_throw_syntax_err(caused_by!())), } - }, + } Side::LhsLambda => { let params = self.try_reduce_params()?; match self.peek() { @@ -1158,21 +1288,30 @@ impl Parser { let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty()); let op = self.lpop(); self.counter.inc(); - Ok(Expr::Lambda(Lambda::new(sig, op, self.try_reduce_block()?, self.counter))) - }, + Ok(Expr::Lambda(Lambda::new( + sig, + op, + self.try_reduce_block()?, + self.counter, + ))) + } Some(t) if t.is(Colon) => { self.lpop(); let spec_t = self.try_reduce_type_spec()?; - let sig = LambdaSignature::new(params, Some(spec_t), TypeBoundSpecs::empty()); + let sig = + LambdaSignature::new(params, Some(spec_t), TypeBoundSpecs::empty()); let op = self.lpop(); self.counter.inc(); - Ok(Expr::Lambda(Lambda::new(sig, op, self.try_reduce_block()?, self.counter))) - }, - _other => { - Err(self.skip_and_throw_syntax_err(caused_by!())) + Ok(Expr::Lambda(Lambda::new( + sig, + op, + self.try_reduce_block()?, + self.counter, + ))) } + _other => Err(self.skip_and_throw_syntax_err(caused_by!())), } - }, + } Side::Rhs => { stack.push(ExprOrOp::Expr(self.try_reduce_lhs()?)); loop { @@ -1181,11 +1320,15 @@ impl Parser { let op_prec = op.kind.precedence(); if stack.len() >= 2 { while let Some(ExprOrOp::Op(prev_op)) = stack.get(stack.len() - 2) { - if prev_op.category_is(TC::BinOp) && - prev_op.kind.precedence() >= op_prec { - let rhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); - let prev_op = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_))); - let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); + if prev_op.category_is(TC::BinOp) + && prev_op.kind.precedence() >= op_prec + { + let rhs = + enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); + let prev_op = + enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_))); + let lhs = + enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); let bin = BinOp::new(prev_op, lhs, rhs); stack.push(ExprOrOp::Expr(Expr::BinOp(bin))); } else { @@ -1199,7 +1342,9 @@ impl Parser { stack.push(ExprOrOp::Op(self.lpop())); stack.push(ExprOrOp::Expr(self.try_reduce_lhs()?)); } - Some(t) if t.category_is(TC::DefOp) => { switch_unreachable!() } + Some(t) if t.category_is(TC::DefOp) => { + switch_unreachable!() + } Some(t) if t.is(Dot) => { self.skip(); match self.lpop() { @@ -1207,7 +1352,7 @@ impl Parser { let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() { expr } else { - return Err(self.skip_and_throw_syntax_err(caused_by!())) + return Err(self.skip_and_throw_syntax_err(caused_by!())); }; let acc = Accessor::attr(obj, Local::new(symbol)); if let Ok(args) = self.try_reduce_args() { @@ -1219,7 +1364,7 @@ impl Parser { } other => { self.restore(other); - return Err(self.skip_and_throw_syntax_err(caused_by!())) + return Err(self.skip_and_throw_syntax_err(caused_by!())); } } } @@ -1248,7 +1393,8 @@ impl Parser { ExprOrOp::Expr(expr) => expr.loc(), ExprOrOp::Op(op) => op.loc(), }; - self.warns.push(ParseError::compiler_bug(0, loc, fn_name!(), line!())); + self.warns + .push(ParseError::compiler_bug(0, loc, fn_name!(), line!())); Ok(expr) } Some(ExprOrOp::Op(op)) => { @@ -1269,12 +1415,8 @@ impl Parser { // TODO: 10.times ...などメソッド呼び出しもある Ok(Expr::Lit(self.try_reduce_lit()?)) } - Some(t) if t.is(Symbol) || t.is(Dot) => { - Ok(self.try_reduce_call_or_acc()?) - } - Some(t) if t.category_is(TC::UnaryOp) => { - Ok(Expr::UnaryOp(self.try_reduce_unary()?)) - } + Some(t) if t.is(Symbol) || t.is(Dot) => Ok(self.try_reduce_call_or_acc()?), + Some(t) if t.category_is(TC::UnaryOp) => Ok(Expr::UnaryOp(self.try_reduce_unary()?)), Some(t) if t.category_is(TC::Caret) => { let lambda = self.try_reduce_lambda()?; Ok(Expr::Lambda(lambda)) @@ -1282,20 +1424,21 @@ impl Parser { Some(t) if t.is(LParen) => { self.skip(); let expr = self.try_reduce_expr()?; - if self.cur_is(RParen) { self.skip(); } - else { return Err(self.skip_and_throw_syntax_err(caused_by!())) } + if self.cur_is(RParen) { + self.skip(); + } else { + return Err(self.skip_and_throw_syntax_err(caused_by!())); + } Ok(expr) } - Some(t) if t.is(LSqBr) => { - Ok(Expr::Array(self.try_reduce_array()?)) - } + Some(t) if t.is(LSqBr) => Ok(Expr::Array(self.try_reduce_array()?)), Some(t) if t.is(LBrace) => { todo!() } Some(t) if t.is(UBar) => { let token = self.lpop(); Err(ParseError::feature_error(0, token.loc(), "discard pattern")) - }, + } _ => Err(self.skip_and_throw_syntax_err(caused_by!())), } } @@ -1319,7 +1462,7 @@ impl Parser { let sig = self.try_reduce_lambda_sig()?; let op = self.lpop(); if op.category() != TC::LambdaOp { - return Err(self.skip_and_throw_syntax_err(caused_by!())) + return Err(self.skip_and_throw_syntax_err(caused_by!())); } // REVIEW: この箇所必要か while self.cur_is(Newline) { @@ -1345,7 +1488,7 @@ impl Parser { let elems = self.try_reduce_args()?; let r_sqbr = self.lpop(); if !r_sqbr.is(RSqBr) { - return Err(ParseError::simple_syntax_error(0, r_sqbr.loc())) + return Err(ParseError::simple_syntax_error(0, r_sqbr.loc())); } let arr = Array::new(l_sqbr, r_sqbr, elems, None); Ok(arr) @@ -1355,9 +1498,7 @@ impl Parser { fn try_reduce_name(&mut self) -> ParseResult { debug_call_info!(self); match self.peek() { - Some(t) if t.is(Symbol) => { - Ok(VarName::new(self.lpop())) - } + Some(t) if t.is(Symbol) => Ok(VarName::new(self.lpop())), _ => Err(self.skip_and_throw_syntax_err(caused_by!())), } } @@ -1366,9 +1507,7 @@ impl Parser { fn try_reduce_lit(&mut self) -> ParseResult { debug_call_info!(self); match self.peek() { - Some(t) if t.category_is(TC::Literal) => { - Ok(Literal::from(self.lpop())) - } + Some(t) if t.category_is(TC::Literal) => Ok(Literal::from(self.lpop())), _ => Err(self.skip_and_throw_syntax_err(caused_by!())), } } diff --git a/compiler/erg_parser/tests/test.rs b/compiler/erg_parser/tests/test.rs index 2ac52560..07ce1d0b 100644 --- a/compiler/erg_parser/tests/test.rs +++ b/compiler/erg_parser/tests/test.rs @@ -130,7 +130,11 @@ mod tests { let cfg = ErgConfig::new("exec", 1, false, None, input.clone(), "", 2); let lexer = Lexer::new(input.clone()); let mut parser = ParserRunner::new(cfg); - match parser.parse(lexer.lex().map_err(|errs| ParserRunnerErrors::convert(&input, errs))?) { + match parser.parse( + lexer + .lex() + .map_err(|errs| ParserRunnerErrors::convert(&input, errs))?, + ) { Ok(module) => { println!("{module}"); Ok(()) diff --git a/compiler/erg_parser/token.rs b/compiler/erg_parser/token.rs index 5e66ba18..9b7cf7ab 100644 --- a/compiler/erg_parser/token.rs +++ b/compiler/erg_parser/token.rs @@ -4,12 +4,12 @@ use std::fmt; use std::hash::{Hash, Hasher}; -use erg_common::str::Str; use erg_common::error::Location; use erg_common::impl_displayable_stream_for_wrapper; -use erg_common::traits::{Stream, Locational}; -use erg_common::value::ValueObj; +use erg_common::str::Str; +use erg_common::traits::{Locational, Stream}; use erg_common::ty::Type; +use erg_common::value::ValueObj; /// 意味論的名前と記号自体の名前が混在しているが、Pythonの名残である #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -243,11 +243,13 @@ impl TokenKind { pub const fn category(&self) -> TokenCategory { match self { Symbol => TokenCategory::Symbol, - NatLit | IntLit | RatioLit | StrLit | BoolLit - | NoneLit | EllipsisLit | NoImplLit | InfLit => TokenCategory::Literal, + NatLit | IntLit | RatioLit | StrLit | BoolLit | NoneLit | EllipsisLit | NoImplLit + | InfLit => TokenCategory::Literal, PrePlus | PreMinus | PreStar | PreBitNot | Mutate => TokenCategory::UnaryOp, Try => TokenCategory::PostfixOp, - Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | OrEqual => TokenCategory::SpecialBinOp, + Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | OrEqual => { + TokenCategory::SpecialBinOp + } Equal => TokenCategory::DefOp, FuncArrow | ProcArrow => TokenCategory::LambdaOp, Semi | Newline => TokenCategory::Separator, @@ -266,27 +268,26 @@ impl TokenKind { pub const fn precedence(&self) -> Option { let prec = match self { - Dot | DblColon => 200, // . - Pow => 190, // ** - PrePlus | PreMinus | PreBitNot => 180, // (unary) + - * ~ + Dot | DblColon => 200, // . + Pow => 190, // ** + PrePlus | PreMinus | PreBitNot => 180, // (unary) + - * ~ Star | Slash | FloorDiv | Mod | CrossOp | DotOp => 170, // * / // % cross dot - Plus | Minus => 160, // + - - Shl | Shr => 150, // << >> - BitAnd => 140, // && - BitXor => 130, // ^^ - BitOr => 120, // || - Closed | LeftOpen | RightOpen | Open => 100, // range operators - Less | Gre | LessEq | GreEq | DblEq | NotEq - | InOp | NotInOp | IsOp | IsNotOp => 90, // < > <= >= == != in notin is isnot - AndOp => 80, // and - OrOp => 70, // or - FuncArrow | ProcArrow => 60, // -> => + Plus | Minus => 160, // + - + Shl | Shr => 150, // << >> + BitAnd => 140, // && + BitXor => 130, // ^^ + BitOr => 120, // || + Closed | LeftOpen | RightOpen | Open => 100, // range operators + Less | Gre | LessEq | GreEq | DblEq | NotEq | InOp | NotInOp | IsOp | IsNotOp => 90, // < > <= >= == != in notin is isnot + AndOp => 80, // and + OrOp => 70, // or + FuncArrow | ProcArrow => 60, // -> => Colon | SupertypeOf | SubtypeOf => 50, // : :> <: - Comma => 40, // , - Equal | OrEqual => 20, // = |= - Newline | Semi => 10, // \n ; + Comma => 40, // , + Equal | OrEqual => 20, // = |= + Newline | Semi => 10, // \n ; LParen | LBrace | LSqBr | Indent => 0, // ( { [ Indent - _ => { return None }, + _ => return None, }; Some(prec) } @@ -302,7 +303,9 @@ impl TokenKind { impl fmt::Display for TokenKind { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self:?}") } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{self:?}") + } } #[derive(Clone, Eq)] @@ -350,7 +353,9 @@ impl fmt::Display for Token { // the values of lineno and col are not relevant for comparison impl PartialEq for Token { #[inline] - fn eq(&self, other: &Self) -> bool { self.is(other.kind) && self.content == other.content } + fn eq(&self, other: &Self) -> bool { + self.is(other.kind) && self.content == other.content + } } impl Hash for Token { @@ -362,7 +367,9 @@ impl Hash for Token { impl Locational for Token { fn loc(&self) -> Location { - if self.lineno == 0 { Location::Unknown } else { + if self.lineno == 0 { + Location::Unknown + } else { Location::range( self.lineno, self.col_begin, @@ -373,43 +380,79 @@ impl Locational for Token { } #[inline] - fn col_end(&self) -> Option { Some(self.col_begin + self.content.len()) } + fn col_end(&self) -> Option { + Some(self.col_begin + self.content.len()) + } } impl Token { #[inline] pub fn dummy() -> Self { - Token{ kind: TokenKind::Illegal, content: "DUMMY".into(), lineno: 1, col_begin: 0 } + Token { + kind: TokenKind::Illegal, + content: "DUMMY".into(), + lineno: 1, + col_begin: 0, + } } #[inline] pub fn new>(kind: TokenKind, cont: S, lineno: usize, col_begin: usize) -> Self { - Token{ kind, content: cont.into(), lineno, col_begin } + Token { + kind, + content: cont.into(), + lineno, + col_begin, + } } #[inline] pub fn from_str(kind: TokenKind, cont: &str) -> Self { - Token{ kind, content: Str::rc(cont), lineno: 0, col_begin: 0 } + Token { + kind, + content: Str::rc(cont), + lineno: 0, + col_begin: 0, + } } #[inline] - pub fn symbol(cont: &str) -> Self { Self::from_str(TokenKind::Symbol, cont) } - - pub const fn static_symbol(s: &'static str) -> Self { - Token{ kind: TokenKind::Symbol, content: Str::ever(s), lineno: 0, col_begin: 0 } + pub fn symbol(cont: &str) -> Self { + Self::from_str(TokenKind::Symbol, cont) } - pub const fn category(&self) -> TokenCategory { self.kind.category() } + pub const fn static_symbol(s: &'static str) -> Self { + Token { + kind: TokenKind::Symbol, + content: Str::ever(s), + lineno: 0, + col_begin: 0, + } + } - pub fn category_is(&self, category: TokenCategory) -> bool { self.kind.category() == category } + pub const fn category(&self) -> TokenCategory { + self.kind.category() + } - pub fn is(&self, kind: TokenKind) -> bool { self.kind == kind } + pub fn category_is(&self, category: TokenCategory) -> bool { + self.kind.category() == category + } - pub const fn is_block_op(&self) -> bool { self.category().is_block_op() } + pub fn is(&self, kind: TokenKind) -> bool { + self.kind == kind + } - pub const fn inspect(&self) -> &Str { &self.content } + pub const fn is_block_op(&self) -> bool { + self.category().is_block_op() + } - pub fn is_procedural(&self) -> bool { self.inspect().ends_with("!") } + pub const fn inspect(&self) -> &Str { + &self.content + } + + pub fn is_procedural(&self) -> bool { + self.inspect().ends_with("!") + } } #[derive(Debug, Clone)] diff --git a/src/dummy.rs b/src/dummy.rs index cadb8b0b..a08482c6 100644 --- a/src/dummy.rs +++ b/src/dummy.rs @@ -1,15 +1,15 @@ -use std::net::TcpStream; use std::io::{Read, Write}; +use std::net::TcpStream; use std::thread::sleep; use std::time::Duration; -use erg_common::config::{ErgConfig, Input, SEMVER, BUILD_INFO}; +use erg_common::config::{ErgConfig, Input, BUILD_INFO, SEMVER}; use erg_common::python_util::exec_py; use erg_common::str::Str; use erg_common::traits::Runnable; -use erg_compiler::Compiler; use erg_compiler::error::{CompileError, CompileErrors}; +use erg_compiler::Compiler; /// Pythonインタープリタをサーバーとして開き、通信を仲介することでErgインタープリタとして振る舞う #[derive(Debug)] @@ -33,7 +33,7 @@ impl Runnable for DummyVM { let addr = format!("{repl_server_ip}:{repl_server_port}"); let stream = loop { match TcpStream::connect(&addr) { - Ok(stream) => { break stream }, + Ok(stream) => break stream, Err(_) => { println!("Retrying to connect to the REPL server..."); sleep(Duration::from_millis(500)); @@ -49,10 +49,14 @@ impl Runnable for DummyVM { } #[inline] - fn input(&self) -> &Input { &self.cfg.input } + fn input(&self) -> &Input { + &self.cfg.input + } #[inline] - fn start_message(&self) -> String { format!("Erg interpreter {} {}\n", SEMVER, &*BUILD_INFO) } + fn start_message(&self) -> String { + format!("Erg interpreter {} {}\n", SEMVER, &*BUILD_INFO) + } fn finish(&mut self) { self.stream.write("exit".as_bytes()).unwrap(); @@ -88,7 +92,7 @@ impl Runnable for DummyVM { panic!("{}", format!("Read error: {e}")); } } - }, + } Result::Err(e) => panic!("{}", format!("Sending error: {e}")), }; if res.ends_with("None") { diff --git a/src/main.rs b/src/main.rs index c382cf06..f4877b93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,10 @@ +extern crate erg; extern crate erg_compiler; extern crate erg_parser; -extern crate erg; use std::process; -use erg_common::config::{ErgConfig}; +use erg_common::config::ErgConfig; use erg_common::deserialize::Deserializer; use erg_common::traits::Runnable; @@ -18,11 +18,21 @@ use erg::dummy::DummyVM; fn main() { let cfg = ErgConfig::parse(); match cfg.mode { - "lex" => { LexerRunner::run(cfg); } - "parse" => { ParserRunner::run(cfg); } - "compile" => { Compiler::run(cfg); } - "exec" => { DummyVM::run(cfg); } - "read" => { Deserializer::run(cfg); } + "lex" => { + LexerRunner::run(cfg); + } + "parse" => { + ParserRunner::run(cfg); + } + "compile" => { + Compiler::run(cfg); + } + "exec" => { + DummyVM::run(cfg); + } + "read" => { + Deserializer::run(cfg); + } other => { eprintln!("invalid mode: {other}"); process::exit(1);