mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Apply trivial clippy fixes
This commit is contained in:
parent
6d3dda8129
commit
7d3116f546
26 changed files with 360 additions and 384 deletions
|
@ -58,33 +58,33 @@ pub enum CodeObjFlags {
|
||||||
Illegal = 0x0000,
|
Illegal = 0x0000,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<CodeObjFlags> for u32 {
|
impl From<u32> for CodeObjFlags {
|
||||||
fn into(self) -> CodeObjFlags {
|
fn from(flags: u32) -> Self {
|
||||||
match self {
|
match flags {
|
||||||
0x0001 => CodeObjFlags::Optimized,
|
0x0001 => Self::Optimized,
|
||||||
0x0002 => CodeObjFlags::NewLocals,
|
0x0002 => Self::NewLocals,
|
||||||
0x0004 => CodeObjFlags::VarArgs,
|
0x0004 => Self::VarArgs,
|
||||||
0x0008 => CodeObjFlags::VarKeywords,
|
0x0008 => Self::VarKeywords,
|
||||||
0x0010 => CodeObjFlags::Nested,
|
0x0010 => Self::Nested,
|
||||||
0x0020 => CodeObjFlags::Generator,
|
0x0020 => Self::Generator,
|
||||||
0x0040 => CodeObjFlags::NoFree,
|
0x0040 => Self::NoFree,
|
||||||
0x0080 => CodeObjFlags::Coroutine,
|
0x0080 => Self::Coroutine,
|
||||||
0x0100 => CodeObjFlags::IterableCoroutine,
|
0x0100 => Self::IterableCoroutine,
|
||||||
0x0200 => CodeObjFlags::AsyncGenerator,
|
0x0200 => Self::AsyncGenerator,
|
||||||
// CO_GENERATOR_ALLOWED,
|
// CO_GENERATOR_ALLOWED,
|
||||||
0x2000 => CodeObjFlags::FutureDivision,
|
0x2000 => Self::FutureDivision,
|
||||||
0x4000 => CodeObjFlags::FutureAbsoluteImport,
|
0x4000 => Self::FutureAbsoluteImport,
|
||||||
0x8000 => CodeObjFlags::FutureWithStatement,
|
0x8000 => Self::FutureWithStatement,
|
||||||
0x1_0000 => CodeObjFlags::FuturePrintFunction,
|
0x1_0000 => Self::FuturePrintFunction,
|
||||||
0x2_0000 => CodeObjFlags::FutureUnicodeLiterals,
|
0x2_0000 => Self::FutureUnicodeLiterals,
|
||||||
0x4_0000 => CodeObjFlags::FutureBarryAsBDFL,
|
0x4_0000 => Self::FutureBarryAsBDFL,
|
||||||
0x8_0000 => CodeObjFlags::FutureGeneratorStop,
|
0x8_0000 => Self::FutureGeneratorStop,
|
||||||
0x10_0000 => CodeObjFlags::FutureAnnotations,
|
0x10_0000 => Self::FutureAnnotations,
|
||||||
// EVM flags
|
// EVM flags
|
||||||
0x1000_0000 => CodeObjFlags::EvmDynParam,
|
0x1000_0000 => Self::EvmDynParam,
|
||||||
0x2000_0000 => CodeObjFlags::EvmDynamic,
|
0x2000_0000 => Self::EvmDynamic,
|
||||||
0x4000_0000 => CodeObjFlags::EvmNoGC,
|
0x4000_0000 => Self::EvmNoGC,
|
||||||
_ => CodeObjFlags::Illegal,
|
_ => Self::Illegal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,31 +330,31 @@ impl CodeObj {
|
||||||
fn tables_info(&self) -> String {
|
fn tables_info(&self) -> String {
|
||||||
let mut tables = "".to_string();
|
let mut tables = "".to_string();
|
||||||
if !self.consts.is_empty() {
|
if !self.consts.is_empty() {
|
||||||
tables += &format!("Constants:\n");
|
tables += "Constants:\n";
|
||||||
}
|
}
|
||||||
for (i, obj) in self.consts.iter().enumerate() {
|
for (i, obj) in self.consts.iter().enumerate() {
|
||||||
tables += &format!(" {}: {}\n", i, obj);
|
tables += &format!(" {}: {}\n", i, obj);
|
||||||
}
|
}
|
||||||
if !self.names.is_empty() {
|
if !self.names.is_empty() {
|
||||||
tables += &format!("Names:\n");
|
tables += "Names:\n";
|
||||||
}
|
}
|
||||||
for (i, name) in self.names.iter().enumerate() {
|
for (i, name) in self.names.iter().enumerate() {
|
||||||
tables += &format!(" {}: {}\n", i, name);
|
tables += &format!(" {}: {}\n", i, name);
|
||||||
}
|
}
|
||||||
if !self.varnames.is_empty() {
|
if !self.varnames.is_empty() {
|
||||||
tables += &format!("Varnames:\n");
|
tables += "Varnames:\n";
|
||||||
}
|
}
|
||||||
for (i, varname) in self.varnames.iter().enumerate() {
|
for (i, varname) in self.varnames.iter().enumerate() {
|
||||||
tables += &format!(" {}: {}\n", i, varname);
|
tables += &format!(" {}: {}\n", i, varname);
|
||||||
}
|
}
|
||||||
if !self.cellvars.is_empty() {
|
if !self.cellvars.is_empty() {
|
||||||
tables += &format!("Cellvars:\n");
|
tables += "Cellvars:\n";
|
||||||
}
|
}
|
||||||
for (i, cellvar) in self.cellvars.iter().enumerate() {
|
for (i, cellvar) in self.cellvars.iter().enumerate() {
|
||||||
tables += &format!(" {}: {}\n", i, cellvar);
|
tables += &format!(" {}: {}\n", i, cellvar);
|
||||||
}
|
}
|
||||||
if !self.freevars.is_empty() {
|
if !self.freevars.is_empty() {
|
||||||
tables += &format!("Freevars:\n");
|
tables += "Freevars:\n";
|
||||||
}
|
}
|
||||||
for (i, freevar) in self.freevars.iter().enumerate() {
|
for (i, freevar) in self.freevars.iter().enumerate() {
|
||||||
tables += &format!(" {}: {}\n", i, freevar);
|
tables += &format!(" {}: {}\n", i, freevar);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::hash_map::{IntoIter, IntoValues, Iter, IterMut, Keys, Values, ValuesMut};
|
use std::collections::hash_map::{IntoIter, IntoValues, Iter, IterMut, Keys, Values, ValuesMut};
|
||||||
use std::fmt;
|
use std::fmt::{self, Write};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ impl<K: fmt::Display, V: fmt::Display> fmt::Display for Dict<K, V> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut s = "".to_string();
|
let mut s = "".to_string();
|
||||||
for (k, v) in self.dict.iter() {
|
for (k, v) in self.dict.iter() {
|
||||||
s += &format!("{k}: {v}, ");
|
write!(s, "{k}: {v}, ")?;
|
||||||
}
|
}
|
||||||
s.pop();
|
s.pop();
|
||||||
s.pop();
|
s.pop();
|
||||||
|
|
|
@ -328,8 +328,8 @@ impl ErrorCore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const VBAR_UNICODE: &'static str = "│";
|
pub const VBAR_UNICODE: &str = "│";
|
||||||
pub const VBAR_BREAK_UNICODE: &'static str = "·";
|
pub const VBAR_BREAK_UNICODE: &str = "·";
|
||||||
|
|
||||||
/// format:
|
/// format:
|
||||||
/// ```console
|
/// ```console
|
||||||
|
@ -399,9 +399,9 @@ pub trait ErrorDisplay {
|
||||||
let kind = self.core().kind as u8;
|
let kind = self.core().kind as u8;
|
||||||
let (color, err_or_warn) = if kind < 100 {
|
let (color, err_or_warn) = if kind < 100 {
|
||||||
(RED, "Error")
|
(RED, "Error")
|
||||||
} else if 100 <= kind && kind < 150 {
|
} else if (100..150).contains(&kind) {
|
||||||
(YELLOW, "Warning")
|
(YELLOW, "Warning")
|
||||||
} else if 150 <= kind && kind < 200 {
|
} else if (150..200).contains(&kind) {
|
||||||
(DEEP_RED, "Error")
|
(DEEP_RED, "Error")
|
||||||
} else {
|
} else {
|
||||||
("", "Exception")
|
("", "Exception")
|
||||||
|
|
|
@ -52,6 +52,7 @@ pub type FxHashSet<T> = HashSet<T, BuildHasherDefault<FxHasher>>;
|
||||||
/// out-performs an FNV-based hash within rustc itself -- the collision rate is
|
/// out-performs an FNV-based hash within rustc itself -- the collision rate is
|
||||||
/// similar or slightly worse than FNV, but the speed of the hash function
|
/// similar or slightly worse than FNV, but the speed of the hash function
|
||||||
/// itself is much higher because it works on up to 8 bytes at a time.
|
/// itself is much higher because it works on up to 8 bytes at a time.
|
||||||
|
#[derive(Default)]
|
||||||
pub struct FxHasher {
|
pub struct FxHasher {
|
||||||
hash: usize,
|
hash: usize,
|
||||||
}
|
}
|
||||||
|
@ -61,13 +62,6 @@ const K: usize = 0x9e3779b9;
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
const K: usize = 0x517cc1b727220a95;
|
const K: usize = 0x517cc1b727220a95;
|
||||||
|
|
||||||
impl Default for FxHasher {
|
|
||||||
#[inline]
|
|
||||||
fn default() -> FxHasher {
|
|
||||||
FxHasher { hash: 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FxHasher {
|
impl FxHasher {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_to_hash(&mut self, i: usize) {
|
fn add_to_hash(&mut self, i: usize) {
|
||||||
|
@ -97,7 +91,7 @@ impl Hasher for FxHasher {
|
||||||
hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize);
|
hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize);
|
||||||
bytes = &bytes[2..];
|
bytes = &bytes[2..];
|
||||||
}
|
}
|
||||||
if (size_of::<usize>() > 1) && bytes.len() >= 1 {
|
if (size_of::<usize>() > 1) && !bytes.is_empty() {
|
||||||
hash.add_to_hash(bytes[0] as usize);
|
hash.add_to_hash(bytes[0] as usize);
|
||||||
}
|
}
|
||||||
self.hash = hash.hash;
|
self.hash = hash.hash;
|
||||||
|
|
|
@ -27,6 +27,10 @@ where
|
||||||
self.buffer.len()
|
self.buffer.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.buffer.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_next(&mut self) -> bool {
|
pub fn get_next(&mut self) -> bool {
|
||||||
if self.done {
|
if self.done {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub fn read_file(mut f: std::fs::File) -> std::io::Result<String> {
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_vec<T: fmt::Display>(v: &Vec<T>) -> String {
|
pub fn fmt_vec<T: fmt::Display>(v: &[T]) -> String {
|
||||||
fmt_iter(v.iter())
|
fmt_iter(v.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ pub fn fmt_slice<T: fmt::Display>(v: &[T]) -> String {
|
||||||
fmt_iter(v.iter())
|
fmt_iter(v.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_vec_split_with<T: fmt::Display>(v: &Vec<T>, splitter: &str) -> String {
|
pub fn fmt_vec_split_with<T: fmt::Display>(v: &[T], splitter: &str) -> String {
|
||||||
fmt_iter_split_with(v.iter(), splitter)
|
fmt_iter_split_with(v.iter(), splitter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,13 +102,13 @@ pub fn get_hash<T: std::hash::Hash>(t: &T) -> usize {
|
||||||
/// \r\n (Windows), \r (old MacOS) -> \n (Unix)
|
/// \r\n (Windows), \r (old MacOS) -> \n (Unix)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn normalize_newline(src: &str) -> String {
|
pub fn normalize_newline(src: &str) -> String {
|
||||||
src.replace("\r\n", "\n").replace("\r", "\n")
|
src.replace("\r\n", "\n").replace('\r', "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// cut \n
|
/// cut \n
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn chomp(src: &str) -> String {
|
pub fn chomp(src: &str) -> String {
|
||||||
normalize_newline(src).replace("\n", "")
|
normalize_newline(src).replace('\n', "")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_map<T, U, E, F, I>(i: I, f: F) -> Result<Vec<U>, E>
|
pub fn try_map<T, U, E, F, I>(i: I, f: F) -> Result<Vec<U>, E>
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub fn which_python() -> String {
|
||||||
if res.is_empty() {
|
if res.is_empty() {
|
||||||
panic!("python not found");
|
panic!("python not found");
|
||||||
}
|
}
|
||||||
res.to_string()
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detect_magic_number() -> u32 {
|
pub fn detect_magic_number() -> u32 {
|
||||||
|
|
|
@ -37,30 +37,30 @@ pub fn get_timestamp_bytes() -> [u8; 4] {
|
||||||
pub enum DataTypePrefix {
|
pub enum DataTypePrefix {
|
||||||
/* sized objects */
|
/* sized objects */
|
||||||
Illegal = 0,
|
Illegal = 0,
|
||||||
Int32 = 'i' as u8, // 0x69
|
Int32 = b'i', // 0x69
|
||||||
Int64 = 'I' as u8, // 0x49
|
Int64 = b'I', // 0x49
|
||||||
Float = 'f' as u8, // 0x66 (float32, not generated anymore?)
|
Float = b'f', // 0x66 (float32, not generated anymore?)
|
||||||
BinFloat = 'g' as u8, // 0x67 (float64)
|
BinFloat = b'g', // 0x67 (float64)
|
||||||
Complex = 'x' as u8, // 0x78
|
Complex = b'x', // 0x78
|
||||||
BinComplex = 'y' as u8, // 0x79
|
BinComplex = b'y', // 0x79
|
||||||
True = 'T' as u8, // 0x54
|
True = b'T', // 0x54
|
||||||
False = 'F' as u8, // 0x46
|
False = b'F', // 0x46
|
||||||
None = 'N' as u8, // 0x4E
|
None = b'N', // 0x4E
|
||||||
StopIter = 'S' as u8, // 0x53
|
StopIter = b'S', // 0x53
|
||||||
Ref = 'r' as u8,
|
Ref = b'r',
|
||||||
/* unsized objects (ref counted) */
|
/* unsized objects (ref counted) */
|
||||||
Long = 'l' as u8, // 0x6C + len: u32 + payload: 2*len+3byte (~ -2^31-1 && 2^31 ~)
|
Long = b'l', // 0x6C + len: u32 + payload: 2*len+3byte (~ -2^31-1 && 2^31 ~)
|
||||||
Str = 's' as u8, // 0x73 + len: u32 + payload
|
Str = b's', // 0x73 + len: u32 + payload
|
||||||
ShortAscii = 'z' as u8, // 0x7A + len: u8 + payload
|
ShortAscii = b'z', // 0x7A + len: u8 + payload
|
||||||
ShortAsciiInterned = 'Z' as u8, // 0x5A + len: u8 + payload
|
ShortAsciiInterned = b'Z', // 0x5A + len: u8 + payload
|
||||||
Unicode = 'u' as u8, // 0x75 + len: u32 + payload
|
Unicode = b'u', // 0x75 + len: u32 + payload
|
||||||
Interned = 't' as u8, // 0x74 + len + payload
|
Interned = b't', // 0x74 + len + payload
|
||||||
SmallTuple = ')' as u8, // 0x29 + len: u8 + payload
|
SmallTuple = b')', // 0x29 + len: u8 + payload
|
||||||
Tuple = '(' as u8, // 0x28 + len: u32 + payload
|
Tuple = b'(', // 0x28 + len: u32 + payload
|
||||||
Code = 'c' as u8, // 0x63
|
Code = b'c', // 0x63
|
||||||
/* Erg specific prefix */
|
/* Erg specific prefix */
|
||||||
Builtin = 'b' as u8, // 0x62 + str
|
Builtin = b'b', // 0x62 + str
|
||||||
Nat = 'n' as u8,
|
Nat = b'n',
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_from_debug!(DataTypePrefix);
|
impl_display_from_debug!(DataTypePrefix);
|
||||||
|
@ -103,7 +103,7 @@ impl From<u8> for DataTypePrefix {
|
||||||
|
|
||||||
impl DataTypePrefix {
|
impl DataTypePrefix {
|
||||||
pub const fn is_sized(&self) -> bool {
|
pub const fn is_sized(&self) -> bool {
|
||||||
match self {
|
matches!(self,
|
||||||
Self::Long
|
Self::Long
|
||||||
| Self::Str
|
| Self::Str
|
||||||
| Self::ShortAscii
|
| Self::ShortAscii
|
||||||
|
@ -113,9 +113,7 @@ impl DataTypePrefix {
|
||||||
| Self::SmallTuple
|
| Self::SmallTuple
|
||||||
| Self::Tuple
|
| Self::Tuple
|
||||||
| Self::Code
|
| Self::Code
|
||||||
| Self::Builtin => false,
|
| Self::Builtin)
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ impl<T: Hash + Eq + Clone> Set<T> {
|
||||||
pub fn union(&self, other: &Set<T>) -> Set<T> {
|
pub fn union(&self, other: &Set<T>) -> Set<T> {
|
||||||
let u = self.elems.union(&other.elems);
|
let u = self.elems.union(&other.elems);
|
||||||
Self {
|
Self {
|
||||||
elems: u.into_iter().map(|x| x.clone()).collect(),
|
elems: u.into_iter().cloned().collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ impl<T: Hash + Eq + Clone> Set<T> {
|
||||||
pub fn intersection(&self, other: &Set<T>) -> Set<T> {
|
pub fn intersection(&self, other: &Set<T>) -> Set<T> {
|
||||||
let u = self.elems.intersection(&other.elems);
|
let u = self.elems.intersection(&other.elems);
|
||||||
Self {
|
Self {
|
||||||
elems: u.into_iter().map(|x| x.clone()).collect(),
|
elems: u.into_iter().cloned().collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl Add<&str> for Str {
|
||||||
impl Hash for Str {
|
impl Hash for Str {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
match self {
|
match self {
|
||||||
Str::Rc(s) => (&s[..]).hash(state),
|
Str::Rc(s) => (s[..]).hash(state),
|
||||||
Str::Static(s) => s.hash(state),
|
Str::Static(s) => s.hash(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,14 +59,14 @@ impl From<&'static str> for Str {
|
||||||
impl From<&String> for Str {
|
impl From<&String> for Str {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(s: &String) -> Self {
|
fn from(s: &String) -> Self {
|
||||||
Str::Rc((&s[..]).into())
|
Str::Rc((s[..]).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Str {
|
impl From<String> for Str {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(s: String) -> Self {
|
fn from(s: String) -> Self {
|
||||||
Str::Rc((&s[..]).into())
|
Str::Rc((s[..]).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn reorder_by_key<T: Eq, U>(mut g: Graph<T, U>, idx: Vec<T>) -> Graph<T, U> {
|
||||||
|
|
||||||
fn dfs<T: Eq + Hash + Clone, U>(g: &Graph<T, U>, v: T, used: &mut Set<T>, idx: &mut Vec<T>) {
|
fn dfs<T: Eq + Hash + Clone, U>(g: &Graph<T, U>, v: T, used: &mut Set<T>, idx: &mut Vec<T>) {
|
||||||
used.insert(v.clone());
|
used.insert(v.clone());
|
||||||
for node_id in g.iter().find(|n| &n.id == &v).unwrap().depends_on.iter() {
|
for node_id in g.iter().find(|n| n.id == v).unwrap().depends_on.iter() {
|
||||||
if !used.contains(node_id) {
|
if !used.contains(node_id) {
|
||||||
dfs(g, node_id.clone(), used, idx);
|
dfs(g, node_id.clone(), used, idx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ thread_local! {
|
||||||
pub fn fresh_varname() -> String {
|
pub fn fresh_varname() -> String {
|
||||||
REFINEMENT_VAR_ID.with(|id| {
|
REFINEMENT_VAR_ID.with(|id| {
|
||||||
*id.borrow_mut() += 1;
|
*id.borrow_mut() += 1;
|
||||||
let i = id.borrow().clone();
|
let i = *id.borrow();
|
||||||
format!("%v{i}")
|
format!("%v{i}")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ pub fn fresh_varname() -> String {
|
||||||
pub fn fresh_param_name() -> String {
|
pub fn fresh_param_name() -> String {
|
||||||
REFINEMENT_VAR_ID.with(|id| {
|
REFINEMENT_VAR_ID.with(|id| {
|
||||||
*id.borrow_mut() += 1;
|
*id.borrow_mut() += 1;
|
||||||
let i = id.borrow().clone();
|
let i = *id.borrow();
|
||||||
format!("%p{i}")
|
format!("%p{i}")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1472,9 +1472,9 @@ impl HasLevel for SubrKind {
|
||||||
Self::FuncMethod(t) => t.update_level(level),
|
Self::FuncMethod(t) => t.update_level(level),
|
||||||
Self::ProcMethod { before, after } => {
|
Self::ProcMethod { before, after } => {
|
||||||
before.update_level(level);
|
before.update_level(level);
|
||||||
after.as_ref().map(|t| {
|
if let Some(t) = after.as_ref() {
|
||||||
t.update_level(level);
|
t.update_level(level);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1485,9 +1485,9 @@ impl HasLevel for SubrKind {
|
||||||
Self::FuncMethod(t) => t.lift(),
|
Self::FuncMethod(t) => t.lift(),
|
||||||
Self::ProcMethod { before, after } => {
|
Self::ProcMethod { before, after } => {
|
||||||
before.lift();
|
before.lift();
|
||||||
after.as_ref().map(|t| {
|
if let Some(t) = after.as_ref() {
|
||||||
t.lift();
|
t.lift();
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1546,13 +1546,11 @@ impl SubrKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn same_kind_as(&self, other: &Self) -> bool {
|
pub fn same_kind_as(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
matches!((self, other),
|
||||||
(Self::Func, Self::Func)
|
(Self::Func, Self::Func)
|
||||||
| (Self::Proc, Self::Proc)
|
| (Self::Proc, Self::Proc)
|
||||||
| (Self::FuncMethod(_), Self::FuncMethod(_))
|
| (Self::FuncMethod(_), Self::FuncMethod(_))
|
||||||
| (Self::ProcMethod { .. }, Self::ProcMethod { .. }) => true,
|
| (Self::ProcMethod { .. }, Self::ProcMethod { .. }))
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn self_t(&self) -> Option<&SelfType> {
|
pub fn self_t(&self) -> Option<&SelfType> {
|
||||||
|
@ -2029,7 +2027,7 @@ impl Type {
|
||||||
Predicate::le(name.clone(), r),
|
Predicate::le(name.clone(), r),
|
||||||
),
|
),
|
||||||
IntervalOp::Open if l == TyParam::value(NegInf) && r == TyParam::value(Inf) => {
|
IntervalOp::Open if l == TyParam::value(NegInf) && r == TyParam::value(Inf) => {
|
||||||
return Type::refinement(name.clone(), Type::Int, set! {})
|
return Type::refinement(name, Type::Int, set! {})
|
||||||
}
|
}
|
||||||
// l<..<r => {I: classof(l) | I >= l+ε and I <= r-ε}
|
// l<..<r => {I: classof(l) | I >= l+ε and I <= r-ε}
|
||||||
IntervalOp::Open => Predicate::and(
|
IntervalOp::Open => Predicate::and(
|
||||||
|
@ -2037,7 +2035,7 @@ impl Type {
|
||||||
Predicate::le(name.clone(), TyParam::pred(r)),
|
Predicate::le(name.clone(), TyParam::pred(r)),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
Type::refinement(name.clone(), Type::Int, set! {pred})
|
Type::refinement(name, Type::Int, set! {pred})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(t: Type) -> Self {
|
pub fn iter(t: Type) -> Self {
|
||||||
|
@ -2333,7 +2331,7 @@ impl Type {
|
||||||
if fv.is_linked() {
|
if fv.is_linked() {
|
||||||
fv.crack().is_mut()
|
fv.crack().is_mut()
|
||||||
} else {
|
} else {
|
||||||
fv.unbound_name().unwrap().ends_with("!")
|
fv.unbound_name().unwrap().ends_with('!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::IntMut
|
Self::IntMut
|
||||||
|
@ -2346,7 +2344,7 @@ impl Type {
|
||||||
| Self::MonoQVar(name)
|
| Self::MonoQVar(name)
|
||||||
| Self::Poly { name, .. }
|
| Self::Poly { name, .. }
|
||||||
| Self::PolyQVar { name, .. }
|
| Self::PolyQVar { name, .. }
|
||||||
| Self::MonoProj { rhs: name, .. } => name.ends_with("!"),
|
| Self::MonoProj { rhs: name, .. } => name.ends_with('!'),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2460,9 +2458,9 @@ impl Type {
|
||||||
},
|
},
|
||||||
) => todo!(),
|
) => todo!(),
|
||||||
(Self::Record(_l), Self::Record(_r)) => todo!(),
|
(Self::Record(_l), Self::Record(_r)) => todo!(),
|
||||||
(Self::Refinement(l), Self::Refinement(r)) => l.t.rec_eq(&r.t) && &l.preds == &r.preds,
|
(Self::Refinement(l), Self::Refinement(r)) => l.t.rec_eq(&r.t) && l.preds == r.preds,
|
||||||
(Self::Quantified(l), Self::Quantified(r)) => {
|
(Self::Quantified(l), Self::Quantified(r)) => {
|
||||||
l.unbound_callable.rec_eq(&r.unbound_callable) && &l.bounds == &r.bounds
|
l.unbound_callable.rec_eq(&r.unbound_callable) && l.bounds == r.bounds
|
||||||
}
|
}
|
||||||
(Self::And(l), Self::And(r))
|
(Self::And(l), Self::And(r))
|
||||||
| (Self::Not(l), Self::Not(r))
|
| (Self::Not(l), Self::Not(r))
|
||||||
|
@ -2567,7 +2565,7 @@ impl Type {
|
||||||
Self::Callable { .. } => "Callable",
|
Self::Callable { .. } => "Callable",
|
||||||
Self::Record(_) => "Record",
|
Self::Record(_) => "Record",
|
||||||
Self::VarArgs(_) => "VarArgs",
|
Self::VarArgs(_) => "VarArgs",
|
||||||
Self::Poly { name, .. } | Self::PolyQVar { name, .. } => &*name,
|
Self::Poly { name, .. } | Self::PolyQVar { name, .. } => name,
|
||||||
// NOTE: compiler/codegen/convert_to_python_methodでクラス名を使うため、こうすると都合が良い
|
// NOTE: compiler/codegen/convert_to_python_methodでクラス名を使うため、こうすると都合が良い
|
||||||
Self::Refinement(refine) => refine.t.name(),
|
Self::Refinement(refine) => refine.t.name(),
|
||||||
Self::Quantified(_) => "Quantified",
|
Self::Quantified(_) => "Quantified",
|
||||||
|
@ -3038,7 +3036,7 @@ impl From<u8> for TypePair {
|
||||||
62 => Self::ProcArray,
|
62 => Self::ProcArray,
|
||||||
63 => Self::ProcProc,
|
63 => Self::ProcProc,
|
||||||
64 => Self::Others,
|
64 => Self::Others,
|
||||||
65 | _ => Self::Illegals,
|
_ => Self::Illegals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! コンパイラ、VM等で使われる(データも保持した)値オブジェクトを定義する
|
//! コンパイラ、VM等で使われる(データも保持した)値オブジェクトを定義する
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt::{self, Write};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -56,7 +56,7 @@ impl fmt::Debug for ValueObj {
|
||||||
Self::Dict(dict) => {
|
Self::Dict(dict) => {
|
||||||
let mut s = "".to_string();
|
let mut s = "".to_string();
|
||||||
for (k, v) in dict.iter() {
|
for (k, v) in dict.iter() {
|
||||||
s += &format!("{k}: {v}, ");
|
write!(s, "{k}: {v}, ")?;
|
||||||
}
|
}
|
||||||
s.pop();
|
s.pop();
|
||||||
s.pop();
|
s.pop();
|
||||||
|
@ -255,11 +255,11 @@ impl ValueObj {
|
||||||
|
|
||||||
pub fn from_str(t: Type, content: Str) -> Self {
|
pub fn from_str(t: Type, content: Str) -> Self {
|
||||||
match t {
|
match t {
|
||||||
Type::Int => Self::Int(content.replace("_", "").parse::<i32>().unwrap()),
|
Type::Int => Self::Int(content.replace('_', "").parse::<i32>().unwrap()),
|
||||||
Type::Nat => Self::Nat(content.replace("_", "").parse::<u64>().unwrap()),
|
Type::Nat => Self::Nat(content.replace('_', "").parse::<u64>().unwrap()),
|
||||||
Type::Float => Self::Float(content.replace("_", "").parse::<f64>().unwrap()),
|
Type::Float => Self::Float(content.replace('_', "").parse::<f64>().unwrap()),
|
||||||
// TODO:
|
// TODO:
|
||||||
Type::Ratio => Self::Float(content.replace("_", "").parse::<f64>().unwrap()),
|
Type::Ratio => Self::Float(content.replace('_', "").parse::<f64>().unwrap()),
|
||||||
Type::Str => {
|
Type::Str => {
|
||||||
if &content[..] == "\"\"" {
|
if &content[..] == "\"\"" {
|
||||||
Self::Str(Str::from(""))
|
Self::Str(Str::from(""))
|
||||||
|
@ -288,18 +288,18 @@ impl ValueObj {
|
||||||
match self {
|
match self {
|
||||||
Self::Int(i) => [
|
Self::Int(i) => [
|
||||||
vec![DataTypePrefix::Int32 as u8],
|
vec![DataTypePrefix::Int32 as u8],
|
||||||
i32::from(i).to_le_bytes().to_vec(),
|
i.to_le_bytes().to_vec(),
|
||||||
]
|
]
|
||||||
.concat(),
|
.concat(),
|
||||||
// TODO: Natとしてシリアライズ
|
// TODO: Natとしてシリアライズ
|
||||||
Self::Nat(n) => [
|
Self::Nat(n) => [
|
||||||
vec![DataTypePrefix::Int32 as u8],
|
vec![DataTypePrefix::Int32 as u8],
|
||||||
i32::from(n as i32).to_le_bytes().to_vec(),
|
(n as i32).to_le_bytes().to_vec(),
|
||||||
]
|
]
|
||||||
.concat(),
|
.concat(),
|
||||||
Self::Float(f) => [
|
Self::Float(f) => [
|
||||||
vec![DataTypePrefix::BinFloat as u8],
|
vec![DataTypePrefix::BinFloat as u8],
|
||||||
f64::from(f).to_le_bytes().to_vec(),
|
f.to_le_bytes().to_vec(),
|
||||||
]
|
]
|
||||||
.concat(),
|
.concat(),
|
||||||
Self::Str(s) => str_into_bytes(s, false),
|
Self::Str(s) => str_into_bytes(s, false),
|
||||||
|
@ -310,7 +310,7 @@ impl ValueObj {
|
||||||
let mut bytes = Vec::with_capacity(arr.len());
|
let mut bytes = Vec::with_capacity(arr.len());
|
||||||
bytes.push(DataTypePrefix::Tuple as u8);
|
bytes.push(DataTypePrefix::Tuple as u8);
|
||||||
bytes.append(&mut (arr.len() as u32).to_le_bytes().to_vec());
|
bytes.append(&mut (arr.len() as u32).to_le_bytes().to_vec());
|
||||||
for obj in arr.to_vec().into_iter() {
|
for obj in arr.iter().cloned() {
|
||||||
bytes.append(&mut obj.into_bytes());
|
bytes.append(&mut obj.into_bytes());
|
||||||
}
|
}
|
||||||
bytes
|
bytes
|
||||||
|
|
|
@ -51,8 +51,8 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -
|
||||||
|
|
||||||
fn escape_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -> Str {
|
fn escape_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -> Str {
|
||||||
let mut name = convert_to_python_attr(class, uniq_obj_name, name).to_string();
|
let mut name = convert_to_python_attr(class, uniq_obj_name, name).to_string();
|
||||||
name = name.replace("!", "__erg_proc__");
|
name = name.replace('!', "__erg_proc__");
|
||||||
name = name.replace("$", "__erg_shared__");
|
name = name.replace('$', "__erg_shared__");
|
||||||
Str::rc(&name)
|
Str::rc(&name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,8 +78,8 @@ fn convert_to_python_name(name: Str) -> Str {
|
||||||
|
|
||||||
fn escape_name(name: Str) -> Str {
|
fn escape_name(name: Str) -> Str {
|
||||||
let mut name = convert_to_python_name(name).to_string();
|
let mut name = convert_to_python_name(name).to_string();
|
||||||
name = name.replace("!", "__erg_proc__");
|
name = name.replace('!', "__erg_proc__");
|
||||||
name = name.replace("$", "__erg_shared__");
|
name = name.replace('$', "__erg_shared__");
|
||||||
Str::rc(&name)
|
Str::rc(&name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,15 +290,12 @@ impl CodeGenerator {
|
||||||
} else {
|
} else {
|
||||||
Some(Name::fast(idx))
|
Some(Name::fast(idx))
|
||||||
}
|
}
|
||||||
} else if let Some(idx) = self
|
} else { self
|
||||||
.cur_block_codeobj()
|
.cur_block_codeobj()
|
||||||
.freevars
|
.freevars
|
||||||
.iter()
|
.iter()
|
||||||
.position(|f| &**f == name)
|
.position(|f| &**f == name)
|
||||||
{
|
.map(Name::deref)
|
||||||
Some(Name::deref(idx))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +304,7 @@ impl CodeGenerator {
|
||||||
// search_name()を実行した後なのでcur_blockはskipする
|
// search_name()を実行した後なのでcur_blockはskipする
|
||||||
for (nth_from_toplevel, block) in self.units.iter_mut().enumerate().rev().skip(1) {
|
for (nth_from_toplevel, block) in self.units.iter_mut().enumerate().rev().skip(1) {
|
||||||
let block_is_toplevel = nth_from_toplevel == 0;
|
let block_is_toplevel = nth_from_toplevel == 0;
|
||||||
if let Some(_) = block.codeobj.cellvars.iter().position(|c| &**c == name) {
|
if block.codeobj.cellvars.iter().any(|c| &**c == name) {
|
||||||
return Some(StoreLoadKind::Deref);
|
return Some(StoreLoadKind::Deref);
|
||||||
} else if let Some(idx) = block.codeobj.varnames.iter().position(|v| &**v == name) {
|
} else if let Some(idx) = block.codeobj.varnames.iter().position(|v| &**v == name) {
|
||||||
if block_is_toplevel {
|
if block_is_toplevel {
|
||||||
|
@ -319,12 +316,10 @@ impl CodeGenerator {
|
||||||
return Some(StoreLoadKind::Deref);
|
return Some(StoreLoadKind::Deref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if block_is_toplevel {
|
if block_is_toplevel && block.codeobj.names.iter().any(|n| &**n == name) {
|
||||||
if let Some(_) = block.codeobj.names.iter().position(|n| &**n == name) {
|
|
||||||
return Some(StoreLoadKind::Global);
|
return Some(StoreLoadKind::Global);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// 見つからなかった変数(前方参照変数など)はグローバル
|
// 見つからなかった変数(前方参照変数など)はグローバル
|
||||||
Some(StoreLoadKind::Global)
|
Some(StoreLoadKind::Global)
|
||||||
}
|
}
|
||||||
|
@ -363,14 +358,14 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_attr(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name {
|
fn register_attr(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name {
|
||||||
let name = Str::rc(name.split(".").last().unwrap());
|
let name = Str::rc(name.split('.').last().unwrap());
|
||||||
let name = escape_attr(class, uniq_obj_name, name);
|
let name = escape_attr(class, uniq_obj_name, name);
|
||||||
self.mut_cur_block_codeobj().names.push(name);
|
self.mut_cur_block_codeobj().names.push(name);
|
||||||
Name::local(self.cur_block_codeobj().names.len() - 1)
|
Name::local(self.cur_block_codeobj().names.len() - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_method(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name {
|
fn register_method(&mut self, class: &str, uniq_obj_name: Option<&str>, name: Str) -> Name {
|
||||||
let name = Str::rc(name.split(".").last().unwrap());
|
let name = Str::rc(name.split('.').last().unwrap());
|
||||||
let name = escape_attr(class, uniq_obj_name, name);
|
let name = escape_attr(class, uniq_obj_name, name);
|
||||||
self.mut_cur_block_codeobj().names.push(name);
|
self.mut_cur_block_codeobj().names.push(name);
|
||||||
Name::local(self.cur_block_codeobj().names.len() - 1)
|
Name::local(self.cur_block_codeobj().names.len() - 1)
|
||||||
|
@ -493,7 +488,7 @@ impl CodeGenerator {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")),
|
.map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")),
|
||||||
)
|
)
|
||||||
.map(|s| self.get_cached(&s))
|
.map(|s| self.get_cached(s))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +585,7 @@ impl CodeGenerator {
|
||||||
let idx_pop_jump_if_false = self.cur_block().lasti;
|
let idx_pop_jump_if_false = self.cur_block().lasti;
|
||||||
self.write_instr(POP_JUMP_IF_FALSE);
|
self.write_instr(POP_JUMP_IF_FALSE);
|
||||||
// cannot detect where to jump to at this moment, so put as 0
|
// cannot detect where to jump to at this moment, so put as 0
|
||||||
self.write_arg(0 as u8);
|
self.write_arg(0_u8);
|
||||||
match args.remove(0) {
|
match args.remove(0) {
|
||||||
// then block
|
// then block
|
||||||
Expr::Lambda(lambda) => {
|
Expr::Lambda(lambda) => {
|
||||||
|
@ -603,7 +598,7 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
if args.get(0).is_some() {
|
if args.get(0).is_some() {
|
||||||
self.write_instr(JUMP_FORWARD); // jump to end
|
self.write_instr(JUMP_FORWARD); // jump to end
|
||||||
self.write_arg(0 as u8);
|
self.write_arg(0_u8);
|
||||||
// else block
|
// else block
|
||||||
let idx_else_begin = self.cur_block().lasti;
|
let idx_else_begin = self.cur_block().lasti;
|
||||||
self.edit_code(idx_pop_jump_if_false + 1, idx_else_begin / 2);
|
self.edit_code(idx_pop_jump_if_false + 1, idx_else_begin / 2);
|
||||||
|
@ -659,7 +654,7 @@ impl CodeGenerator {
|
||||||
let mut absolute_jump_points = vec![];
|
let mut absolute_jump_points = vec![];
|
||||||
while let Some(expr) = args.try_remove(0) {
|
while let Some(expr) = args.try_remove(0) {
|
||||||
// パターンが複数ある場合引数を複製する、ただし最後はしない
|
// パターンが複数ある場合引数を複製する、ただし最後はしない
|
||||||
if len > 1 && args.len() > 0 {
|
if len > 1 && !args.is_empty() {
|
||||||
self.write_instr(Opcode::DUP_TOP);
|
self.write_instr(Opcode::DUP_TOP);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_inc();
|
self.stack_inc();
|
||||||
|
@ -1145,9 +1140,9 @@ impl CodeGenerator {
|
||||||
if !self.units.is_empty() {
|
if !self.units.is_empty() {
|
||||||
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
|
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
|
||||||
if ld != 0 {
|
if ld != 0 {
|
||||||
self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| {
|
if let Some(l) = self.mut_cur_block_codeobj().lnotab.last_mut() {
|
||||||
*l += ld as u8;
|
*l += ld as u8;
|
||||||
});
|
}
|
||||||
self.mut_cur_block().prev_lineno += ld;
|
self.mut_cur_block().prev_lineno += ld;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1204,9 +1199,9 @@ impl CodeGenerator {
|
||||||
if !self.units.is_empty() {
|
if !self.units.is_empty() {
|
||||||
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
|
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
|
||||||
if ld != 0 {
|
if ld != 0 {
|
||||||
self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| {
|
if let Some(l) = self.mut_cur_block_codeobj().lnotab.last_mut() {
|
||||||
*l += ld as u8;
|
*l += ld as u8;
|
||||||
});
|
}
|
||||||
self.mut_cur_block().prev_lineno += ld;
|
self.mut_cur_block().prev_lineno += ld;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1242,7 +1237,7 @@ impl CodeGenerator {
|
||||||
self.edit_code(print_point, Opcode::NOP as usize);
|
self.edit_code(print_point, Opcode::NOP as usize);
|
||||||
} else {
|
} else {
|
||||||
self.write_instr(CALL_FUNCTION);
|
self.write_instr(CALL_FUNCTION);
|
||||||
self.write_arg(1 as u8);
|
self.write_arg(1_u8);
|
||||||
}
|
}
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
|
@ -1271,9 +1266,9 @@ impl CodeGenerator {
|
||||||
if !self.units.is_empty() {
|
if !self.units.is_empty() {
|
||||||
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
|
let ld = unit.prev_lineno - self.cur_block().prev_lineno;
|
||||||
if ld != 0 {
|
if ld != 0 {
|
||||||
self.mut_cur_block_codeobj().lnotab.last_mut().map(|l| {
|
if let Some(l) = self.mut_cur_block_codeobj().lnotab.last_mut() {
|
||||||
*l += ld as u8;
|
*l += ld as u8;
|
||||||
});
|
}
|
||||||
self.mut_cur_block().prev_lineno += ld;
|
self.mut_cur_block().prev_lineno += ld;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ impl TyVarContext {
|
||||||
Type::Poly { params, .. } => params.iter().fold(dep, |acc, arg| {
|
Type::Poly { params, .. } => params.iter().fold(dep, |acc, arg| {
|
||||||
[acc, Self::rec_tp_inner_qvars(arg, vec![])].concat()
|
[acc, Self::rec_tp_inner_qvars(arg, vec![])].concat()
|
||||||
}),
|
}),
|
||||||
Type::VarArgs(t) => Self::rec_t_inner_qvars(&t, dep),
|
Type::VarArgs(t) => Self::rec_t_inner_qvars(t, dep),
|
||||||
Type::Subr(_subr) => todo!(),
|
Type::Subr(_subr) => todo!(),
|
||||||
Type::Callable { param_ts: _, return_t: _ } => todo!(),
|
Type::Callable { param_ts: _, return_t: _ } => todo!(),
|
||||||
Type::And(_) | Type::Or(_) | Type::Not(_) => todo!(),
|
Type::And(_) | Type::Or(_) | Type::Not(_) => todo!(),
|
||||||
|
@ -210,11 +210,10 @@ impl TyVarContext {
|
||||||
TyBound::Subtype { sub, sup } => {
|
TyBound::Subtype { sub, sup } => {
|
||||||
let sup = match sup {
|
let sup = match sup {
|
||||||
Type::Poly { name, params } => {
|
Type::Poly { name, params } => {
|
||||||
let sup = Type::poly(
|
Type::poly(
|
||||||
name,
|
name,
|
||||||
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
||||||
);
|
)
|
||||||
sup
|
|
||||||
}
|
}
|
||||||
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
|
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
|
||||||
sup => sup,
|
sup => sup,
|
||||||
|
@ -226,11 +225,10 @@ impl TyVarContext {
|
||||||
TyBound::Supertype { sup, sub } => {
|
TyBound::Supertype { sup, sub } => {
|
||||||
let sub = match sub {
|
let sub = match sub {
|
||||||
Type::Poly { name, params } => {
|
Type::Poly { name, params } => {
|
||||||
let sub = Type::poly(
|
Type::poly(
|
||||||
name,
|
name,
|
||||||
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
||||||
);
|
)
|
||||||
sub
|
|
||||||
}
|
}
|
||||||
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
|
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
|
||||||
sub => sub,
|
sub => sub,
|
||||||
|
@ -242,22 +240,20 @@ impl TyVarContext {
|
||||||
TyBound::Sandwiched { sub, mid, sup } => {
|
TyBound::Sandwiched { sub, mid, sup } => {
|
||||||
let sub = match sub {
|
let sub = match sub {
|
||||||
Type::Poly { name, params } => {
|
Type::Poly { name, params } => {
|
||||||
let sub = Type::poly(
|
Type::poly(
|
||||||
name,
|
name,
|
||||||
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
||||||
);
|
)
|
||||||
sub
|
|
||||||
}
|
}
|
||||||
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
|
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
|
||||||
sub => sub,
|
sub => sub,
|
||||||
};
|
};
|
||||||
let sup = match sup {
|
let sup = match sup {
|
||||||
Type::Poly { name, params } => {
|
Type::Poly { name, params } => {
|
||||||
let sup = Type::poly(
|
Type::poly(
|
||||||
name,
|
name,
|
||||||
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
||||||
);
|
)
|
||||||
sup
|
|
||||||
}
|
}
|
||||||
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
|
Type::MonoProj { lhs, rhs } => Type::mono_proj(self.instantiate_t(*lhs), rhs),
|
||||||
sup => sup,
|
sup => sup,
|
||||||
|
@ -269,16 +265,15 @@ impl TyVarContext {
|
||||||
TyBound::Instance { name, t } => {
|
TyBound::Instance { name, t } => {
|
||||||
let t = match t {
|
let t = match t {
|
||||||
Type::Poly { name, params } => {
|
Type::Poly { name, params } => {
|
||||||
let t = Type::poly(
|
Type::poly(
|
||||||
name,
|
name,
|
||||||
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
params.into_iter().map(|p| self.instantiate_tp(p)).collect(),
|
||||||
);
|
)
|
||||||
t
|
|
||||||
}
|
}
|
||||||
t => t,
|
t => t,
|
||||||
};
|
};
|
||||||
// TODO: type-like types
|
// TODO: type-like types
|
||||||
if &t == &Type {
|
if t == Type {
|
||||||
let constraint = Constraint::TypeOf(t);
|
let constraint = Constraint::TypeOf(t);
|
||||||
self.push_tyvar(
|
self.push_tyvar(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
|
@ -299,10 +294,10 @@ impl TyVarContext {
|
||||||
match quantified {
|
match quantified {
|
||||||
Type::MonoQVar(n) => {
|
Type::MonoQVar(n) => {
|
||||||
if let Some(t) = self.get_tyvar(&n) {
|
if let Some(t) = self.get_tyvar(&n) {
|
||||||
return t.clone();
|
t.clone()
|
||||||
} else if let Some(t) = self.get_typaram(&n) {
|
} else if let Some(t) = self.get_typaram(&n) {
|
||||||
if let TyParam::Type(t) = t {
|
if let TyParam::Type(t) = t {
|
||||||
return *t.clone();
|
*t.clone()
|
||||||
} else {
|
} else {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -318,9 +313,9 @@ impl TyVarContext {
|
||||||
match quantified {
|
match quantified {
|
||||||
TyParam::MonoQVar(n) => {
|
TyParam::MonoQVar(n) => {
|
||||||
if let Some(t) = self.get_typaram(&n) {
|
if let Some(t) = self.get_typaram(&n) {
|
||||||
return t.clone();
|
t.clone()
|
||||||
} else if let Some(t) = self.get_tyvar(&n) {
|
} else if let Some(t) = self.get_tyvar(&n) {
|
||||||
return TyParam::t(t.clone());
|
TyParam::t(t.clone())
|
||||||
} else {
|
} else {
|
||||||
panic!("Type parameter {n} is not found. This is a bug.")
|
panic!("Type parameter {n} is not found. This is a bug.")
|
||||||
}
|
}
|
||||||
|
@ -328,9 +323,9 @@ impl TyVarContext {
|
||||||
TyParam::Type(t) => {
|
TyParam::Type(t) => {
|
||||||
if let Type::MonoQVar(n) = *t {
|
if let Type::MonoQVar(n) = *t {
|
||||||
if let Some(t) = self.get_typaram(&n) {
|
if let Some(t) = self.get_typaram(&n) {
|
||||||
return t.clone();
|
t.clone()
|
||||||
} else if let Some(t) = self.get_tyvar(&n) {
|
} else if let Some(t) = self.get_tyvar(&n) {
|
||||||
return TyParam::t(t.clone());
|
TyParam::t(t.clone())
|
||||||
} else {
|
} else {
|
||||||
panic!("Type variable {n} is not found. This is a bug.")
|
panic!("Type variable {n} is not found. This is a bug.")
|
||||||
}
|
}
|
||||||
|
@ -710,9 +705,7 @@ impl Context {
|
||||||
v.inspect(),
|
v.inspect(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let kind = id
|
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
||||||
.map(|id| VarKind::Defined(id))
|
|
||||||
.unwrap_or(VarKind::Declared);
|
|
||||||
let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?;
|
let sig_t = self.instantiate_var_sig_t(sig, opt_t, PreRegister)?;
|
||||||
self.decls
|
self.decls
|
||||||
.insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind));
|
.insert(v.clone(), VarInfo::new(sig_t, muty, vis, kind));
|
||||||
|
@ -743,9 +736,7 @@ impl Context {
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
let name = sig.name.inspect();
|
let name = sig.name.inspect();
|
||||||
let muty = Mutability::from(&name[..]);
|
let muty = Mutability::from(&name[..]);
|
||||||
let kind = id
|
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
||||||
.map(|id| VarKind::Defined(id))
|
|
||||||
.unwrap_or(VarKind::Declared);
|
|
||||||
if self.registered(name, name.is_uppercase()) {
|
if self.registered(name, name.is_uppercase()) {
|
||||||
return Err(TyCheckError::duplicate_decl_error(
|
return Err(TyCheckError::duplicate_decl_error(
|
||||||
sig.loc(),
|
sig.loc(),
|
||||||
|
@ -805,7 +796,7 @@ impl Context {
|
||||||
v.inspect(),
|
v.inspect(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
if let Some(_) = self.decls.remove(v.inspect()) {
|
if self.decls.remove(v.inspect()).is_some() {
|
||||||
// something to do?
|
// something to do?
|
||||||
}
|
}
|
||||||
let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id));
|
let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id));
|
||||||
|
@ -957,7 +948,7 @@ impl Context {
|
||||||
let name = &sig.name;
|
let name = &sig.name;
|
||||||
// FIXME: constでない関数
|
// FIXME: constでない関数
|
||||||
let t = self
|
let t = self
|
||||||
.get_current_scope_var(&name.inspect())
|
.get_current_scope_var(name.inspect())
|
||||||
.map(|v| &v.t)
|
.map(|v| &v.t)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let non_default_params = t.non_default_params().unwrap();
|
let non_default_params = t.non_default_params().unwrap();
|
||||||
|
@ -1490,7 +1481,7 @@ impl Context {
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
// REVIEW:
|
// REVIEW:
|
||||||
let name = callee.var_full_name().unwrap_or("".to_string());
|
let name = callee.var_full_name().unwrap_or_else(|| "".to_string());
|
||||||
let name =
|
let name =
|
||||||
name + "::" + param_ty.name.as_ref().map(|s| &s[..]).unwrap_or("");
|
name + "::" + param_ty.name.as_ref().map(|s| &s[..]).unwrap_or("");
|
||||||
TyCheckError::type_mismatch_error(
|
TyCheckError::type_mismatch_error(
|
||||||
|
@ -1649,19 +1640,13 @@ impl Context {
|
||||||
|
|
||||||
/// 可変依存型の変更を伝搬させる
|
/// 可変依存型の変更を伝搬させる
|
||||||
fn propagate(&self, t: &Type, callee: &hir::Expr) -> TyCheckResult<()> {
|
fn propagate(&self, t: &Type, callee: &hir::Expr) -> TyCheckResult<()> {
|
||||||
match t {
|
if let Type::Subr(SubrType {
|
||||||
Type::Subr(subr) => match &subr.kind {
|
kind: SubrKind::ProcMethod { after: Some(after), .. },
|
||||||
SubrKind::ProcMethod {
|
..
|
||||||
before: _,
|
}) = t {
|
||||||
after: Some(after),
|
|
||||||
} => {
|
|
||||||
let receiver_t = callee.receiver_t().unwrap();
|
let receiver_t = callee.receiver_t().unwrap();
|
||||||
self.reunify(receiver_t, after, Some(callee.loc()), None)?;
|
self.reunify(receiver_t, after, Some(callee.loc()), None)?;
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1682,7 +1667,7 @@ impl Context {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
match (l, r) {
|
match (l, r) {
|
||||||
(TyParam::Type(l), TyParam::Type(r)) => self.unify(&l, &r, None, None),
|
(TyParam::Type(l), TyParam::Type(r)) => self.unify(l, r, None, None),
|
||||||
(ltp @ TyParam::FreeVar(lfv), rtp @ TyParam::FreeVar(rfv))
|
(ltp @ TyParam::FreeVar(lfv), rtp @ TyParam::FreeVar(rfv))
|
||||||
if lfv.is_unbound() && rfv.is_unbound() =>
|
if lfv.is_unbound() && rfv.is_unbound() =>
|
||||||
{
|
{
|
||||||
|
@ -1701,11 +1686,11 @@ impl Context {
|
||||||
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {}
|
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {}
|
||||||
} // &fv is dropped
|
} // &fv is dropped
|
||||||
let fv_t = fv.borrow().constraint().unwrap().typ().unwrap().clone(); // fvを参照しないよいにcloneする(あとでborrow_mutするため)
|
let fv_t = fv.borrow().constraint().unwrap().typ().unwrap().clone(); // fvを参照しないよいにcloneする(あとでborrow_mutするため)
|
||||||
let tp_t = self.eval.get_tp_t(tp, bounds, &self)?;
|
let tp_t = self.eval.get_tp_t(tp, bounds, self)?;
|
||||||
if self.rec_full_supertype_of(&fv_t, &tp_t) {
|
if self.rec_full_supertype_of(&fv_t, &tp_t) {
|
||||||
// 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md)
|
// 外部未連携型変数の場合、linkしないで制約を弱めるだけにする(see compiler/inference.md)
|
||||||
if fv.level() < Some(self.level) {
|
if fv.level() < Some(self.level) {
|
||||||
let new_constraint = Constraint::SubtypeOf(tp_t.clone());
|
let new_constraint = Constraint::SubtypeOf(tp_t);
|
||||||
if self.is_sub_constraint_of(
|
if self.is_sub_constraint_of(
|
||||||
fv.borrow().constraint().unwrap(),
|
fv.borrow().constraint().unwrap(),
|
||||||
&new_constraint,
|
&new_constraint,
|
||||||
|
@ -1717,10 +1702,9 @@ impl Context {
|
||||||
fv.link(tp);
|
fv.link(tp);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else if allow_divergence
|
||||||
if allow_divergence
|
&& (self.eq_tp(tp, &TyParam::value(Inf), None, None)
|
||||||
&& (self.eq_tp(&tp, &TyParam::value(Inf), None, None)
|
|| self.eq_tp(tp, &TyParam::value(NegInf), None, None))
|
||||||
|| self.eq_tp(&tp, &TyParam::value(NegInf), None, None))
|
|
||||||
&& self.rec_full_subtype_of(&fv_t, &Type::mono("Num"))
|
&& self.rec_full_subtype_of(&fv_t, &Type::mono("Num"))
|
||||||
{
|
{
|
||||||
fv.link(tp);
|
fv.link(tp);
|
||||||
|
@ -1729,7 +1713,6 @@ impl Context {
|
||||||
Err(TyCheckError::unreachable(fn_name!(), line!()))
|
Err(TyCheckError::unreachable(fn_name!(), line!()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval })
|
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval })
|
||||||
if lop == rop =>
|
if lop == rop =>
|
||||||
{
|
{
|
||||||
|
@ -1769,7 +1752,7 @@ impl Context {
|
||||||
*l.borrow_mut() = r.borrow().clone();
|
*l.borrow_mut() = r.borrow().clone();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
(TyParam::Type(l), TyParam::Type(r)) => self.reunify(&l, &r, None, None),
|
(TyParam::Type(l), TyParam::Type(r)) => self.reunify(l, r, None, None),
|
||||||
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval })
|
(TyParam::UnaryOp { op: lop, val: lval }, TyParam::UnaryOp { op: rop, val: rval })
|
||||||
if lop == rop =>
|
if lop == rop =>
|
||||||
{
|
{
|
||||||
|
@ -2333,7 +2316,7 @@ impl Context {
|
||||||
self.instantiate_typespec(spec, mode)?
|
self.instantiate_typespec(spec, mode)?
|
||||||
} else {
|
} else {
|
||||||
match &sig.pat {
|
match &sig.pat {
|
||||||
ast::ParamPattern::Lit(lit) => Type::enum_t(set![self.eval.eval_const_lit(&lit)]),
|
ast::ParamPattern::Lit(lit) => Type::enum_t(set![self.eval.eval_const_lit(lit)]),
|
||||||
// TODO: Array<Lit>
|
// TODO: Array<Lit>
|
||||||
_ => {
|
_ => {
|
||||||
let level = if mode == PreRegister {
|
let level = if mode == PreRegister {
|
||||||
|
@ -2607,7 +2590,7 @@ impl Context {
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
"match",
|
"match",
|
||||||
&Type::mono("LambdaFunc"),
|
&Type::mono("LambdaFunc"),
|
||||||
&t,
|
t,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2633,13 +2616,13 @@ impl Context {
|
||||||
// NG: expr_t: Nat, union_pat_t: {1, 2}
|
// NG: expr_t: Nat, union_pat_t: {1, 2}
|
||||||
// OK: expr_t: Int, union_pat_t: {1} | 'T
|
// OK: expr_t: Int, union_pat_t: {1} | 'T
|
||||||
if expr_t.has_no_unbound_var()
|
if expr_t.has_no_unbound_var()
|
||||||
&& self.formal_supertype_of(&expr_t, &union_pat_t, None, None)
|
&& self.formal_supertype_of(expr_t, &union_pat_t, None, None)
|
||||||
&& !self.formal_supertype_of(&union_pat_t, &expr_t, None, None)
|
&& !self.formal_supertype_of(&union_pat_t, expr_t, None, None)
|
||||||
{
|
{
|
||||||
return Err(TyCheckError::match_error(
|
return Err(TyCheckError::match_error(
|
||||||
pos_args[0].loc(),
|
pos_args[0].loc(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
&expr_t,
|
expr_t,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let branch_ts = pos_args
|
let branch_ts = pos_args
|
||||||
|
@ -2658,7 +2641,7 @@ impl Context {
|
||||||
};
|
};
|
||||||
let param_ts = [
|
let param_ts = [
|
||||||
vec![ParamTy::anonymous(expr_t)],
|
vec![ParamTy::anonymous(expr_t)],
|
||||||
branch_ts.iter().map(|pt| pt.clone()).collect(),
|
branch_ts.to_vec(),
|
||||||
]
|
]
|
||||||
.concat();
|
.concat();
|
||||||
let t = Type::func(param_ts, vec![], return_t);
|
let t = Type::func(param_ts, vec![], return_t);
|
||||||
|
@ -2749,8 +2732,8 @@ impl Context {
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
erg_common::debug_power_assert!(args.len() == 2);
|
erg_common::debug_power_assert!(args.len() == 2);
|
||||||
let symbol = Token::symbol(binop_to_dname(op.inspect()));
|
let symbol = Token::symbol(binop_to_dname(op.inspect()));
|
||||||
let mut op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
|
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
|
||||||
self.get_call_t(&mut op, args, &[], namespace).map_err(|e| {
|
self.get_call_t(&op, args, &[], namespace).map_err(|e| {
|
||||||
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
|
// HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
|
||||||
let core = ErrorCore::new(
|
let core = ErrorCore::new(
|
||||||
e.core.errno,
|
e.core.errno,
|
||||||
|
@ -2771,8 +2754,8 @@ impl Context {
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
erg_common::debug_power_assert!(args.len() == 1);
|
erg_common::debug_power_assert!(args.len() == 1);
|
||||||
let symbol = Token::symbol(unaryop_to_dname(op.inspect()));
|
let symbol = Token::symbol(unaryop_to_dname(op.inspect()));
|
||||||
let mut op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
|
let op = hir::Expr::Accessor(hir::Accessor::local(symbol, Type::ASTOmitted));
|
||||||
self.get_call_t(&mut op, args, &[], namespace).map_err(|e| {
|
self.get_call_t(&op, args, &[], namespace).map_err(|e| {
|
||||||
let core = ErrorCore::new(
|
let core = ErrorCore::new(
|
||||||
e.core.errno,
|
e.core.errno,
|
||||||
e.core.kind,
|
e.core.kind,
|
||||||
|
@ -2809,7 +2792,7 @@ impl Context {
|
||||||
log!("Substituted:\ninstance: {instance}");
|
log!("Substituted:\ninstance: {instance}");
|
||||||
let res = self.deref_tyvar(instance)?;
|
let res = self.deref_tyvar(instance)?;
|
||||||
log!("Eliminated:\nres: {res}\n");
|
log!("Eliminated:\nres: {res}\n");
|
||||||
let res = self.eval.eval_t_params(res, &self, self.level)?;
|
let res = self.eval.eval_t_params(res, self, self.level)?;
|
||||||
log!("Params Evaluated:\nres: {res}\n");
|
log!("Params Evaluated:\nres: {res}\n");
|
||||||
let res = self.deref_tyvar(res)?;
|
let res = self.deref_tyvar(res)?;
|
||||||
log!("Eliminated (2):\nres: {res}\n");
|
log!("Eliminated (2):\nres: {res}\n");
|
||||||
|
@ -2873,13 +2856,13 @@ impl Context {
|
||||||
| FreeKind::NamedUnbound { constraint, .. } => {
|
| FreeKind::NamedUnbound { constraint, .. } => {
|
||||||
let t = constraint.typ().unwrap();
|
let t = constraint.typ().unwrap();
|
||||||
let other_t = self.type_of(other, bounds);
|
let other_t = self.type_of(other, bounds);
|
||||||
return self.formal_supertype_of(&t, &other_t, bounds, lhs_variance);
|
return self.formal_supertype_of(t, &other_t, bounds, lhs_variance);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(l, r) if l == r => return true,
|
(l, r) if l == r => return true,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.eval.shallow_eq_tp(lhs, rhs, &self)
|
self.eval.shallow_eq_tp(lhs, rhs, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// e.g.
|
/// e.g.
|
||||||
|
@ -3292,7 +3275,7 @@ impl Context {
|
||||||
// try_cmp((n: 2.._), 1) -> Some(Greater)
|
// try_cmp((n: 2.._), 1) -> Some(Greater)
|
||||||
// try_cmp((n: -1.._), 1) -> Some(Any)
|
// try_cmp((n: -1.._), 1) -> Some(Any)
|
||||||
(l @ (TyParam::Erased(_) | TyParam::FreeVar(_) | TyParam::MonoQVar(_)), p) => {
|
(l @ (TyParam::Erased(_) | TyParam::FreeVar(_) | TyParam::MonoQVar(_)), p) => {
|
||||||
let t = self.eval.get_tp_t(l, bounds, &self).unwrap();
|
let t = self.eval.get_tp_t(l, bounds, self).unwrap();
|
||||||
let inf = self.inf(&t);
|
let inf = self.inf(&t);
|
||||||
let sup = self.sup(&t);
|
let sup = self.sup(&t);
|
||||||
if let (Some(inf), Some(sup)) = (inf, sup) {
|
if let (Some(inf), Some(sup)) = (inf, sup) {
|
||||||
|
@ -3355,7 +3338,7 @@ impl Context {
|
||||||
Refinement(r) => r,
|
Refinement(r) => r,
|
||||||
t => {
|
t => {
|
||||||
let var = Str::from(fresh_varname());
|
let var = Str::from(fresh_varname());
|
||||||
RefinementType::new(var.clone(), t, set! {})
|
RefinementType::new(var, t, set! {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3486,7 +3469,7 @@ impl Context {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn type_of(&self, p: &TyParam, bounds: Option<&Set<TyBound>>) -> Type {
|
fn type_of(&self, p: &TyParam, bounds: Option<&Set<TyBound>>) -> Type {
|
||||||
self.eval.get_tp_t(p, bounds, &self).unwrap()
|
self.eval.get_tp_t(p, bounds, self).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// sup/inf({±∞}) = ±∞ではあるが、Inf/NegInfにはOrdを実装しない
|
// sup/inf({±∞}) = ±∞ではあるが、Inf/NegInfにはOrdを実装しない
|
||||||
|
@ -3501,7 +3484,7 @@ impl Context {
|
||||||
if lhs == &refine.var =>
|
if lhs == &refine.var =>
|
||||||
{
|
{
|
||||||
if let Some(max) = &maybe_max {
|
if let Some(max) = &maybe_max {
|
||||||
if self.try_cmp(rhs, &max, None).unwrap() == Greater {
|
if self.try_cmp(rhs, max, None).unwrap() == Greater {
|
||||||
maybe_max = Some(rhs.clone());
|
maybe_max = Some(rhs.clone());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3529,7 +3512,7 @@ impl Context {
|
||||||
if lhs == &refine.var =>
|
if lhs == &refine.var =>
|
||||||
{
|
{
|
||||||
if let Some(min) = &maybe_min {
|
if let Some(min) = &maybe_min {
|
||||||
if self.try_cmp(rhs, &min, None).unwrap() == Less {
|
if self.try_cmp(rhs, min, None).unwrap() == Less {
|
||||||
maybe_min = Some(rhs.clone());
|
maybe_min = Some(rhs.clone());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3753,25 +3736,23 @@ impl Context {
|
||||||
|
|
||||||
fn rec_get_patch(&self, name: &VarName) -> Option<&Context> {
|
fn rec_get_patch(&self, name: &VarName) -> Option<&Context> {
|
||||||
if let Some(patch) = self.patches.get(name) {
|
if let Some(patch) = self.patches.get(name) {
|
||||||
return Some(patch);
|
Some(patch)
|
||||||
|
} else if let Some(outer) = &self.outer {
|
||||||
|
outer.rec_get_patch(name)
|
||||||
} else {
|
} else {
|
||||||
if let Some(outer) = &self.outer {
|
|
||||||
return outer.rec_get_patch(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn rec_get_mod(&self, name: &str) -> Option<&Context> {
|
fn rec_get_mod(&self, name: &str) -> Option<&Context> {
|
||||||
if let Some(mod_) = self.mods.get(name) {
|
if let Some(mod_) = self.mods.get(name) {
|
||||||
return Some(mod_);
|
Some(mod_)
|
||||||
|
} else if let Some(outer) = &self.outer {
|
||||||
|
outer.rec_get_mod(name)
|
||||||
} else {
|
} else {
|
||||||
if let Some(outer) = &self.outer {
|
|
||||||
return outer.rec_get_mod(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn rec_get_trait_impls(&self, name: &Str) -> Vec<Type> {
|
fn rec_get_trait_impls(&self, name: &Str) -> Vec<Type> {
|
||||||
let impls = if let Some(impls) = self.poly_trait_impls.get(name) {
|
let impls = if let Some(impls) = self.poly_trait_impls.get(name) {
|
||||||
|
@ -3785,14 +3766,13 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 再帰サブルーチン/型の推論を可能にするため、予め登録しておく
|
// 再帰サブルーチン/型の推論を可能にするため、予め登録しておく
|
||||||
pub(crate) fn preregister(&mut self, block: &Vec<ast::Expr>) -> TyCheckResult<()> {
|
pub(crate) fn preregister(&mut self, block: &[ast::Expr]) -> TyCheckResult<()> {
|
||||||
for expr in block.iter() {
|
for expr in block.iter() {
|
||||||
match expr {
|
if let ast::Expr::Def(def) = expr {
|
||||||
ast::Expr::Def(def) => {
|
|
||||||
let id = Some(def.body.id);
|
let id = Some(def.body.id);
|
||||||
let eval_body_t = || {
|
let eval_body_t = || {
|
||||||
self.eval
|
self.eval
|
||||||
.eval_const_block(&def.body.block, &self)
|
.eval_const_block(&def.body.block, self)
|
||||||
.map(|c| Type::enum_t(set![c]))
|
.map(|c| Type::enum_t(set![c]))
|
||||||
};
|
};
|
||||||
match &def.sig {
|
match &def.sig {
|
||||||
|
@ -3802,7 +3782,7 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
eval_body_t()
|
eval_body_t()
|
||||||
};
|
};
|
||||||
self.declare_sub(&sig, opt_ret_t, id)?;
|
self.declare_sub(sig, opt_ret_t, id)?;
|
||||||
}
|
}
|
||||||
ast::Signature::Var(sig) if sig.is_const() => {
|
ast::Signature::Var(sig) if sig.is_const() => {
|
||||||
let t = if let Some(spec) = sig.t_spec.as_ref() {
|
let t = if let Some(spec) = sig.t_spec.as_ref() {
|
||||||
|
@ -3810,13 +3790,11 @@ impl Context {
|
||||||
} else {
|
} else {
|
||||||
eval_body_t()
|
eval_body_t()
|
||||||
};
|
};
|
||||||
self.declare_var(&sig, t, id)?;
|
self.declare_var(sig, t, id)?;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,3 +219,9 @@ impl SideEffectChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for SideEffectChecker {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,17 +28,14 @@ impl SubstContext {
|
||||||
let param_names = ty_ctx.params.iter().map(|(opt_name, _)| {
|
let param_names = ty_ctx.params.iter().map(|(opt_name, _)| {
|
||||||
opt_name
|
opt_name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|n| n.inspect().clone())
|
.map_or_else(|| Str::ever("_"), |n| n.inspect().clone())
|
||||||
.unwrap_or(Str::ever("_"))
|
|
||||||
.clone()
|
|
||||||
});
|
});
|
||||||
let self_ = SubstContext {
|
// REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は?
|
||||||
|
SubstContext {
|
||||||
params: param_names
|
params: param_names
|
||||||
.zip(substituted.typarams().into_iter())
|
.zip(substituted.typarams().into_iter())
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
}
|
||||||
// REVIEW: 順番は保証されるか? 引数がunnamed_paramsに入る可能性は?
|
|
||||||
self_
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn substitute(&self, quant_t: Type, ty_ctx: &Context, level: usize) -> TyCheckResult<Type> {
|
fn substitute(&self, quant_t: Type, ty_ctx: &Context, level: usize) -> TyCheckResult<Type> {
|
||||||
|
@ -58,12 +55,10 @@ impl SubstContext {
|
||||||
if let Some(v) = self.params.get(&name) {
|
if let Some(v) = self.params.get(&name) {
|
||||||
ty_ctx.unify_tp(param, v, None, None, false)?;
|
ty_ctx.unify_tp(param, v, None, None, false)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else if fv.is_unbound() {
|
||||||
if fv.is_unbound() {
|
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
TyParam::BinOp { lhs, rhs, .. } => {
|
TyParam::BinOp { lhs, rhs, .. } => {
|
||||||
self.substitute_tp(lhs, ty_ctx)?;
|
self.substitute_tp(lhs, ty_ctx)?;
|
||||||
self.substitute_tp(rhs, ty_ctx)?;
|
self.substitute_tp(rhs, ty_ctx)?;
|
||||||
|
@ -192,28 +187,28 @@ impl Evaluator {
|
||||||
match op {
|
match op {
|
||||||
Add => lhs
|
Add => lhs
|
||||||
.try_add(rhs)
|
.try_add(rhs)
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
Sub => lhs
|
Sub => lhs
|
||||||
.try_sub(rhs)
|
.try_sub(rhs)
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
Mul => lhs
|
Mul => lhs
|
||||||
.try_mul(rhs)
|
.try_mul(rhs)
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
Div => lhs
|
Div => lhs
|
||||||
.try_div(rhs)
|
.try_div(rhs)
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
Gt => lhs
|
Gt => lhs
|
||||||
.try_gt(rhs)
|
.try_gt(rhs)
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
Ge => lhs
|
Ge => lhs
|
||||||
.try_ge(rhs)
|
.try_ge(rhs)
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
Eq => lhs
|
Eq => lhs
|
||||||
.try_eq(rhs)
|
.try_eq(rhs)
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
Ne => lhs
|
Ne => lhs
|
||||||
.try_ne(rhs)
|
.try_ne(rhs)
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
other => todo!("{other}"),
|
other => todo!("{other}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,7 +222,7 @@ impl Evaluator {
|
||||||
match (lhs, rhs) {
|
match (lhs, rhs) {
|
||||||
(TyParam::ConstObj(ConstObj::Value(lhs)), TyParam::ConstObj(ConstObj::Value(rhs))) => {
|
(TyParam::ConstObj(ConstObj::Value(lhs)), TyParam::ConstObj(ConstObj::Value(rhs))) => {
|
||||||
self.eval_bin_lit(op, lhs.clone(), rhs.clone())
|
self.eval_bin_lit(op, lhs.clone(), rhs.clone())
|
||||||
.map(|v| TyParam::value(v))
|
.map(TyParam::value)
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
TyParam::ConstObj(ConstObj::MutValue(lhs)),
|
TyParam::ConstObj(ConstObj::MutValue(lhs)),
|
||||||
|
@ -272,14 +267,14 @@ impl Evaluator {
|
||||||
|
|
||||||
fn eval_unary_tp(&self, op: OpKind, val: &TyParam) -> EvalResult<TyParam> {
|
fn eval_unary_tp(&self, op: OpKind, val: &TyParam) -> EvalResult<TyParam> {
|
||||||
match val {
|
match val {
|
||||||
TyParam::ConstObj(c) => self.eval_unary_lit(op, c.clone()).map(|c| TyParam::cons(c)),
|
TyParam::ConstObj(c) => self.eval_unary_lit(op, c.clone()).map(TyParam::cons),
|
||||||
TyParam::FreeVar(fv) if fv.is_linked() => self.eval_unary_tp(op, &*fv.crack()),
|
TyParam::FreeVar(fv) if fv.is_linked() => self.eval_unary_tp(op, &*fv.crack()),
|
||||||
e @ TyParam::Erased(_) => Ok(e.clone()),
|
e @ TyParam::Erased(_) => Ok(e.clone()),
|
||||||
other => todo!("{op} {other}"),
|
other => todo!("{op} {other}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_app(&self, _name: &Str, _args: &Vec<TyParam>) -> EvalResult<TyParam> {
|
fn eval_app(&self, _name: &Str, _args: &[TyParam]) -> EvalResult<TyParam> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +289,7 @@ impl Evaluator {
|
||||||
ConstObj::Value(v) => Some(TyParam::value(v.clone())),
|
ConstObj::Value(v) => Some(TyParam::value(v.clone())),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
TyParam::BinOp { op, lhs, rhs } => self.eval_bin_tp(*op, lhs, rhs),
|
TyParam::BinOp { op, lhs, rhs } => self.eval_bin_tp(*op, lhs, rhs),
|
||||||
TyParam::UnaryOp { op, val } => self.eval_unary_tp(*op, val),
|
TyParam::UnaryOp { op, val } => self.eval_unary_tp(*op, val),
|
||||||
TyParam::App { name, args } => self.eval_app(name, args),
|
TyParam::App { name, args } => self.eval_app(name, args),
|
||||||
|
@ -443,7 +438,7 @@ impl Evaluator {
|
||||||
match p {
|
match p {
|
||||||
TyParam::ConstObj(ConstObj::Value(v)) => Ok(Type::enum_t(set![v])),
|
TyParam::ConstObj(ConstObj::Value(v)) => Ok(Type::enum_t(set![v])),
|
||||||
TyParam::ConstObj(ConstObj::MutValue(v)) => Ok(v.borrow().class().mutate()),
|
TyParam::ConstObj(ConstObj::MutValue(v)) => Ok(v.borrow().class().mutate()),
|
||||||
TyParam::Erased(t) => Ok((&*t).clone()),
|
TyParam::Erased(t) => Ok((*t).clone()),
|
||||||
TyParam::FreeVar(fv) => {
|
TyParam::FreeVar(fv) => {
|
||||||
if let Some(t) = fv.type_of() {
|
if let Some(t) = fv.type_of() {
|
||||||
Ok(t)
|
Ok(t)
|
||||||
|
@ -459,7 +454,7 @@ impl Evaluator {
|
||||||
ConstObj::Value(v) => Some(Type::enum_t(set![v.clone()])),
|
ConstObj::Value(v) => Some(Type::enum_t(set![v.clone()])),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
TyParam::MonoQVar(name) => {
|
TyParam::MonoQVar(name) => {
|
||||||
if let Some(bs) = bounds {
|
if let Some(bs) = bounds {
|
||||||
if let Some(bound) = bs.iter().find(|b| b.mentions_as_instance(&name)) {
|
if let Some(bound) = bs.iter().find(|b| b.mentions_as_instance(&name)) {
|
||||||
|
@ -483,7 +478,7 @@ impl Evaluator {
|
||||||
let p = self.eval_tp(p, ctx)?;
|
let p = self.eval_tp(p, ctx)?;
|
||||||
match p {
|
match p {
|
||||||
TyParam::ConstObj(ConstObj::Value(v)) => Ok(v.class()),
|
TyParam::ConstObj(ConstObj::Value(v)) => Ok(v.class()),
|
||||||
TyParam::Erased(t) => Ok((&*t).clone()),
|
TyParam::Erased(t) => Ok((*t).clone()),
|
||||||
TyParam::FreeVar(fv) => {
|
TyParam::FreeVar(fv) => {
|
||||||
if let Some(t) = fv.type_of() {
|
if let Some(t) = fv.type_of() {
|
||||||
Ok(t)
|
Ok(t)
|
||||||
|
@ -499,7 +494,7 @@ impl Evaluator {
|
||||||
ConstObj::Value(v) => Some(v.class()),
|
ConstObj::Value(v) => Some(v.class()),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.ok_or(EvalError::unreachable(fn_name!(), line!())),
|
.ok_or_else(|| EvalError::unreachable(fn_name!(), line!())),
|
||||||
other => todo!("{other}"),
|
other => todo!("{other}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ pub struct KwArg {
|
||||||
|
|
||||||
impl NestedDisplay for KwArg {
|
impl NestedDisplay for KwArg {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
write!(f, "{}:\n", self.keyword)?;
|
writeln!(f, "{}:", self.keyword)?;
|
||||||
self.expr.fmt_nest(f, level + 1)
|
self.expr.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,11 @@ impl Args {
|
||||||
self.pos_args.len() + self.kw_args.len()
|
self.pos_args.len() + self.kw_args.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.pos_args.is_empty() && self.kw_args.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn kw_len(&self) -> usize {
|
pub fn kw_len(&self) -> usize {
|
||||||
self.kw_args.len()
|
self.kw_args.len()
|
||||||
|
@ -563,9 +568,9 @@ pub struct BinOp {
|
||||||
|
|
||||||
impl NestedDisplay for BinOp {
|
impl NestedDisplay for BinOp {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "`{}`:\n", self.op.content)?;
|
writeln!(f, "`{}`:", self.op.content)?;
|
||||||
self.lhs.fmt_nest(f, level + 1)?;
|
self.lhs.fmt_nest(f, level + 1)?;
|
||||||
write!(f, "\n")?;
|
writeln!(f)?;
|
||||||
self.rhs.fmt_nest(f, level + 1)
|
self.rhs.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -573,15 +578,15 @@ impl NestedDisplay for BinOp {
|
||||||
impl HasType for BinOp {
|
impl HasType for BinOp {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ref_t(&self) -> &Type {
|
fn ref_t(&self) -> &Type {
|
||||||
&self.sig_t.return_t().unwrap()
|
self.sig_t.return_t().unwrap()
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn lhs_t(&self) -> &Type {
|
fn lhs_t(&self) -> &Type {
|
||||||
&self.sig_t.lhs_t()
|
self.sig_t.lhs_t()
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rhs_t(&self) -> &Type {
|
fn rhs_t(&self) -> &Type {
|
||||||
&self.sig_t.rhs_t()
|
self.sig_t.rhs_t()
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn signature_t(&self) -> Option<&Type> {
|
fn signature_t(&self) -> Option<&Type> {
|
||||||
|
@ -613,7 +618,7 @@ pub struct UnaryOp {
|
||||||
impl HasType for UnaryOp {
|
impl HasType for UnaryOp {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ref_t(&self) -> &Type {
|
fn ref_t(&self) -> &Type {
|
||||||
&self.sig_t.return_t().unwrap()
|
self.sig_t.return_t().unwrap()
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn lhs_t(&self) -> &Type {
|
fn lhs_t(&self) -> &Type {
|
||||||
|
@ -631,7 +636,7 @@ impl HasType for UnaryOp {
|
||||||
|
|
||||||
impl NestedDisplay for UnaryOp {
|
impl NestedDisplay for UnaryOp {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "`{}`: {}:\n", self.op, self.sig_t)?;
|
writeln!(f, "`{}`: {}:", self.op, self.sig_t)?;
|
||||||
self.expr.fmt_nest(f, level + 1)
|
self.expr.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,7 +665,7 @@ pub struct Call {
|
||||||
|
|
||||||
impl NestedDisplay for Call {
|
impl NestedDisplay for Call {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
write!(f, "({}): {}:\n", self.obj, self.sig_t)?;
|
writeln!(f, "({}): {}:", self.obj, self.sig_t)?;
|
||||||
self.args.fmt_nest(f, level + 1)
|
self.args.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -670,7 +675,7 @@ impl_display_from_nested!(Call);
|
||||||
impl HasType for Call {
|
impl HasType for Call {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ref_t(&self) -> &Type {
|
fn ref_t(&self) -> &Type {
|
||||||
&self.sig_t.return_t().unwrap()
|
self.sig_t.return_t().unwrap()
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn lhs_t(&self) -> &Type {
|
fn lhs_t(&self) -> &Type {
|
||||||
|
@ -821,7 +826,7 @@ impl HasType for Lambda {
|
||||||
|
|
||||||
impl NestedDisplay for Lambda {
|
impl NestedDisplay for Lambda {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "{} {}\n", self.params, self.op.content)?;
|
writeln!(f, "{} {}", self.params, self.op.content)?;
|
||||||
self.body.fmt_nest(f, level + 1)
|
self.body.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -943,7 +948,7 @@ pub struct Def {
|
||||||
|
|
||||||
impl NestedDisplay for Def {
|
impl NestedDisplay for Def {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "{} {}\n", self.sig, self.body.op.content)?;
|
writeln!(f, "{} {}", self.sig, self.body.op.content)?;
|
||||||
self.body.block.fmt_nest(f, level + 1)
|
self.body.block.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ impl Context {
|
||||||
op_t,
|
op_t,
|
||||||
set! {subtype(mono_q("Self"), mono("Eq")), subtype(mono_q("R"), poly("Eq", vec![]))},
|
set! {subtype(mono_q("Self"), mono("Eq")), subtype(mono_q("R"), poly("Eq", vec![]))},
|
||||||
);
|
);
|
||||||
eq.register_decl("__eq__", op_t.clone(), Public);
|
eq.register_decl("__eq__", op_t, Public);
|
||||||
let mut ord = Self::poly_trait(
|
let mut ord = Self::poly_trait(
|
||||||
"Ord",
|
"Ord",
|
||||||
vec![PS::t("R", WithDefault)],
|
vec![PS::t("R", WithDefault)],
|
||||||
|
@ -123,7 +123,7 @@ impl Context {
|
||||||
op_t,
|
op_t,
|
||||||
set! {subtype(mono_q("Self"), mono("Ord")), subtype(mono_q("R"), poly("Ord", vec![]))},
|
set! {subtype(mono_q("Self"), mono("Ord")), subtype(mono_q("R"), poly("Ord", vec![]))},
|
||||||
);
|
);
|
||||||
ord.register_decl("__lt__", op_t.clone(), Public);
|
ord.register_decl("__lt__", op_t, Public);
|
||||||
let mut seq = Self::poly_trait(
|
let mut seq = Self::poly_trait(
|
||||||
"Seq",
|
"Seq",
|
||||||
vec![PS::t("T", NonDefault)],
|
vec![PS::t("T", NonDefault)],
|
||||||
|
@ -142,7 +142,7 @@ impl Context {
|
||||||
seq.register_decl("get", t, Public);
|
seq.register_decl("get", t, Public);
|
||||||
let params = vec![PS::t("T", NonDefault)];
|
let params = vec![PS::t("T", NonDefault)];
|
||||||
let input = Self::poly_trait("Input", params.clone(), vec![], Self::TOP_LEVEL);
|
let input = Self::poly_trait("Input", params.clone(), vec![], Self::TOP_LEVEL);
|
||||||
let output = Self::poly_trait("Output", params.clone(), vec![], Self::TOP_LEVEL);
|
let output = Self::poly_trait("Output", params, vec![], Self::TOP_LEVEL);
|
||||||
let (r, o) = (mono_q("R"), mono_q("O"));
|
let (r, o) = (mono_q("R"), mono_q("O"));
|
||||||
let (r_bound, o_bound) = (static_instance("R", Type), static_instance("O", Type));
|
let (r_bound, o_bound) = (static_instance("R", Type), static_instance("O", Type));
|
||||||
let params = vec![PS::t("R", WithDefault), PS::t("O", WithDefault)];
|
let params = vec![PS::t("R", WithDefault), PS::t("O", WithDefault)];
|
||||||
|
@ -167,7 +167,7 @@ impl Context {
|
||||||
poly("Sub", ty_params.clone()),
|
poly("Sub", ty_params.clone()),
|
||||||
);
|
);
|
||||||
let op_t = fn1_met(poly_q("Self", ty_params.clone()), r.clone(), o.clone());
|
let op_t = fn1_met(poly_q("Self", ty_params.clone()), r.clone(), o.clone());
|
||||||
let op_t = quant(op_t, set! {r_bound.clone(), o_bound.clone(), self_bound});
|
let op_t = quant(op_t, set! {r_bound, o_bound, self_bound});
|
||||||
sub.register_decl("__sub__", op_t, Public);
|
sub.register_decl("__sub__", op_t, Public);
|
||||||
let mut mul = Self::poly_trait("Mul", params.clone(), vec![
|
let mut mul = Self::poly_trait("Mul", params.clone(), vec![
|
||||||
poly("Output", vec![ty_tp(mono_q("R"))]),
|
poly("Output", vec![ty_tp(mono_q("R"))]),
|
||||||
|
@ -175,7 +175,7 @@ impl Context {
|
||||||
], Self::TOP_LEVEL);
|
], Self::TOP_LEVEL);
|
||||||
let op_t = fn1_met(poly("Mul", ty_params.clone()), r.clone(), o.clone());
|
let op_t = fn1_met(poly("Mul", ty_params.clone()), r.clone(), o.clone());
|
||||||
mul.register_decl("__mul__", op_t, Public);
|
mul.register_decl("__mul__", op_t, Public);
|
||||||
let mut div = Self::poly_trait("Div", params.clone(), vec![
|
let mut div = Self::poly_trait("Div", params, vec![
|
||||||
poly("Output", vec![ty_tp(mono_q("R"))]),
|
poly("Output", vec![ty_tp(mono_q("R"))]),
|
||||||
poly("Output", vec![ty_tp(mono_q("O"))]),
|
poly("Output", vec![ty_tp(mono_q("O"))]),
|
||||||
], Self::TOP_LEVEL);
|
], Self::TOP_LEVEL);
|
||||||
|
@ -618,8 +618,8 @@ impl Context {
|
||||||
let op_t = Type::func2(l.clone(), r.clone(), o.clone());
|
let op_t = Type::func2(l.clone(), r.clone(), o.clone());
|
||||||
let op_t = quant(op_t, set! {subtype(l.clone(), poly("Mul", params.clone()))});
|
let op_t = quant(op_t, set! {subtype(l.clone(), poly("Mul", params.clone()))});
|
||||||
self.register_impl("__mul__", op_t, Const, Private);
|
self.register_impl("__mul__", op_t, Const, Private);
|
||||||
let op_t = Type::func2(l.clone(), r.clone(), o.clone());
|
let op_t = Type::func2(l.clone(), r, o);
|
||||||
let op_t = quant(op_t, set! {subtype(l, poly("Mul", params.clone()))});
|
let op_t = quant(op_t, set! {subtype(l, poly("Mul", params))});
|
||||||
self.register_impl("__div__", op_t, Const, Private);
|
self.register_impl("__div__", op_t, Const, Private);
|
||||||
let m = mono_q("M");
|
let m = mono_q("M");
|
||||||
let op_t = Type::func2(m.clone(), m.clone(), m.clone());
|
let op_t = Type::func2(m.clone(), m.clone(), m.clone());
|
||||||
|
|
|
@ -50,14 +50,14 @@ impl ASTLowerer {
|
||||||
expect: &Type,
|
expect: &Type,
|
||||||
found: &Type,
|
found: &Type,
|
||||||
) -> LowerResult<()> {
|
) -> LowerResult<()> {
|
||||||
self.ctx.unify(expect, found, Some(loc), None).or_else(|_| {
|
self.ctx.unify(expect, found, Some(loc), None).map_err(|_| {
|
||||||
Err(LowerError::type_mismatch_error(
|
LowerError::type_mismatch_error(
|
||||||
loc,
|
loc,
|
||||||
self.ctx.caused_by(),
|
self.ctx.caused_by(),
|
||||||
name,
|
name,
|
||||||
expect,
|
expect,
|
||||||
found,
|
found,
|
||||||
))
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,9 +176,9 @@ impl ASTLowerer {
|
||||||
self.lower_expr(arg.expr, true)?,
|
self.lower_expr(arg.expr, true)?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let mut obj = self.lower_expr(*call.obj, false)?;
|
let obj = self.lower_expr(*call.obj, false)?;
|
||||||
let t = self.ctx.get_call_t(
|
let t = self.ctx.get_call_t(
|
||||||
&mut obj,
|
&obj,
|
||||||
hir_args.pos_args(),
|
hir_args.pos_args(),
|
||||||
hir_args.kw_args(),
|
hir_args.kw_args(),
|
||||||
&self.ctx.name,
|
&self.ctx.name,
|
||||||
|
@ -283,7 +283,7 @@ impl ASTLowerer {
|
||||||
.map(|vi| vi.t.clone());
|
.map(|vi| vi.t.clone());
|
||||||
let name = sig.pat.inspect().unwrap();
|
let name = sig.pat.inspect().unwrap();
|
||||||
if let Some(expect_body_t) = opt_expect_body_t {
|
if let Some(expect_body_t) = opt_expect_body_t {
|
||||||
if let Err(e) = self.return_t_check(sig.loc(), name, &expect_body_t, &found_body_t) {
|
if let Err(e) = self.return_t_check(sig.loc(), name, &expect_body_t, found_body_t) {
|
||||||
self.errs.push(e);
|
self.errs.push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,3 +416,9 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ASTLowerer {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ impl OwnershipChecker {
|
||||||
fn check_expr(&mut self, expr: &Expr, ownership: Ownership) {
|
fn check_expr(&mut self, expr: &Expr, ownership: Ownership) {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Def(def) => {
|
Expr::Def(def) => {
|
||||||
self.define(&def);
|
self.define(def);
|
||||||
let name_and_vis = match &def.sig {
|
let name_and_vis = match &def.sig {
|
||||||
Signature::Var(var) =>
|
Signature::Var(var) =>
|
||||||
// TODO: visibility
|
// TODO: visibility
|
||||||
|
@ -249,3 +249,9 @@ impl OwnershipChecker {
|
||||||
panic!("variable not found: {name}");
|
panic!("variable not found: {name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for OwnershipChecker {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub fn fmt_lines<'a, T: NestedDisplay + 'a>(
|
||||||
line.fmt_nest(f, level)?;
|
line.fmt_nest(f, level)?;
|
||||||
}
|
}
|
||||||
for arg in iter {
|
for arg in iter {
|
||||||
write!(f, "\n")?;
|
writeln!(f)?;
|
||||||
arg.fmt_nest(f, level)?;
|
arg.fmt_nest(f, level)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -107,7 +107,7 @@ pub struct KwArg {
|
||||||
|
|
||||||
impl NestedDisplay for KwArg {
|
impl NestedDisplay for KwArg {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
write!(f, "{}:\n", self.keyword)?;
|
writeln!(f, "{}:", self.keyword)?;
|
||||||
self.expr.fmt_nest(f, level + 1)
|
self.expr.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,9 +453,9 @@ pub struct BinOp {
|
||||||
|
|
||||||
impl NestedDisplay for BinOp {
|
impl NestedDisplay for BinOp {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "`{}`:\n", self.op.content)?;
|
writeln!(f, "`{}`:", self.op.content)?;
|
||||||
self.args[0].fmt_nest(f, level + 1)?;
|
self.args[0].fmt_nest(f, level + 1)?;
|
||||||
write!(f, "\n")?;
|
writeln!(f)?;
|
||||||
self.args[1].fmt_nest(f, level + 1)
|
self.args[1].fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -485,7 +485,7 @@ pub struct UnaryOp {
|
||||||
|
|
||||||
impl NestedDisplay for UnaryOp {
|
impl NestedDisplay for UnaryOp {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "`{}`:\n", self.op.content)?;
|
writeln!(f, "`{}`:", self.op.content)?;
|
||||||
self.args[0].fmt_nest(f, level + 1)
|
self.args[0].fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -515,7 +515,7 @@ pub struct Call {
|
||||||
|
|
||||||
impl NestedDisplay for Call {
|
impl NestedDisplay for Call {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
write!(f, "({}):\n", self.obj)?;
|
writeln!(f, "({}):", self.obj)?;
|
||||||
self.args.fmt_nest(f, level + 1)
|
self.args.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1186,7 +1186,7 @@ impl fmt::Display for TypeSpec {
|
||||||
Self::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"),
|
Self::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"),
|
||||||
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
|
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
|
||||||
Self::Array { t, len } => write!(f, "[{t}; {len}]"),
|
Self::Array { t, len } => write!(f, "[{t}; {len}]"),
|
||||||
Self::Tuple(tys) => write!(f, "({})", fmt_vec(&tys)),
|
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
|
||||||
Self::Enum(elems) => write!(f, "{{{elems}}}"),
|
Self::Enum(elems) => write!(f, "{{{elems}}}"),
|
||||||
Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()),
|
Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()),
|
||||||
Self::Subr(s) => write!(f, "{s}"),
|
Self::Subr(s) => write!(f, "{s}"),
|
||||||
|
@ -1537,7 +1537,7 @@ impl VarPattern {
|
||||||
Self::Array(VarArrayPattern { elems, .. })
|
Self::Array(VarArrayPattern { elems, .. })
|
||||||
| Self::Tuple(VarTuplePattern { elems, .. })
|
| Self::Tuple(VarTuplePattern { elems, .. })
|
||||||
| Self::Record(VarRecordPattern { elems, .. }) => {
|
| Self::Record(VarRecordPattern { elems, .. }) => {
|
||||||
elems.iter().map(|s| s.pat.inspects()).flatten().collect()
|
elems.iter().flat_map(|s| s.pat.inspects()).collect()
|
||||||
}
|
}
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
|
@ -1992,7 +1992,7 @@ pub struct Lambda {
|
||||||
|
|
||||||
impl NestedDisplay for Lambda {
|
impl NestedDisplay for Lambda {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "{} {}\n", self.sig, self.op.content)?;
|
writeln!(f, "{} {}", self.sig, self.op.content)?;
|
||||||
self.body.fmt_nest(f, level + 1)
|
self.body.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2026,7 +2026,7 @@ impl Signature {
|
||||||
pub fn name_as_str(&self) -> &Str {
|
pub fn name_as_str(&self) -> &Str {
|
||||||
match self {
|
match self {
|
||||||
Self::Var(v) => v.pat.inspect().unwrap(),
|
Self::Var(v) => v.pat.inspect().unwrap(),
|
||||||
Self::Subr(s) => &s.name.inspect(),
|
Self::Subr(s) => s.name.inspect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2083,7 +2083,7 @@ pub struct Def {
|
||||||
|
|
||||||
impl NestedDisplay for Def {
|
impl NestedDisplay for Def {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
write!(f, "{} {}\n", self.sig, self.body.op.content)?;
|
writeln!(f, "{} {}", self.sig, self.body.op.content)?;
|
||||||
self.body.block.fmt_nest(f, level + 1)
|
self.body.block.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,3 +193,9 @@ impl Desugarer {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Desugarer {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
//! defines and implements `Lexer` (Tokenizer).
|
//! defines and implements `Lexer` (Tokenizer).
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use erg_common::cache::Cache;
|
use erg_common::cache::Cache;
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
use erg_common::config::Input;
|
use erg_common::config::Input;
|
||||||
|
@ -105,7 +107,7 @@ impl Lexer /*<'a>*/ {
|
||||||
pub fn lex(self) -> Result<TokenStream, LexErrors> {
|
pub fn lex(self) -> Result<TokenStream, LexErrors> {
|
||||||
let mut result = TokenStream::empty();
|
let mut result = TokenStream::empty();
|
||||||
let mut errs = LexErrors::empty();
|
let mut errs = LexErrors::empty();
|
||||||
for i in self.into_iter() {
|
for i in self {
|
||||||
match i {
|
match i {
|
||||||
Ok(token) => result.push(token),
|
Ok(token) => result.push(token),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -172,19 +174,14 @@ impl Lexer /*<'a>*/ {
|
||||||
/// Detect `c` is a bidirectional overriding character.
|
/// Detect `c` is a bidirectional overriding character.
|
||||||
/// [CVE-2021-42574: homoglyph atack](https://blog.rust-lang.org/2021/11/01/cve-2021-42574.html) countermeasures.
|
/// [CVE-2021-42574: homoglyph atack](https://blog.rust-lang.org/2021/11/01/cve-2021-42574.html) countermeasures.
|
||||||
pub fn is_bidi(c: char) -> bool {
|
pub fn is_bidi(c: char) -> bool {
|
||||||
match c {
|
matches!(c, '\u{200F}' | '\u{202B}' | '\u{202E}' | '\u{2067}')
|
||||||
'\u{200F}' | '\u{202B}' | '\u{202E}' | '\u{2067}' => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_definable_operator(s: &str) -> bool {
|
fn is_definable_operator(s: &str) -> bool {
|
||||||
match s {
|
matches!(s,
|
||||||
"+" | "-" | "*" | "/" | "//" | "**" | "%" | ".." | "..=" | "~" | "&&" | "||" | "^^"
|
"+" | "-" | "*" | "/" | "//" | "**" | "%" | ".." | "..=" | "~" | "&&" | "||" | "^^"
|
||||||
| ">>" | "<<" | "==" | "!=" | ">" | "<" | ">=" | "<=" | "dot" | "cross" => true,
|
| ">>" | "<<" | "==" | "!=" | ">" | "<" | ">=" | "<=" | "dot" | "cross")
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// +, -, * etc. may be pre/bin
|
// +, -, * etc. may be pre/bin
|
||||||
|
@ -209,32 +206,32 @@ impl Lexer /*<'a>*/ {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_zero(s: &str) -> bool {
|
fn is_zero(s: &str) -> bool {
|
||||||
s.replace("-0", "").replace("0", "").is_empty()
|
s.replace("-0", "").replace('0', "").is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// emit_tokenで一気にcol_token_startsを移動させるのでここでは移動させない
|
/// emit_tokenで一気にcol_token_startsを移動させるのでここでは移動させない
|
||||||
fn consume(&mut self) -> Option<char> {
|
fn consume(&mut self) -> Option<char> {
|
||||||
let now = self.cursor;
|
let now = self.cursor;
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
self.chars.get(now).map(|x| *x)
|
self.chars.get(now).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek_prev_ch(&self) -> Option<char> {
|
fn peek_prev_ch(&self) -> Option<char> {
|
||||||
if self.cursor == 0 {
|
if self.cursor == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
self.chars.get(self.cursor - 1).map(|x| *x)
|
self.chars.get(self.cursor - 1).copied()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn peek_cur_ch(&self) -> Option<char> {
|
fn peek_cur_ch(&self) -> Option<char> {
|
||||||
self.chars.get(self.cursor).map(|x| *x)
|
self.chars.get(self.cursor).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn peek_next_ch(&self) -> Option<char> {
|
fn peek_next_ch(&self) -> Option<char> {
|
||||||
self.chars.get(self.cursor + 1).map(|x| *x)
|
self.chars.get(self.cursor + 1).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lex_comment(&mut self) -> LexResult<()> {
|
fn lex_comment(&mut self) -> LexResult<()> {
|
||||||
|
@ -322,13 +319,15 @@ impl Lexer /*<'a>*/ {
|
||||||
sum + *x
|
sum + *x
|
||||||
};
|
};
|
||||||
let sum_indent = self.indent_stack.iter().fold(0, calc_indent_and_validate);
|
let sum_indent = self.indent_stack.iter().fold(0, calc_indent_and_validate);
|
||||||
if sum_indent < spaces.len() {
|
match sum_indent.cmp(&spaces.len()) {
|
||||||
|
Ordering::Less => {
|
||||||
let indent_len = spaces.len() - sum_indent;
|
let indent_len = spaces.len() - sum_indent;
|
||||||
self.col_token_starts += sum_indent;
|
self.col_token_starts += sum_indent;
|
||||||
let indent = self.emit_token(Indent, &" ".repeat(indent_len));
|
let indent = self.emit_token(Indent, &" ".repeat(indent_len));
|
||||||
self.indent_stack.push(indent_len);
|
self.indent_stack.push(indent_len);
|
||||||
Some(Ok(indent))
|
Some(Ok(indent))
|
||||||
} else if sum_indent > spaces.len() {
|
}
|
||||||
|
Ordering::Greater => {
|
||||||
if is_valid_dedent {
|
if is_valid_dedent {
|
||||||
let dedent = self.emit_token(Dedent, "");
|
let dedent = self.emit_token(Dedent, "");
|
||||||
self.indent_stack.pop();
|
self.indent_stack.pop();
|
||||||
|
@ -342,13 +341,13 @@ impl Lexer /*<'a>*/ {
|
||||||
None,
|
None,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
/* if indent_sum == space.len() */
|
Ordering::Equal /* if indent_sum == space.len() */ => {
|
||||||
{
|
|
||||||
self.col_token_starts += spaces.len();
|
self.col_token_starts += spaces.len();
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn lex_exponent(&mut self, mantissa: String) -> LexResult<Token> {
|
fn lex_exponent(&mut self, mantissa: String) -> LexResult<Token> {
|
||||||
let mut num = mantissa;
|
let mut num = mantissa;
|
||||||
|
@ -495,7 +494,7 @@ impl Lexer /*<'a>*/ {
|
||||||
fn lex_str(&mut self) -> LexResult<Token> {
|
fn lex_str(&mut self) -> LexResult<Token> {
|
||||||
let mut s = "\"".to_string();
|
let mut s = "\"".to_string();
|
||||||
while let Some(c) = self.peek_cur_ch() {
|
while let Some(c) = self.peek_cur_ch() {
|
||||||
if c == '\"' && s.chars().last() != Some('\\') {
|
if c == '\"' && !s.ends_with('\\') {
|
||||||
s.push(self.consume().unwrap());
|
s.push(self.consume().unwrap());
|
||||||
let token = self.emit_token(StrLit, &s);
|
let token = self.emit_token(StrLit, &s);
|
||||||
return Ok(token);
|
return Ok(token);
|
||||||
|
@ -805,7 +804,7 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if self.indent_stack.len() == 0 {
|
if self.indent_stack.is_empty() {
|
||||||
self.accept(EOF, "")
|
self.accept(EOF, "")
|
||||||
} else {
|
} else {
|
||||||
self.indent_stack.pop();
|
self.indent_stack.pop();
|
||||||
|
|
|
@ -158,15 +158,13 @@ impl Parser {
|
||||||
Side::LhsAssign
|
Side::LhsAssign
|
||||||
}
|
}
|
||||||
// (cur) -> ... ; ... =
|
// (cur) -> ... ; ... =
|
||||||
else {
|
else if self.arrow_distance(0, 0) == 1 {
|
||||||
if self.arrow_distance(0, 0) == 1 {
|
|
||||||
Side::LhsLambda
|
Side::LhsLambda
|
||||||
} else {
|
} else {
|
||||||
Side::Rhs
|
Side::Rhs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// (cur) = ... -> ...
|
// (cur) = ... -> ...
|
||||||
// (cur) -> ... = ...
|
// (cur) -> ... = ...
|
||||||
(Some(_eq), Some(_arrow), None) => Side::LhsAssign,
|
(Some(_eq), Some(_arrow), None) => Side::LhsAssign,
|
||||||
|
@ -454,16 +452,9 @@ impl Parser {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn opt_reduce_decorators(&mut self) -> ParseResult<Set<Decorator>> {
|
fn opt_reduce_decorators(&mut self) -> ParseResult<Set<Decorator>> {
|
||||||
let mut decs = set![];
|
let mut decs = set![];
|
||||||
loop {
|
while let Some(deco) = self.opt_reduce_decorator()? {
|
||||||
match self.opt_reduce_decorator()? {
|
|
||||||
Some(deco) => {
|
|
||||||
decs.insert(deco);
|
decs.insert(deco);
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(decs)
|
Ok(decs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,14 +512,13 @@ impl Parser {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else if self.cur_is(Colon) {
|
||||||
if self.cur_is(Colon) {
|
|
||||||
self.skip();
|
self.skip();
|
||||||
Some(self.try_reduce_type_spec()?)
|
Some(self.try_reduce_type_spec()?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Signature::Var(VarSignature::new(
|
Ok(Signature::Var(VarSignature::new(
|
||||||
VarPattern::VarName(name),
|
VarPattern::VarName(name),
|
||||||
t_spec,
|
t_spec,
|
||||||
|
@ -1236,7 +1226,7 @@ impl Parser {
|
||||||
};
|
};
|
||||||
Ok(KwArg::new(keyword, self.try_reduce_expr()?))
|
Ok(KwArg::new(keyword, self.try_reduce_expr()?))
|
||||||
} else {
|
} else {
|
||||||
return Err(ParseError::simple_syntax_error(0, t.loc()));
|
Err(ParseError::simple_syntax_error(0, t.loc()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(other) => Err(ParseError::simple_syntax_error(0, other.loc())),
|
Some(other) => Err(ParseError::simple_syntax_error(0, other.loc())),
|
||||||
|
|
|
@ -293,11 +293,7 @@ impl TokenKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn is_right_associative(&self) -> bool {
|
pub const fn is_right_associative(&self) -> bool {
|
||||||
match self {
|
matches!(self, FuncArrow | ProcArrow | Equal /* | PreDollar | PreAt */)
|
||||||
FuncArrow | ProcArrow | Equal => true,
|
|
||||||
// PreDollar | PreAt => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +333,7 @@ impl fmt::Debug for Token {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("Token")
|
f.debug_struct("Token")
|
||||||
.field("kind", &self.kind)
|
.field("kind", &self.kind)
|
||||||
.field("content", &self.content.replace("\n", "\\n"))
|
.field("content", &self.content.replace('\n', "\\n"))
|
||||||
.field("lineno", &self.lineno)
|
.field("lineno", &self.lineno)
|
||||||
.field("col_begin", &self.col_begin)
|
.field("col_begin", &self.col_begin)
|
||||||
.finish()
|
.finish()
|
||||||
|
@ -346,7 +342,7 @@ impl fmt::Debug for Token {
|
||||||
|
|
||||||
impl fmt::Display for Token {
|
impl fmt::Display for Token {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:?} {}", self.kind, self.content.replace("\n", "\\n"))
|
write!(f, "{:?} {}", self.kind, self.content.replace('\n', "\\n"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +447,7 @@ impl Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_procedural(&self) -> bool {
|
pub fn is_procedural(&self) -> bool {
|
||||||
self.inspect().ends_with("!")
|
self.inspect().ends_with('!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue