diff --git a/README.md b/README.md
index f70cee36..a736c6cd 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,10 @@
+
+
+
+
日本語 | 简体中文 | 繁體中文
diff --git a/README_JA.md b/README_JA.md
index e27c472c..091e3e8d 100644
--- a/README_JA.md
+++ b/README_JA.md
@@ -10,6 +10,9 @@
+
+
+
[
diff --git a/README_zh-CN.md b/README_zh-CN.md
index e9933928..8352037c 100644
--- a/README_zh-CN.md
+++ b/README_zh-CN.md
@@ -10,6 +10,9 @@
+
+
+
[
diff --git a/README_zh-TW.md b/README_zh-TW.md
index 6258b25b..b05728f9 100644
--- a/README_zh-TW.md
+++ b/README_zh-TW.md
@@ -10,6 +10,9 @@
+
+
+
[
diff --git a/compiler/erg_common/astr.rs b/compiler/erg_common/astr.rs
deleted file mode 100644
index df65cbbe..00000000
--- a/compiler/erg_common/astr.rs
+++ /dev/null
@@ -1,181 +0,0 @@
-use std::borrow::Borrow;
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::ops::{Add, Deref};
-
-use crate::style::{StyledString, StyledStrings};
-use crate::Str;
-
-pub type ArcStr = std::sync::Arc;
-
-/// Used to hold an immutable string.
-///
-/// It can construct as a const (by AtomicStr::ever).
-#[derive(Debug, Clone, Eq)]
-pub enum AtomicStr {
- Arc(ArcStr),
- Static(&'static str),
-}
-
-// unsafe impl Sync for AtomicStr {}
-
-impl PartialEq for AtomicStr {
- #[inline]
- fn eq(&self, other: &AtomicStr) -> bool {
- self[..] == other[..]
- }
-}
-
-impl Add<&str> for AtomicStr {
- type Output = AtomicStr;
- #[inline]
- fn add(self, other: &str) -> AtomicStr {
- AtomicStr::from(&format!("{self}{other}"))
- }
-}
-
-impl Hash for AtomicStr {
- fn hash(&self, state: &mut H) {
- match self {
- AtomicStr::Arc(s) => s[..].hash(state),
- AtomicStr::Static(s) => (*s).hash(state),
- }
- }
-}
-
-impl fmt::Display for AtomicStr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- AtomicStr::Arc(s) => write!(f, "{s}"),
- AtomicStr::Static(s) => write!(f, "{s}"),
- }
- }
-}
-
-// &'static str -> &strになってしまわないように
-// あえて`impl> From for AtomicStr { ... }`はしない
-impl From<&'static str> for AtomicStr {
- #[inline]
- fn from(s: &'static str) -> Self {
- AtomicStr::ever(s)
- }
-}
-
-impl From<&String> for AtomicStr {
- #[inline]
- fn from(s: &String) -> Self {
- AtomicStr::Arc((s[..]).into())
- }
-}
-
-impl From for AtomicStr {
- #[inline]
- fn from(s: String) -> Self {
- AtomicStr::Arc((s[..]).into())
- }
-}
-
-impl From<&ArcStr> for AtomicStr {
- #[inline]
- fn from(s: &ArcStr) -> Self {
- AtomicStr::Arc(s.clone())
- }
-}
-
-impl From for AtomicStr {
- #[inline]
- fn from(s: ArcStr) -> Self {
- AtomicStr::Arc(s)
- }
-}
-
-impl From<&AtomicStr> for AtomicStr {
- #[inline]
- fn from(s: &AtomicStr) -> Self {
- match s {
- AtomicStr::Arc(s) => AtomicStr::Arc(s.clone()),
- AtomicStr::Static(s) => AtomicStr::Static(s),
- }
- }
-}
-
-impl From for AtomicStr {
- #[inline]
- fn from(s: Str) -> Self {
- match s {
- Str::Rc(s) => AtomicStr::Arc((&s[..]).into()),
- Str::Static(s) => AtomicStr::Static(s),
- }
- }
-}
-
-impl From<&Str> for AtomicStr {
- #[inline]
- fn from(s: &Str) -> Self {
- match s {
- Str::Rc(s) => AtomicStr::Arc((&s[..]).into()),
- Str::Static(s) => AtomicStr::Static(s),
- }
- }
-}
-
-impl From for AtomicStr {
- #[inline]
- fn from(s: StyledString) -> Self {
- AtomicStr::Arc(s.to_string().into())
- }
-}
-
-impl From for AtomicStr {
- #[inline]
- fn from(s: StyledStrings) -> Self {
- AtomicStr::Arc(s.to_string().into())
- }
-}
-
-impl Deref for AtomicStr {
- type Target = str;
- fn deref(&self) -> &Self::Target {
- self.borrow()
- }
-}
-
-impl Borrow for AtomicStr {
- #[inline]
- fn borrow(&self) -> &str {
- match self {
- AtomicStr::Arc(s) => s.borrow(),
- AtomicStr::Static(s) => s,
- }
- }
-}
-
-impl AsRef for AtomicStr {
- fn as_ref(&self) -> &str {
- self.borrow()
- }
-}
-
-impl AtomicStr {
- pub const fn ever(s: &'static str) -> Self {
- AtomicStr::Static(s)
- }
-
- pub fn arc(s: &str) -> Self {
- AtomicStr::Arc(s.into())
- }
-
- pub fn into_rc(self) -> ArcStr {
- match self {
- AtomicStr::Arc(s) => s,
- AtomicStr::Static(s) => ArcStr::from(s),
- }
- }
-
- pub fn is_uppercase(&self) -> bool {
- self.chars()
- .next()
- .map(|c| c.is_uppercase())
- .unwrap_or(false)
- }
-}
diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs
index f60189cf..bee93dd0 100644
--- a/compiler/erg_common/error.rs
+++ b/compiler/erg_common/error.rs
@@ -5,7 +5,6 @@ use std::cmp;
use std::fmt;
use std::io::{stderr, BufWriter, Write as _};
-use crate::astr::AtomicStr;
use crate::config::Input;
use crate::style::Attribute;
use crate::style::Characters;
@@ -25,95 +24,95 @@ use crate::{impl_display_from_debug, switch_lang};
pub enum ErrorKind {
/* compile errors */
AssignError = 0,
- AttributeError,
- BytecodeError,
- CompilerSystemError,
- EnvironmentError,
- FeatureError,
- ImportError,
- IndentationError,
- NameError,
- NotImplementedError,
- PatternError,
- SyntaxError,
- TabError,
- TypeError,
- UnboundLocalError,
- PurityError,
- HasEffect,
- MoveError,
- NotConstExpr,
- InheritanceError,
- VisibilityError,
- MethodError,
- DummyError,
+ AttributeError = 1,
+ BytecodeError = 2,
+ CompilerSystemError = 3,
+ EnvironmentError = 4,
+ FeatureError = 5,
+ ImportError = 6,
+ IndentationError = 7,
+ NameError = 8,
+ NotImplementedError = 9,
+ PatternError = 10,
+ SyntaxError = 11,
+ TabError = 12,
+ TypeError = 13,
+ UnboundLocalError = 14,
+ PurityError = 15,
+ HasEffect = 16,
+ MoveError = 17,
+ NotConstExpr = 18,
+ InheritanceError = 19,
+ VisibilityError = 20,
+ MethodError = 21,
+ DummyError = 22,
/* compile warnings */
AttributeWarning = 60,
- CastWarning,
- DeprecationWarning,
- FutureWarning,
- ImportWarning,
- PendingDeprecationWarning,
- SyntaxWarning,
- TypeWarning,
- NameWarning,
- UnusedWarning,
- Warning,
+ CastWarning = 61,
+ DeprecationWarning = 62,
+ FutureWarning = 63,
+ ImportWarning = 64,
+ PendingDeprecationWarning = 65,
+ SyntaxWarning = 66,
+ TypeWarning = 67,
+ NameWarning = 68,
+ UnusedWarning = 69,
+ Warning = 70,
/* runtime errors */
ArithmeticError = 100,
- AssertionError,
- BlockingIOError,
- BrokenPipeError,
- BufferError,
- ChildProcessError,
- ConnectionAbortedError,
- ConnectionError,
- ConnectionRefusedError,
- ConnectionResetError,
- EOFError,
- FileExistsError,
- FileNotFoundError,
- IndexError,
- InterruptedError,
- IoError,
- IsADirectoryError,
- KeyError,
- LookupError,
- MemoryError,
- ModuleNotFoundError,
- NotADirectoryError,
- OSError,
- OverflowError,
- PermissionError,
- ProcessLookupError,
- RecursionError,
- ReferenceError,
- RuntimeAttributeError,
- RuntimeError,
- RuntimeTypeError,
- RuntimeUnicodeError,
- TimeoutError,
- UnicodeError,
- UserError,
- ValueError,
- VMSystemError,
- WindowsError,
- ZeroDivisionError,
+ AssertionError = 101,
+ BlockingIOError = 102,
+ BrokenPipeError = 103,
+ BufferError = 104,
+ ChildProcessError = 105,
+ ConnectionAbortedError = 106,
+ ConnectionError = 107,
+ ConnectionRefusedError = 108,
+ ConnectionResetError = 109,
+ EOFError = 110,
+ FileExistsError = 111,
+ FileNotFoundError = 112,
+ IndexError = 113,
+ InterruptedError = 114,
+ IoError = 115,
+ IsADirectoryError = 116,
+ KeyError = 117,
+ LookupError = 118,
+ MemoryError = 119,
+ ModuleNotFoundError = 120,
+ NotADirectoryError = 121,
+ OSError = 122,
+ OverflowError = 123,
+ PermissionError = 124,
+ ProcessLookupError = 125,
+ RecursionError = 126,
+ ReferenceError = 127,
+ RuntimeAttributeError = 128,
+ RuntimeError = 129,
+ RuntimeTypeError = 130,
+ RuntimeUnicodeError = 131,
+ TimeoutError = 132,
+ UnicodeError = 133,
+ UserError = 134,
+ ValueError = 135,
+ VMSystemError = 136,
+ WindowsError = 137,
+ ZeroDivisionError = 138,
/* runtime warnings */
BytesWarning = 180,
- ResourceWarning,
- RuntimeWarning,
- UnicodeWarning,
- UserWarning,
+ ResourceWarning = 181,
+ RuntimeWarning = 182,
+ UnicodeWarning = 183,
+ UserWarning = 184,
/* exceptions */
BaseException = 200,
- Exception,
- GeneratorExit,
- KeyboardInterrupt,
- StopAsyncIteration,
- StopIteration,
- SystemExit,
- UserException,
+ Exception = 201,
+ GeneratorExit = 202,
+ KeyboardInterrupt = 203,
+ StopAsyncIteration = 204,
+ StopIteration = 205,
+ SystemExit = 206,
+ UserException = 207,
}
use ErrorKind::*;
@@ -327,8 +326,8 @@ fn format_context(
chars: &Characters,
// kinds of error for specify the color
mark: char,
- sub_msg: &[AtomicStr],
- hint: Option<&AtomicStr>,
+ sub_msg: &[String],
+ hint: Option<&String>,
) -> String {
let mark = mark.to_string();
let codes = if e.input().is_repl() {
@@ -388,12 +387,12 @@ fn format_context(
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SubMessage {
pub loc: Location,
- msg: Vec,
- hint: Option,
+ msg: Vec,
+ hint: Option,
}
impl SubMessage {
- pub fn ambiguous_new(loc: Location, msg: Vec, hint: Option) -> Self {
+ pub fn ambiguous_new(loc: Location, msg: Vec, hint: Option) -> Self {
Self { loc, msg, hint }
}
@@ -405,11 +404,11 @@ impl SubMessage {
}
}
- pub fn set_hint>(&mut self, hint: S) {
+ pub fn set_hint>(&mut self, hint: S) {
self.hint = Some(hint.into());
}
- pub fn get_hint(self) -> Option {
+ pub fn get_hint(self) -> Option {
self.hint
}
@@ -500,7 +499,7 @@ impl SubMessage {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ErrorCore {
pub sub_messages: Vec,
- pub main_message: AtomicStr,
+ pub main_message: String,
pub errno: usize,
pub kind: ErrorKind,
pub loc: Location,
@@ -508,7 +507,7 @@ pub struct ErrorCore {
}
impl ErrorCore {
- pub fn new>(
+ pub fn new>(
sub_messages: Vec,
main_message: S,
errno: usize,
diff --git a/compiler/erg_common/lib.rs b/compiler/erg_common/lib.rs
index fb17b9a5..7598e73c 100644
--- a/compiler/erg_common/lib.rs
+++ b/compiler/erg_common/lib.rs
@@ -1,7 +1,6 @@
//! provides utilities for parser, compiler, and vm crate.
use std::fmt;
-pub mod astr;
pub mod cache;
pub mod config;
pub mod datetime;
diff --git a/compiler/erg_common/python_util.rs b/compiler/erg_common/python_util.rs
index 4977149c..6bb144b0 100644
--- a/compiler/erg_common/python_util.rs
+++ b/compiler/erg_common/python_util.rs
@@ -357,6 +357,174 @@ pub const BUILTIN_PYTHON_MODS: [&str; 170] = [
"zlib",
"zoneinfo",
];
+#[cfg(not(any(windows, unix)))]
+pub const BUILTIN_PYTHON_MODS: [&str; 165] = [
+ "abc",
+ "argparse",
+ "array",
+ "ast",
+ "asyncio",
+ "atexit",
+ "base64",
+ "bdb",
+ "binascii",
+ "binhex",
+ "bisect",
+ "builtins",
+ "bz2",
+ "calendar",
+ "cmath",
+ "code",
+ "codecs",
+ "codeop",
+ "collections",
+ "colorsys",
+ "compileall",
+ "concurrent",
+ "configparser",
+ "contextlib",
+ "contextvars",
+ "copy",
+ "copyreg",
+ "cProfile",
+ "csv",
+ "ctypes",
+ "dataclasses",
+ "datetime",
+ "dbm",
+ "decimal",
+ "difflib",
+ "dis",
+ "distutils",
+ "doctest",
+ "email",
+ "encodings",
+ "ensurepip",
+ "enum",
+ "errno",
+ "faulthandler",
+ "filecmp",
+ "fileinput",
+ "fnmatch",
+ "fractions",
+ "ftplib",
+ "functools",
+ "gc",
+ "getopt",
+ "getpass",
+ "gettext",
+ "glob",
+ "graphlib",
+ "gzip",
+ "hashlib",
+ "heapq",
+ "hmac",
+ "html",
+ "http",
+ "imaplib",
+ "importlib",
+ "inspect",
+ "io",
+ "ipaddress",
+ "itertools",
+ "json",
+ "keyword",
+ "lib2to3",
+ "linecache",
+ "locale",
+ "logging",
+ "lzma",
+ "mailbox",
+ "marshal",
+ "math",
+ "mimetypes",
+ "mmap",
+ "modulefinder",
+ "multiprocessing",
+ "netrc",
+ "numbers",
+ "operator",
+ "os",
+ "pathlib",
+ "pdb",
+ "pickle",
+ "pickletools",
+ "pkgutil",
+ "platform",
+ "plistlib",
+ "poplib",
+ "pprint",
+ "profile",
+ "pstats",
+ "py_compile",
+ "pyclbr",
+ "pydoc",
+ "queue",
+ "quopri",
+ "random",
+ "re",
+ "reprlib",
+ "rlcompleter",
+ "runpy",
+ "sched",
+ "secrets",
+ "select",
+ "selectors",
+ "shelve",
+ "shlex",
+ "shutil",
+ "signal",
+ "site",
+ "smtplib",
+ "socket",
+ "socketserver",
+ "sqlite3",
+ "ssl",
+ "stat",
+ "statistics",
+ "string",
+ "stringprep",
+ "struct",
+ "subprocess",
+ "symtable",
+ "sys",
+ "sysconfig",
+ "tabnanny",
+ "tarfile",
+ "tempfile",
+ "test",
+ "textwrap",
+ "threading",
+ "time",
+ "timeit",
+ "tkinter",
+ "token",
+ "tokenize",
+ "trace",
+ "traceback",
+ "tracemalloc",
+ "turtle",
+ "turtledemo",
+ "types",
+ "typing",
+ "unicodedata",
+ "unittest",
+ "urllib",
+ "uuid",
+ "venv",
+ "warnings",
+ "wave",
+ "weakref",
+ "webbrowser",
+ "wsgiref",
+ "xml",
+ "xmlrpc",
+ "zipapp",
+ "zipfile",
+ "zipimport",
+ "zlib",
+ "zoneinfo",
+];
pub fn which_python() -> String {
let (cmd, python) = if cfg!(windows) {
@@ -416,6 +584,12 @@ pub struct PythonVersion {
pub micro: Option,
}
+impl Default for PythonVersion {
+ fn default() -> Self {
+ Self::new(3, Some(11), Some(0))
+ }
+}
+
impl PythonVersion {
pub const fn new(major: u8, minor: Option, micro: Option) -> Self {
Self {
diff --git a/compiler/erg_common/str.rs b/compiler/erg_common/str.rs
index 0fc25366..425a0441 100644
--- a/compiler/erg_common/str.rs
+++ b/compiler/erg_common/str.rs
@@ -47,6 +47,20 @@ impl fmt::Display for Str {
}
}
+impl From<&Str> for String {
+ #[inline]
+ fn from(s: &Str) -> Self {
+ s.to_string()
+ }
+}
+
+impl From for String {
+ #[inline]
+ fn from(s: Str) -> Self {
+ s.to_string()
+ }
+}
+
// &'static str -> &strになってしまわないように
// あえて`impl> From for Str { ... }`はしない
impl From<&'static str> for Str {
diff --git a/compiler/erg_common/style.rs b/compiler/erg_common/style.rs
index 52c556a4..63fff6bb 100644
--- a/compiler/erg_common/style.rs
+++ b/compiler/erg_common/style.rs
@@ -464,6 +464,12 @@ impl std::fmt::Display for StyledStrings {
}
}
+impl From for String {
+ fn from(s: StyledStrings) -> Self {
+ s.to_string()
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/compiler/erg_common/traits.rs b/compiler/erg_common/traits.rs
index 6225bfc7..10017ba6 100644
--- a/compiler/erg_common/traits.rs
+++ b/compiler/erg_common/traits.rs
@@ -350,7 +350,7 @@ fn is_in_the_expected_block(src: &str, lines: &str, in_block: &mut bool) -> bool
/// This trait implements REPL (Read-Eval-Print-Loop) automatically
/// The `exec` method is called for file input, etc.
-pub trait Runnable: Sized {
+pub trait Runnable: Sized + Default {
type Err: ErrorDisplay;
type Errs: MultiErrorDisplay;
const NAME: &'static str;
diff --git a/compiler/erg_common/tty.rs b/compiler/erg_common/tty.rs
index 70afa5b9..0cb2fe3f 100644
--- a/compiler/erg_common/tty.rs
+++ b/compiler/erg_common/tty.rs
@@ -45,7 +45,7 @@ impl IsTty for S {
/// returns true if this is a tty
#[cfg(any(target_arch = "wasm32", target_env = "sgx"))]
-impl IsTty for S {
+impl IsTty for std::io::Stdin {
fn is_tty(&self) -> bool {
false
}
diff --git a/compiler/erg_compiler/build_hir.rs b/compiler/erg_compiler/build_hir.rs
index c73f3116..0a4bf5df 100644
--- a/compiler/erg_compiler/build_hir.rs
+++ b/compiler/erg_compiler/build_hir.rs
@@ -16,7 +16,7 @@ use crate::mod_cache::SharedModuleCache;
use crate::ownercheck::OwnershipChecker;
/// Summarize lowering, side-effect checking, and ownership checking
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct HIRBuilder {
lowerer: ASTLowerer,
ownership_checker: OwnershipChecker,
diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs
index 90972965..18110790 100644
--- a/compiler/erg_compiler/codegen.rs
+++ b/compiler/erg_compiler/codegen.rs
@@ -7,7 +7,6 @@ use std::process;
use crate::ty::codeobj::MakeFunctionFlags;
use crate::ty::codeobj::{CodeObj, CodeObjFlags};
use crate::ty::value::GenTypeObj;
-use erg_common::astr::AtomicStr;
use erg_common::cache::CacheSet;
use erg_common::config::{ErgConfig, Input};
use erg_common::env::erg_std_path;
@@ -131,7 +130,7 @@ pub struct PyCodeGenStack(Vec);
impl_stream_for_wrapper!(PyCodeGenStack, PyCodeGenUnit);
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct PyCodeGenerator {
cfg: ErgConfig,
pub(crate) py_version: PythonVersion,
@@ -1265,7 +1264,7 @@ impl PyCodeGenerator {
self.cfg.input.clone(),
unary.op.loc(),
&unary.op.inspect().clone(),
- AtomicStr::from(unary.op.content),
+ String::from(unary.op.content),
)
.write_to_stderr();
NOT_IMPLEMENTED
@@ -1348,7 +1347,7 @@ impl PyCodeGenerator {
self.cfg.input.clone(),
binop.loc(),
&binop.inspect().clone(),
- AtomicStr::from(binop.content),
+ String::from(binop.content),
)
.write_to_stderr();
Opcode310::NOT_IMPLEMENTED
@@ -1416,7 +1415,7 @@ impl PyCodeGenerator {
self.cfg.input.clone(),
binop.loc(),
&binop.inspect().clone(),
- AtomicStr::from(binop.content),
+ String::from(binop.content),
)
.write_to_stderr();
Opcode311::NOT_IMPLEMENTED
diff --git a/compiler/erg_compiler/compile.rs b/compiler/erg_compiler/compile.rs
index 6eda4532..86117c80 100644
--- a/compiler/erg_compiler/compile.rs
+++ b/compiler/erg_compiler/compile.rs
@@ -91,7 +91,7 @@ impl AccessKind {
}
/// Generates a `CodeObj` from an String or other File inputs.
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct Compiler {
pub cfg: ErgConfig,
builder: HIRBuilder,
diff --git a/compiler/erg_compiler/context/hint.rs b/compiler/erg_compiler/context/hint.rs
index a43fbea7..63a459e1 100644
--- a/compiler/erg_compiler/context/hint.rs
+++ b/compiler/erg_compiler/context/hint.rs
@@ -1,4 +1,3 @@
-use erg_common::astr::AtomicStr;
use erg_common::enum_unwrap;
use crate::ty::typaram::TyParam;
@@ -26,11 +25,7 @@ impl Context {
}
}
- pub(crate) fn get_type_mismatch_hint(
- &self,
- expected: &Type,
- found: &Type,
- ) -> Option {
+ pub(crate) fn get_type_mismatch_hint(&self, expected: &Type, found: &Type) -> Option {
let expected = if let Type::FreeVar(fv) = expected {
if fv.is_linked() {
fv.crack().clone()
@@ -42,12 +37,12 @@ impl Context {
expected.clone()
};
match (&expected.qual_name()[..], &found.qual_name()[..]) {
- ("Eq", "Float") => Some(AtomicStr::ever("Float has no equivalence relation defined. you should use `l - r <= Float.EPSILON` instead of `l == r`.")),
+ ("Eq", "Float") => Some(String::from("Float has no equivalence relation defined. you should use `l - r <= Float.EPSILON` instead of `l == r`.")),
_ => None,
}
}
- pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option {
+ pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option {
match proj {
Type::Proj { lhs, rhs: _ } => {
if let Type::FreeVar(fv) = lhs.as_ref() {
@@ -69,9 +64,7 @@ impl Context {
} else {
(sup, sub)
};
- Some(AtomicStr::from(format!(
- "cannot {verb} {l} {preposition} {r}"
- )))
+ Some(format!("cannot {verb} {l} {preposition} {r}"))
} else {
None
}
diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs
index cd814e20..6b707d8b 100644
--- a/compiler/erg_compiler/context/initialize/const_func.rs
+++ b/compiler/erg_compiler/context/initialize/const_func.rs
@@ -6,7 +6,6 @@ use crate::context::Context;
use crate::ty::constructors::{and, mono};
use crate::ty::value::{EvalValueResult, GenTypeObj, TypeObj, ValueObj};
use crate::ty::ValueArgs;
-use erg_common::astr::AtomicStr;
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
use erg_common::style::{Color, StyledStr, StyledString, THEME};
@@ -24,7 +23,7 @@ pub fn class_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult EvalValueResult EvalValueResult EvalValueResult EvalValueResult<
let class = args.remove_left_or_key("Class").ok_or_else(|| {
ErrorCore::new(
vec![SubMessage::only_loc(Location::Unknown)],
- AtomicStr::from(format!("{CLASS_ERR} is not passed")),
+ format!("{CLASS_ERR} is not passed"),
line!() as usize,
ErrorKind::KeyError,
Location::Unknown,
@@ -120,7 +119,7 @@ pub fn trait_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult EvalValueResult EvalValueResult EvalValueResult EvalValueResult<
} else {
Err(ErrorCore::new(
vec![SubMessage::only_loc(Location::Unknown)],
- AtomicStr::from(format!(
+ format!(
"[{}] has {} elements, but accessed {}th element",
erg_common::fmt_vec(&slf),
slf.len(),
index
- )),
+ ),
line!() as usize,
ErrorKind::IndexError,
Location::Unknown,
@@ -226,7 +225,7 @@ pub fn __dict_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult EvalValueResult
} else {
Err(ErrorCore::new(
vec![SubMessage::only_loc(Location::Unknown)],
- AtomicStr::from(format!("Index out of range: {}", index)),
+ format!("Index out of range: {}", index),
line!() as usize,
ErrorKind::IndexError,
Location::Unknown,
diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs
index 8cd19d63..d01b579b 100644
--- a/compiler/erg_compiler/context/initialize/mod.rs
+++ b/compiler/erg_compiler/context/initialize/mod.rs
@@ -921,6 +921,12 @@ impl Context {
Immutable,
Public,
);
+ str_.register_builtin_impl(
+ "format",
+ fn_met(Str, vec![], Some(kw("args", Obj)), vec![], Str),
+ Immutable,
+ Public,
+ );
let mut str_eq = Self::builtin_methods(Some(mono("Eq")), 2);
str_eq.register_builtin_impl("__eq__", fn1_met(Str, Str, Bool), Const, Public);
str_.register_trait(Str, str_eq);
diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs
index 6bb3ef67..0b29264c 100644
--- a/compiler/erg_compiler/context/mod.rs
+++ b/compiler/erg_compiler/context/mod.rs
@@ -18,7 +18,6 @@ use std::mem;
use std::option::Option; // conflicting to Type::Option
use std::path::Path;
-use erg_common::astr::AtomicStr;
use erg_common::config::ErgConfig;
use erg_common::dict::Dict;
use erg_common::error::Location;
@@ -792,8 +791,8 @@ impl Context {
}
#[inline]
- pub fn caused_by(&self) -> AtomicStr {
- AtomicStr::arc(&self.name[..])
+ pub fn caused_by(&self) -> String {
+ String::from(&self.name[..])
}
pub(crate) fn get_outer(&self) -> Option<&Context> {
diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs
index 2f34dcda..2c02f260 100644
--- a/compiler/erg_compiler/error.rs
+++ b/compiler/erg_compiler/error.rs
@@ -1,12 +1,12 @@
+use std::fmt;
use std::fmt::Display;
-use erg_common::astr::AtomicStr;
use erg_common::config::Input;
use erg_common::error::{
ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay, SubMessage,
};
use erg_common::set::Set;
-use erg_common::style::{Attribute, Color, StyledStr, StyledString, StyledStrings, THEME};
+use erg_common::style::{Attribute, Color, StyledStr, StyledString, StyledStrings, Theme, THEME};
use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility;
use erg_common::{
@@ -113,7 +113,8 @@ pub fn readable_name(name: &str) -> &str {
pub struct CompileError {
pub core: Box, // ErrorCore is large, so box it
pub input: Input,
- pub caused_by: AtomicStr,
+ pub caused_by: String,
+ pub theme: Theme,
}
impl_display_and_error!(CompileError);
@@ -123,7 +124,8 @@ impl From for CompileError {
Self {
core: Box::new(err.core),
input: err.input,
- caused_by: "".into(),
+ caused_by: "".to_owned(),
+ theme: THEME,
}
}
}
@@ -151,11 +153,12 @@ const URL: StyledStr = StyledStr::new(
);
impl CompileError {
- pub fn new(core: ErrorCore, input: Input, caused_by: AtomicStr) -> Self {
+ pub fn new(core: ErrorCore, input: Input, caused_by: String) -> Self {
Self {
core: Box::new(core),
input,
caused_by,
+ theme: THEME,
}
}
@@ -217,7 +220,7 @@ impl CompileError {
)
}
- pub fn feature_error(input: Input, loc: Location, name: &str, caused_by: AtomicStr) -> Self {
+ pub fn feature_error(input: Input, loc: Location, name: &str, caused_by: String) -> Self {
Self::new(
ErrorCore::new(
vec![SubMessage::only_loc(loc)],
@@ -300,7 +303,7 @@ impl TyCheckError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
) -> Self {
let name = readable_name(name);
@@ -327,7 +330,7 @@ impl TyCheckError {
errno: usize,
callee: &C,
param_ts: impl Iterator- ,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let param_ts = fmt_iter(param_ts);
Self::new(
@@ -357,13 +360,13 @@ impl TyCheckError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
nth_param: Option,
expect: &Type,
found: &Type,
candidates: Option>,
- hint: Option,
+ hint: Option,
) -> Self {
let ord = match nth_param {
Some(pos) => switch_lang!(
@@ -422,7 +425,7 @@ impl TyCheckError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
expect: &Type,
found: &Type,
@@ -471,7 +474,7 @@ impl TyCheckError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
t: &Type,
) -> Self {
@@ -497,7 +500,7 @@ impl TyCheckError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
expect: usize,
found: usize,
) -> Self {
@@ -541,7 +544,7 @@ impl TyCheckError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
expr_t: &Type,
) -> Self {
Self::new(
@@ -566,7 +569,7 @@ impl TyCheckError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
expr: &str,
) -> Self {
Self::new(
@@ -601,7 +604,7 @@ impl TyCheckError {
errno: usize,
loc: Location,
callee_name: &str,
- caused_by: AtomicStr,
+ caused_by: String,
params_len: usize,
pos_args_len: usize,
kw_args_len: usize,
@@ -667,7 +670,7 @@ passed keyword args: {kw_args_len}"
errno: usize,
loc: Location,
callee_name: &str,
- caused_by: AtomicStr,
+ caused_by: String,
missing_len: usize,
missing_params: Vec,
) -> Self {
@@ -697,7 +700,7 @@ passed keyword args: {kw_args_len}"
errno: usize,
loc: Location,
callee_name: &str,
- caused_by: AtomicStr,
+ caused_by: String,
arg_name: &str,
) -> Self {
let name = readable_name(callee_name);
@@ -725,7 +728,7 @@ passed keyword args: {kw_args_len}"
errno: usize,
loc: Location,
callee_name: &str,
- caused_by: AtomicStr,
+ caused_by: String,
param_name: &str,
) -> Self {
let name = readable_name(callee_name);
@@ -754,7 +757,7 @@ passed keyword args: {kw_args_len}"
lhs_t: &Type,
rhs_t: &Type,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let mut lhs_typ = StyledStrings::default();
switch_lang!(
@@ -800,7 +803,7 @@ passed keyword args: {kw_args_len}"
lhs_t: &Type,
rhs_t: &Type,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let lhs_t = StyledString::new(&format!("{}", lhs_t), Some(WARN), Some(Attribute::Bold));
let rhs_t = StyledString::new(&format!("{}", rhs_t), Some(WARN), Some(Attribute::Bold));
@@ -828,7 +831,7 @@ passed keyword args: {kw_args_len}"
sub_t: &Type,
sup_t: &Type,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let mut sub_type = StyledStrings::default();
switch_lang!(
@@ -875,7 +878,7 @@ passed keyword args: {kw_args_len}"
errno: usize,
lhs: &Predicate,
rhs: &Predicate,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let mut lhs_uni = StyledStrings::default();
switch_lang!(
@@ -920,8 +923,8 @@ passed keyword args: {kw_args_len}"
errno: usize,
proj: &Type,
loc: Location,
- caused_by: AtomicStr,
- hint: Option,
+ caused_by: String,
+ hint: Option,
) -> Self {
Self::new(
ErrorCore::new(
@@ -947,8 +950,8 @@ passed keyword args: {kw_args_len}"
class: &Type,
trait_: &Type,
loc: Location,
- caused_by: AtomicStr,
- hint: Option,
+ caused_by: String,
+ hint: Option,
) -> Self {
Self::new(
ErrorCore::new(
@@ -972,9 +975,9 @@ passed keyword args: {kw_args_len}"
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
- hint: Option,
+ hint: Option,
) -> Self {
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold));
Self::new(
@@ -1008,12 +1011,12 @@ passed keyword args: {kw_args_len}"
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
member_name: &str,
trait_type: &Type,
expect: &Type,
found: &Type,
- hint: Option,
+ hint: Option,
) -> Self {
let mut expct = StyledStrings::default();
expct.push_str_with_color_and_attribute(&format!("{}", trait_type), WARN, Attribute::Bold);
@@ -1059,11 +1062,11 @@ passed keyword args: {kw_args_len}"
pub fn trait_member_not_defined_error(
input: Input,
errno: usize,
- caused_by: AtomicStr,
+ caused_by: String,
member_name: &str,
trait_type: &Type,
class_type: &Type,
- hint: Option,
+ hint: Option,
) -> Self {
let member_name = StyledString::new(member_name, Some(WARN), Some(Attribute::Bold));
Self::new(
@@ -1088,11 +1091,11 @@ passed keyword args: {kw_args_len}"
pub fn not_in_trait_error(
input: Input,
errno: usize,
- caused_by: AtomicStr,
+ caused_by: String,
member_name: &str,
trait_type: &Type,
class_type: &Type,
- hint: Option,
+ hint: Option,
) -> Self {
let member_name = StyledString::new(member_name, Some(WARN), Some(Attribute::Bold));
Self::new(
@@ -1118,7 +1121,7 @@ passed keyword args: {kw_args_len}"
errno: usize,
name: &str,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold));
Self::new(
@@ -1144,7 +1147,7 @@ passed keyword args: {kw_args_len}"
errno: usize,
expr: &(impl Locational + Display),
candidates: &[Type],
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let hint = Some(
switch_lang!(
@@ -1197,7 +1200,7 @@ pub type EvalResult = TyCheckResult;
pub type SingleEvalResult = SingleTyCheckResult;
impl EvalError {
- pub fn not_const_expr(input: Input, errno: usize, loc: Location, caused_by: AtomicStr) -> Self {
+ pub fn not_const_expr(input: Input, errno: usize, loc: Location, caused_by: String) -> Self {
Self::new(
ErrorCore::new(
vec![SubMessage::only_loc(loc)],
@@ -1216,12 +1219,7 @@ impl EvalError {
)
}
- pub fn invalid_literal(
- input: Input,
- errno: usize,
- loc: Location,
- caused_by: AtomicStr,
- ) -> Self {
+ pub fn invalid_literal(input: Input, errno: usize, loc: Location, caused_by: String) -> Self {
Self::new(
ErrorCore::new(
vec![SubMessage::only_loc(loc)],
@@ -1245,7 +1243,7 @@ pub type EffectError = TyCheckError;
pub type EffectErrors = TyCheckErrors;
impl EffectError {
- pub fn has_effect>(
+ pub fn has_effect>(
input: Input,
errno: usize,
expr: &Expr,
@@ -1269,7 +1267,7 @@ impl EffectError {
)
}
- pub fn proc_assign_error>(
+ pub fn proc_assign_error>(
input: Input,
errno: usize,
sig: &Signature,
@@ -1307,7 +1305,7 @@ pub type OwnershipError = TyCheckError;
pub type OwnershipErrors = TyCheckErrors;
impl OwnershipError {
- pub fn move_error>(
+ pub fn move_error>(
input: Input,
errno: usize,
name: &str,
@@ -1355,13 +1353,13 @@ pub type LowerResult = TyCheckResult;
pub type SingleLowerResult = SingleTyCheckResult;
impl LowerError {
- pub fn syntax_error>(
+ pub fn syntax_error>(
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
desc: S,
- hint: Option,
+ hint: Option,
) -> Self {
Self::new(
ErrorCore::new(
@@ -1380,7 +1378,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
) -> Self {
let name = readable_name(name);
@@ -1406,7 +1404,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
) -> Self {
let name = readable_name(name);
@@ -1432,7 +1430,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
spec_t: &Type,
found_t: &Type,
@@ -1462,7 +1460,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
similar_name: Option<&str>,
) -> Self {
@@ -1475,7 +1473,6 @@ impl LowerError {
"traditional_chinese" => format!("存在相同名稱變量: {n}"),
"english" => format!("exists a similar name variable: {n}"),
)
- .into()
});
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold));
Self::new(
@@ -1500,7 +1497,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
typ: &Type,
) -> Self {
let typ = StyledString::new(&typ.to_string(), Some(ERR), Some(Attribute::Bold));
@@ -1533,7 +1530,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
obj_t: &Type,
name: &str,
similar_name: Option<&str>,
@@ -1545,7 +1542,6 @@ impl LowerError {
"traditional_chinese" => format!("具有相同名稱的屬性: {n}"),
"english" => format!("has a similar name attribute: {n}"),
)
- .into()
});
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold));
Self::new(
@@ -1571,7 +1567,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
obj_name: &str,
obj_t: &Type,
name: &str,
@@ -1585,7 +1581,6 @@ impl LowerError {
"traditional_chinese" => format!("具有相同名稱的屬性: {n}"),
"english" => format!("has a similar name attribute: {n}"),
)
- .into()
});
let found = StyledString::new(name, Some(ERR), Some(Attribute::Bold));
Self::new(
@@ -1610,7 +1605,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
) -> Self {
let name = StyledString::new(readable_name(name), Some(WARN), Some(Attribute::Bold));
@@ -1637,7 +1632,7 @@ impl LowerError {
errno: usize,
loc: Location,
name: &str,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let name = StyledString::new(readable_name(name), Some(WARN), Some(Attribute::Bold));
Self::new(
@@ -1658,7 +1653,7 @@ impl LowerError {
)
}
- pub fn del_error(input: Input, errno: usize, ident: &Identifier, caused_by: AtomicStr) -> Self {
+ pub fn del_error(input: Input, errno: usize, ident: &Identifier, caused_by: String) -> Self {
let name = StyledString::new(
readable_name(ident.inspect()),
Some(WARN),
@@ -1686,7 +1681,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
vis: Visibility,
) -> Self {
@@ -1725,7 +1720,7 @@ impl LowerError {
)
}
- pub fn override_error>(
+ pub fn override_error>(
input: Input,
errno: usize,
name: &str,
@@ -1789,7 +1784,7 @@ impl LowerError {
errno: usize,
class: String,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
Self::new(
ErrorCore::new(
@@ -1814,8 +1809,8 @@ impl LowerError {
errno: usize,
desc: String,
loc: Location,
- caused_by: AtomicStr,
- hint: Option,
+ caused_by: String,
+ hint: Option,
) -> Self {
Self::new(
ErrorCore::new(
@@ -1835,7 +1830,7 @@ impl LowerError {
errno: usize,
mod_name: &str,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
let desc = switch_lang!(
"japanese" => format!("{mod_name}モジュールはお使いの環境をサポートしていません"),
@@ -1851,7 +1846,7 @@ impl LowerError {
errno: usize,
desc: String,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
similar_erg_mod: Option,
similar_py_mod: Option,
) -> Self {
@@ -1948,7 +1943,6 @@ impl LowerError {
}
},
);
- let hint = hint.map(AtomicStr::from);
Self::new(
ErrorCore::new(
vec![SubMessage::ambiguous_new(
@@ -1970,7 +1964,7 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
) -> Self {
Self::new(
ErrorCore::new(
@@ -1990,7 +1984,7 @@ impl LowerError {
)
}
- pub fn declare_error(input: Input, errno: usize, loc: Location, caused_by: AtomicStr) -> Self {
+ pub fn declare_error(input: Input, errno: usize, loc: Location, caused_by: String) -> Self {
Self::new(
ErrorCore::new(
vec![SubMessage::only_loc(loc)],
@@ -2014,10 +2008,10 @@ impl LowerError {
input: Input,
errno: usize,
loc: Location,
- caused_by: AtomicStr,
+ caused_by: String,
name: &str,
cast_to: &Type,
- hint: Option,
+ hint: Option,
) -> Self {
let name = StyledString::new(name, Some(WARN), Some(Attribute::Bold));
let found = StyledString::new(&format!("{}", cast_to), Some(WARN), Some(Attribute::Bold));
@@ -2065,6 +2059,12 @@ impl From for CompileErrors {
impl MultiErrorDisplay for CompileErrors {}
+impl fmt::Display for CompileErrors {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.fmt_all(f)
+ }
+}
+
impl CompileErrors {
pub fn flush(&mut self) -> Self {
Self(self.0.drain(..).collect())
diff --git a/compiler/erg_compiler/lib.rs b/compiler/erg_compiler/lib.rs
index d3013842..f8629da8 100644
--- a/compiler/erg_compiler/lib.rs
+++ b/compiler/erg_compiler/lib.rs
@@ -21,5 +21,6 @@ pub mod mod_cache;
pub mod optimize;
pub mod ownercheck;
pub mod reorder;
+pub mod transpile;
pub mod ty;
pub mod varinfo;
diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs
index ac8b282c..ba73865f 100644
--- a/compiler/erg_compiler/lower.rs
+++ b/compiler/erg_compiler/lower.rs
@@ -2,7 +2,6 @@
//!
//! ASTLowerer(ASTからHIRへの変換器)を実装
-use erg_common::astr::AtomicStr;
use erg_common::config::ErgConfig;
use erg_common::dict;
use erg_common::error::{Location, MultiErrorDisplay};
@@ -161,7 +160,7 @@ impl ASTLowerer {
self.cfg.input.clone(),
line!() as usize,
expr.loc(),
- AtomicStr::arc(&self.ctx.name[..]),
+ String::from(&self.ctx.name[..]),
switch_lang!(
"japanese" => format!("式の評価結果(: {})が使われていません", expr.ref_t()),
"simplified_chinese" => format!("表达式评估结果(: {})未使用", expr.ref_t()),
@@ -226,7 +225,7 @@ impl ASTLowerer {
self.cfg.input.clone(),
line!() as usize,
elem.loc(),
- AtomicStr::arc(&self.ctx.name[..]),
+ String::from(&self.ctx.name[..]),
switch_lang!(
"japanese" => "配列の要素は全て同じ型である必要があります",
"simplified_chinese" => "数组元素必须全部是相同类型",
@@ -372,7 +371,7 @@ impl ASTLowerer {
self.cfg.input.clone(),
line!() as usize,
elem.loc(),
- AtomicStr::arc(&self.ctx.name[..]),
+ String::from(&self.ctx.name[..]),
switch_lang!(
"japanese" => "集合の要素は全て同じ型である必要があります",
"simplified_chinese" => "集合元素必须全部是相同类型",
@@ -404,7 +403,7 @@ impl ASTLowerer {
self.cfg.input.clone(),
line!() as usize,
normal_set.loc(),
- AtomicStr::arc(&self.ctx.name[..]),
+ String::arc(&self.ctx.name[..]),
switch_lang!(
"japanese" => "要素が重複しています",
"simplified_chinese" => "元素重复",
@@ -498,7 +497,7 @@ impl ASTLowerer {
self.cfg.input.clone(),
line!() as usize,
loc,
- AtomicStr::arc(&self.ctx.name[..]),
+ String::from(&self.ctx.name[..]),
switch_lang!(
"japanese" => "Dictの値は全て同じ型である必要があります",
"simplified_chinese" => "Dict的值必须是同一类型",
@@ -543,7 +542,7 @@ impl ASTLowerer {
self.cfg.input.clone(),
line!() as usize,
normal_set.loc(),
- AtomicStr::arc(&self.ctx.name[..]),
+ String::arc(&self.ctx.name[..]),
switch_lang!(
"japanese" => "要素が重複しています",
"simplified_chinese" => "元素重复",
diff --git a/compiler/erg_compiler/main.rs b/compiler/erg_compiler/main.rs
index 66cd9105..cfb8190f 100644
--- a/compiler/erg_compiler/main.rs
+++ b/compiler/erg_compiler/main.rs
@@ -10,6 +10,7 @@ use erg_common::traits::Runnable;
use erg_compiler::build_hir::HIRBuilder;
use erg_compiler::lower::ASTLowerer;
+use erg_compiler::transpile::Transpiler;
use erg_compiler::ty::deserialize::Deserializer;
use erg_compiler::Compiler;
@@ -31,6 +32,9 @@ fn run() {
"check" => {
HIRBuilder::run(cfg);
}
+ "transpile" => {
+ Transpiler::run(cfg);
+ }
"compile" | "exec" => {
Compiler::run(cfg);
}
diff --git a/compiler/erg_compiler/transpile.rs b/compiler/erg_compiler/transpile.rs
new file mode 100644
index 00000000..928e28f2
--- /dev/null
+++ b/compiler/erg_compiler/transpile.rs
@@ -0,0 +1,429 @@
+use std::fs::File;
+use std::io::Write;
+
+use erg_common::config::ErgConfig;
+use erg_common::log;
+use erg_common::traits::{Runnable, Stream};
+use erg_common::Str;
+
+use erg_parser::ast::ParamPattern;
+
+use crate::build_hir::HIRBuilder;
+use crate::desugar_hir::HIRDesugarer;
+use crate::error::{CompileError, CompileErrors};
+use crate::hir::{
+ Accessor, Array, Block, Call, ClassDef, Def, Dict, Expr, Identifier, Lambda, Params, Set,
+ Signature, Tuple, HIR,
+};
+use crate::link::Linker;
+use crate::mod_cache::SharedModuleCache;
+use crate::ty::Type;
+
+#[derive(Debug, Clone)]
+pub struct PyScript {
+ pub filename: Str,
+ pub code: String,
+}
+
+/// Generates a `PyScript` from an String or other File inputs.
+#[derive(Debug, Default)]
+pub struct Transpiler {
+ pub cfg: ErgConfig,
+ builder: HIRBuilder,
+ mod_cache: SharedModuleCache,
+ script_generator: ScriptGenerator,
+}
+
+impl Runnable for Transpiler {
+ type Err = CompileError;
+ type Errs = CompileErrors;
+ const NAME: &'static str = "Erg transpiler";
+
+ fn new(cfg: ErgConfig) -> Self {
+ let mod_cache = SharedModuleCache::new();
+ let py_mod_cache = SharedModuleCache::new();
+ Self {
+ builder: HIRBuilder::new_with_cache(
+ cfg.copy(),
+ "",
+ mod_cache.clone(),
+ py_mod_cache,
+ ),
+ script_generator: ScriptGenerator::new(),
+ mod_cache,
+ cfg,
+ }
+ }
+
+ #[inline]
+ fn cfg(&self) -> &ErgConfig {
+ &self.cfg
+ }
+
+ #[inline]
+ fn finish(&mut self) {}
+
+ fn clear(&mut self) {
+ // self.builder.clear();
+ }
+
+ fn exec(&mut self) -> Result {
+ let path = self.input().filename().replace(".er", ".py");
+ let script = self.transpile(self.input().read(), "exec")?;
+ let mut f = File::create(&path).unwrap();
+ f.write_all(script.code.as_bytes()).unwrap();
+ Ok(0)
+ }
+
+ fn eval(&mut self, src: String) -> Result {
+ let script = self.transpile(src, "eval")?;
+ Ok(script.code)
+ }
+}
+
+impl Transpiler {
+ pub fn transpile(&mut self, src: String, mode: &str) -> Result {
+ log!(info "the transpiling process has started.");
+ let hir = self.build_link_desugar(src, mode)?;
+ let script = self.script_generator.transpile(hir);
+ log!(info "code:\n{}", script.code);
+ log!(info "the transpiling process has completed");
+ Ok(script)
+ }
+
+ fn build_link_desugar(&mut self, src: String, mode: &str) -> Result {
+ let artifact = self
+ .builder
+ .build(src, mode)
+ .map_err(|artifact| artifact.errors)?;
+ let linker = Linker::new(&self.cfg, &self.mod_cache);
+ let hir = linker.link(artifact.hir);
+ Ok(HIRDesugarer::desugar(hir))
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct ScriptGenerator {
+ level: usize,
+}
+
+impl ScriptGenerator {
+ pub const fn new() -> Self {
+ Self { level: 0 }
+ }
+
+ pub fn transpile(&mut self, hir: HIR) -> PyScript {
+ let mut code = self.load_prelude();
+ for chunk in hir.module.into_iter() {
+ code += &self.transpile_expr(chunk);
+ code.push('\n');
+ }
+ PyScript {
+ filename: hir.name,
+ code,
+ }
+ }
+
+ fn load_prelude(&mut self) -> String {
+ "from collections import namedtuple as NamedTuple__\n".to_string()
+ }
+
+ fn transpile_expr(&mut self, expr: Expr) -> String {
+ match expr {
+ Expr::Lit(lit) => lit.token.content.to_string(),
+ Expr::Call(call) => self.transpile_call(call),
+ Expr::BinOp(bin) => {
+ let mut code = "(".to_string();
+ code += &self.transpile_expr(*bin.lhs);
+ code += &bin.op.content;
+ code += &self.transpile_expr(*bin.rhs);
+ code += ")";
+ code
+ }
+ Expr::UnaryOp(unary) => {
+ let mut code = "(".to_string();
+ code += &unary.op.content;
+ code += &self.transpile_expr(*unary.expr);
+ code += ")";
+ code
+ }
+ Expr::Array(array) => match array {
+ Array::Normal(arr) => {
+ let mut code = "[".to_string();
+ for elem in arr.elems.pos_args {
+ code += &format!("{},", self.transpile_expr(elem.expr));
+ }
+ code += "]";
+ code
+ }
+ other => todo!("transpiling {other}"),
+ },
+ Expr::Set(set) => match set {
+ Set::Normal(st) => {
+ let mut code = "{".to_string();
+ for elem in st.elems.pos_args {
+ code += &format!("{},", self.transpile_expr(elem.expr));
+ }
+ code += "}";
+ code
+ }
+ other => todo!("transpiling {other}"),
+ },
+ Expr::Record(rec) => {
+ let mut attrs = "[".to_string();
+ let mut values = "(".to_string();
+ for mut attr in rec.attrs.into_iter() {
+ attrs += &format!("'{}',", Self::transpile_ident(attr.sig.into_ident()));
+ if attr.body.block.len() > 1 {
+ todo!("transpile instant blocks")
+ }
+ values += &format!("{},", self.transpile_expr(attr.body.block.remove(0)));
+ }
+ attrs += "]";
+ values += ")";
+ format!("NamedTuple__('Record', {attrs}){values}")
+ }
+ Expr::Tuple(tuple) => match tuple {
+ Tuple::Normal(tup) => {
+ let mut code = "(".to_string();
+ for elem in tup.elems.pos_args {
+ code += &format!("{},", self.transpile_expr(elem.expr));
+ }
+ code += ")";
+ code
+ }
+ },
+ Expr::Dict(dict) => match dict {
+ Dict::Normal(dic) => {
+ let mut code = "{".to_string();
+ for kv in dic.kvs {
+ code += &format!(
+ "({}): ({}),",
+ self.transpile_expr(kv.key),
+ self.transpile_expr(kv.value)
+ );
+ }
+ code += "}";
+ code
+ }
+ other => todo!("transpiling {other}"),
+ },
+ Expr::Accessor(acc) => match acc {
+ Accessor::Ident(ident) => Self::transpile_ident(ident),
+ Accessor::Attr(attr) => {
+ format!(
+ "({}).{}",
+ self.transpile_expr(*attr.obj),
+ Self::transpile_ident(attr.ident)
+ )
+ }
+ },
+ Expr::Def(def) => self.transpile_def(def),
+ Expr::Lambda(lambda) => self.transpile_lambda(lambda),
+ Expr::ClassDef(classdef) => self.transpile_classdef(classdef),
+ Expr::AttrDef(mut adef) => {
+ let mut code = format!("{} = ", self.transpile_expr(Expr::Accessor(adef.attr)));
+ if adef.block.len() > 1 {
+ todo!("transpile instant blocks")
+ }
+ let expr = adef.block.remove(0);
+ code += &self.transpile_expr(expr);
+ code
+ }
+ // TODO:
+ Expr::Compound(comp) => {
+ let mut code = "".to_string();
+ for expr in comp.into_iter() {
+ code += &self.transpile_expr(expr);
+ code += &format!("\n{}", " ".repeat(self.level));
+ }
+ code
+ }
+ other => todo!("transpile {other}"),
+ }
+ }
+
+ fn transpile_call(&mut self, mut call: Call) -> String {
+ match call.obj.local_name() {
+ Some("assert") => {
+ let mut code = format!("assert {}", self.transpile_expr(call.args.remove(0)));
+ if let Some(msg) = call.args.try_remove(0) {
+ code += &format!(", {}", self.transpile_expr(msg));
+ }
+ code
+ }
+ Some("if" | "if!") => {
+ let cond = self.transpile_expr(call.args.remove(0));
+ let Expr::Lambda(mut block) = call.args.remove(0) else { todo!() };
+ let then = self.transpile_expr(block.body.remove(0));
+ if let Some(Expr::Lambda(mut block)) = call.args.try_remove(0) {
+ let els = self.transpile_expr(block.body.remove(0));
+ format!("{then} if {cond} else {els}")
+ } else {
+ format!("{then} if {cond} else None")
+ }
+ }
+ Some("for" | "for!") => {
+ let mut code = "for ".to_string();
+ let iter = call.args.remove(0);
+ let Expr::Lambda(block) = call.args.remove(0) else { todo!() };
+ let sig = block.params.non_defaults.get(0).unwrap();
+ let ParamPattern::VarName(param) = &sig.pat else { todo!() };
+ code += &format!("{}__ ", ¶m.token().content);
+ code += &format!("in {}:\n", self.transpile_expr(iter));
+ code += &self.transpile_block(block.body, false);
+ code
+ }
+ Some("while" | "while!") => {
+ let mut code = "while ".to_string();
+ let cond = call.args.remove(0);
+ let Expr::Lambda(block) = call.args.remove(0) else { todo!() };
+ code += &format!("{}:\n", self.transpile_expr(cond));
+ code += &self.transpile_block(block.body, false);
+ code
+ }
+ // TODO:
+ Some("match" | "match!") => {
+ let mut code = "match ".to_string();
+ let cond = call.args.remove(0);
+ code += &format!("{}:\n", self.transpile_expr(cond));
+ while let Some(Expr::Lambda(arm)) = call.args.try_remove(0) {
+ self.level += 1;
+ code += &" ".repeat(self.level);
+ let target = arm.params.non_defaults.get(0).unwrap();
+ let ParamPattern::VarName(param) = &target.pat else { todo!() };
+ code += &format!("case {}__:\n", ¶m.token().content);
+ code += &self.transpile_block(arm.body, false);
+ self.level -= 1;
+ }
+ code
+ }
+ _ => self.transpile_simple_call(call),
+ }
+ }
+
+ fn transpile_simple_call(&mut self, mut call: Call) -> String {
+ let mut code = format!("({})", self.transpile_expr(*call.obj));
+ if let Some(attr) = call.attr_name {
+ code += &format!(".{}", Self::transpile_ident(attr));
+ }
+ code.push('(');
+ while let Some(arg) = call.args.try_remove_pos(0) {
+ code += &self.transpile_expr(arg.expr);
+ code.push(',');
+ }
+ while let Some(arg) = call.args.try_remove_kw(0) {
+ code += &format!("{}={},", arg.keyword, self.transpile_expr(arg.expr));
+ }
+ code.push(')');
+ code
+ }
+
+ fn transpile_ident(ident: Identifier) -> String {
+ if let Some(py_name) = ident.vi.py_name {
+ py_name.to_string()
+ } else if ident.dot.is_some() {
+ ident.name.into_token().content.to_string()
+ } else {
+ let name = ident.name.into_token().content;
+ let name = name.replace('!', "__erg_proc__");
+ let name = name.replace('$', "erg_shared__");
+ format!("{name}__")
+ }
+ }
+
+ fn transpile_params(&mut self, params: Params) -> String {
+ let mut code = String::new();
+ for non_default in params.non_defaults {
+ let ParamPattern::VarName(param) = non_default.pat else { todo!() };
+ code += &format!("{}__,", param.into_token().content);
+ }
+ for default in params.defaults {
+ let ParamPattern::VarName(param) = default.sig.pat else { todo!() };
+ code += &format!(
+ "{}__ = {},",
+ param.into_token().content,
+ self.transpile_expr(default.default_val)
+ );
+ }
+ code
+ }
+
+ fn transpile_block(&mut self, block: Block, return_last: bool) -> String {
+ self.level += 1;
+ let mut code = String::new();
+ let last = block.len() - 1;
+ for (i, chunk) in block.into_iter().enumerate() {
+ code += &" ".repeat(self.level);
+ if i == last && return_last {
+ code += "return ";
+ }
+ code += &self.transpile_expr(chunk);
+ code.push('\n');
+ }
+ self.level -= 1;
+ code
+ }
+
+ fn transpile_lambda(&mut self, lambda: Lambda) -> String {
+ let mut code = format!("(lambda {}:", self.transpile_params(lambda.params));
+ if lambda.body.len() > 1 {
+ todo!("multi line lambda");
+ }
+ code += &self.transpile_block(lambda.body, false);
+ code.pop(); // \n
+ code.push(')');
+ code
+ }
+
+ fn transpile_def(&mut self, mut def: Def) -> String {
+ match def.sig {
+ Signature::Var(var) => {
+ let mut code = format!("{} = ", Self::transpile_ident(var.ident));
+ if def.body.block.len() > 1 {
+ todo!("transpile instant blocks")
+ }
+ let expr = def.body.block.remove(0);
+ code += &self.transpile_expr(expr);
+ code
+ }
+ Signature::Subr(subr) => {
+ let mut code = format!(
+ "def {}({}):\n",
+ Self::transpile_ident(subr.ident),
+ self.transpile_params(subr.params)
+ );
+ code += &self.transpile_block(def.body.block, true);
+ code
+ }
+ }
+ }
+
+ fn transpile_classdef(&mut self, classdef: ClassDef) -> String {
+ let class_name = Self::transpile_ident(classdef.sig.into_ident());
+ let mut code = format!("class {class_name}():\n");
+ let mut init_method = format!(
+ "{}def __init__(self, param__):\n",
+ " ".repeat(self.level + 1)
+ );
+ match classdef.__new__.non_default_params().unwrap()[0].typ() {
+ Type::Record(rec) => {
+ for field in rec.keys() {
+ init_method += &format!(
+ "{}self.{} = param__.{}\n",
+ " ".repeat(self.level + 2),
+ field.symbol,
+ field.symbol
+ );
+ }
+ }
+ other => todo!("{other}"),
+ }
+ code += &init_method;
+ if classdef.need_to_gen_new {
+ code += &format!("def new(x): return {class_name}.__call__(x)\n");
+ }
+ code += &self.transpile_block(classdef.methods, false);
+ code
+ }
+}
diff --git a/compiler/erg_compiler/ty/deserialize.rs b/compiler/erg_compiler/ty/deserialize.rs
index 7820205a..d2353ca7 100644
--- a/compiler/erg_compiler/ty/deserialize.rs
+++ b/compiler/erg_compiler/ty/deserialize.rs
@@ -2,7 +2,6 @@
use std::process;
use std::string::FromUtf8Error;
-use erg_common::astr::AtomicStr;
use erg_common::cache::CacheSet;
use erg_common::config::{ErgConfig, Input};
use erg_common::dict::Dict;
@@ -21,8 +20,8 @@ use super::{HasType, Type};
#[derive(Debug)]
pub struct DeserializeError {
pub errno: usize,
- pub caused_by: AtomicStr,
- pub desc: AtomicStr,
+ pub caused_by: String,
+ pub desc: String,
}
impl From for DeserializeError {
@@ -50,11 +49,7 @@ impl From for ErrorCore {
}
impl DeserializeError {
- pub fn new, T: Into>(
- errno: usize,
- caused_by: S,
- desc: T,
- ) -> Self {
+ pub fn new, T: Into>(errno: usize, caused_by: S, desc: T) -> Self {
Self {
errno,
caused_by: caused_by.into(),
diff --git a/compiler/erg_parser/build_ast.rs b/compiler/erg_parser/build_ast.rs
index 635405ec..d2a33050 100644
--- a/compiler/erg_parser/build_ast.rs
+++ b/compiler/erg_parser/build_ast.rs
@@ -8,6 +8,7 @@ use crate::error::{ParserRunnerError, ParserRunnerErrors};
use crate::parse::ParserRunner;
/// Summarize parsing and desugaring
+#[derive(Debug, Default)]
pub struct ASTBuilder {
runner: ParserRunner,
}
diff --git a/compiler/erg_parser/error.rs b/compiler/erg_parser/error.rs
index 2d29857b..ab88193c 100644
--- a/compiler/erg_parser/error.rs
+++ b/compiler/erg_parser/error.rs
@@ -1,7 +1,8 @@
//! defines `ParseError` and others.
//!
//! パーサーが出すエラーを定義
-use erg_common::astr::AtomicStr;
+use std::fmt;
+
use erg_common::config::Input;
use erg_common::error::{
ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay, SubMessage,
@@ -39,7 +40,7 @@ impl LexError {
Self(Box::new(core))
}
- pub fn set_hint>(&mut self, hint: S) {
+ pub fn set_hint>(&mut self, hint: S) {
if let Some(sub_msg) = self.0.sub_messages.get_mut(0) {
sub_msg.set_hint(hint)
}
@@ -95,11 +96,11 @@ impl LexError {
))
}
- pub fn syntax_error>(
+ pub fn syntax_error>(
errno: usize,
loc: Location,
desc: S,
- hint: Option,
+ hint: Option,
) -> Self {
Self::new(ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@@ -110,11 +111,11 @@ impl LexError {
))
}
- pub fn syntax_warning>(
+ pub fn syntax_warning>(
errno: usize,
loc: Location,
desc: S,
- hint: Option,
+ hint: Option,
) -> Self {
Self::new(ErrorCore::new(
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
@@ -139,7 +140,6 @@ impl LexError {
"traditional_chinese" => format!("存在相同名稱變量: {n}"),
"english" => format!("exists a similar name variable: {n}"),
)
- .into()
});
let name = StyledString::new(name, Some(ERR), Some(Attribute::Underline));
Self::new(ErrorCore::new(
@@ -217,6 +217,12 @@ impl_stream_for_wrapper!(ParserRunnerErrors, ParserRunnerError);
impl MultiErrorDisplay for ParserRunnerErrors {}
+impl fmt::Display for ParserRunnerErrors {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.fmt_all(f)
+ }
+}
+
impl ParserRunnerErrors {
pub fn convert(input: &Input, errs: ParseErrors) -> Self {
Self(
diff --git a/compiler/erg_parser/lex.rs b/compiler/erg_parser/lex.rs
index dde1c872..c38abd99 100644
--- a/compiler/erg_parser/lex.rs
+++ b/compiler/erg_parser/lex.rs
@@ -12,6 +12,7 @@ use crate::token::{Token, TokenCategory, TokenKind, TokenStream};
use TokenKind::*;
/// Lexerは使い捨てなので、Runnerを用意
+#[derive(Debug, Default)]
pub struct LexerRunner {
cfg: ErgConfig,
}
diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs
index a7704834..750cc454 100644
--- a/compiler/erg_parser/parse.rs
+++ b/compiler/erg_parser/parse.rs
@@ -164,7 +164,7 @@ impl Parser {
}
}
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct ParserRunner {
cfg: ErgConfig,
}
diff --git a/src/dummy.rs b/src/dummy.rs
index a0442fe1..b132da3f 100644
--- a/src/dummy.rs
+++ b/src/dummy.rs
@@ -26,6 +26,12 @@ pub struct DummyVM {
stream: Option,
}
+impl Default for DummyVM {
+ fn default() -> Self {
+ Self::new(ErgConfig::default())
+ }
+}
+
impl Runnable for DummyVM {
type Err = EvalError;
type Errs = EvalErrors;
diff --git a/src/main.rs b/src/main.rs
index 1d7a226e..363f2201 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -14,6 +14,7 @@ use erg_parser::ParserRunner;
use erg_compiler::build_hir::HIRBuilder;
use erg_compiler::lower::ASTLowerer;
+use erg_compiler::transpile::Transpiler;
use erg_compiler::ty::deserialize::Deserializer;
use erg_compiler::Compiler;
@@ -37,6 +38,9 @@ fn run() {
"compile" => {
Compiler::run(cfg);
}
+ "transpile" => {
+ Transpiler::run(cfg);
+ }
"exec" => {
DummyVM::run(cfg);
}