mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 18:58:30 +00:00
chore: add InlineModule
This commit is contained in:
parent
e71c0d7720
commit
bbb8ed7a91
4 changed files with 118 additions and 53 deletions
|
@ -2764,9 +2764,21 @@ impl Expr {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Module(Vec<Expr>);
|
||||
|
||||
impl fmt::Display for Module {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt_lines(self.0.iter(), f, 0)
|
||||
impl NestedDisplay for Module {
|
||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||
fmt_lines(self.0.iter(), f, level)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Module);
|
||||
|
||||
impl NoTypeDisplay for Module {
|
||||
fn to_string_notype(&self) -> String {
|
||||
self.0
|
||||
.iter()
|
||||
.map(|e| e.to_string_notype())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -409,42 +409,53 @@ impl<'a> HIRLinker<'a> {
|
|||
// let sig = option_enum_unwrap!(&def.sig, Signature::Var)
|
||||
// .unwrap_or_else(|| todo!("module subroutines are not allowed"));
|
||||
if let Some((hir, cfg)) = hir_cfg {
|
||||
let tmp = Identifier::private_with_line(self.fresh_gen.fresh_varname(), line);
|
||||
let mod_var = Expr::Accessor(Accessor::Ident(tmp.clone()));
|
||||
let module_type =
|
||||
Expr::Accessor(Accessor::private_with_line(Str::ever("#ModuleType"), line));
|
||||
let args = Args::single(PosArg::new(mod_name.clone()));
|
||||
let block = Block::new(vec![module_type.call_expr(args)]);
|
||||
let mod_def = Expr::Def(Def::new(
|
||||
Signature::Var(VarSignature::global(tmp, None)),
|
||||
DefBody::new(EQUAL, block, DefId(0)),
|
||||
));
|
||||
self.removed_mods
|
||||
.borrow_mut()
|
||||
.insert(path, Mod::new(mod_var.clone(), mod_def));
|
||||
let linker = self.inherit(&cfg);
|
||||
let hir = linker.link_child(hir);
|
||||
let code = Expr::Code(Block::new(Vec::from(hir.module)));
|
||||
let __dict__ = Identifier::public("__dict__");
|
||||
let m_dict = mod_var.clone().attr_expr(__dict__);
|
||||
let locals = Expr::Accessor(Accessor::public_with_line(Str::ever("locals"), line));
|
||||
let locals_call = locals.call_expr(Args::empty());
|
||||
let args = Args::single(PosArg::new(locals_call));
|
||||
let mod_update = Expr::Call(Call::new(
|
||||
m_dict.clone(),
|
||||
Some(Identifier::public("update")),
|
||||
args,
|
||||
));
|
||||
let exec = Expr::Accessor(Accessor::public_with_line(Str::ever("exec"), line));
|
||||
let args = Args::pos_only(vec![PosArg::new(code), PosArg::new(m_dict)], None);
|
||||
let exec_code = exec.call_expr(args);
|
||||
let compound = Block::new(vec![mod_update, exec_code, mod_var]);
|
||||
*expr = Expr::Compound(compound);
|
||||
*expr = self.modularize(mod_name.clone(), hir, cfg, line, path);
|
||||
} else if let Some(module) = self.removed_mods.borrow().get(&path) {
|
||||
*expr = module.variable.clone();
|
||||
}
|
||||
}
|
||||
|
||||
fn modularize(
|
||||
&self,
|
||||
mod_name: Expr,
|
||||
hir: HIR,
|
||||
cfg: ErgConfig,
|
||||
line: u32,
|
||||
path: PathBuf,
|
||||
) -> Expr {
|
||||
let tmp = Identifier::private_with_line(self.fresh_gen.fresh_varname(), line);
|
||||
let mod_var = Expr::Accessor(Accessor::Ident(tmp.clone()));
|
||||
let module_type =
|
||||
Expr::Accessor(Accessor::private_with_line(Str::ever("#ModuleType"), line));
|
||||
let args = Args::single(PosArg::new(mod_name));
|
||||
let block = Block::new(vec![module_type.call_expr(args)]);
|
||||
let mod_def = Expr::Def(Def::new(
|
||||
Signature::Var(VarSignature::global(tmp, None)),
|
||||
DefBody::new(EQUAL, block, DefId(0)),
|
||||
));
|
||||
self.removed_mods
|
||||
.borrow_mut()
|
||||
.insert(path, Mod::new(mod_var.clone(), mod_def));
|
||||
let linker = self.inherit(&cfg);
|
||||
let hir = linker.link_child(hir);
|
||||
let code = Expr::Code(Block::new(Vec::from(hir.module)));
|
||||
let __dict__ = Identifier::public("__dict__");
|
||||
let m_dict = mod_var.clone().attr_expr(__dict__);
|
||||
let locals = Expr::Accessor(Accessor::public_with_line(Str::ever("locals"), line));
|
||||
let locals_call = locals.call_expr(Args::empty());
|
||||
let args = Args::single(PosArg::new(locals_call));
|
||||
let mod_update = Expr::Call(Call::new(
|
||||
m_dict.clone(),
|
||||
Some(Identifier::public("update")),
|
||||
args,
|
||||
));
|
||||
let exec = Expr::Accessor(Accessor::public_with_line(Str::ever("exec"), line));
|
||||
let args = Args::pos_only(vec![PosArg::new(code), PosArg::new(m_dict)], None);
|
||||
let exec_code = exec.call_expr(args);
|
||||
let compound = Block::new(vec![mod_update, exec_code, mod_var]);
|
||||
Expr::Compound(compound)
|
||||
}
|
||||
|
||||
/// ```erg
|
||||
/// x = pyimport "x" # called from dir "a"
|
||||
/// ```
|
||||
|
|
|
@ -9,10 +9,10 @@ use erg_common::set::Set as HashSet;
|
|||
// use erg_common::dict::Dict as HashMap;
|
||||
use erg_common::traits::{Locational, NestedDisplay, Stream};
|
||||
use erg_common::{
|
||||
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
|
||||
impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_from_trait_for_enum,
|
||||
impl_locational, impl_locational_for_enum, impl_nested_display_for_chunk_enum,
|
||||
impl_nested_display_for_enum, impl_stream,
|
||||
fmt_option, fmt_vec, impl_display_for_enum, impl_display_from_nested,
|
||||
impl_displayable_stream_for_wrapper, impl_from_trait_for_enum, impl_locational,
|
||||
impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum,
|
||||
impl_stream,
|
||||
};
|
||||
use erg_common::{fmt_vec_split_with, Str};
|
||||
|
||||
|
@ -4890,14 +4890,15 @@ pub enum Expr {
|
|||
PatchDef(PatchDef),
|
||||
ReDef(ReDef),
|
||||
Compound(Compound),
|
||||
InlineModule(InlineModule),
|
||||
/// for mapping to Python AST
|
||||
Dummy(Dummy),
|
||||
}
|
||||
|
||||
impl_nested_display_for_chunk_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, Dummy);
|
||||
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, Dummy);
|
||||
impl_nested_display_for_chunk_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
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, Dummy);
|
||||
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 Expr {
|
||||
pub fn is_match_call(&self) -> bool {
|
||||
|
@ -4936,6 +4937,7 @@ impl Expr {
|
|||
Self::PatchDef(_) => "patch definition",
|
||||
Self::ReDef(_) => "re-definition",
|
||||
Self::Compound(_) => "compound",
|
||||
Self::InlineModule(_) => "inline module",
|
||||
Self::Dummy(_) => "dummy",
|
||||
}
|
||||
}
|
||||
|
@ -5044,12 +5046,14 @@ impl Expr {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Module(Block);
|
||||
|
||||
impl fmt::Display for Module {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt_lines(self.0.iter(), f, 0)
|
||||
impl NestedDisplay for Module {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
fmt_lines(self.0.iter(), f, level)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Module);
|
||||
|
||||
impl Locational for Module {
|
||||
fn loc(&self) -> Location {
|
||||
Location::concat(self.0.first().unwrap(), self.0.last().unwrap())
|
||||
|
@ -5100,13 +5104,20 @@ impl Module {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct AST {
|
||||
pub name: Str,
|
||||
pub module: Module,
|
||||
}
|
||||
|
||||
impl_display_for_single_struct!(AST, module);
|
||||
impl NestedDisplay for AST {
|
||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||
self.module.fmt_nest(f, level)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(AST);
|
||||
impl_locational!(AST, module);
|
||||
|
||||
impl AST {
|
||||
pub const fn new(name: Str, module: Module) -> Self {
|
||||
|
@ -5117,3 +5128,25 @@ impl AST {
|
|||
self.module.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct InlineModule {
|
||||
pub ast: AST,
|
||||
pub import: Call,
|
||||
}
|
||||
|
||||
impl NestedDisplay for InlineModule {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
writeln!(f, "inline-module({})", self.import)?;
|
||||
self.ast.fmt_nest(f, level)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(InlineModule);
|
||||
impl_locational!(InlineModule, ast);
|
||||
|
||||
impl InlineModule {
|
||||
pub const fn new(ast: AST, import: Call) -> Self {
|
||||
Self { ast, import }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,14 @@ use erg_common::{enum_unwrap, get_hash, log, set};
|
|||
use crate::ast::{
|
||||
Accessor, Args, Array, ArrayComprehension, ArrayTypeSpec, ArrayWithLength, BinOp, Block, Call,
|
||||
ClassAttr, ClassAttrs, ClassDef, Compound, ConstExpr, DataPack, Def, DefBody, DefId,
|
||||
DefaultParamSignature, Dict, Dummy, Expr, GuardClause, Identifier, KeyValue, KwArg, Lambda,
|
||||
LambdaSignature, Literal, Methods, MixedRecord, Module, NonDefaultParamSignature, NormalArray,
|
||||
NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamRecordAttr,
|
||||
ParamTuplePattern, Params, PatchDef, PosArg, ReDef, Record, RecordAttrOrIdent, RecordAttrs,
|
||||
RecordTypeSpec, Set as astSet, SetComprehension, SetWithLength, Signature, SubrSignature,
|
||||
Tuple, TupleTypeSpec, TypeAppArgs, TypeAppArgsKind, TypeBoundSpecs, TypeSpec, TypeSpecWithOp,
|
||||
UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature, VisModifierSpec,
|
||||
DefaultParamSignature, Dict, Dummy, Expr, GuardClause, Identifier, InlineModule, KeyValue,
|
||||
KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module,
|
||||
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
|
||||
ParamPattern, ParamRecordAttr, ParamTuplePattern, Params, PatchDef, PosArg, ReDef, Record,
|
||||
RecordAttrOrIdent, RecordAttrs, RecordTypeSpec, Set as astSet, SetComprehension, SetWithLength,
|
||||
Signature, SubrSignature, Tuple, TupleTypeSpec, TypeAppArgs, TypeAppArgsKind, TypeBoundSpecs,
|
||||
TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
|
||||
VisModifierSpec, AST,
|
||||
};
|
||||
use crate::token::{Token, TokenKind, COLON, DOT};
|
||||
|
||||
|
@ -399,6 +400,14 @@ impl Desugarer {
|
|||
}
|
||||
Expr::Compound(Compound::new(chunks))
|
||||
}
|
||||
Expr::InlineModule(module) => {
|
||||
let mut chunks = vec![];
|
||||
for chunk in module.ast.module.into_iter() {
|
||||
chunks.push(desugar(chunk));
|
||||
}
|
||||
let ast = AST::new(module.ast.name, Module::new(chunks));
|
||||
Expr::InlineModule(InlineModule::new(ast, module.import))
|
||||
}
|
||||
Expr::Dummy(exprs) => {
|
||||
let loc = exprs.loc;
|
||||
let mut chunks = vec![];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue