Improve: LHS are parsed once as RHS, then conv to LHS

This commit is contained in:
Shunsuke Shibayama 2022-09-01 16:46:10 +09:00
parent 29b395d96d
commit d790063ec2
2 changed files with 487 additions and 287 deletions

View file

@ -646,6 +646,12 @@ impl NestedDisplay for RecordAttrs {
} }
} }
impl Locational for RecordAttrs {
fn loc(&self) -> Location {
Location::concat(self.0.first().unwrap(), self.0.last().unwrap())
}
}
impl From<Vec<Def>> for RecordAttrs { impl From<Vec<Def>> for RecordAttrs {
fn from(attrs: Vec<Def>) -> Self { fn from(attrs: Vec<Def>) -> Self {
Self(attrs) Self(attrs)
@ -1403,7 +1409,7 @@ impl SubrKindSpec {
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SubrTySpec { pub struct SubrTypeSpec {
pub kind: SubrKindSpec, pub kind: SubrKindSpec,
pub lparen: Option<Token>, pub lparen: Option<Token>,
pub non_defaults: Vec<ParamTySpec>, pub non_defaults: Vec<ParamTySpec>,
@ -1412,7 +1418,7 @@ pub struct SubrTySpec {
pub return_t: Box<TypeSpec>, pub return_t: Box<TypeSpec>,
} }
impl fmt::Display for SubrTySpec { impl fmt::Display for SubrTypeSpec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
@ -1426,7 +1432,7 @@ impl fmt::Display for SubrTySpec {
} }
} }
impl Locational for SubrTySpec { impl Locational for SubrTypeSpec {
fn loc(&self) -> Location { fn loc(&self) -> Location {
if let Some(lparen) = &self.lparen { if let Some(lparen) = &self.lparen {
Location::concat(lparen, self.return_t.as_ref()) Location::concat(lparen, self.return_t.as_ref())
@ -1437,7 +1443,7 @@ impl Locational for SubrTySpec {
} }
} }
impl SubrTySpec { impl SubrTypeSpec {
pub fn new( pub fn new(
kind: SubrKindSpec, kind: SubrKindSpec,
lparen: Option<Token>, lparen: Option<Token>,
@ -1457,24 +1463,34 @@ impl SubrTySpec {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ArrayTypeSpec {
pub ty: Box<TypeSpec>,
pub len: ConstExpr,
}
impl fmt::Display for ArrayTypeSpec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[{}; {}]", self.ty, self.len)
}
}
impl_locational!(ArrayTypeSpec, ty, len);
/// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc. /// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc.
/// * Dict: `[Str: Str]`, etc. /// * Dict: `[Str: Str]`, etc.
/// * Option: `Int?`, etc.
/// * And (Intersection type): Add and Sub and Mul (== Num), etc. /// * And (Intersection type): Add and Sub and Mul (== Num), etc.
/// * Not (Diff type): Pos == Nat not {0}, etc. /// * Not (Diff type): Pos == Nat not {0}, etc.
/// * Or (Union type): Int or None (== Option Int), etc. /// * Or (Union type): Int or None (== Option Int), etc.
/// * Enum: `{0, 1}` (== Binary), etc. /// * Enum: `{0, 1}` (== Binary), etc.
/// * Range: 1..12, 0.0<..1.0, etc. /// * Range: 1..12, 0.0<..1.0, etc.
/// * Record: {.into_s: Self.() -> Str }, etc. /// * Record: {.into_s: Self.() -> Str }, etc.
/// * Func: Int -> Int, etc. /// * Subr: Int -> Int, Int => None, T.(X) -> Int, etc.
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TypeSpec { pub enum TypeSpec {
PreDeclTy(PreDeclTypeSpec), PreDeclTy(PreDeclTypeSpec),
/* Composite types */ /* Composite types */
Array { Array(ArrayTypeSpec),
t: PreDeclTypeSpec,
len: ConstExpr,
},
Tuple(Vec<TypeSpec>), Tuple(Vec<TypeSpec>),
// Dict(), // Dict(),
// Option(), // Option(),
@ -1488,7 +1504,7 @@ pub enum TypeSpec {
rhs: ConstExpr, rhs: ConstExpr,
}, },
// Record(), // Record(),
Subr(SubrTySpec), Subr(SubrTypeSpec),
} }
impl fmt::Display for TypeSpec { impl fmt::Display for TypeSpec {
@ -1498,7 +1514,7 @@ impl fmt::Display for TypeSpec {
Self::And(lhs, rhs) => write!(f, "{lhs} and {rhs}"), Self::And(lhs, rhs) => write!(f, "{lhs} and {rhs}"),
Self::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"), Self::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"),
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"), Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
Self::Array { t, len } => write!(f, "[{t}; {len}]"), Self::Array(arr) => write!(f, "{arr}"),
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)), Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
Self::Enum(elems) => write!(f, "{{{elems}}}"), Self::Enum(elems) => write!(f, "{{{elems}}}"),
Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()), Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()),
@ -1514,7 +1530,7 @@ impl Locational for TypeSpec {
Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => { Self::And(lhs, rhs) | Self::Not(lhs, rhs) | Self::Or(lhs, rhs) => {
Location::concat(lhs.as_ref(), rhs.as_ref()) Location::concat(lhs.as_ref(), rhs.as_ref())
} }
Self::Array { t, len } => Location::concat(t, len), Self::Array(arr) => arr.loc(),
// TODO: ユニット // TODO: ユニット
Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()), Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()),
Self::Enum(set) => set.loc(), Self::Enum(set) => set.loc(),
@ -1548,7 +1564,7 @@ impl TypeSpec {
defaults: Vec<ParamTySpec>, defaults: Vec<ParamTySpec>,
return_t: TypeSpec, return_t: TypeSpec,
) -> Self { ) -> Self {
Self::Subr(SubrTySpec::new( Self::Subr(SubrTypeSpec::new(
SubrKindSpec::Func, SubrKindSpec::Func,
lparen, lparen,
non_defaults, non_defaults,
@ -1565,7 +1581,7 @@ impl TypeSpec {
defaults: Vec<ParamTySpec>, defaults: Vec<ParamTySpec>,
return_t: TypeSpec, return_t: TypeSpec,
) -> Self { ) -> Self {
Self::Subr(SubrTySpec::new( Self::Subr(SubrTypeSpec::new(
SubrKindSpec::Proc, SubrKindSpec::Proc,
lparen, lparen,
non_defaults, non_defaults,
@ -2100,6 +2116,7 @@ pub enum ParamPattern {
VarArgsName(VarName), VarArgsName(VarName),
Lit(Literal), Lit(Literal),
Array(ParamArrayPattern), Array(ParamArrayPattern),
// Tuple(),
Record(ParamRecordPattern), Record(ParamRecordPattern),
} }
@ -2340,9 +2357,9 @@ impl SubrSignature {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct LambdaSignature { pub struct LambdaSignature {
pub bounds: TypeBoundSpecs,
pub params: Params, pub params: Params,
pub return_t_spec: Option<TypeSpec>, pub return_t_spec: Option<TypeSpec>,
pub bounds: TypeBoundSpecs,
} }
impl fmt::Display for LambdaSignature { impl fmt::Display for LambdaSignature {
@ -2492,7 +2509,21 @@ impl Signature {
} }
} }
pub type Decl = Signature; /// type_ascription ::= expr ':' type
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TypeAscription {
pub expr: Box<Expr>,
pub t_spec: TypeSpec,
}
impl NestedDisplay for TypeAscription {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
writeln!(f, "{}: {}", self.expr, self.t_spec)
}
}
impl_display_from_nested!(TypeAscription);
impl_locational!(TypeAscription, expr, t_spec);
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DefBody { pub struct DefBody {
@ -2539,6 +2570,36 @@ impl Def {
} }
} }
/// e.g.
/// ```erg
/// T = Class ...
/// T.
/// x = 1
/// f(a) = ...
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MethodDefs {
pub class: TypeSpec,
pub vis: Token, // `.` or `::`
pub defs: RecordAttrs, // TODO: allow declaration
}
impl NestedDisplay for MethodDefs {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
writeln!(f, "{}{}", self.class, self.vis)?;
self.defs.fmt_nest(f, level + 1)
}
}
impl_display_from_nested!(MethodDefs);
impl_locational!(MethodDefs, class, defs);
impl MethodDefs {
pub const fn new(class: TypeSpec, vis: Token, defs: RecordAttrs) -> Self {
Self { class, vis, defs }
}
}
/// Expression(式) /// Expression(式)
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Expr { pub enum Expr {
@ -2553,13 +2614,14 @@ pub enum Expr {
UnaryOp(UnaryOp), UnaryOp(UnaryOp),
Call(Call), Call(Call),
Lambda(Lambda), Lambda(Lambda),
Decl(Decl), TypeAsc(TypeAscription),
Def(Def), Def(Def),
MethodDefs(MethodDefs),
} }
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, TypeAsc, Def, MethodDefs);
impl_display_from_nested!(Expr); impl_display_from_nested!(Expr);
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, TypeAsc, Def, MethodDefs);
impl Expr { impl Expr {
pub fn is_match_call(&self) -> bool { pub fn is_match_call(&self) -> bool {

View file

@ -50,13 +50,6 @@ enum PosOrKwArg {
Kw(KwArg), Kw(KwArg),
} }
pub enum Side {
LhsAssign,
LhsLambda,
Do,
Rhs,
}
pub enum ArrayInner { pub enum ArrayInner {
Normal(Args), Normal(Args),
WithLength(PosArg, Expr), WithLength(PosArg, Expr),
@ -132,141 +125,8 @@ impl Parser {
self.nth(idx).map(|t| t.is(kind)).unwrap_or(false) self.nth(idx).map(|t| t.is(kind)).unwrap_or(false)
} }
fn nth_category(&self, idx: usize) -> Option<TokenCategory> {
self.nth(idx).map(|t| t.category())
}
/// `+1`: true
/// `+ 1`: false
/// `F()`: true
/// `F ()`: false
fn cur_is_in_contact_with_next(&self) -> bool {
let cur_loc = self.peek().unwrap().ln_end().unwrap();
let next_loc = self.nth(1).unwrap().ln_end().unwrap();
cur_loc + 1 == next_loc
}
/// returns if the current position is a left-hand side value.
///
/// ```
/// f(x: Int) = { y = x+1; z = [v: Int, w: Int] -> w + x }
/// LhsAssign | Rhs | LhsLambda | Rhs
/// ```
/// `(Rhs) ; (LhsAssign) =`
/// `(Rhs) ; (LhsLambda) ->`
/// `(Rhs) , (LhsLambda) ->`
/// `(Rhs) (LhsLambda) -> (Rhs);`
fn cur_side(&self) -> Side {
match self.peek() {
Some(t) => {
let name = &t.inspect()[..];
if name == "do" || name == "do!" {
return Side::Do;
}
}
_ => {}
}
// 以降に=, ->などがないならすべて右辺値
let opt_equal_pos = self.tokens.iter().skip(1).position(|t| t.is(Equal));
let opt_arrow_pos = self
.tokens
.iter()
.skip(1)
.position(|t| t.category_is(TC::LambdaOp));
let opt_sep_pos = self
.tokens
.iter()
.skip(1)
.position(|t| t.category_is(TC::Separator));
match (opt_equal_pos, opt_arrow_pos, opt_sep_pos) {
(Some(equal), Some(arrow), Some(sep)) => {
let min = [equal, arrow, sep].into_iter().min().unwrap();
if min == sep {
Side::Rhs
} else if min == equal {
Side::LhsAssign
} else {
// (cur) -> ... = ... ;
if equal < sep {
Side::LhsAssign
}
// (cur) -> ... ; ... =
else if self.arrow_distance(0, 0) == 1 {
Side::LhsLambda
} else {
Side::Rhs
}
}
}
// (cur) = ... -> ...
// (cur) -> ... = ...
(Some(_eq), Some(_arrow), None) => Side::LhsAssign,
// (cur) = ... ;
// (cur) ; ... =
(Some(equal), None, Some(sep)) => {
if equal < sep {
Side::LhsAssign
} else {
Side::Rhs
}
}
(None, Some(arrow), Some(sep)) => {
// (cur) -> ... ;
if arrow < sep {
if self.arrow_distance(0, 0) == 1 {
Side::LhsLambda
} else {
Side::Rhs
}
}
// (cur) ; ... ->
else {
Side::Rhs
}
}
(Some(_eq), None, None) => Side::LhsAssign,
(None, Some(_arrow), None) => {
if self.arrow_distance(0, 0) == 1 {
Side::LhsLambda
} else {
Side::Rhs
}
}
(None, None, Some(_)) | (None, None, None) => Side::Rhs,
}
}
/// `->`: 0
/// `i ->`: 1
/// `i: Int ->`: 1
/// `a: Array(Int) ->`: 1
/// `(i, j) ->`: 1
/// `F () ->`: 2
/// `F() ->`: 1
/// `if True, () ->`: 3
fn arrow_distance(&self, cur: usize, enc_nest_level: usize) -> usize {
match self.nth_category(cur).unwrap() {
TC::LambdaOp => 0,
TC::LEnclosure => {
if self.nth_category(cur + 1).unwrap() == TC::REnclosure {
1 + self.arrow_distance(cur + 2, enc_nest_level)
} else {
self.arrow_distance(cur + 1, enc_nest_level + 1)
}
}
TC::REnclosure => self.arrow_distance(cur + 1, enc_nest_level - 1),
_ => match self.nth_category(cur + 1).unwrap() {
TC::SpecialBinOp => self.arrow_distance(cur + 1, enc_nest_level),
TC::LEnclosure if self.cur_is_in_contact_with_next() => {
self.arrow_distance(cur + 2, enc_nest_level + 1)
}
_ if enc_nest_level == 0 => 1 + self.arrow_distance(cur + 1, enc_nest_level),
_ => self.arrow_distance(cur + 1, enc_nest_level),
},
}
}
/// 解析を諦めて次の解析できる要素に移行する /// 解析を諦めて次の解析できる要素に移行する
/// give up parsing and move to the next element that can be parsed
fn next_expr(&mut self) { fn next_expr(&mut self) {
while let Some(t) = self.peek() { while let Some(t) = self.peek() {
match t.category() { match t.category() {
@ -1080,6 +940,10 @@ impl Parser {
return Err(()); return Err(());
} }
} }
Some(t) if t.is(LBrace) => {
// let elems = self.try_reduce_record_pattern().map_err(|_| self.stack_dec())?;
todo!("record pattern")
}
Some(t) if t.is(LParen) => { Some(t) if t.is(LParen) => {
self.skip(); self.skip();
let pat = self let pat = self
@ -1694,6 +1558,37 @@ impl Parser {
Ok(Lambda::new(sig, op, body, self.counter)) Ok(Lambda::new(sig, op, body, self.counter))
} }
fn try_reduce_method_defs(&mut self, class: Expr, vis: Token) -> ParseResult<MethodDefs> {
debug_call_info!(self);
if self.cur_is(Indent) {
self.skip();
} else {
todo!()
}
let first = self.try_reduce_def().map_err(|_| self.stack_dec())?;
let mut defs = vec![first];
loop {
match self.peek() {
Some(t) if t.category_is(TC::Separator) => {
self.skip();
if self.cur_is(Dedent) {
self.skip();
break;
}
let def = self.try_reduce_def().map_err(|_| self.stack_dec())?;
defs.push(def);
}
_ => todo!(),
}
}
let defs = RecordAttrs::from(defs);
let class = self
.convert_rhs_to_type_spec(class)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(MethodDefs::new(class, vis, defs))
}
fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> { fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> {
debug_call_info!(self); debug_call_info!(self);
let do_symbol = self.lpop(); let do_symbol = self.lpop();
@ -1721,28 +1616,35 @@ impl Parser {
fn try_reduce_expr(&mut self, winding: bool) -> ParseResult<Expr> { fn try_reduce_expr(&mut self, winding: bool) -> ParseResult<Expr> {
debug_call_info!(self); debug_call_info!(self);
let mut stack = Vec::<ExprOrOp>::new(); let mut stack = Vec::<ExprOrOp>::new();
match self.cur_side() {
Side::LhsAssign => {
let def = self.try_reduce_def().map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(Expr::Def(def))
}
Side::LhsLambda => {
let lambda = self.try_reduce_lambda().map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(Expr::Lambda(lambda))
}
Side::Do => {
let lambda = self.try_reduce_do_block().map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(Expr::Lambda(lambda))
}
Side::Rhs => {
stack.push(ExprOrOp::Expr( stack.push(ExprOrOp::Expr(
self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?, self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?,
)); ));
loop { loop {
match self.peek() { match self.peek() {
Some(op) if op.category_is(TC::DefOp) => {
let op = self.lpop();
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let sig = self.convert_rhs_to_sig(lhs).map_err(|_| self.stack_dec())?;
self.counter.inc();
let block = self.try_reduce_block().map_err(|_| self.stack_dec())?;
let body = DefBody::new(op, block, self.counter);
stack.push(ExprOrOp::Expr(Expr::Def(Def::new(sig, body))));
}
Some(op) if op.category_is(TC::LambdaOp) => {
let op = self.lpop();
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let sig = self
.convert_rhs_to_lambda_sig(lhs)
.map_err(|_| self.stack_dec())?;
self.counter.inc();
let block = self.try_reduce_block().map_err(|_| self.stack_dec())?;
stack.push(ExprOrOp::Expr(Expr::Lambda(Lambda::new(
sig,
op,
block,
self.counter,
))));
}
Some(op) if op.category_is(TC::BinOp) => { Some(op) if op.category_is(TC::BinOp) => {
let op_prec = op.kind.precedence(); let op_prec = op.kind.precedence();
if stack.len() >= 2 { if stack.len() >= 2 {
@ -1750,12 +1652,9 @@ impl Parser {
if prev_op.category_is(TC::BinOp) if prev_op.category_is(TC::BinOp)
&& prev_op.kind.precedence() >= op_prec && prev_op.kind.precedence() >= op_prec
{ {
let rhs = let rhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); let prev_op = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_)));
let prev_op = let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_)));
let lhs =
enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let bin = BinOp::new(prev_op, lhs, rhs); let bin = BinOp::new(prev_op, lhs, rhs);
stack.push(ExprOrOp::Expr(Expr::BinOp(bin))); stack.push(ExprOrOp::Expr(Expr::BinOp(bin)));
} else { } else {
@ -1771,11 +1670,27 @@ impl Parser {
self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?, self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?,
)); ));
} }
Some(t) if t.category_is(TC::DefOp) => { Some(t) if t.is(DblColon) => {
switch_unreachable!() let dbl_colon = self.lpop();
match self.lpop() {
line_break if line_break.is(Newline) => {
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let defs = self
.try_reduce_method_defs(maybe_class, dbl_colon)
.map_err(|_| self.stack_dec())?;
return Ok(Expr::MethodDefs(defs));
}
other => {
self.restore(other);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
}
} }
Some(t) if t.is(Dot) => { Some(t) if t.is(Dot) => {
self.skip(); let dot = self.lpop();
match self.lpop() { match self.lpop() {
symbol if symbol.is(Symbol) => { symbol if symbol.is(Symbol) => {
let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() { let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() {
@ -1798,6 +1713,13 @@ impl Parser {
stack.push(ExprOrOp::Expr(Expr::Accessor(acc))); stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
} }
} }
line_break if line_break.is(Newline) => {
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
let defs = self
.try_reduce_method_defs(maybe_class, dot)
.map_err(|_| self.stack_dec())?;
return Ok(Expr::MethodDefs(defs));
}
other => { other => {
self.restore(other); self.restore(other);
self.level -= 1; self.level -= 1;
@ -1857,8 +1779,6 @@ impl Parser {
_ => switch_unreachable!(), _ => switch_unreachable!(),
} }
} }
}
}
/// "LHS" is the smallest unit that can be the left-hand side of an BinOp. /// "LHS" is the smallest unit that can be the left-hand side of an BinOp.
/// e.g. Call, Name, UnaryOp, Lambda /// e.g. Call, Name, UnaryOp, Lambda
@ -2040,7 +1960,7 @@ impl Parser {
self.level -= 1; self.level -= 1;
Ok(BraceContainer::Record(record)) Ok(BraceContainer::Record(record))
} }
Expr::Decl(_) => todo!(), // invalid syntax Expr::TypeAsc(_) => todo!(), // invalid syntax
other => { other => {
let set = self let set = self
.try_reduce_set(l_brace, other) .try_reduce_set(l_brace, other)
@ -2174,4 +2094,222 @@ impl Parser {
} }
} }
} }
/// Call: F(x) -> SubrSignature: F(x)
fn convert_rhs_to_sig(&mut self, rhs: Expr) -> ParseResult<Signature> {
debug_call_info!(self);
match rhs {
Expr::Accessor(accessor) => {
let var = self
.convert_accessor_to_var_sig(accessor)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(Signature::Var(var))
}
Expr::Call(call) => {
let subr = self
.convert_call_to_subr_sig(call)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(Signature::Subr(subr))
}
Expr::Array(array) => {
let array_pat = self
.convert_array_to_array_pat(array)
.map_err(|_| self.stack_dec())?;
let var = VarSignature::new(VarPattern::Array(array_pat), None);
self.level -= 1;
Ok(Signature::Var(var))
}
Expr::Record(record) => {
let record_pat = self
.convert_record_to_record_pat(record)
.map_err(|_| self.stack_dec())?;
let var = VarSignature::new(VarPattern::Record(record_pat), None);
self.level -= 1;
Ok(Signature::Var(var))
}
Expr::Tuple(tuple) => {
let tuple_pat = self
.convert_tuple_to_tuple_pat(tuple)
.map_err(|_| self.stack_dec())?;
let var = VarSignature::new(VarPattern::Tuple(tuple_pat), None);
self.level -= 1;
Ok(Signature::Var(var))
}
Expr::TypeAsc(tasc) => {
let sig = self
.convert_type_asc_to_sig(tasc)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(sig)
}
_ => todo!(), // Error
}
}
fn convert_call_to_subr_sig(&mut self, _call: Call) -> ParseResult<SubrSignature> {
debug_call_info!(self);
todo!()
}
fn convert_accessor_to_var_sig(&mut self, _accessor: Accessor) -> ParseResult<VarSignature> {
debug_call_info!(self);
todo!()
}
fn convert_array_to_array_pat(&mut self, _array: Array) -> ParseResult<VarArrayPattern> {
debug_call_info!(self);
todo!()
}
fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult<VarRecordPattern> {
debug_call_info!(self);
todo!()
}
fn convert_tuple_to_tuple_pat(&mut self, _tuple: Tuple) -> ParseResult<VarTuplePattern> {
debug_call_info!(self);
todo!()
}
fn convert_type_asc_to_sig(&mut self, _tasc: TypeAscription) -> ParseResult<Signature> {
debug_call_info!(self);
todo!()
}
fn convert_rhs_to_lambda_sig(&mut self, rhs: Expr) -> ParseResult<LambdaSignature> {
debug_call_info!(self);
match rhs {
Expr::Accessor(accessor) => {
let param = self
.convert_accessor_to_param_sig(accessor)
.map_err(|_| self.stack_dec())?;
let params = Params::new(vec![param], None, vec![], None);
self.level -= 1;
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
}
Expr::Tuple(tuple) => {
let params = self
.convert_tuple_to_params(tuple)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
}
Expr::Array(array) => {
let arr = self
.convert_array_to_param_pat(array)
.map_err(|_| self.stack_dec())?;
let param = ParamSignature::new(ParamPattern::Array(arr), None, None);
let params = Params::new(vec![param], None, vec![], None);
self.level -= 1;
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
}
Expr::Record(record) => {
let rec = self
.convert_record_to_param_pat(record)
.map_err(|_| self.stack_dec())?;
let param = ParamSignature::new(ParamPattern::Record(rec), None, None);
let params = Params::new(vec![param], None, vec![], None);
self.level -= 1;
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
}
Expr::TypeAsc(tasc) => {
let sig = self
.convert_type_asc_to_lambda_sig(tasc)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(sig)
}
_ => todo!(), // Error
}
}
fn convert_accessor_to_param_sig(
&mut self,
_accessor: Accessor,
) -> ParseResult<ParamSignature> {
debug_call_info!(self);
todo!()
}
fn convert_tuple_to_params(&mut self, _tuple: Tuple) -> ParseResult<Params> {
debug_call_info!(self);
todo!()
}
fn convert_array_to_param_pat(&mut self, _array: Array) -> ParseResult<ParamArrayPattern> {
debug_call_info!(self);
todo!()
}
fn convert_record_to_param_pat(&mut self, _record: Record) -> ParseResult<ParamRecordPattern> {
debug_call_info!(self);
todo!()
}
fn convert_type_asc_to_lambda_sig(
&mut self,
_tasc: TypeAscription,
) -> ParseResult<LambdaSignature> {
debug_call_info!(self);
todo!()
}
fn convert_rhs_to_type_spec(&mut self, rhs: Expr) -> ParseResult<TypeSpec> {
match rhs {
Expr::Accessor(acc) => {
let predecl = self
.convert_accessor_to_predecl_type_spec(acc)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(TypeSpec::PreDeclTy(predecl))
}
Expr::Call(call) => {
let predecl = self
.convert_call_to_predecl_type_spec(call)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(TypeSpec::PreDeclTy(predecl))
}
Expr::Lambda(lambda) => {
let lambda = self
.convert_lambda_to_subr_type_spec(lambda)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(TypeSpec::Subr(lambda))
}
Expr::Array(array) => {
let array = self
.convert_array_to_array_type_spec(array)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
Ok(TypeSpec::Array(array))
}
_ => todo!(),
}
}
fn convert_accessor_to_predecl_type_spec(
&mut self,
_accessor: Accessor,
) -> ParseResult<PreDeclTypeSpec> {
debug_call_info!(self);
todo!()
}
fn convert_call_to_predecl_type_spec(&mut self, _call: Call) -> ParseResult<PreDeclTypeSpec> {
debug_call_info!(self);
todo!()
}
fn convert_lambda_to_subr_type_spec(&mut self, _lambda: Lambda) -> ParseResult<SubrTypeSpec> {
debug_call_info!(self);
todo!()
}
fn convert_array_to_array_type_spec(&mut self, _array: Array) -> ParseResult<ArrayTypeSpec> {
debug_call_info!(self);
todo!()
}
} }