mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 20:34:44 +00:00
Merge branch 'main' of https://github.com/GreasySlug/erg into split-err-msg
This commit is contained in:
commit
ff24c62de1
31 changed files with 878 additions and 412 deletions
|
@ -9,6 +9,10 @@
|
|||
<p align='center'>
|
||||
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
||||
<a href="https://github.com/erg-lang/erg/actions/workflows/rust.yml"><img alt="Build status" src="https://github.com/erg-lang/erg/actions/workflows/rust.yml/badge.svg"></a>
|
||||
<br>
|
||||
<a href="https://erg-lang.org/erg-playground" data-size="large">
|
||||
<img src="https://img.shields.io/static/v1?style=for-the-badge&label=&message=playground&color=green">
|
||||
</a>
|
||||
<br>
|
||||
<a href='./README_JA.md'>日本語</a> | <a href='./README_zh-CN.md'>简体中文</a> | <a href='./README_zh-TW.md'>繁體中文</a>
|
||||
</p>
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
||||
<a href="https://github.com/erg-lang/erg/actions/workflows/rust.yml"><img alt="Build status" src="https://github.com/erg-lang/erg/actions/workflows/rust.yml/badge.svg"></a>
|
||||
<br>
|
||||
<a href="https://erg-lang.org/erg-playground" data-size="large">
|
||||
<img src="https://img.shields.io/static/v1?style=for-the-badge&label=&message=playground&color=green">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
[
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
||||
<a href="https://github.com/erg-lang/erg/actions/workflows/rust.yml"><img alt="Build status" src="https://github.com/erg-lang/erg/actions/workflows/rust.yml/badge.svg"></a>
|
||||
<br>
|
||||
<a href="https://erg-lang.org/erg-playground" data-size="large">
|
||||
<img src="https://img.shields.io/static/v1?style=for-the-badge&label=&message=playground&color=green">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
[
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
||||
<a href="https://github.com/erg-lang/erg/actions/workflows/rust.yml"><img alt="Build status" src="https://github.com/erg-lang/erg/actions/workflows/rust.yml/badge.svg"></a>
|
||||
<br>
|
||||
<a href="https://erg-lang.org/erg-playground" data-size="large">
|
||||
<img src="https://img.shields.io/static/v1?style=for-the-badge&label=&message=playground&color=green">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
[
|
||||
|
|
|
@ -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<str>;
|
||||
|
||||
/// 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<H: Hasher>(&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<S: Into<Str>> From<S> 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<String> 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<ArcStr> 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<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<&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<StyledString> for AtomicStr {
|
||||
#[inline]
|
||||
fn from(s: StyledString) -> Self {
|
||||
AtomicStr::Arc(s.to_string().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StyledStrings> 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<str> for AtomicStr {
|
||||
#[inline]
|
||||
fn borrow(&self) -> &str {
|
||||
match self {
|
||||
AtomicStr::Arc(s) => s.borrow(),
|
||||
AtomicStr::Static(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> 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)
|
||||
}
|
||||
}
|
|
@ -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<E: ErrorDisplay + ?Sized>(
|
|||
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<E: ErrorDisplay + ?Sized>(
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct SubMessage {
|
||||
pub loc: Location,
|
||||
msg: Vec<AtomicStr>,
|
||||
hint: Option<AtomicStr>,
|
||||
msg: Vec<String>,
|
||||
hint: Option<String>,
|
||||
}
|
||||
|
||||
impl SubMessage {
|
||||
pub fn ambiguous_new(loc: Location, msg: Vec<AtomicStr>, hint: Option<AtomicStr>) -> Self {
|
||||
pub fn ambiguous_new(loc: Location, msg: Vec<String>, hint: Option<String>) -> Self {
|
||||
Self { loc, msg, hint }
|
||||
}
|
||||
|
||||
|
@ -405,11 +404,11 @@ impl SubMessage {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_hint<S: Into<AtomicStr>>(&mut self, hint: S) {
|
||||
pub fn set_hint<S: Into<String>>(&mut self, hint: S) {
|
||||
self.hint = Some(hint.into());
|
||||
}
|
||||
|
||||
pub fn get_hint(self) -> Option<AtomicStr> {
|
||||
pub fn get_hint(self) -> Option<String> {
|
||||
self.hint
|
||||
}
|
||||
|
||||
|
@ -500,7 +499,7 @@ impl SubMessage {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ErrorCore {
|
||||
pub sub_messages: Vec<SubMessage>,
|
||||
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<S: Into<AtomicStr>>(
|
||||
pub fn new<S: Into<String>>(
|
||||
sub_messages: Vec<SubMessage>,
|
||||
main_message: S,
|
||||
errno: usize,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<u8>,
|
||||
}
|
||||
|
||||
impl Default for PythonVersion {
|
||||
fn default() -> Self {
|
||||
Self::new(3, Some(11), Some(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl PythonVersion {
|
||||
pub const fn new(major: u8, minor: Option<u8>, micro: Option<u8>) -> Self {
|
||||
Self {
|
||||
|
|
|
@ -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<Str> for String {
|
||||
#[inline]
|
||||
fn from(s: Str) -> Self {
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
// &'static str -> &strになってしまわないように
|
||||
// あえて`impl<S: Into<Str>> From<S> for Str { ... }`はしない
|
||||
impl From<&'static str> for Str {
|
||||
|
|
|
@ -464,6 +464,12 @@ impl std::fmt::Display for StyledStrings {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<StyledStrings> for String {
|
||||
fn from(s: StyledStrings) -> Self {
|
||||
s.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -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<Self::Err>;
|
||||
const NAME: &'static str;
|
||||
|
|
|
@ -45,7 +45,7 @@ impl<S: AsRawFd> IsTty for S {
|
|||
|
||||
/// returns true if this is a tty
|
||||
#[cfg(any(target_arch = "wasm32", target_env = "sgx"))]
|
||||
impl<S: AsRawFd> IsTty for S {
|
||||
impl IsTty for std::io::Stdin {
|
||||
fn is_tty(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<PyCodeGenUnit>);
|
|||
|
||||
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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<AtomicStr> {
|
||||
pub(crate) fn get_type_mismatch_hint(&self, expected: &Type, found: &Type) -> Option<String> {
|
||||
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<AtomicStr> {
|
||||
pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option<String> {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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<ValueOb
|
|||
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!("{REQ_ERR} is not passed")),
|
||||
format!("{REQ_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
|
@ -34,9 +33,9 @@ pub fn class_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueOb
|
|||
let require = StyledString::new(&format!("{}", require), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!(
|
||||
format!(
|
||||
"non-type object {require} is passed to {REQ_WARN}",
|
||||
)),
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
|
@ -54,7 +53,7 @@ pub fn inherit_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<Value
|
|||
let sup = StyledStr::new("Super", Some(ERR), None);
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!("{sup} is not passed")),
|
||||
format!("{sup} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
|
@ -64,9 +63,9 @@ pub fn inherit_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<Value
|
|||
let sup_ty = StyledString::new(&format!("{}", sup), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!(
|
||||
format!(
|
||||
"non-class object {sup_ty} is passed to {SUP_WARN}",
|
||||
)),
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
|
@ -88,7 +87,7 @@ pub fn inheritable_func(mut args: ValueArgs, _ctx: &Context) -> 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<ValueOb
|
|||
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!("{REQ_ERR} is not passed")),
|
||||
format!("{REQ_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
|
@ -130,9 +129,9 @@ pub fn trait_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<ValueOb
|
|||
let require = StyledString::new(&format!("{}", require), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!(
|
||||
format!(
|
||||
"non-type object {require} is passed to {REQ_WARN}",
|
||||
)),
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
|
@ -149,7 +148,7 @@ pub fn subsume_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<Value
|
|||
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!("{SUP_ERR} is not passed")),
|
||||
format!("{SUP_ERR} is not passed"),
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
Location::Unknown,
|
||||
|
@ -159,9 +158,9 @@ pub fn subsume_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<Value
|
|||
let sup = StyledString::new(&format!("{}", sup), Some(ERR), None);
|
||||
return Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!(
|
||||
format!(
|
||||
"non-trait object {sup} is passed to {SUP_WARN}",
|
||||
)),
|
||||
),
|
||||
line!() as usize,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
|
@ -187,12 +186,12 @@ pub fn __array_getitem__(mut args: ValueArgs, ctx: &Context) -> 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<V
|
|||
} else {
|
||||
Err(ErrorCore::new(
|
||||
vec![SubMessage::only_loc(Location::Unknown)],
|
||||
AtomicStr::from(format!("{slf} has no key {index}",)),
|
||||
format!("{slf} has no key {index}"),
|
||||
line!() as usize,
|
||||
ErrorKind::IndexError,
|
||||
Location::Unknown,
|
||||
|
@ -251,7 +250,7 @@ pub fn __range_getitem__(mut args: ValueArgs, _ctx: &Context) -> 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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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>, // 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<ParserRunnerError> 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<Item = &'a Type>,
|
||||
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<usize>,
|
||||
expect: &Type,
|
||||
found: &Type,
|
||||
candidates: Option<Set<Type>>,
|
||||
hint: Option<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> 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<Str>,
|
||||
) -> 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<AtomicStr>,
|
||||
caused_by: String,
|
||||
hint: Option<String>,
|
||||
) -> 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<AtomicStr>,
|
||||
caused_by: String,
|
||||
hint: Option<String>,
|
||||
) -> 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<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> 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<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> 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<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> 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<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> 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<T> = TyCheckResult<T>;
|
|||
pub type SingleEvalResult<T> = SingleTyCheckResult<T>;
|
||||
|
||||
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<S: Into<AtomicStr>>(
|
||||
pub fn has_effect<S: Into<String>>(
|
||||
input: Input,
|
||||
errno: usize,
|
||||
expr: &Expr,
|
||||
|
@ -1269,7 +1267,7 @@ impl EffectError {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn proc_assign_error<S: Into<AtomicStr>>(
|
||||
pub fn proc_assign_error<S: Into<String>>(
|
||||
input: Input,
|
||||
errno: usize,
|
||||
sig: &Signature,
|
||||
|
@ -1307,7 +1305,7 @@ pub type OwnershipError = TyCheckError;
|
|||
pub type OwnershipErrors = TyCheckErrors;
|
||||
|
||||
impl OwnershipError {
|
||||
pub fn move_error<S: Into<AtomicStr>>(
|
||||
pub fn move_error<S: Into<String>>(
|
||||
input: Input,
|
||||
errno: usize,
|
||||
name: &str,
|
||||
|
@ -1355,13 +1353,13 @@ pub type LowerResult<T> = TyCheckResult<T>;
|
|||
pub type SingleLowerResult<T> = SingleTyCheckResult<T>;
|
||||
|
||||
impl LowerError {
|
||||
pub fn syntax_error<S: Into<AtomicStr>>(
|
||||
pub fn syntax_error<S: Into<String>>(
|
||||
input: Input,
|
||||
errno: usize,
|
||||
loc: Location,
|
||||
caused_by: AtomicStr,
|
||||
caused_by: String,
|
||||
desc: S,
|
||||
hint: Option<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> 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<S: Into<AtomicStr>>(
|
||||
pub fn override_error<S: Into<String>>(
|
||||
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<AtomicStr>,
|
||||
caused_by: String,
|
||||
hint: Option<String>,
|
||||
) -> 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<Str>,
|
||||
similar_py_mod: Option<Str>,
|
||||
) -> 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<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> 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<CompileError> for CompileErrors {
|
|||
|
||||
impl MultiErrorDisplay<CompileError> 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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" => "元素重复",
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
429
compiler/erg_compiler/transpile.rs
Normal file
429
compiler/erg_compiler/transpile.rs
Normal file
|
@ -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(),
|
||||
"<module>",
|
||||
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<i32, Self::Errs> {
|
||||
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<String, CompileErrors> {
|
||||
let script = self.transpile(src, "eval")?;
|
||||
Ok(script.code)
|
||||
}
|
||||
}
|
||||
|
||||
impl Transpiler {
|
||||
pub fn transpile(&mut self, src: String, mode: &str) -> Result<PyScript, CompileErrors> {
|
||||
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<HIR, CompileErrors> {
|
||||
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
|
||||
}
|
||||
}
|
|
@ -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<std::io::Error> for DeserializeError {
|
||||
|
@ -50,11 +49,7 @@ impl From<DeserializeError> for ErrorCore {
|
|||
}
|
||||
|
||||
impl DeserializeError {
|
||||
pub fn new<S: Into<AtomicStr>, T: Into<AtomicStr>>(
|
||||
errno: usize,
|
||||
caused_by: S,
|
||||
desc: T,
|
||||
) -> Self {
|
||||
pub fn new<S: Into<String>, T: Into<String>>(errno: usize, caused_by: S, desc: T) -> Self {
|
||||
Self {
|
||||
errno,
|
||||
caused_by: caused_by.into(),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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<S: Into<AtomicStr>>(&mut self, hint: S) {
|
||||
pub fn set_hint<S: Into<String>>(&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<S: Into<AtomicStr>>(
|
||||
pub fn syntax_error<S: Into<String>>(
|
||||
errno: usize,
|
||||
loc: Location,
|
||||
desc: S,
|
||||
hint: Option<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> Self {
|
||||
Self::new(ErrorCore::new(
|
||||
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
|
||||
|
@ -110,11 +111,11 @@ impl LexError {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn syntax_warning<S: Into<AtomicStr>>(
|
||||
pub fn syntax_warning<S: Into<String>>(
|
||||
errno: usize,
|
||||
loc: Location,
|
||||
desc: S,
|
||||
hint: Option<AtomicStr>,
|
||||
hint: Option<String>,
|
||||
) -> 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<ParserRunnerError> 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(
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::token::{Token, TokenCategory, TokenKind, TokenStream};
|
|||
use TokenKind::*;
|
||||
|
||||
/// Lexerは使い捨てなので、Runnerを用意
|
||||
#[derive(Debug, Default)]
|
||||
pub struct LexerRunner {
|
||||
cfg: ErgConfig,
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ParserRunner {
|
||||
cfg: ErgConfig,
|
||||
}
|
||||
|
|
|
@ -26,6 +26,12 @@ pub struct DummyVM {
|
|||
stream: Option<TcpStream>,
|
||||
}
|
||||
|
||||
impl Default for DummyVM {
|
||||
fn default() -> Self {
|
||||
Self::new(ErgConfig::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for DummyVM {
|
||||
type Err = EvalError;
|
||||
type Errs = EvalErrors;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue