Merge branch 'main' into codegen-bug

This commit is contained in:
Shunsuke Shibayama 2023-07-12 16:51:03 +09:00
commit 91aaa0702a
15 changed files with 287 additions and 31 deletions

10
Cargo.lock generated
View file

@ -94,7 +94,7 @@ dependencies = [
[[package]] [[package]]
name = "els" name = "els"
version = "0.1.28-nightly.7" version = "0.1.28"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"erg_compiler", "erg_compiler",
@ -105,7 +105,7 @@ dependencies = [
[[package]] [[package]]
name = "erg" name = "erg"
version = "0.6.16-nightly.7" version = "0.6.16"
dependencies = [ dependencies = [
"els", "els",
"erg_common", "erg_common",
@ -115,7 +115,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_common" name = "erg_common"
version = "0.6.16-nightly.7" version = "0.6.16"
dependencies = [ dependencies = [
"backtrace-on-stack-overflow", "backtrace-on-stack-overflow",
"crossterm", "crossterm",
@ -125,7 +125,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_compiler" name = "erg_compiler"
version = "0.6.16-nightly.7" version = "0.6.16"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"erg_parser", "erg_parser",
@ -133,7 +133,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_parser" name = "erg_parser"
version = "0.6.16-nightly.7" version = "0.6.16"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"unicode-xid", "unicode-xid",

View file

@ -20,7 +20,7 @@ members = [
] ]
[workspace.package] [workspace.package]
version = "0.6.16-nightly.7" version = "0.6.16"
authors = ["erg-lang team <moderation.erglang@gmail.com>"] authors = ["erg-lang team <moderation.erglang@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
edition = "2021" edition = "2021"
@ -64,10 +64,10 @@ full = ["els", "full-repl", "unicode", "pretty"]
experimental = ["erg_common/experimental", "erg_parser/experimental", "erg_compiler/experimental"] experimental = ["erg_common/experimental", "erg_parser/experimental", "erg_compiler/experimental"]
[workspace.dependencies] [workspace.dependencies]
erg_common = { version = "0.6.16-nightly.7", path = "./crates/erg_common" } erg_common = { version = "0.6.16", path = "./crates/erg_common" }
erg_parser = { version = "0.6.16-nightly.7", path = "./crates/erg_parser" } erg_parser = { version = "0.6.16", path = "./crates/erg_parser" }
erg_compiler = { version = "0.6.16-nightly.7", path = "./crates/erg_compiler" } erg_compiler = { version = "0.6.16", path = "./crates/erg_compiler" }
els = { version = "0.1.28-nightly.7", path = "./crates/els" } els = { version = "0.1.28", path = "./crates/els" }
[dependencies] [dependencies]
erg_common = { workspace = true } erg_common = { workspace = true }

View file

@ -2,7 +2,7 @@
name = "els" name = "els"
description = "An Erg compiler frontend for IDEs, implements LSP." description = "An Erg compiler frontend for IDEs, implements LSP."
documentation = "http://docs.rs/els" documentation = "http://docs.rs/els"
version = "0.1.28-nightly.7" version = "0.1.28"
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true edition.workspace = true

View file

@ -355,24 +355,44 @@ impl CompletionCache {
move || { move || {
crate::_log!("load_modules"); crate::_log!("load_modules");
let major_mods = [ let major_mods = [
"argparse",
"array",
"asyncio",
"base64",
"datetime", "datetime",
"decimal",
"fraction",
"glob", "glob",
"html",
"http", "http",
"http/client", "http/client",
"http/server", "http/server",
"io", "io",
"json", "json",
"logging",
"math", "math",
"os", "os",
"os/path", "os/path",
"pathlib",
"platform",
"random", "random",
"re", "re",
"shutil",
"socket",
"sqlite3",
"ssl",
"string",
"subprocess",
"sys", "sys",
"tempfile",
"time", "time",
"timeit",
"unittest",
"urllib", "urllib",
"zipfile",
]; ];
#[cfg(feature = "py_compat")] #[cfg(feature = "py_compat")]
let py_specific_mods = ["typing", "collections/abc"]; let py_specific_mods = ["dataclasses", "typing", "collections/abc"];
#[cfg(not(feature = "py_compat"))] #[cfg(not(feature = "py_compat"))]
let py_specific_mods = []; let py_specific_mods = [];
let ext_mods = ["numpy", "pandas", "matplotlib", "matplotlib/pyplot"]; let ext_mods = ["numpy", "pandas", "matplotlib", "matplotlib/pyplot"];

View file

@ -124,10 +124,14 @@ impl HIRDiff {
old.module.insert(idx, expr); old.module.insert(idx, expr);
} }
Self::Deletion(usize) => { Self::Deletion(usize) => {
if old.module.get(usize).is_some() {
old.module.remove(usize); old.module.remove(usize);
} }
}
Self::Modification(idx, expr) => { Self::Modification(idx, expr) => {
*old.module.get_mut(idx).unwrap() = expr; if let Some(old_expr) = old.module.get_mut(idx) {
*old_expr = expr;
}
} }
Self::Nop => {} Self::Nop => {}
} }

View file

@ -48,7 +48,7 @@ pub fn type_from_token_kind(kind: TokenKind) -> Type {
use TokenKind::*; use TokenKind::*;
match kind { match kind {
NatLit => Type::Nat, NatLit | BinLit | OctLit | HexLit => Type::Nat,
IntLit => Type::Int, IntLit => Type::Int,
RatioLit => Type::Ratio, RatioLit => Type::Ratio,
StrLit | DocComment => Type::Str, StrLit | DocComment => Type::Str,

View file

@ -8,6 +8,7 @@ The name of the operating system dependent module imported. The following names
.name: Str .name: Str
.chdir!: (path: PathLike, ) => NoneType .chdir!: (path: PathLike, ) => NoneType
.chmod!: (path: PathLike, mode: Nat) => NoneType
.getcwd!: () => Str .getcwd!: () => Str
.getenv!: (key: Str, default: Str or NoneType := NoneType) => Str .getenv!: (key: Str, default: Str or NoneType := NoneType) => Str
.listdir!: (path := PathLike,) => [Str; _] .listdir!: (path := PathLike,) => [Str; _]

View file

@ -1,7 +1,37 @@
.PurePath: ClassType .PurePath: ClassType
.PurePath.parts: [Str; _] .PurePath.
parts: [Str; _]
drive: Str
root: Str
anchor: Str
parents: [.PurePath; _]
parent: .PurePath
name: Str
suffix: Str
suffixes: [Str; _]
stem: Str
__call__: (*segments: Str) -> .PurePath
as_posix: (self: .PurePath) -> Str
as_uri: (self: .PurePath) -> Str
is_absolute: (self: .PurePath) -> Bool
is_relative_to: (self: .PurePath, *other: .PurePath) -> Bool
is_reserved: (self: .PurePath) -> Bool
joinpath: (self: .PurePath, *other: .PurePath) -> .PurePath
match: (self: .PurePath, pattern: Str) -> Bool
relative_to: (self: .PurePath, *other: .PurePath) -> .PurePath
with_name: (self: .PurePath, name: Str) -> .PurePath
with_stem: (self: .PurePath, suffix: Str) -> .PurePath
with_suffix: (self: .PurePath, suffix: Str) -> .PurePath
.PurePosixPath: ClassType .PurePosixPath: ClassType
.PureWindowsPath: ClassType .PureWindowsPath: ClassType
.Path: ClassType .Path: ClassType
.Path <: .PurePath
.Path.
__call__: (*segments: Str) -> .Path
cwd!: () => .Path
home!: () => .Path
samefile!: (self: .Path, other: .Path) => Bool
open!: (self: .Path, mode := Str) => File!
chmod!: (self: .Path, mode: Nat) => NoneType
.PosixPath: ClassType .PosixPath: ClassType
.WindowsPath: ClassType .WindowsPath: ClassType

View file

@ -0,0 +1,88 @@
.ST_MMODE: {0}
.ST_INO: {1}
.ST_DEV: {2}
.ST_NLINK: {3}
.ST_UID: {4}
.ST_GID: {5}
.ST_SIZE: {6}
.ST_ATIME: {7}
.ST_MTIME: {8}
.ST_CTIME: {9}
.S_IMODE: (mode: Nat) -> Nat
.S_IFMT: (mode: Nat) -> Nat
.S_IFDIR: {0o04000}
.S_IFCHR: {0o02000}
.S_IFBLK: {0o06000}
.S_IFREG: {0o10000}
.S_IFIFO: {0o01000}
.S_IFLNK: {0o12000}
.S_IFSOCK: {0o14000}
.S_IFDOOR: {0}
.S_IFPORT: {0}
.S_IFWHT: {0}
.S_ISDIR: (mode: Nat) -> Bool
.S_ISCHR: (mode: Nat) -> Bool
.S_ISBLK: (mode: Nat) -> Bool
.S_ISREG: (mode: Nat) -> Bool
.S_ISFIFO: (mode: Nat) -> Bool
.S_ISLNK: (mode: Nat) -> Bool
.S_ISSOCK: (mode: Nat) -> Bool
.S_ISDOOR: (mode: Nat) -> Bool
.S_ISPORT: (mode: Nat) -> Bool
.S_ISWHT: (mode: Nat) -> Bool
.S_ISUID: {0o4000}
.S_ISGID: {0o2000}
.S_ENFMT: {0o2000}
.S_ISVTX: {0o1000}
.S_IREAD: {0o0400}
.S_IWRITE: {0o0200}
.S_IEXEC: {0o0100}
.S_IRWXU: {0o0700}
.S_IRUSR: {0o0400}
.S_IWUSR: {0o0200}
.S_IXUSR: {0o0100}
.S_IRWXG: {0o0070}
.S_IRGRP: {0o0040}
.S_IWGRP: {0o0020}
.S_IXGRP: {0o0010}
.S_IRWXO: {0o0007}
.S_IROTH: {0o0004}
.S_IWOTH: {0o0002}
.S_IXOTH: {0o0001}
.UF_NODUMP: {0x00000001}
.UF_IMMUTABLE: {0x00000002}
.UF_APPEND: {0x00000004}
.UF_OPAQUE: {0x00000008}
.UF_NOUNLINK: {0x00000010}
.UF_COMPRESSED: {0x00000020}
.UF_HIDDEN: {0x00008000}
.SF_ARCHIVED: {0x00010000}
.SF_IMMUTABLE: {0x00020000}
.SF_APPEND: {0x00040000}
.SF_NOUNLINK: {0x00100000}
.SF_SNAPSHOT: {0x00200000}
.filemode: (mode: Nat) -> Str
.FILE_ATTRIBUTE_ARCHIVE: {32}
.FILE_ATTRIBUTE_COMPRESSED: {2048}
.FILE_ATTRIBUTE_DEVICE: {64}
.FILE_ATTRIBUTE_DIRECTORY: {16}
.FILE_ATTRIBUTE_ENCRYPTED: {16384}
.FILE_ATTRIBUTE_HIDDEN: {2}
.FILE_ATTRIBUTE_INTEGRITY_STREAM: {32768}
.FILE_ATTRIBUTE_NORMAL: {128}
.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED: {8192}
.FILE_ATTRIBUTE_NO_SCRUB_DATA: {131072}
.FILE_ATTRIBUTE_OFFLINE: {4096}
.FILE_ATTRIBUTE_READONLY: {1}
.FILE_ATTRIBUTE_REPARSE_POINT: {1024}
.FILE_ATTRIBUTE_SPARSE_FILE: {512}
.FILE_ATTRIBUTE_SYSTEM: {4}
.FILE_ATTRIBUTE_TEMPORARY: {256}
.FILE_ATTRIBUTE_VIRTUAL: {65536}

View file

@ -920,12 +920,29 @@ impl ValueObj {
pub fn from_str(t: Type, mut content: Str) -> Option<Self> { pub fn from_str(t: Type, mut content: Str) -> Option<Self> {
match t { match t {
Type::Int => content.replace('_', "").parse::<i32>().ok().map(Self::Int), Type::Int => content.replace('_', "").parse::<i32>().ok().map(Self::Int),
Type::Nat => content Type::Nat => {
let content = content
.trim_start_matches('-') // -0 -> 0 .trim_start_matches('-') // -0 -> 0
.replace('_', "") .replace('_', "");
.parse::<u64>() if content.len() <= 1 {
.ok() return content.parse::<u64>().ok().map(Self::Nat);
.map(Self::Nat), }
match &content[0..=1] {
pre @ ("0b" | "0B") => {
let content = content.trim_start_matches(pre);
u64::from_str_radix(content, 2).ok().map(Self::Nat)
}
pre @ ("0o" | "0O") => {
let content = content.trim_start_matches(pre);
u64::from_str_radix(content, 8).ok().map(Self::Nat)
}
pre @ ("0x" | "0X") => {
let content = content.trim_start_matches(pre);
u64::from_str_radix(content, 16).ok().map(Self::Nat)
}
_ => content.parse::<u64>().ok().map(Self::Nat),
}
}
Type::Float => content Type::Float => content
.replace('_', "") .replace('_', "")
.parse::<f64>() .parse::<f64>()

View file

@ -2569,8 +2569,10 @@ impl Locational for TupleTypeSpec {
fn loc(&self) -> Location { fn loc(&self) -> Location {
if let Some((lparen, rparen)) = &self.parens { if let Some((lparen, rparen)) = &self.parens {
Location::concat(lparen, rparen) Location::concat(lparen, rparen)
} else { } else if !self.tys.is_empty() {
Location::concat(self.tys.first().unwrap(), self.tys.last().unwrap()) Location::concat(self.tys.first().unwrap(), self.tys.last().unwrap())
} else {
Location::Unknown
} }
} }
} }
@ -2701,8 +2703,20 @@ impl Locational for TypeSpec {
Self::Array(arr) => arr.loc(), Self::Array(arr) => arr.loc(),
Self::SetWithLen(set) => set.loc(), Self::SetWithLen(set) => set.loc(),
Self::Tuple(tup) => tup.loc(), Self::Tuple(tup) => tup.loc(),
Self::Dict(dict) => Location::concat(&dict.first().unwrap().0, &dict.last().unwrap().1), Self::Dict(dict) => {
Self::Record(rec) => Location::concat(&rec.first().unwrap().0, &rec.last().unwrap().1), if dict.is_empty() {
Location::Unknown
} else {
Location::concat(&dict.first().unwrap().0, &dict.last().unwrap().1)
}
}
Self::Record(rec) => {
if rec.is_empty() {
Location::Unknown
} else {
Location::concat(&rec.first().unwrap().0, &rec.last().unwrap().1)
}
}
Self::Enum(set) => set.loc(), Self::Enum(set) => set.loc(),
Self::Interval { lhs, rhs, .. } => Location::concat(lhs, rhs), Self::Interval { lhs, rhs, .. } => Location::concat(lhs, rhs),
Self::Subr(s) => s.loc(), Self::Subr(s) => s.loc(),
@ -2854,8 +2868,12 @@ impl_displayable_stream_for_wrapper!(TypeBoundSpecs, TypeBoundSpec);
impl Locational for TypeBoundSpecs { impl Locational for TypeBoundSpecs {
fn loc(&self) -> Location { fn loc(&self) -> Location {
if self.0.is_empty() {
Location::Unknown
} else {
Location::concat(self.first().unwrap(), self.last().unwrap()) Location::concat(self.first().unwrap(), self.last().unwrap())
} }
}
} }
/// デコレータは関数を返す関数オブジェクトならば何でも指定できる /// デコレータは関数を返す関数オブジェクトならば何でも指定できる
@ -3003,8 +3021,12 @@ impl NestedDisplay for Namespaces {
impl Locational for Namespaces { impl Locational for Namespaces {
fn loc(&self) -> Location { fn loc(&self) -> Location {
if self.0.is_empty() {
Location::Unknown
} else {
Location::concat(self.first().unwrap(), self.last().unwrap()) Location::concat(self.first().unwrap(), self.last().unwrap())
} }
}
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -3252,7 +3274,7 @@ impl Locational for VarTuplePattern {
fn loc(&self) -> Location { fn loc(&self) -> Location {
match &self.paren { match &self.paren {
Some((l, r)) => Location::concat(l, r), Some((l, r)) => Location::concat(l, r),
None => Location::concat(&self.elems[0], self.elems.last().unwrap()), None => self.elems.loc(),
} }
} }
} }
@ -3506,6 +3528,16 @@ impl NestedDisplay for Vars {
impl_display_from_nested!(Vars); impl_display_from_nested!(Vars);
impl_stream!(Vars, VarSignature, elems); impl_stream!(Vars, VarSignature, elems);
impl Locational for Vars {
fn loc(&self) -> Location {
if self.elems.is_empty() {
Location::Unknown
} else {
Location::concat(self.first().unwrap(), self.last().unwrap())
}
}
}
impl Vars { impl Vars {
pub const fn new(elems: Vec<VarSignature>) -> Self { pub const fn new(elems: Vec<VarSignature>) -> Self {
Self { elems } Self { elems }

View file

@ -621,6 +621,18 @@ impl Lexer /*<'a>*/ {
n if n.is_ascii_digit() || n == '_' => { n if n.is_ascii_digit() || n == '_' => {
num.push(self.consume().unwrap()); num.push(self.consume().unwrap());
} }
'b' | 'B' => {
num.push(self.consume().unwrap());
return self.lex_bin(num);
}
'o' | 'O' => {
num.push(self.consume().unwrap());
return self.lex_oct(num);
}
'x' | 'X' => {
num.push(self.consume().unwrap());
return self.lex_hex(num);
}
c if Self::is_valid_continue_symbol_ch(c) => { c if Self::is_valid_continue_symbol_ch(c) => {
// exponent (e.g. 10e+3) // exponent (e.g. 10e+3)
if c == 'e' if c == 'e'
@ -682,6 +694,39 @@ impl Lexer /*<'a>*/ {
} }
} }
fn lex_bin(&mut self, mut num: String) -> LexResult<Token> {
while let Some(cur) = self.peek_cur_ch() {
if cur == '0' || cur == '1' || cur == '_' {
num.push(self.consume().unwrap());
} else {
break;
}
}
Ok(self.emit_token(BinLit, &num))
}
fn lex_oct(&mut self, mut num: String) -> LexResult<Token> {
while let Some(cur) = self.peek_cur_ch() {
if matches!(cur, '0'..='7') || cur == '_' {
num.push(self.consume().unwrap());
} else {
break;
}
}
Ok(self.emit_token(OctLit, &num))
}
fn lex_hex(&mut self, mut num: String) -> LexResult<Token> {
while let Some(cur) = self.peek_cur_ch() {
if cur.is_ascii_hexdigit() || cur == '_' {
num.push(self.consume().unwrap());
} else {
break;
}
}
Ok(self.emit_token(HexLit, &num))
}
/// int_part_and_point must be like `12.` /// int_part_and_point must be like `12.`
fn lex_ratio(&mut self, intpart_and_point: String) -> LexResult<Token> { fn lex_ratio(&mut self, intpart_and_point: String) -> LexResult<Token> {
let mut num = intpart_and_point; let mut num = intpart_and_point;
@ -1547,7 +1592,7 @@ impl Iterator for Lexer /*<'a>*/ {
None, None,
))) )))
} }
// IntLit or RatioLit // IntLit (or Bin/Oct/Hex) or RatioLit
Some(n) if n.is_ascii_digit() => Some(self.lex_num(n)), Some(n) if n.is_ascii_digit() => Some(self.lex_num(n)),
// Symbol (includes '_') // Symbol (includes '_')
Some(c) if Self::is_valid_start_symbol_ch(c) => Some(self.lex_symbol(c)), Some(c) if Self::is_valid_start_symbol_ch(c) => Some(self.lex_symbol(c)),

View file

@ -24,6 +24,12 @@ pub enum TokenKind {
NatLit, NatLit,
/// e.g. -1, -2 /// e.g. -1, -2
IntLit, IntLit,
/// e.g. 0b101
BinLit,
/// e.g. 0o777
OctLit,
/// e.g. 0xdeadbeef
HexLit,
RatioLit, RatioLit,
BoolLit, BoolLit,
StrLit, StrLit,
@ -232,8 +238,8 @@ impl TokenKind {
pub const fn category(&self) -> TokenCategory { pub const fn category(&self) -> TokenCategory {
match self { match self {
Symbol => TokenCategory::Symbol, Symbol => TokenCategory::Symbol,
NatLit | IntLit | RatioLit | StrLit | BoolLit | NoneLit | EllipsisLit | InfLit NatLit | BinLit | OctLit | HexLit | IntLit | RatioLit | StrLit | BoolLit | NoneLit
| DocComment => TokenCategory::Literal, | EllipsisLit | InfLit | DocComment => TokenCategory::Literal,
StrInterpLeft => TokenCategory::StrInterpLeft, StrInterpLeft => TokenCategory::StrInterpLeft,
StrInterpMid => TokenCategory::StrInterpMid, StrInterpMid => TokenCategory::StrInterpMid,
StrInterpRight => TokenCategory::StrInterpRight, StrInterpRight => TokenCategory::StrInterpRight,

View file

@ -0,0 +1,8 @@
b = 0b010010
assert b == 18
o = 0o22
assert o == 18
h = 0x12
assert h == 18

View file

@ -52,6 +52,11 @@ fn exec_control_expr() -> Result<(), ()> {
expect_success("tests/should_ok/control_expr.er", 3) expect_success("tests/should_ok/control_expr.er", 3)
} }
#[test]
fn exec_decimal() -> Result<(), ()> {
expect_success("tests/should_ok/decimal.er", 0)
}
#[test] #[test]
fn exec_default_param() -> Result<(), ()> { fn exec_default_param() -> Result<(), ()> {
expect_success("tests/should_ok/default_param.er", 0) expect_success("tests/should_ok/default_param.er", 0)