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

View file

@ -367,20 +367,14 @@ impl Desugarer {
todo!("{dict}") todo!("{dict}")
} }
Expr::BinOp(binop) => { Expr::BinOp(binop) => {
let mut args = vec![]; let mut args = binop.args.into_iter();
for arg in binop.args.into_iter() { let lhs = self.rec_desugar_shortened_record(*args.next().unwrap());
args.push(self.rec_desugar_shortened_record(*arg)); let rhs = self.rec_desugar_shortened_record(*args.next().unwrap());
}
let lhs = args.remove(0);
let rhs = args.remove(0);
Expr::BinOp(BinOp::new(binop.op, lhs, rhs)) Expr::BinOp(BinOp::new(binop.op, lhs, rhs))
} }
Expr::UnaryOp(unaryop) => { Expr::UnaryOp(unaryop) => {
let mut args = vec![]; let mut args = unaryop.args.into_iter();
for arg in unaryop.args.into_iter() { let expr = self.rec_desugar_shortened_record(*args.next().unwrap());
args.push(self.rec_desugar_shortened_record(*arg));
}
let expr = args.remove(0);
Expr::UnaryOp(UnaryOp::new(unaryop.op, expr)) Expr::UnaryOp(UnaryOp::new(unaryop.op, expr))
} }
Expr::Call(call) => { Expr::Call(call) => {

View file

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

View file

@ -1692,22 +1692,51 @@ impl Parser {
todo!() 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); debug_call_info!(self);
match _record { match record {
Record::Normal(_rec) => { Record::Normal(rec) => {
todo!() 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( fn convert_data_pack_to_data_pack_pat(
&mut self, &mut self,
_pack: DataPack, pack: DataPack,
) -> ParseResult<VarDataPackPattern> { ) -> ParseResult<VarDataPackPattern> {
debug_call_info!(self); 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> { fn convert_tuple_to_tuple_pat(&mut self, tuple: Tuple) -> ParseResult<VarTuplePattern> {
@ -1868,30 +1897,26 @@ impl Parser {
self.level -= 1; self.level -= 1;
Ok(param) Ok(param)
} }
Expr::Call(mut call) => match *call.obj { Expr::UnaryOp(unary) => match unary.op.kind {
Expr::Accessor(Accessor::Local(local)) => match &local.inspect()[..] { TokenKind::RefOp => {
"ref" => { let var = unary.args.into_iter().next().unwrap();
assert_eq!(call.args.len(), 1); let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_)))
let var = call.args.remove_pos(0).expr; .unwrap_or_else(|| todo!());
let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_))) let pat = ParamPattern::Ref(VarName::new(var.symbol));
.unwrap_or_else(|| todo!()); let param = ParamSignature::new(pat, None, None);
let pat = ParamPattern::Ref(VarName::new(var.symbol)); self.level -= 1;
let param = ParamSignature::new(pat, None, None); Ok(param)
self.level -= 1; }
Ok(param) TokenKind::RefMutOp => {
} let var = unary.args.into_iter().next().unwrap();
"ref!" => { let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_)))
assert_eq!(call.args.len(), 1); .unwrap_or_else(|| todo!());
let var = call.args.remove_pos(0).expr; let pat = ParamPattern::RefMut(VarName::new(var.symbol));
let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_))) let param = ParamSignature::new(pat, None, None);
.unwrap_or_else(|| todo!()); self.level -= 1;
let pat = ParamPattern::RefMut(VarName::new(var.symbol)); Ok(param)
let param = ParamSignature::new(pat, None, None); }
self.level -= 1; // Spread
Ok(param)
}
other => todo!("{other}"),
},
other => todo!("{other}"), other => todo!("{other}"),
}, },
other => todo!("{other}"), // Error other => todo!("{other}"), // Error

View file

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