mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 05:54:33 +00:00
Merge branch 'main' into codegen-bug
This commit is contained in:
commit
91aaa0702a
15 changed files with 287 additions and 31 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -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 }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"];
|
||||||
|
|
|
@ -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 => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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; _]
|
||||||
|
|
|
@ -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
|
||||||
|
|
88
crates/erg_compiler/lib/pystd/stat.d.er
Normal file
88
crates/erg_compiler/lib/pystd/stat.d.er
Normal 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}
|
|
@ -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>()
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
8
tests/should_ok/decimal.er
Normal file
8
tests/should_ok/decimal.er
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
b = 0b010010
|
||||||
|
assert b == 18
|
||||||
|
|
||||||
|
o = 0o22
|
||||||
|
assert o == 18
|
||||||
|
|
||||||
|
h = 0x12
|
||||||
|
assert h == 18
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue