chore: add InlineModule

This commit is contained in:
Shunsuke Shibayama 2023-10-05 22:33:18 +09:00
parent e71c0d7720
commit bbb8ed7a91
4 changed files with 118 additions and 53 deletions

View file

@ -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")
}
}

View file

@ -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"
/// ```

View file

@ -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 }
}
}

View file

@ -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![];