diff --git a/.gitignore b/.gitignore index 20acc993..36bd8fdb 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ /.idea/ /timeit.dat **/__pycache__/ +**/.venv # Nix .direnv diff --git a/Cargo.lock b/Cargo.lock index 0957c616..ad33e097 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,6 +125,7 @@ dependencies = [ "backtrace-on-stack-overflow", "crossterm", "parking_lot", + "pyo3", "thread_local", ] @@ -141,6 +142,8 @@ name = "erg_parser" version = "0.6.25" dependencies = [ "erg_common", + "erg_proc_macros", + "pyo3", "unicode-xid", ] @@ -168,6 +171,12 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "idna" version = "0.4.0" @@ -178,6 +187,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" + [[package]] name = "itoa" version = "1.0.9" @@ -234,6 +249,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -276,7 +300,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -332,6 +356,67 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pyo3" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8453b658fe480c3e70c8ed4e3d3ec33eb74988bd186561b0cc66b85c3bc4b" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset 0.9.0", + "parking_lot", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96fe70b176a89cff78f2fa7b3c930081e163d5379b4dcdf993e3ae29ca662e5" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214929900fd25e6604661ed9cf349727c8920d47deff196c4e28165a6ef2a96b" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac53072f717aa1bfa4db832b39de8c875b7c7af4f4a6fe93cdbf9264cf8383b" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7774b5a8282bd4f25f803b1f0d945120be959a36c72e08e7cd031c792fdfd424" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "quote" version = "1.0.33" @@ -468,6 +553,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "target-lexicon" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" + [[package]] name = "thread_local" version = "1.1.7" @@ -520,6 +611,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" + [[package]] name = "url" version = "2.4.1" diff --git a/Cargo.toml b/Cargo.toml index 11fb78af..2eb98aa1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,6 +71,7 @@ erg_parser = { version = "0.6.25", path = "./crates/erg_parser" } erg_compiler = { version = "0.6.25", path = "./crates/erg_compiler" } els = { version = "0.1.37", path = "./crates/els" } erg_proc_macros = { version = "0.6.25", path = "./crates/erg_proc_macros" } +pyo3 = { version = "0.20", features = ["extension-module"] } [dependencies] erg_common = { workspace = true } diff --git a/crates/erg_common/Cargo.toml b/crates/erg_common/Cargo.toml index 01505b99..6f865f06 100644 --- a/crates/erg_common/Cargo.toml +++ b/crates/erg_common/Cargo.toml @@ -24,6 +24,7 @@ gal = [] no_std = [] full-repl = ["dep:crossterm"] experimental = [] +pylib = ["dep:pyo3"] [target.'cfg(unix)'.dependencies] backtrace-on-stack-overflow = { version = "0.3.0", optional = true } @@ -32,6 +33,7 @@ backtrace-on-stack-overflow = { version = "0.3.0", optional = true } crossterm = { optional = true, version = "0.25.0" } parking_lot = "0.12" thread_local = "1.1" +pyo3 = { workspace = true, optional = true } [lib] path = "lib.rs" diff --git a/crates/erg_common/str.rs b/crates/erg_common/str.rs index 4d903611..f9f7fdd6 100644 --- a/crates/erg_common/str.rs +++ b/crates/erg_common/str.rs @@ -3,6 +3,9 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::ops::{Add, Deref}; +#[cfg(feature = "pylib")] +use pyo3::{IntoPy, PyObject, Python}; + pub type ArcStr = std::sync::Arc; /// Used to hold an immutable string. @@ -14,6 +17,13 @@ pub enum Str { Static(&'static str), } +#[cfg(feature = "pylib")] +impl IntoPy for Str { + fn into_py(self, py: Python<'_>) -> PyObject { + (&self[..]).into_py(py) + } +} + impl PartialEq for Str { #[inline] fn eq(&self, other: &Str) -> bool { diff --git a/crates/erg_parser/Cargo.toml b/crates/erg_parser/Cargo.toml index 2fab8236..accac463 100644 --- a/crates/erg_parser/Cargo.toml +++ b/crates/erg_parser/Cargo.toml @@ -18,12 +18,16 @@ unicode = ["erg_common/unicode"] pretty = ["erg_common/pretty"] large_thread = ["erg_common/large_thread"] experimental = ["erg_common/experimental"] +pylib = ["dep:pyo3", "erg_common/pylib"] [dependencies] erg_common = { workspace = true } +erg_proc_macros = { workspace = true } unicode-xid = "0.2.4" +pyo3 = { workspace = true, optional = true } [lib] +crate-type = ["cdylib", "rlib"] path = "lib.rs" [[bin]] diff --git a/crates/erg_parser/README.md b/crates/erg_parser/README.md index 4d18423f..b617cbf0 100644 --- a/crates/erg_parser/README.md +++ b/crates/erg_parser/README.md @@ -1,5 +1,22 @@ # Erg parser -## Why isn't this module but crate? +## Use `erg_parser` as a Python library -For maintainability. This crate has tests. +`erg_parser` can be built as a Python library by using pyo3/maturin. + +### Example + +```python +import erg_parser + +module = erg_parser.parse("x = 1") +for chunk in module: + if isinstance(chunk, erg_parser.expr.Def): + assert chunk.sig.inspect() == "x" +``` + +### Debug install + +```python +maturin develop --features pylib +``` diff --git a/crates/erg_parser/ast.rs b/crates/erg_parser/ast.rs index ee547473..fee52468 100644 --- a/crates/erg_parser/ast.rs +++ b/crates/erg_parser/ast.rs @@ -19,6 +19,57 @@ use erg_common::{fmt_vec_split_with, Str}; use crate::token::{Token, TokenKind, EQUAL}; +#[cfg(not(feature = "pylib"))] +use erg_proc_macros::{pyclass, pymethods, pyo3}; +#[cfg(feature = "pylib")] +use pyo3::prelude::*; + +macro_rules! impl_into_py_for_enum { + ($Enum: ident; $($Variant: ident $(,)?)*) => { + #[cfg(feature = "pylib")] + impl IntoPy for $Enum { + fn into_py(self, py: Python<'_>) -> PyObject { + match self { + $(Self::$Variant(v) => v.into_py(py),)* + } + } + } + }; +} + +macro_rules! impl_py_iter { + ($Ty: ident <$inner: ident>, $Iter: ident) => { + #[cfg(feature = "pylib")] + #[pyclass] + struct $Iter { + inner: std::vec::IntoIter<$inner>, + } + + #[cfg(feature = "pylib")] + #[pymethods] + impl $Iter { + #[allow(clippy::self_named_constructors)] + fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { + slf + } + fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<$inner> { + slf.inner.next() + } + } + + #[cfg(feature = "pylib")] + #[pymethods] + impl $Ty { + fn __iter__(slf: PyRef<'_, Self>) -> PyResult> { + let iter = $Iter { + inner: slf.clone().into_iter(), + }; + Py::new(slf.py(), iter) + } + } + }; +} + /// Some Erg functions require additional operation by the compiler. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum OperationKind { @@ -65,6 +116,7 @@ pub fn fmt_lines<'a, T: NestedDisplay + 'a>( /// リテラルに実際の値が格納された構造体(定数畳み込み用) /// ArrayやDictはまた別に +#[pyclass(get_all)] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Literal { pub token: Token, @@ -118,6 +170,7 @@ impl Literal { } } +#[pyclass(get_all)] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct PosArg { pub expr: Expr, @@ -138,6 +191,7 @@ impl PosArg { } } +#[pyclass(get_all)] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct KwArg { pub keyword: Token, @@ -170,6 +224,7 @@ impl KwArg { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Args { pos_args: Vec, @@ -355,6 +410,7 @@ impl Args { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Attribute { pub obj: Box, @@ -383,6 +439,7 @@ impl Attribute { } } +#[pyclass] /// e.g. obj.0, obj.1 #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TupleAttribute { @@ -412,6 +469,7 @@ impl TupleAttribute { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Subscript { pub obj: Box, @@ -460,6 +518,7 @@ impl NestedDisplay for TypeAppArgsKind { impl_display_from_nested!(TypeAppArgsKind); impl_locational_for_enum!(TypeAppArgsKind; SubtypeOf, Args); +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TypeAppArgs { pub l_vbar: Token, @@ -487,6 +546,7 @@ impl TypeAppArgs { } /// f|T := Int| +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TypeApp { pub obj: Box, @@ -527,6 +587,7 @@ pub enum Accessor { impl_nested_display_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr, TypeApp); impl_display_from_nested!(Accessor); impl_locational_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr, TypeApp); +impl_into_py_for_enum!(Accessor; Ident, Attr, TupleAttr, Subscr, TypeApp); impl Accessor { pub const fn local(symbol: Token) -> Self { @@ -591,6 +652,7 @@ impl Accessor { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NormalArray { pub l_sqbr: Token, @@ -623,6 +685,7 @@ impl NormalArray { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ArrayWithLength { pub l_sqbr: Token, @@ -651,6 +714,7 @@ impl ArrayWithLength { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ArrayComprehension { pub l_sqbr: Token, @@ -707,6 +771,7 @@ pub enum Array { impl_nested_display_for_enum!(Array; Normal, WithLength, Comprehension); impl_display_for_enum!(Array; Normal, WithLength, Comprehension); impl_locational_for_enum!(Array; Normal, WithLength, Comprehension); +impl_into_py_for_enum!(Array; Normal, WithLength, Comprehension); impl Array { pub fn get(&self, index: usize) -> Option<&Expr> { @@ -717,6 +782,7 @@ impl Array { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct NormalTuple { pub elems: Args, @@ -754,6 +820,7 @@ pub enum Tuple { impl_nested_display_for_enum!(Tuple; Normal); impl_display_for_enum!(Tuple; Normal); impl_locational_for_enum!(Tuple; Normal); +impl_into_py_for_enum!(Tuple; Normal); impl Tuple { pub fn paren(&self) -> Option<&(Token, Token)> { @@ -763,6 +830,7 @@ impl Tuple { } } +#[pyclass(get_all)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct KeyValue { pub key: Expr, @@ -784,6 +852,7 @@ impl KeyValue { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct NormalDict { pub l_brace: Token, @@ -810,6 +879,7 @@ impl NormalDict { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DictComprehension { l_brace: Token, @@ -864,6 +934,7 @@ pub enum Dict { impl_nested_display_for_enum!(Dict; Normal, Comprehension); impl_display_for_enum!(Dict; Normal, Comprehension); impl_locational_for_enum!(Dict; Normal, Comprehension); +impl_into_py_for_enum!(Dict; Normal, Comprehension); impl Dict { pub fn braces(&self) -> (&Token, &Token) { @@ -884,7 +955,9 @@ pub enum ClassAttr { impl_nested_display_for_enum!(ClassAttr; Def, Decl, Doc); impl_display_for_enum!(ClassAttr; Def, Decl, Doc); impl_locational_for_enum!(ClassAttr; Def, Decl, Doc); +impl_into_py_for_enum!(ClassAttr; Def, Decl, Doc); +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ClassAttrs(Vec); @@ -909,9 +982,11 @@ impl From> for ClassAttrs { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordAttrs(Vec); +impl_py_iter!(RecordAttrs, DefIter); impl_stream!(RecordAttrs, Def); impl NestedDisplay for RecordAttrs { @@ -933,6 +1008,7 @@ impl From> for RecordAttrs { } } +#[pyclass(get_all)] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct NormalRecord { pub l_brace: Token, @@ -1020,6 +1096,7 @@ pub enum Record { impl_nested_display_for_enum!(Record; Normal, Mixed); impl_display_for_enum!(Record; Normal, Mixed); impl_locational_for_enum!(Record; Normal, Mixed); +impl_into_py_for_enum!(Record; Normal, Mixed); impl Record { pub const fn new_mixed(l_brace: Token, r_brace: Token, attrs: Vec) -> Self { @@ -1069,6 +1146,7 @@ impl Record { } /// Record can be defined with shorthend/normal mixed style, i.e. {x; y=expr; z; ...} +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MixedRecord { pub l_brace: Token, @@ -1115,6 +1193,7 @@ pub enum RecordAttrOrIdent { impl_nested_display_for_enum!(RecordAttrOrIdent; Attr, Ident); impl_display_for_enum!(RecordAttrOrIdent; Attr, Ident); impl_locational_for_enum!(RecordAttrOrIdent; Attr, Ident); +impl_into_py_for_enum!(RecordAttrOrIdent; Attr, Ident); impl RecordAttrOrIdent { pub fn ident(&self) -> Option<&Identifier> { @@ -1125,6 +1204,7 @@ impl RecordAttrOrIdent { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct NormalSet { pub l_brace: Token, @@ -1159,6 +1239,7 @@ impl NormalSet { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SetWithLength { pub l_brace: Token, @@ -1187,6 +1268,7 @@ impl SetWithLength { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SetComprehension { pub l_brace: Token, @@ -1242,7 +1324,9 @@ pub enum Set { impl_nested_display_for_enum!(Set; Normal, WithLength, Comprehension); impl_display_for_enum!(Set; Normal, WithLength, Comprehension); impl_locational_for_enum!(Set; Normal, WithLength, Comprehension); +impl_into_py_for_enum!(Set; Normal, WithLength, Comprehension); +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct BinOp { pub op: Token, @@ -1281,6 +1365,7 @@ impl BinOp { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct UnaryOp { pub op: Token, @@ -1316,6 +1401,7 @@ impl UnaryOp { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Call { pub obj: Box, @@ -1415,6 +1501,7 @@ impl Call { } /// e.g. `Data::{x = 1; y = 2}` +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DataPack { pub class: Box, @@ -1446,6 +1533,7 @@ impl DataPack { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Block(Vec); @@ -1468,7 +1556,9 @@ impl Locational for Block { } impl_stream!(Block, Expr); +impl_py_iter!(Block, BlockIter); +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Dummy { pub loc: Option, @@ -1529,6 +1619,7 @@ impl Dummy { pub type ConstIdentifier = Identifier; +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstAttribute { pub obj: Box, @@ -1561,6 +1652,7 @@ impl ConstAttribute { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstTupleAttribute { tup: Box, @@ -1589,6 +1681,7 @@ impl ConstTupleAttribute { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstSubscript { obj: Box, @@ -1628,6 +1721,7 @@ pub enum ConstAccessor { impl_nested_display_for_enum!(ConstAccessor; Local, Attr, TupleAttr, Subscr); impl_display_from_nested!(ConstAccessor); impl_locational_for_enum!(ConstAccessor; Local, Attr, TupleAttr, Subscr); +impl_into_py_for_enum!(ConstAccessor; Local, Attr, TupleAttr, Subscr); impl ConstAccessor { pub const fn local(symbol: Token) -> Self { @@ -1665,6 +1759,7 @@ pub enum ConstArray { impl_nested_display_for_enum!(ConstArray; Normal, WithLength); impl_display_from_nested!(ConstArray); impl_locational_for_enum!(ConstArray; Normal, WithLength); +impl_into_py_for_enum!(ConstArray; Normal, WithLength); impl ConstArray { pub fn downgrade(self) -> Array { @@ -1675,6 +1770,7 @@ impl ConstArray { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstNormalArray { pub l_sqbr: Token, @@ -1711,6 +1807,7 @@ impl ConstNormalArray { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstArrayWithLength { pub l_sqbr: Token, @@ -1748,6 +1845,7 @@ impl ConstArrayWithLength { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstNormalSet { pub l_brace: Token, @@ -1778,6 +1876,7 @@ impl ConstNormalSet { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstSetComprehension { pub l_brace: Token, @@ -1845,6 +1944,7 @@ pub enum ConstSet { impl_nested_display_for_enum!(ConstSet; Normal, Comprehension); impl_display_from_nested!(ConstSet); impl_locational_for_enum!(ConstSet; Normal, Comprehension); +impl_into_py_for_enum!(ConstSet; Normal, Comprehension); impl ConstSet { pub fn downgrade(self) -> Set { @@ -1855,6 +1955,7 @@ impl ConstSet { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ConstKeyValue { pub key: ConstExpr, @@ -1880,6 +1981,7 @@ impl ConstKeyValue { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstDict { l_brace: Token, @@ -1914,6 +2016,7 @@ impl ConstDict { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstTuple { pub elems: ConstArgs, @@ -1938,6 +2041,7 @@ impl ConstTuple { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstBlock(Vec); @@ -1960,6 +2064,7 @@ impl Locational for ConstBlock { } impl_stream!(ConstBlock, ConstExpr); +impl_py_iter!(ConstBlock, ConstExprIter); impl ConstBlock { pub fn downgrade(self) -> Block { @@ -1967,6 +2072,7 @@ impl ConstBlock { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstDefBody { pub op: Token, @@ -1986,6 +2092,7 @@ impl ConstDefBody { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstDef { pub ident: ConstIdentifier, @@ -2011,6 +2118,7 @@ impl ConstDef { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstLambda { pub sig: Box, @@ -2043,6 +2151,7 @@ impl ConstLambda { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstRecord { pub l_brace: Token, @@ -2082,6 +2191,7 @@ impl ConstRecord { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstBinOp { pub op: Token, @@ -2112,6 +2222,7 @@ impl ConstBinOp { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstUnaryOp { pub op: Token, @@ -2142,6 +2253,7 @@ impl ConstUnaryOp { /// Application /// ex. `Vec Int` of `Option Vec Int` +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstApp { pub obj: Box, @@ -2194,6 +2306,7 @@ impl ConstApp { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstTypeAsc { pub expr: Box, @@ -2252,6 +2365,7 @@ pub enum ConstExpr { impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Set, TypeAsc); impl_display_from_nested!(ConstExpr); impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Set, TypeAsc); +impl_into_py_for_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, Def, Lambda, BinOp, UnaryOp, TypeAsc); impl TryFrom<&ParamPattern> for ConstExpr { type Error = (); @@ -2297,6 +2411,7 @@ impl ConstExpr { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstPosArg { pub expr: ConstExpr, @@ -2316,6 +2431,7 @@ impl ConstPosArg { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstKwArg { pub keyword: Token, @@ -2336,6 +2452,7 @@ impl ConstKwArg { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ConstArgs { pos_args: Vec, @@ -2467,6 +2584,7 @@ impl ConstArgs { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct PolyTypeSpec { pub acc: ConstAccessor, @@ -2576,6 +2694,7 @@ impl PreDeclTypeSpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ParamTySpec { pub name: Option, @@ -2612,6 +2731,7 @@ impl ParamTySpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct DefaultParamTySpec { pub param: ParamTySpec, @@ -2630,6 +2750,7 @@ impl DefaultParamTySpec { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct SubrTypeSpec { pub bounds: TypeBoundSpecs, @@ -2703,6 +2824,7 @@ impl SubrTypeSpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ArrayTypeSpec { pub sqbrs: Option<(Token, Token)>, @@ -2736,6 +2858,7 @@ impl ArrayTypeSpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SetWithLenTypeSpec { pub ty: Box, @@ -2759,6 +2882,7 @@ impl SetWithLenTypeSpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TupleTypeSpec { pub parens: Option<(Token, Token)>, @@ -2789,6 +2913,7 @@ impl TupleTypeSpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct DictTypeSpec { pub braces: Option<(Token, Token)>, @@ -2825,6 +2950,7 @@ impl DictTypeSpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordTypeSpec { pub braces: Option<(Token, Token)>, @@ -2861,6 +2987,7 @@ impl RecordTypeSpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RefinementTypeSpec { pub var: Token, @@ -2929,6 +3056,14 @@ pub enum TypeSpec { Refinement(RefinementTypeSpec), } +// TODO: +#[cfg(feature = "pylib")] +impl IntoPy for TypeSpec { + fn into_py(self, py: Python<'_>) -> PyObject { + pyo3::types::PyNone::get(py).into() + } +} + impl fmt::Display for TypeSpec { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -3035,6 +3170,7 @@ impl TypeSpec { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeSpecWithOp { pub op: Token, @@ -3124,6 +3260,7 @@ impl TypeBoundSpec { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TypeBoundSpecs(Vec); @@ -3141,6 +3278,7 @@ impl Locational for TypeBoundSpecs { /// デコレータは関数を返す関数オブジェクトならば何でも指定できる /// e.g. @(x -> x) +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Decorator(pub Expr); @@ -3159,6 +3297,7 @@ impl Decorator { } /// symbol as a left value +#[pyclass] #[derive(Debug, Clone, Eq)] pub struct VarName(Token); @@ -3283,6 +3422,7 @@ impl VarName { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Namespaces(Vec); @@ -3318,6 +3458,7 @@ pub enum VisRestriction { impl_locational_for_enum!(VisRestriction; Namespaces, SubtypeOf); impl_display_from_nested!(VisRestriction); +impl_into_py_for_enum!(VisRestriction; Namespaces, SubtypeOf); impl NestedDisplay for VisRestriction { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { @@ -3337,6 +3478,19 @@ pub enum VisModifierSpec { Restricted(VisRestriction), } +#[cfg(feature = "pylib")] +impl IntoPy for VisModifierSpec { + fn into_py(self, py: Python<'_>) -> PyObject { + match self { + Self::Private => py.None(), + Self::Auto => py.None(), + Self::Public(token) => token.into_py(py), + Self::ExplicitPrivate(token) => token.into_py(py), + Self::Restricted(rest) => rest.into_py(py), + } + } +} + impl NestedDisplay for VisModifierSpec { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { match self { @@ -3380,6 +3534,7 @@ impl VisModifierSpec { } } +#[pyclass] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum AccessModifier { Private, // `::` @@ -3388,6 +3543,7 @@ pub enum AccessModifier { Force, // can access any identifiers } +#[pyclass(get_all)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Identifier { pub vis: VisModifierSpec, @@ -3415,6 +3571,44 @@ impl From for Expr { } } +#[pymethods] +impl Identifier { + pub fn is_const(&self) -> bool { + self.name.is_const() + } + + pub fn is_discarded(&self) -> bool { + self.name.is_discarded() + } + + pub fn is_raw(&self) -> bool { + self.name.is_raw() + } + + pub fn acc_kind(&self) -> AccessModifier { + match &self.vis { + VisModifierSpec::Auto => AccessModifier::Auto, + VisModifierSpec::Public(_) => AccessModifier::Public, + VisModifierSpec::ExplicitPrivate(_) + | VisModifierSpec::Restricted(_) + | VisModifierSpec::Private => AccessModifier::Private, + } + } + + pub fn is_procedural(&self) -> bool { + self.name.is_procedural() + } + + pub fn trim_end_proc_mark(&mut self) { + self.name.trim_end_proc_mark(); + } + + #[pyo3(name = "inspect")] + fn _inspect(&self) -> Str { + self.name.inspect().clone() + } +} + impl Identifier { pub const fn new(vis: VisModifierSpec, name: VarName) -> Self { Self { vis, name } @@ -3482,40 +3676,10 @@ impl Identifier { Self::new(VisModifierSpec::Auto, VarName::from_str(name)) } - pub fn is_const(&self) -> bool { - self.name.is_const() - } - - pub fn is_discarded(&self) -> bool { - self.name.is_discarded() - } - - pub fn is_raw(&self) -> bool { - self.name.is_raw() - } - - pub fn acc_kind(&self) -> AccessModifier { - match &self.vis { - VisModifierSpec::Auto => AccessModifier::Auto, - VisModifierSpec::Public(_) => AccessModifier::Public, - VisModifierSpec::ExplicitPrivate(_) - | VisModifierSpec::Restricted(_) - | VisModifierSpec::Private => AccessModifier::Private, - } - } - pub const fn inspect(&self) -> &Str { self.name.inspect() } - pub fn is_procedural(&self) -> bool { - self.name.is_procedural() - } - - pub fn trim_end_proc_mark(&mut self) { - self.name.trim_end_proc_mark(); - } - pub fn call1(self, arg: Expr) -> Call { Call::new( self.into(), @@ -3537,6 +3701,7 @@ impl Identifier { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarArrayPattern { l_sqbr: Token, @@ -3577,6 +3742,7 @@ impl VarArrayPattern { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarTuplePattern { pub(crate) paren: Option<(Token, Token)>, @@ -3619,6 +3785,7 @@ impl VarTuplePattern { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarRecordAttr { pub lhs: Identifier, @@ -3640,6 +3807,7 @@ impl VarRecordAttr { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarRecordAttrs { pub(crate) elems: Vec, @@ -3664,6 +3832,7 @@ impl VarRecordAttrs { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarRecordPattern { l_brace: Token, @@ -3689,6 +3858,7 @@ impl VarRecordPattern { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarDataPackPattern { pub class: TypeSpec, @@ -3743,6 +3913,7 @@ impl NestedDisplay for VarPattern { impl_display_from_nested!(VarPattern); impl_locational_for_enum!(VarPattern; Discard, Ident, Array, Tuple, Record, DataPack); +impl_into_py_for_enum!(VarPattern; Discard, Ident, Array, Tuple, Record, DataPack); impl VarPattern { pub const fn inspect(&self) -> Option<&Str> { @@ -3784,6 +3955,7 @@ impl VarPattern { } } +#[pyclass(get_all)] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarSignature { pub pat: VarPattern, @@ -3808,6 +3980,15 @@ impl Locational for VarSignature { } } +#[cfg(feature = "pylib")] +#[pymethods] +impl VarSignature { + #[pyo3(name = "inspect")] + fn _inspect(&self) -> Option { + self.pat.inspect().cloned() + } +} + impl VarSignature { pub const fn new(pat: VarPattern, t_spec: Option) -> Self { Self { pat, t_spec } @@ -3833,6 +4014,7 @@ impl VarSignature { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Vars { pub(crate) elems: Vec, @@ -3867,6 +4049,7 @@ impl Vars { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ParamArrayPattern { pub l_sqbr: Token, @@ -3935,6 +4118,7 @@ impl ParamArrayPattern { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ParamTuplePattern { pub elems: Params, @@ -3981,6 +4165,7 @@ impl ParamTuplePattern { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ParamRecordAttr { pub lhs: Identifier, @@ -4002,6 +4187,7 @@ impl ParamRecordAttr { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ParamRecordAttrs { pub(crate) elems: Vec, @@ -4030,6 +4216,7 @@ impl ParamRecordAttrs { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ParamRecordPattern { pub(crate) l_brace: Token, @@ -4071,6 +4258,8 @@ pub enum ParamPattern { RefMut(VarName), } +impl_into_py_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut); + impl NestedDisplay for ParamPattern { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { match self { @@ -4142,6 +4331,7 @@ impl ParamPattern { } /// Once the default_value is set to Some, all subsequent values must be Some +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct NonDefaultParamSignature { pub pat: ParamPattern, @@ -4185,6 +4375,7 @@ impl NonDefaultParamSignature { } /// Once the default_value is set to Some, all subsequent values must be Some +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DefaultParamSignature { pub sig: NonDefaultParamSignature, @@ -4241,6 +4432,7 @@ impl Locational for GuardClause { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Params { pub non_defaults: Vec, @@ -4370,6 +4562,7 @@ impl Params { } /// 引数を取るならTypeでもSubr扱い +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct SubrSignature { pub decorators: HashSet, @@ -4442,6 +4635,7 @@ impl SubrSignature { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct LambdaSignature { pub bounds: TypeBoundSpecs, @@ -4507,6 +4701,7 @@ impl LambdaSignature { } } +#[pyclass(subclass)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct DefId(pub usize); @@ -4516,6 +4711,7 @@ impl DefId { } } +#[pyclass(get_all)] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Lambda { pub sig: LambdaSignature, @@ -4556,6 +4752,7 @@ pub enum Signature { impl_nested_display_for_chunk_enum!(Signature; Var, Subr); impl_display_from_nested!(Signature); impl_locational_for_enum!(Signature; Var, Subr); +impl_into_py_for_enum!(Signature; Var, Subr); impl Signature { pub fn name_as_str(&self) -> Option<&Str> { @@ -4656,6 +4853,7 @@ impl Signature { } } +#[pyclass] #[derive(Debug, Clone, Copy)] pub enum AscriptionKind { TypeOf, @@ -4673,6 +4871,7 @@ impl AscriptionKind { /// type_ascription ::= expr ':' type /// | expr '<:' type /// | expr ':>' type +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TypeAscription { pub expr: Box, @@ -4701,6 +4900,7 @@ impl TypeAscription { } } +#[pyclass] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum DefKind { Class, @@ -4750,6 +4950,7 @@ impl DefKind { } } +#[pyclass(get_all)] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DefBody { pub op: Token, @@ -4797,6 +4998,7 @@ impl DefBody { } } +#[pyclass(get_all)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Def { pub sig: Signature, @@ -4837,6 +5039,7 @@ impl Def { } /// This is not necessary for Erg syntax, but necessary for mapping ASTs in Python +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ReDef { pub attr: Accessor, @@ -4870,6 +5073,7 @@ impl ReDef { /// x = 1 /// f(a) = ... /// ``` +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Methods { pub id: DefId, @@ -4907,6 +5111,7 @@ impl Methods { } } +#[pyclass(get_all)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ClassDef { pub def: Def, @@ -4937,6 +5142,7 @@ impl ClassDef { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PatchDef { pub def: Def, @@ -4967,6 +5173,7 @@ impl PatchDef { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Compound { pub exprs: Vec, @@ -5031,6 +5238,7 @@ impl_nested_display_for_chunk_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, impl_from_trait_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy); impl_display_from_nested!(Expr); impl_locational_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy); +impl_into_py_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy); impl Expr { pub fn is_match_call(&self) -> bool { @@ -5252,6 +5460,7 @@ impl Expr { } } +#[pyclass] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Module(Block); @@ -5296,6 +5505,8 @@ impl FromIterator for Module { } } +impl_py_iter!(Module, ModuleIter); + impl Module { pub const fn empty() -> Self { Self(Block::empty()) @@ -5338,6 +5549,7 @@ impl AST { } } +#[pyclass] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct InlineModule { pub input: Input, diff --git a/crates/erg_parser/error.rs b/crates/erg_parser/error.rs index 64bd895c..efe07a65 100644 --- a/crates/erg_parser/error.rs +++ b/crates/erg_parser/error.rs @@ -25,6 +25,13 @@ impl fmt::Display for LexError { impl std::error::Error for LexError {} +#[cfg(feature = "pylib")] +impl std::convert::From for pyo3::PyErr { + fn from(err: LexError) -> pyo3::PyErr { + pyo3::exceptions::PyOSError::new_err(err.to_string()) + } +} + impl From for LexError { fn from(core: ErrorCore) -> Self { Self(Box::new(core)) @@ -37,6 +44,7 @@ impl From for ErrorCore { } } +#[cfg_attr(feature = "pylib", pyo3::pyclass)] #[derive(Debug)] pub struct LexErrors(Vec); @@ -50,6 +58,13 @@ impl fmt::Display for LexErrors { impl std::error::Error for LexErrors {} +#[cfg(feature = "pylib")] +impl std::convert::From for pyo3::PyErr { + fn from(errs: LexErrors) -> pyo3::PyErr { + pyo3::exceptions::PyOSError::new_err(errs[0].to_string()) + } +} + const ERR: Color = THEME.colors.error; const WARN: Color = THEME.colors.warning; const HINT: Color = THEME.colors.hint; diff --git a/crates/erg_parser/lib.rs b/crates/erg_parser/lib.rs index ee1af26a..ce3a0fe6 100644 --- a/crates/erg_parser/lib.rs +++ b/crates/erg_parser/lib.rs @@ -17,3 +17,74 @@ pub mod visitor; pub use parse::{Parser, ParserRunner}; pub use visitor::ASTVisitor; + +#[cfg(feature = "pylib")] +use pyo3::prelude::*; + +#[cfg(feature = "pylib")] +#[pyfunction] +#[pyo3(name = "parse")] +fn _parse(code: String) -> Result { + parse::SimpleParser::parse(code) + .map(|art| art.ast) + .map_err(|iart| iart.errors) +} + +#[cfg(feature = "pylib")] +#[pymodule] +fn erg_parser(py: Python<'_>, m: &PyModule) -> PyResult<()> { + m.add_function(wrap_pyfunction!(_parse, m)?)?; + let expr = PyModule::new(py, "expr")?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + expr.add_class::()?; + m.add_submodule(expr)?; + + let ast = PyModule::new(py, "ast")?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + ast.add_class::()?; + m.add_submodule(ast)?; + Ok(()) +} diff --git a/crates/erg_parser/parse.rs b/crates/erg_parser/parse.rs index 445996cd..72e3a5d6 100644 --- a/crates/erg_parser/parse.rs +++ b/crates/erg_parser/parse.rs @@ -102,6 +102,7 @@ pub trait Parsable: 'static { fn parse(code: String) -> Result>; } +#[cfg_attr(feature = "pylib", pyo3::pyclass)] pub struct SimpleParser {} impl Parsable for SimpleParser { @@ -353,11 +354,11 @@ impl Parser { ParseError::unclosed_error(line as usize, loc, closer, ty) } - fn skip_and_throw_invalid_seq_err( + fn skip_and_throw_invalid_seq_err( &mut self, caused_by: &str, errno: usize, - expected: &[S], + expected: &[impl std::fmt::Display], found: TokenKind, ) -> ParseError { log!(err "error caused by: {caused_by}"); diff --git a/crates/erg_parser/token.rs b/crates/erg_parser/token.rs index 074d071b..a6afc964 100644 --- a/crates/erg_parser/token.rs +++ b/crates/erg_parser/token.rs @@ -14,7 +14,13 @@ use erg_common::traits::{DequeStream, Locational}; // use erg_common::typaram::OpKind; // use erg_common::value::ValueObj; +#[cfg(not(feature = "pylib"))] +use erg_proc_macros::pyclass; +#[cfg(feature = "pylib")] +use pyo3::prelude::*; + /// 意味論的名前と記号自体の名前が混在しているが、Pythonの名残である +#[pyclass] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(u8)] pub enum TokenKind { @@ -188,6 +194,7 @@ pub enum TokenKind { use TokenKind::*; +#[pyclass] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TokenCategory { Symbol, @@ -333,6 +340,7 @@ impl From for BinOpCode { } } +#[pyclass(get_all)] #[derive(Clone, Eq)] pub struct Token { pub kind: TokenKind, @@ -547,6 +555,7 @@ impl Token { } } +#[pyclass] #[derive(Debug, Clone)] pub struct TokenStream(VecDeque); diff --git a/crates/erg_proc_macros/src/lib.rs b/crates/erg_proc_macros/src/lib.rs index aede09e5..a31e8a15 100644 --- a/crates/erg_proc_macros/src/lib.rs +++ b/crates/erg_proc_macros/src/lib.rs @@ -54,3 +54,21 @@ pub fn exec_new_thread(_attr: TokenStream, item: TokenStream) -> TokenStream { let item = quote! { #item_fn }; item.into() } + +/// dummy attribute +#[proc_macro_attribute] +pub fn pyo3(_attr: TokenStream, item: TokenStream) -> TokenStream { + item +} + +/// dummy attribute +#[proc_macro_attribute] +pub fn pyclass(_attr: TokenStream, item: TokenStream) -> TokenStream { + item +} + +/// dummy attribute +#[proc_macro_attribute] +pub fn pymethods(_attr: TokenStream, item: TokenStream) -> TokenStream { + item +}