Impl ShortenedRecord desugaring

This commit is contained in:
Shunsuke Shibayama 2022-09-02 14:40:01 +09:00
parent 4557690347
commit d2ed277685
6 changed files with 281 additions and 29 deletions

View file

@ -264,7 +264,14 @@ impl Evaluator {
Some(ValueObj::Array(RcArray::from(elems)))
}
fn eval_const_record(&self, record: &NormalRecord, ctx: &Context) -> Option<ValueObj> {
fn eval_const_record(&self, record: &Record, ctx: &Context) -> Option<ValueObj> {
match record {
Record::Normal(rec) => self.eval_const_normal_record(rec, ctx),
Record::Shortened(_rec) => unreachable!(), // should be desugared
}
}
fn eval_const_normal_record(&self, record: &NormalRecord, ctx: &Context) -> Option<ValueObj> {
let mut attrs = vec![];
for attr in record.attrs.iter() {
if let Some(elem) = self.eval_const_block(&attr.body.block, ctx) {

View file

@ -217,7 +217,15 @@ impl ASTLowerer {
Ok(hir::NormalTuple::new(hir::Args::from(new_tuple)))
}
fn lower_record(&mut self, record: ast::NormalRecord) -> LowerResult<hir::Record> {
fn lower_record(&mut self, record: ast::Record) -> LowerResult<hir::Record> {
log!(info "entered {}({record})", fn_name!());
match record {
ast::Record::Normal(rec) => self.lower_normal_record(rec),
ast::Record::Shortened(_rec) => unreachable!(), // should be desugared
}
}
fn lower_normal_record(&mut self, record: ast::NormalRecord) -> LowerResult<hir::Record> {
log!(info "entered {}({record})", fn_name!());
let mut hir_record =
hir::Record::new(record.l_brace, record.r_brace, hir::RecordAttrs::new());

View file

@ -6,8 +6,6 @@ use erg_common::error::Location;
use erg_common::set::Set as HashSet;
use erg_common::traits::{Locational, NestedDisplay, Stream};
use erg_common::vis::{Field, Visibility};
// use erg_common::ty::SubrKind;
// use erg_common::value::{Field, ValueObj, Visibility};
use erg_common::Str;
use erg_common::{
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
@ -675,6 +673,10 @@ impl From<Vec<Def>> for RecordAttrs {
}
impl RecordAttrs {
pub const fn new(attrs: Vec<Def>) -> Self {
Self(attrs)
}
pub fn iter(&self) -> impl Iterator<Item = &Def> {
self.0.iter()
}
@ -714,12 +716,45 @@ impl NormalRecord {
/// e.g. {x; y; z} (syntax sugar of {x = x; y = y; z = z})
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SimpleRecord {
pub struct ShortenedRecord {
pub l_brace: Token,
pub r_brace: Token,
idents: Vec<Identifier>,
pub idents: Vec<Identifier>,
}
impl NestedDisplay for ShortenedRecord {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
write!(f, "{{")?;
for ident in self.idents.iter() {
write!(f, "{}; ", ident)?;
}
write!(f, "}}")
}
}
impl_display_from_nested!(ShortenedRecord);
impl_locational!(ShortenedRecord, l_brace, r_brace);
impl ShortenedRecord {
pub const fn new(l_brace: Token, r_brace: Token, idents: Vec<Identifier>) -> Self {
Self {
l_brace,
r_brace,
idents,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Record {
Normal(NormalRecord),
Shortened(ShortenedRecord),
}
impl_nested_display_for_enum!(Record; Normal, Shortened);
impl_display_for_enum!(Record; Normal, Shortened);
impl_locational_for_enum!(Record; Normal, Shortened);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct NormalSet {
l_brace: Token,
@ -2610,7 +2645,8 @@ pub struct Def {
impl NestedDisplay for Def {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
writeln!(f, "{} {}", self.sig, self.body.op.content)?;
self.sig.fmt_nest(f, level)?;
writeln!(f, " {}", self.body.op.content)?;
self.body.block.fmt_nest(f, level + 1)
}
}
@ -2671,7 +2707,7 @@ pub enum Expr {
Tuple(Tuple),
Dict(Dict),
Set(Set),
Record(NormalRecord),
Record(Record),
BinOp(BinOp),
UnaryOp(UnaryOp),
Call(Call),

View file

@ -11,9 +11,11 @@ use erg_common::Str;
use erg_common::{enum_unwrap, get_hash, set};
use crate::ast::{
Accessor, Args, Block, Call, Def, DefBody, DefId, Expr, Identifier, Lambda, LambdaSignature,
Literal, Local, Module, ParamPattern, ParamSignature, Params, PosArg, Signature, SubrSignature,
TypeBoundSpecs, TypeSpec, VarName, VarPattern, VarSignature,
Accessor, Args, Array, BinOp, Block, Call, Def, DefBody, DefId, Expr, Identifier, KwArg,
Lambda, LambdaSignature, Literal, Local, MethodDefs, Module, NormalArray, NormalRecord,
NormalTuple, ParamPattern, ParamSignature, Params, PosArg, Record, RecordAttrs,
ShortenedRecord, Signature, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
UnaryOp, VarName, VarPattern, VarSignature,
};
use crate::token::{Token, TokenKind};
@ -46,7 +48,9 @@ impl Desugarer {
pub fn desugar(&mut self, module: Module) -> Module {
let module = self.desugar_multiple_pattern_def(module);
self.desugar_pattern(module)
let module = self.desugar_pattern(module);
let module = self.desugar_shortened_record(module);
module
}
fn desugar_ubar_lambda(&self, _module: Module) -> Module {
@ -306,6 +310,149 @@ impl Desugarer {
}
}
/// `{x; y}` -> `{x = x; y = y}`
fn desugar_shortened_record(&self, mut module: Module) -> Module {
let mut new = Module::with_capacity(module.len());
while let Some(chunk) = module.lpop() {
new.push(self.rec_desugar_shortened_record(chunk));
}
new
}
fn rec_desugar_shortened_record(&self, expr: Expr) -> Expr {
match expr {
Expr::Record(Record::Shortened(rec)) => {
let rec = self.desugar_shortened_record_inner(rec);
Expr::Record(Record::Normal(rec))
}
Expr::Array(array) => match array {
Array::Normal(arr) => {
let (elems, _, _) = arr.elems.deconstruct();
let elems = elems
.into_iter()
.map(|elem| PosArg::new(self.rec_desugar_shortened_record(elem.expr)))
.collect();
let elems = Args::new(elems, vec![], None);
let arr = NormalArray::new(arr.l_sqbr, arr.r_sqbr, elems);
Expr::Array(Array::Normal(arr))
}
_ => todo!(),
},
Expr::Tuple(tuple) => match tuple {
Tuple::Normal(tup) => {
let (elems, _, paren) = tup.elems.deconstruct();
let elems = elems
.into_iter()
.map(|elem| PosArg::new(self.rec_desugar_shortened_record(elem.expr)))
.collect();
let new_tup = Args::new(elems, vec![], paren);
let tup = NormalTuple::new(new_tup);
Expr::Tuple(Tuple::Normal(tup))
}
},
Expr::Set(set) => {
todo!("{set}")
}
Expr::Dict(dict) => {
todo!("{dict}")
}
Expr::BinOp(binop) => {
let mut args = vec![];
for arg in binop.args.into_iter() {
args.push(self.rec_desugar_shortened_record(*arg));
}
let lhs = args.remove(0);
let rhs = args.remove(0);
Expr::BinOp(BinOp::new(binop.op, lhs, rhs))
}
Expr::UnaryOp(unaryop) => {
let mut args = vec![];
for arg in unaryop.args.into_iter() {
args.push(self.rec_desugar_shortened_record(*arg));
}
let expr = args.remove(0);
Expr::UnaryOp(UnaryOp::new(unaryop.op, expr))
}
Expr::Call(call) => {
let obj = self.rec_desugar_shortened_record(*call.obj);
let (pos_args, kw_args, paren) = call.args.deconstruct();
let pos_args = pos_args
.into_iter()
.map(|arg| PosArg::new(self.rec_desugar_shortened_record(arg.expr)))
.collect();
let kw_args = kw_args
.into_iter()
.map(|arg| {
let expr = self.rec_desugar_shortened_record(arg.expr);
KwArg::new(arg.keyword, arg.t_spec, expr) // TODO: t_spec
})
.collect();
let args = Args::new(pos_args, kw_args, paren);
Expr::Call(Call::new(obj, call.method_name, args))
}
Expr::Def(def) => {
let mut chunks = vec![];
for chunk in def.body.block.into_iter() {
chunks.push(self.rec_desugar_shortened_record(chunk));
}
let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id);
Expr::Def(Def::new(def.sig, body))
}
Expr::Lambda(lambda) => {
let mut chunks = vec![];
for chunk in lambda.body.into_iter() {
chunks.push(self.rec_desugar_shortened_record(chunk));
}
let body = Block::new(chunks);
Expr::Lambda(Lambda::new(lambda.sig, lambda.op, body, lambda.id))
}
Expr::TypeAsc(tasc) => {
let expr = self.rec_desugar_shortened_record(*tasc.expr);
Expr::TypeAsc(TypeAscription::new(expr, tasc.t_spec))
}
Expr::MethodDefs(method_defs) => {
let mut new_defs = vec![];
for def in method_defs.defs.into_iter() {
let mut chunks = vec![];
for chunk in def.body.block.into_iter() {
chunks.push(self.rec_desugar_shortened_record(chunk));
}
let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id);
new_defs.push(Def::new(def.sig, body));
}
let new_defs = RecordAttrs::from(new_defs);
Expr::MethodDefs(MethodDefs::new(
method_defs.class,
method_defs.vis,
new_defs,
))
}
// TODO: Accessorにも一応レコードを入れられる
other => other,
}
}
fn desugar_shortened_record_inner(&self, rec: ShortenedRecord) -> NormalRecord {
let mut attrs = vec![];
for attr in rec.idents.into_iter() {
let var = VarSignature::new(VarPattern::Ident(attr.clone()), None);
let sig = Signature::Var(var);
let body = DefBody::new(
Token::from_str(TokenKind::Equal, "="),
Block::new(vec![Expr::local(
attr.inspect(),
attr.ln_begin().unwrap(),
attr.col_begin().unwrap(),
)]),
DefId(get_hash(&(&sig, attr.inspect()))),
);
let def = Def::new(sig, body);
attrs.push(def);
}
let attrs = RecordAttrs::new(attrs);
NormalRecord::new(rec.l_brace, rec.r_brace, attrs)
}
/// `F(I | I > 0)` -> `F(I: {I: Int | I > 0})`
fn desugar_refinement_pattern(&self, _mod: Module) -> Module {
todo!()

View file

@ -64,7 +64,7 @@ pub enum ArrayInner {
pub enum BraceContainer {
Set(Set),
Dict(Dict),
Record(NormalRecord),
Record(Record),
}
/// Perform recursive descent parsing.
@ -1410,12 +1410,20 @@ impl Parser {
match first {
Expr::Def(def) => {
let record = self
.try_reduce_record(l_brace, def)
.try_reduce_normal_record(l_brace, def)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(BraceContainer::Record(record))
Ok(BraceContainer::Record(Record::Normal(record)))
}
// Dict
Expr::TypeAsc(_) => todo!(),
Expr::Accessor(acc) if self.cur_is(Semi) => {
let record = self
.try_reduce_shortened_record(l_brace, acc)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(BraceContainer::Record(Record::Shortened(record)))
}
Expr::TypeAsc(_) => todo!(), // invalid syntax
other => {
let set = self
.try_reduce_set(l_brace, other)
@ -1426,7 +1434,11 @@ impl Parser {
}
}
fn try_reduce_record(&mut self, l_brace: Token, first: Def) -> ParseResult<NormalRecord> {
fn try_reduce_normal_record(
&mut self,
l_brace: Token,
first: Def,
) -> ParseResult<NormalRecord> {
debug_call_info!(self);
let mut attrs = vec![first];
loop {
@ -1459,6 +1471,54 @@ impl Parser {
}
}
fn try_reduce_shortened_record(
&mut self,
l_brace: Token,
first: Accessor,
) -> ParseResult<ShortenedRecord> {
debug_call_info!(self);
let first = match first {
Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)),
Accessor::Public(public) => {
Identifier::new(Some(public.dot), VarName::new(public.symbol))
}
other => todo!("{other}"), // syntax error
};
let mut idents = vec![first];
loop {
match self.peek() {
Some(t) if t.category_is(TC::Separator) => {
self.skip();
if self.cur_is(Dedent) {
self.skip();
if self.cur_is(RBrace) {
let r_brace = self.lpop();
self.level -= 1;
return Ok(ShortenedRecord::new(l_brace, r_brace, idents));
} else {
todo!()
}
}
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
let acc = match acc {
Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)),
Accessor::Public(public) => {
Identifier::new(Some(public.dot), VarName::new(public.symbol))
}
other => todo!("{other}"), // syntax error
};
idents.push(acc);
}
Some(term) if term.is(RBrace) => {
let r_brace = self.lpop();
self.level -= 1;
return Ok(ShortenedRecord::new(l_brace, r_brace, idents));
}
_ => todo!(),
}
}
}
fn _try_reduce_dict() -> ParseResult<Dict> {
todo!()
}
@ -1594,10 +1654,7 @@ impl Parser {
todo!()
}
fn convert_record_to_record_pat(
&mut self,
_record: NormalRecord,
) -> ParseResult<VarRecordPattern> {
fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult<VarRecordPattern> {
debug_call_info!(self);
todo!()
}
@ -1809,7 +1866,7 @@ impl Parser {
fn convert_record_to_param_record_pat(
&mut self,
_record: NormalRecord,
_record: Record,
) -> ParseResult<ParamRecordPattern> {
debug_call_info!(self);
todo!()
@ -1920,10 +1977,7 @@ impl Parser {
todo!()
}
fn convert_record_to_param_pat(
&mut self,
_record: NormalRecord,
) -> ParseResult<ParamRecordPattern> {
fn convert_record_to_param_pat(&mut self, _record: Record) -> ParseResult<ParamRecordPattern> {
debug_call_info!(self);
todo!()
}

View file

@ -1,17 +1,17 @@
@Inheritable
Point2D = Class {x = Int; y = Int}
Point2D.
new x, y = Self::__new__ {x = x; y = y}
new x, y = Self::__new__ {x; y}
norm ref self = self::x**2 + self::y**2
Point3D = Inherit Point2D, Additional := {z = Int}
Point3D.
@Override
new x, y, z = Self::__new__ {x = x; y = y; z = z}
new x, y, z = Self::__new__ {x; y; z}
@Override
norm ref self = self::x**2 + self::y**2 + self::z**2
UnpackPoint2D = Class {x = Int; y = Int}, Impl := Unpack
p = UnpackPoint2D::{x = 1; y = 2}
UnpackPoint2D::{x = x; y = x} = p
UnpackPoint2D::{x; y} = p