Implement helper methods for AST/HIR construction

This commit is contained in:
Shunsuke Shibayama 2022-10-18 18:30:09 +09:00
parent ae15f95191
commit a0714b218c
8 changed files with 114 additions and 70 deletions

View file

@ -29,8 +29,8 @@ use crate::compile::{AccessKind, Name, StoreLoadKind};
use crate::context::eval::type_from_token_kind;
use crate::error::CompileError;
use crate::hir::{
Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, Def, DefBody, Expr,
Identifier, Lambda, Literal, Params, PosArg, Record, Signature, SubrSignature, Tuple, UnaryOp,
Accessor, Args, Array, AttrDef, BinOp, Block, Call, ClassDef, Def, DefBody, Expr, Identifier,
Lambda, Literal, Params, PosArg, Record, Signature, SubrSignature, Tuple, UnaryOp,
VarSignature, HIR,
};
use crate::ty::free::fresh_varname;
@ -1717,22 +1717,19 @@ impl CodeGenerator {
for field in rec.keys() {
let obj =
Expr::Accessor(Accessor::private_with_line(Str::from(&param_name), line));
let expr = Expr::Accessor(Accessor::Attr(Attribute::new(
obj,
Identifier::bare(
Some(Token::dummy()),
VarName::from_str(field.symbol.clone()),
),
)));
let expr = obj.attr_expr(Identifier::bare(
Some(Token::dummy()),
VarName::from_str(field.symbol.clone()),
));
let obj = Expr::Accessor(Accessor::private_with_line(Str::ever("self"), line));
let dot = if field.vis.is_private() {
None
} else {
Some(Token::dummy())
};
let attr = Accessor::Attr(Attribute::new(
obj,
Identifier::bare(dot, VarName::from_str(field.symbol.clone())),
let attr = obj.attr(Identifier::bare(
dot,
VarName::from_str(field.symbol.clone()),
));
let attr_def = AttrDef::new(attr, Block::new(vec![expr]));
attrs.push(Expr::AttrDef(attr_def));
@ -1769,12 +1766,8 @@ impl CodeGenerator {
let mut new_ident =
Identifier::bare(None, VarName::from_str_and_line(Str::ever("__new__"), line));
new_ident.vi.py_name = Some(Str::ever("__call__"));
let class_new = Expr::Accessor(Accessor::attr(class, new_ident));
let call = Expr::Call(Call::new(
class_new,
None,
Args::new(vec![arg], None, vec![], None),
));
let class_new = class.attr_expr(new_ident);
let call = class_new.call_expr(Args::new(vec![arg], None, vec![], None));
let block = Block::new(vec![call]);
let body = DefBody::new(Token::dummy(), block, DefId(0));
self.emit_subr_def(Some(class_ident.inspect()), sig, body);

View file

@ -39,7 +39,7 @@ impl HIRDesugarer {
.into_iter()
.map(|expr| match expr {
Expr::Def(def) => {
let acc = Accessor::attr(class.clone(), def.sig.into_ident());
let acc = class.clone().attr(def.sig.into_ident());
let attr_def = AttrDef::new(acc, def.body.block);
Expr::AttrDef(attr_def)
}

View file

@ -1836,6 +1836,33 @@ impl Expr {
pub fn is_type_asc(&self) -> bool {
matches!(self, Expr::TypeAsc(_))
}
pub fn call(self, args: Args) -> Call {
match self {
Self::Accessor(Accessor::Attr(attr)) => Call::new(*attr.obj, Some(attr.ident), args),
other => Call::new(other, None, args),
}
}
pub fn call_expr(self, args: Args) -> Self {
Self::Call(self.call(args))
}
pub fn attr(self, ident: Identifier) -> Accessor {
Accessor::attr(self, ident)
}
pub fn attr_expr(self, ident: Identifier) -> Self {
Self::Accessor(self.attr(ident))
}
pub fn type_asc(self, t_spec: TypeSpec) -> TypeAscription {
TypeAscription::new(self, t_spec)
}
pub fn type_asc_expr(self, t_spec: TypeSpec) -> Self {
Self::TypeAsc(self.type_asc(t_spec))
}
}
/// Toplevel grammar unit

View file

@ -185,7 +185,7 @@ impl<'a> Linker<'a> {
let module_type =
Expr::Accessor(Accessor::private_with_line(Str::ever("#ModuleType"), line));
let args = Args::new(vec![PosArg::new(mod_name.clone())], None, vec![], None);
let block = Block::new(vec![Expr::Call(Call::new(module_type, None, args))]);
let block = Block::new(vec![module_type.call_expr(args)]);
let tmp =
Identifier::private_with_line(Str::from(fresh_varname()), expr.ln_begin().unwrap());
let mod_def = Expr::Def(Def::new(
@ -194,9 +194,9 @@ impl<'a> Linker<'a> {
));
let module = Expr::Accessor(Accessor::Ident(tmp));
let __dict__ = Identifier::public("__dict__");
let m_dict = Expr::Accessor(Accessor::attr(module.clone(), __dict__));
let m_dict = module.clone().attr_expr(__dict__);
let locals = Expr::Accessor(Accessor::public_with_line(Str::ever("locals"), line));
let locals_call = Expr::Call(Call::new(locals, None, Args::empty()));
let locals_call = locals.call_expr(Args::empty());
let args = Args::new(vec![PosArg::new(locals_call)], None, vec![], None);
let mod_update = Expr::Call(Call::new(
m_dict.clone(),
@ -210,7 +210,7 @@ impl<'a> Linker<'a> {
vec![],
None,
);
let exec_code = Expr::Call(Call::new(exec, None, args));
let exec_code = exec.call_expr(args);
let compound = Block::new(vec![mod_def, mod_update, exec_code, module]);
*expr = Expr::Compound(compound);
}
@ -256,15 +256,13 @@ impl<'a> Linker<'a> {
args.insert_pos(0, PosArg::new(mod_name));
let line = expr.ln_begin().unwrap_or(0);
for attr in comps {
*expr = Expr::Accessor(Accessor::attr(
// instead of mem::take(),
mem::replace(expr, Expr::Code(Block::empty())),
*expr = mem::replace(expr, Expr::Code(Block::empty())).attr_expr(
Identifier::public_with_line(
Token::dummy(),
Str::rc(attr.as_os_str().to_str().unwrap()),
line,
),
));
);
}
}
}

View file

@ -1418,7 +1418,7 @@ impl ASTLowerer {
expr.loc(),
Some(&Str::from(expr.to_string())),
)?;
Ok(hir::TypeAscription::new(expr, tasc.t_spec))
Ok(expr.type_asc(tasc.t_spec))
}
// Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments)
@ -1527,8 +1527,7 @@ impl ASTLowerer {
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
let obj = self.fake_lower_obj(*attr.obj)?;
let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name);
let acc = hir::Accessor::attr(obj, ident);
Ok(hir::Expr::Accessor(acc))
Ok(obj.attr_expr(ident))
}
other => Err(LowerErrors::from(LowerError::declare_error(
self.cfg.input.clone(),
@ -1596,10 +1595,7 @@ impl ASTLowerer {
let py_name = Str::rc(ident.inspect().trim_end_matches('!'));
let vi = VarInfo::new(t, muty, vis, VarKind::Declared, None, None, Some(py_name));
let ident = hir::Identifier::new(ident.dot, ident.name, None, vi);
Ok(hir::TypeAscription::new(
hir::Expr::Accessor(hir::Accessor::Ident(ident)),
tasc.t_spec,
))
Ok(hir::Expr::Accessor(hir::Accessor::Ident(ident)).type_asc(tasc.t_spec))
}
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
@ -1625,11 +1621,8 @@ impl ASTLowerer {
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
let vi = VarInfo::new(t, muty, vis, VarKind::Declared, None, None, Some(py_name));
let ident = hir::Identifier::new(attr.ident.dot, attr.ident.name, None, vi);
let attr = hir::Accessor::attr(obj, ident);
Ok(hir::TypeAscription::new(
hir::Expr::Accessor(attr),
tasc.t_spec,
))
let attr = obj.attr_expr(ident);
Ok(attr.type_asc(tasc.t_spec))
}
other => Err(LowerErrors::from(LowerError::declare_error(
self.cfg.input.clone(),