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

View file

@ -39,7 +39,7 @@ impl HIRDesugarer {
.into_iter() .into_iter()
.map(|expr| match expr { .map(|expr| match expr {
Expr::Def(def) => { 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); let attr_def = AttrDef::new(acc, def.body.block);
Expr::AttrDef(attr_def) Expr::AttrDef(attr_def)
} }

View file

@ -1836,6 +1836,33 @@ impl Expr {
pub fn is_type_asc(&self) -> bool { pub fn is_type_asc(&self) -> bool {
matches!(self, Expr::TypeAsc(_)) 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 /// Toplevel grammar unit

View file

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

View file

@ -1418,7 +1418,7 @@ impl ASTLowerer {
expr.loc(), expr.loc(),
Some(&Str::from(expr.to_string())), 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) // 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)) => { ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
let obj = self.fake_lower_obj(*attr.obj)?; let obj = self.fake_lower_obj(*attr.obj)?;
let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name); let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name);
let acc = hir::Accessor::attr(obj, ident); Ok(obj.attr_expr(ident))
Ok(hir::Expr::Accessor(acc))
} }
other => Err(LowerErrors::from(LowerError::declare_error( other => Err(LowerErrors::from(LowerError::declare_error(
self.cfg.input.clone(), self.cfg.input.clone(),
@ -1596,10 +1595,7 @@ impl ASTLowerer {
let py_name = Str::rc(ident.inspect().trim_end_matches('!')); 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 vi = VarInfo::new(t, muty, vis, VarKind::Declared, None, None, Some(py_name));
let ident = hir::Identifier::new(ident.dot, ident.name, None, vi); let ident = hir::Identifier::new(ident.dot, ident.name, None, vi);
Ok(hir::TypeAscription::new( Ok(hir::Expr::Accessor(hir::Accessor::Ident(ident)).type_asc(tasc.t_spec))
hir::Expr::Accessor(hir::Accessor::Ident(ident)),
tasc.t_spec,
))
} }
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => { ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!')); 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 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 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 ident = hir::Identifier::new(attr.ident.dot, attr.ident.name, None, vi);
let attr = hir::Accessor::attr(obj, ident); let attr = obj.attr_expr(ident);
Ok(hir::TypeAscription::new( Ok(attr.type_asc(tasc.t_spec))
hir::Expr::Accessor(attr),
tasc.t_spec,
))
} }
other => Err(LowerErrors::from(LowerError::declare_error( other => Err(LowerErrors::from(LowerError::declare_error(
self.cfg.input.clone(), self.cfg.input.clone(),

View file

@ -3222,6 +3222,49 @@ impl Expr {
pub fn static_local(name: &'static str) -> Self { pub fn static_local(name: &'static str) -> Self {
Self::Accessor(Accessor::local(Token::static_symbol(name))) Self::Accessor(Accessor::local(Token::static_symbol(name)))
} }
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 subscr(self, index: Expr, r_sqbr: Token) -> Accessor {
Accessor::subscr(self, index, r_sqbr)
}
pub fn subscr_expr(self, index: Expr, r_sqbr: Token) -> Self {
Self::Accessor(self.subscr(index, r_sqbr))
}
pub fn tuple_attr(self, index: Literal) -> Accessor {
Accessor::tuple_attr(self, index)
}
pub fn tuple_attr_expr(self, index: Literal) -> Self {
Self::Accessor(self.tuple_attr(index))
}
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 type_asc(self, op: Token, t_spec: TypeSpec) -> TypeAscription {
TypeAscription::new(self, op, t_spec)
}
pub fn type_asc_expr(self, op: Token, t_spec: TypeSpec) -> Self {
Self::TypeAsc(self.type_asc(op, t_spec))
}
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]

View file

@ -15,8 +15,8 @@ use crate::ast::{
DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal,
Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet,
NormalTuple, ParamPattern, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength, NormalTuple, ParamPattern, Params, PosArg, Record, RecordAttrs, Set as astSet, SetWithLength,
ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, ShortenedRecord, Signature, SubrSignature, Tuple, TypeBoundSpecs, TypeSpec, UnaryOp, VarName,
UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature, VarPattern, VarRecordAttr, VarSignature,
}; };
use crate::token::{Token, TokenKind}; use crate::token::{Token, TokenKind};
@ -201,7 +201,7 @@ impl Desugarer {
} }
Expr::TypeAsc(tasc) => { Expr::TypeAsc(tasc) => {
let expr = desugar(*tasc.expr); let expr = desugar(*tasc.expr);
Expr::TypeAsc(TypeAscription::new(expr, tasc.op, tasc.t_spec)) expr.type_asc_expr(tasc.op, tasc.t_spec)
} }
Expr::Methods(method_defs) => { Expr::Methods(method_defs) => {
let mut new_defs = vec![]; let mut new_defs = vec![];
@ -323,7 +323,7 @@ impl Desugarer {
vec![], vec![],
None, None,
); );
let call = Call::new(match_symbol, None, args); let call = match_symbol.call(args);
(call, return_t_spec) (call, return_t_spec)
} }
@ -439,9 +439,7 @@ impl Desugarer {
) { ) {
let obj = Expr::local(buf_name, sig.ln_begin().unwrap(), sig.col_begin().unwrap()); let obj = Expr::local(buf_name, sig.ln_begin().unwrap(), sig.col_begin().unwrap());
let acc = match buf_index { let acc = match buf_index {
BufIndex::Tuple(n) => { BufIndex::Tuple(n) => obj.tuple_attr(Literal::nat(n, sig.ln_begin().unwrap())),
Accessor::tuple_attr(obj, Literal::nat(n, sig.ln_begin().unwrap()))
}
BufIndex::Array(n) => { BufIndex::Array(n) => {
let r_brace = Token::new( let r_brace = Token::new(
TokenKind::RBrace, TokenKind::RBrace,
@ -449,13 +447,9 @@ impl Desugarer {
sig.ln_begin().unwrap(), sig.ln_begin().unwrap(),
sig.col_begin().unwrap(), sig.col_begin().unwrap(),
); );
Accessor::subscr( obj.subscr(Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())), r_brace)
obj,
Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())),
r_brace,
)
} }
BufIndex::Record(attr) => Accessor::attr(obj, attr.clone()), BufIndex::Record(attr) => obj.attr(attr.clone()),
}; };
let id = DefId(get_hash(&(&acc, buf_name))); let id = DefId(get_hash(&(&acc, buf_name)));
let block = Block::new(vec![Expr::Accessor(acc)]); let block = Block::new(vec![Expr::Accessor(acc)]);

View file

@ -885,7 +885,7 @@ impl Parser {
Some(arg) if arg.is(Symbol) || arg.category_is(TC::Literal) => { Some(arg) if arg.is(Symbol) || arg.category_is(TC::Literal) => {
let args = self.try_reduce_args(false).map_err(|_| self.stack_dec())?; let args = self.try_reduce_args(false).map_err(|_| self.stack_dec())?;
let obj = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); let obj = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
stack.push(ExprOrOp::Expr(Expr::Call(Call::new(obj, None, args)))); stack.push(ExprOrOp::Expr(obj.call_expr(args)));
} }
Some(op) if op.category_is(TC::DefOp) => { Some(op) if op.category_is(TC::DefOp) => {
let op = self.lpop(); let op = self.lpop();
@ -934,7 +934,7 @@ impl Parser {
.try_reduce_expr(false, false, false, false) .try_reduce_expr(false, false, false, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?; let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec)); let expr = lhs.type_asc_expr(op, t_spec);
stack.push(ExprOrOp::Expr(expr)); stack.push(ExprOrOp::Expr(expr));
} }
Some(op) if op.category_is(TC::BinOp) => { Some(op) if op.category_is(TC::BinOp) => {
@ -985,8 +985,7 @@ impl Parser {
stack.push(ExprOrOp::Expr(Expr::Call(call))); stack.push(ExprOrOp::Expr(Expr::Call(call)));
} else { } else {
let ident = Identifier::new(None, VarName::new(symbol)); let ident = Identifier::new(None, VarName::new(symbol));
let acc = Accessor::attr(obj, ident); stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
} }
} }
line_break if line_break.is(Newline) => { line_break if line_break.is(Newline) => {
@ -1049,13 +1048,12 @@ impl Parser {
let mut call = Expr::Call(Call::new(obj, Some(ident), args)); let mut call = Expr::Call(Call::new(obj, Some(ident), args));
while let Some(res) = self.opt_reduce_args(false) { while let Some(res) = self.opt_reduce_args(false) {
let args = res.map_err(|_| self.stack_dec())?; let args = res.map_err(|_| self.stack_dec())?;
call = Expr::Call(Call::new(call, None, args)); call = call.call_expr(args);
} }
stack.push(ExprOrOp::Expr(call)); stack.push(ExprOrOp::Expr(call));
} else { } else {
let ident = Identifier::new(Some(vis), VarName::new(symbol)); let ident = Identifier::new(Some(vis), VarName::new(symbol));
let acc = Accessor::attr(obj, ident); stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
} }
} }
line_break if line_break.is(Newline) => { line_break if line_break.is(Newline) => {
@ -1201,7 +1199,7 @@ impl Parser {
.try_reduce_expr(false, in_type_args, in_brace, false) .try_reduce_expr(false, in_type_args, in_brace, false)
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?; let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec)); let expr = lhs.type_asc_expr(op, t_spec);
stack.push(ExprOrOp::Expr(expr)); stack.push(ExprOrOp::Expr(expr));
} }
Some(op) if op.category_is(TC::BinOp) => { Some(op) if op.category_is(TC::BinOp) => {
@ -1252,8 +1250,7 @@ impl Parser {
stack.push(ExprOrOp::Expr(Expr::Call(call))); stack.push(ExprOrOp::Expr(Expr::Call(call)));
} else { } else {
let ident = Identifier::new(Some(vis), VarName::new(symbol)); let ident = Identifier::new(Some(vis), VarName::new(symbol));
let acc = Accessor::attr(obj, ident); stack.push(ExprOrOp::Expr(obj.attr_expr(ident)));
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
} }
} }
other => { other => {
@ -1353,10 +1350,10 @@ impl Parser {
Signature::Var(var) => { Signature::Var(var) => {
let mut last = def.body.block.pop().unwrap(); let mut last = def.body.block.pop().unwrap();
for deco in decos.into_iter() { for deco in decos.into_iter() {
last = Expr::Call(Call::new( last = deco.into_expr().call_expr(Args::new(
deco.into_expr(), vec![PosArg::new(last)],
vec![],
None, None,
Args::new(vec![PosArg::new(last)], vec![], None),
)); ));
} }
def.body.block.push(last); def.body.block.push(last);
@ -1501,11 +1498,11 @@ impl Parser {
match token.kind { match token.kind {
Symbol => { Symbol => {
let ident = Identifier::new(Some(vis), VarName::new(token)); let ident = Identifier::new(Some(vis), VarName::new(token));
obj = Expr::Accessor(Accessor::attr(obj, ident)); obj = obj.attr_expr(ident);
} }
NatLit => { NatLit => {
let index = Literal::from(token); let index = Literal::from(token);
obj = Expr::Accessor(Accessor::tuple_attr(obj, index)); obj = obj.tuple_attr_expr(index);
} }
Newline => { Newline => {
self.restore(token); self.restore(token);
@ -1527,8 +1524,7 @@ impl Parser {
token.content = Str::rc(&token.content[1..]); token.content = Str::rc(&token.content[1..]);
token.kind = NatLit; token.kind = NatLit;
token.col_begin += 1; token.col_begin += 1;
let index = Literal::from(token); obj = obj.tuple_attr_expr(Literal::from(token));
obj = Expr::Accessor(Accessor::tuple_attr(obj, index));
} }
Some(t) if t.is(DblColon) && obj.col_end() == t.col_begin() => { Some(t) if t.is(DblColon) && obj.col_end() == t.col_begin() => {
let vis = self.lpop(); let vis = self.lpop();
@ -1536,7 +1532,7 @@ impl Parser {
match token.kind { match token.kind {
Symbol => { Symbol => {
let ident = Identifier::new(None, VarName::new(token)); let ident = Identifier::new(None, VarName::new(token));
obj = Expr::Accessor(Accessor::attr(obj, ident)); obj = obj.attr_expr(ident);
} }
LBrace => { LBrace => {
self.restore(token); self.restore(token);