Change ref and ref! to unary operators

This commit is contained in:
Shunsuke Shibayama 2022-09-02 22:49:34 +09:00
parent 62e89a1edf
commit f0d686cd7b
5 changed files with 87 additions and 55 deletions

View file

@ -1987,6 +1987,12 @@ impl NestedDisplay for VarRecordAttr {
impl_display_from_nested!(VarRecordAttr);
impl_locational!(VarRecordAttr, lhs, rhs);
impl VarRecordAttr {
pub const fn new(lhs: Identifier, rhs: Identifier) -> Self {
Self { lhs, rhs }
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct VarRecordAttrs {
pub(crate) elems: Vec<VarRecordAttr>,
@ -2038,7 +2044,7 @@ impl VarRecordPattern {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct VarDataPackPattern {
pub class: Identifier, // TODO: allow Attribute
pub class: Accessor, // TODO: allow polymorphic
pub args: VarRecordPattern,
}
@ -2051,7 +2057,7 @@ impl fmt::Display for VarDataPackPattern {
impl_locational!(VarDataPackPattern, class, args);
impl VarDataPackPattern {
pub const fn new(class: Identifier, args: VarRecordPattern) -> Self {
pub const fn new(class: Accessor, args: VarRecordPattern) -> Self {
Self { class, args }
}
}
@ -2275,6 +2281,7 @@ pub enum ParamPattern {
Array(ParamArrayPattern),
Tuple(ParamTuplePattern),
Record(ParamRecordPattern),
// DataPack(ParamDataPackPattern),
Ref(VarName),
RefMut(VarName),
// e.g. `a` of `[...a, b] = [1, 2, 3]` (a == [1, 2], b == 3)

View file

@ -367,20 +367,14 @@ impl Desugarer {
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);
let mut args = binop.args.into_iter();
let lhs = self.rec_desugar_shortened_record(*args.next().unwrap());
let rhs = self.rec_desugar_shortened_record(*args.next().unwrap());
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);
let mut args = unaryop.args.into_iter();
let expr = self.rec_desugar_shortened_record(*args.next().unwrap());
Expr::UnaryOp(UnaryOp::new(unaryop.op, expr))
}
Expr::Call(call) => {

View file

@ -525,6 +525,8 @@ impl Lexer /*<'a>*/ {
"isnot" => IsNotOp,
"dot" => DotOp,
"cross" => CrossOp,
"ref" => RefOp,
"ref!" => RefMutOp,
// これらはリテラルというより定数だが便宜的にリテラルということにしておく
"True" | "False" => BoolLit,
"None" => NoneLit,

View file

@ -1692,22 +1692,51 @@ impl Parser {
todo!()
}
fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult<VarRecordPattern> {
fn convert_record_to_record_pat(&mut self, record: Record) -> ParseResult<VarRecordPattern> {
debug_call_info!(self);
match _record {
Record::Normal(_rec) => {
todo!()
match record {
Record::Normal(rec) => {
let mut pats = vec![];
for mut attr in rec.attrs.into_iter() {
let lhs =
option_enum_unwrap!(attr.sig, Signature::Var).unwrap_or_else(|| todo!());
let lhs =
option_enum_unwrap!(lhs.pat, VarPattern::Ident).unwrap_or_else(|| todo!());
assert_eq!(attr.body.block.len(), 1);
let rhs = option_enum_unwrap!(attr.body.block.remove(0), Expr::Accessor)
.unwrap_or_else(|| todo!());
let rhs = self
.convert_accessor_to_ident(rhs)
.map_err(|_| self.stack_dec())?;
pats.push(VarRecordAttr::new(lhs, rhs));
}
let attrs = VarRecordAttrs::new(pats);
self.level -= 1;
Ok(VarRecordPattern::new(rec.l_brace, attrs, rec.r_brace))
}
Record::Shortened(rec) => {
let mut pats = vec![];
for ident in rec.idents.into_iter() {
pats.push(VarRecordAttr::new(ident.clone(), ident));
}
let attrs = VarRecordAttrs::new(pats);
self.level -= 1;
Ok(VarRecordPattern::new(rec.l_brace, attrs, rec.r_brace))
}
_ => todo!(),
}
}
fn convert_data_pack_to_data_pack_pat(
&mut self,
_pack: DataPack,
pack: DataPack,
) -> ParseResult<VarDataPackPattern> {
debug_call_info!(self);
todo!()
let class = option_enum_unwrap!(*pack.class, Expr::Accessor).unwrap_or_else(|| todo!());
let args = self
.convert_record_to_record_pat(pack.args)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(VarDataPackPattern::new(class, args))
}
fn convert_tuple_to_tuple_pat(&mut self, tuple: Tuple) -> ParseResult<VarTuplePattern> {
@ -1868,30 +1897,26 @@ impl Parser {
self.level -= 1;
Ok(param)
}
Expr::Call(mut call) => match *call.obj {
Expr::Accessor(Accessor::Local(local)) => match &local.inspect()[..] {
"ref" => {
assert_eq!(call.args.len(), 1);
let var = call.args.remove_pos(0).expr;
let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_)))
.unwrap_or_else(|| todo!());
let pat = ParamPattern::Ref(VarName::new(var.symbol));
let param = ParamSignature::new(pat, None, None);
self.level -= 1;
Ok(param)
}
"ref!" => {
assert_eq!(call.args.len(), 1);
let var = call.args.remove_pos(0).expr;
let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_)))
.unwrap_or_else(|| todo!());
let pat = ParamPattern::RefMut(VarName::new(var.symbol));
let param = ParamSignature::new(pat, None, None);
self.level -= 1;
Ok(param)
}
other => todo!("{other}"),
},
Expr::UnaryOp(unary) => match unary.op.kind {
TokenKind::RefOp => {
let var = unary.args.into_iter().next().unwrap();
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_)))
.unwrap_or_else(|| todo!());
let pat = ParamPattern::Ref(VarName::new(var.symbol));
let param = ParamSignature::new(pat, None, None);
self.level -= 1;
Ok(param)
}
TokenKind::RefMutOp => {
let var = unary.args.into_iter().next().unwrap();
let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_)))
.unwrap_or_else(|| todo!());
let pat = ParamPattern::RefMut(VarName::new(var.symbol));
let param = ParamSignature::new(pat, None, None);
self.level -= 1;
Ok(param)
}
// Spread
other => todo!("{other}"),
},
other => todo!("{other}"), // Error

View file

@ -103,6 +103,10 @@ pub enum TokenKind {
DotOp,
/// `cross` (vector product)
CrossOp,
/// `ref` (special unary)
RefOp,
/// `ref!` (special unary)
RefMutOp,
/// =
Equal,
/// :=
@ -210,7 +214,7 @@ impl TokenKind {
Symbol => TokenCategory::Symbol,
NatLit | IntLit | RatioLit | StrLit | BoolLit | NoneLit | EllipsisLit | NoImplLit
| InfLit => TokenCategory::Literal,
PrePlus | PreMinus | PreBitNot | Mutate => TokenCategory::UnaryOp,
PrePlus | PreMinus | PreBitNot | Mutate | RefOp | RefMutOp => TokenCategory::UnaryOp,
Try => TokenCategory::PostfixOp,
Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | Walrus => {
TokenCategory::SpecialBinOp
@ -234,16 +238,16 @@ impl TokenKind {
pub const fn precedence(&self) -> Option<usize> {
let prec = match self {
Dot | DblColon => 200, // .
Pow => 190, // **
PrePlus | PreMinus | PreBitNot => 180, // (unary) + - * ~
Star | Slash | FloorDiv | Mod | CrossOp | DotOp => 170, // * / // % cross dot
Plus | Minus => 160, // + -
Shl | Shr => 150, // << >>
BitAnd => 140, // &&
BitXor => 130, // ^^
BitOr => 120, // ||
Closed | LeftOpen | RightOpen | Open => 100, // range operators
Dot | DblColon => 200, // .
Pow => 190, // **
PrePlus | PreMinus | PreBitNot | RefOp | RefMutOp => 180, // (unary) + - * ~ ref ref!
Star | Slash | FloorDiv | Mod | CrossOp | DotOp => 170, // * / // % cross dot
Plus | Minus => 160, // + -
Shl | Shr => 150, // << >>
BitAnd => 140, // &&
BitXor => 130, // ^^
BitOr => 120, // ||
Closed | LeftOpen | RightOpen | Open => 100, // range operators
Less | Gre | LessEq | GreEq | DblEq | NotEq | InOp | NotInOp | IsOp | IsNotOp => 90, // < > <= >= == != in notin is isnot
AndOp => 80, // and
OrOp => 70, // or