diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index df855381..63c8b79a 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -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> for RecordAttrs { fn from(attrs: Vec) -> Self { Self(attrs) @@ -1403,7 +1409,7 @@ impl SubrKindSpec { } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct SubrTySpec { +pub struct SubrTypeSpec { pub kind: SubrKindSpec, pub lparen: Option, pub non_defaults: Vec, @@ -1412,7 +1418,7 @@ pub struct SubrTySpec { pub return_t: Box, } -impl fmt::Display for SubrTySpec { +impl fmt::Display for SubrTypeSpec { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, @@ -1426,7 +1432,7 @@ impl fmt::Display for SubrTySpec { } } -impl Locational for SubrTySpec { +impl Locational for SubrTypeSpec { fn loc(&self) -> Location { if let Some(lparen) = &self.lparen { Location::concat(lparen, self.return_t.as_ref()) @@ -1437,7 +1443,7 @@ impl Locational for SubrTySpec { } } -impl SubrTySpec { +impl SubrTypeSpec { pub fn new( kind: SubrKindSpec, lparen: Option, @@ -1457,24 +1463,34 @@ impl SubrTySpec { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ArrayTypeSpec { + pub ty: Box, + 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. /// * Dict: `[Str: Str]`, etc. -/// * Option: `Int?`, etc. /// * And (Intersection type): Add and Sub and Mul (== Num), etc. /// * Not (Diff type): Pos == Nat not {0}, etc. /// * Or (Union type): Int or None (== Option Int), etc. /// * Enum: `{0, 1}` (== Binary), etc. /// * Range: 1..12, 0.0<..1.0, etc. /// * Record: {.into_s: Self.() -> Str }, etc. -/// * Func: Int -> Int, etc. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +/// * Subr: Int -> Int, Int => None, T.(X) -> Int, etc. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TypeSpec { PreDeclTy(PreDeclTypeSpec), /* Composite types */ - Array { - t: PreDeclTypeSpec, - len: ConstExpr, - }, + Array(ArrayTypeSpec), Tuple(Vec), // Dict(), // Option(), @@ -1488,7 +1504,7 @@ pub enum TypeSpec { rhs: ConstExpr, }, // Record(), - Subr(SubrTySpec), + Subr(SubrTypeSpec), } impl fmt::Display for TypeSpec { @@ -1498,7 +1514,7 @@ impl fmt::Display for TypeSpec { Self::And(lhs, rhs) => write!(f, "{lhs} and {rhs}"), Self::Not(lhs, rhs) => write!(f, "{lhs} not {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::Enum(elems) => write!(f, "{{{elems}}}"), 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) => { Location::concat(lhs.as_ref(), rhs.as_ref()) } - Self::Array { t, len } => Location::concat(t, len), + Self::Array(arr) => arr.loc(), // TODO: ユニット Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()), Self::Enum(set) => set.loc(), @@ -1548,7 +1564,7 @@ impl TypeSpec { defaults: Vec, return_t: TypeSpec, ) -> Self { - Self::Subr(SubrTySpec::new( + Self::Subr(SubrTypeSpec::new( SubrKindSpec::Func, lparen, non_defaults, @@ -1565,7 +1581,7 @@ impl TypeSpec { defaults: Vec, return_t: TypeSpec, ) -> Self { - Self::Subr(SubrTySpec::new( + Self::Subr(SubrTypeSpec::new( SubrKindSpec::Proc, lparen, non_defaults, @@ -2100,6 +2116,7 @@ pub enum ParamPattern { VarArgsName(VarName), Lit(Literal), Array(ParamArrayPattern), + // Tuple(), Record(ParamRecordPattern), } @@ -2340,9 +2357,9 @@ impl SubrSignature { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct LambdaSignature { + pub bounds: TypeBoundSpecs, pub params: Params, pub return_t_spec: Option, - pub bounds: TypeBoundSpecs, } 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, + 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)] 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(式) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Expr { @@ -2553,13 +2614,14 @@ pub enum Expr { UnaryOp(UnaryOp), Call(Call), Lambda(Lambda), - Decl(Decl), + TypeAsc(TypeAscription), 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_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 { pub fn is_match_call(&self) -> bool { diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index a50ab878..9c623fb8 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -50,13 +50,6 @@ enum PosOrKwArg { Kw(KwArg), } -pub enum Side { - LhsAssign, - LhsLambda, - Do, - Rhs, -} - pub enum ArrayInner { Normal(Args), WithLength(PosArg, Expr), @@ -132,141 +125,8 @@ impl Parser { self.nth(idx).map(|t| t.is(kind)).unwrap_or(false) } - fn nth_category(&self, idx: usize) -> Option { - 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) { while let Some(t) = self.peek() { match t.category() { @@ -1080,6 +940,10 @@ impl Parser { 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) => { self.skip(); let pat = self @@ -1694,6 +1558,37 @@ impl Parser { Ok(Lambda::new(sig, op, body, self.counter)) } + fn try_reduce_method_defs(&mut self, class: Expr, vis: Token) -> ParseResult { + 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 { debug_call_info!(self); let do_symbol = self.lpop(); @@ -1721,143 +1616,168 @@ impl Parser { fn try_reduce_expr(&mut self, winding: bool) -> ParseResult { debug_call_info!(self); let mut stack = Vec::::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( - self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?, - )); - loop { - match self.peek() { - Some(op) if op.category_is(TC::BinOp) => { - let op_prec = op.kind.precedence(); - if stack.len() >= 2 { - while let Some(ExprOrOp::Op(prev_op)) = stack.get(stack.len() - 2) { - if prev_op.category_is(TC::BinOp) - && prev_op.kind.precedence() >= op_prec - { - let rhs = - enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); - let prev_op = - enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_))); - let lhs = - enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); - let bin = BinOp::new(prev_op, lhs, rhs); - stack.push(ExprOrOp::Expr(Expr::BinOp(bin))); - } else { - break; - } - if stack.len() <= 1 { - break; - } - } + stack.push(ExprOrOp::Expr( + self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?, + )); + loop { + 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) => { + let op_prec = op.kind.precedence(); + if stack.len() >= 2 { + while let Some(ExprOrOp::Op(prev_op)) = stack.get(stack.len() - 2) { + if prev_op.category_is(TC::BinOp) + && prev_op.kind.precedence() >= op_prec + { + let rhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); + let prev_op = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_))); + let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); + let bin = BinOp::new(prev_op, lhs, rhs); + stack.push(ExprOrOp::Expr(Expr::BinOp(bin))); + } else { + break; } - stack.push(ExprOrOp::Op(self.lpop())); - stack.push(ExprOrOp::Expr( - self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?, - )); - } - Some(t) if t.category_is(TC::DefOp) => { - switch_unreachable!() - } - Some(t) if t.is(Dot) => { - self.skip(); - match self.lpop() { - symbol if symbol.is(Symbol) => { - let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() { - expr - } else { - self.level -= 1; - let err = self.skip_and_throw_syntax_err(caused_by!()); - self.errs.push(err); - return Err(()); - }; - if let Some(args) = self - .opt_reduce_args() - .transpose() - .map_err(|_| self.stack_dec())? - { - let call = Call::new(obj, Some(symbol), args); - stack.push(ExprOrOp::Expr(Expr::Call(call))); - } else { - let acc = Accessor::attr(obj, Local::new(symbol)); - stack.push(ExprOrOp::Expr(Expr::Accessor(acc))); - } - } - 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(Comma) && winding => { - let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); - let tup = self - .try_reduce_tuple(first_elem) - .map_err(|_| self.stack_dec())?; - self.level -= 1; - return Ok(Expr::Tuple(tup)); - } - _ => { if stack.len() <= 1 { break; } - // else if stack.len() == 2 { switch_unreachable!() } - else { - while stack.len() >= 3 { - let rhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); - let op = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_))); - let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); - let bin = BinOp::new(op, lhs, rhs); - stack.push(ExprOrOp::Expr(Expr::BinOp(bin))); - } - } + } + } + stack.push(ExprOrOp::Op(self.lpop())); + stack.push(ExprOrOp::Expr( + self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?, + )); + } + Some(t) if t.is(DblColon) => { + 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(()); } } } - match stack.pop() { - Some(ExprOrOp::Expr(expr)) if stack.is_empty() => { - self.level -= 1; - Ok(expr) + Some(t) if t.is(Dot) => { + let dot = self.lpop(); + match self.lpop() { + symbol if symbol.is(Symbol) => { + let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() { + expr + } else { + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); + return Err(()); + }; + if let Some(args) = self + .opt_reduce_args() + .transpose() + .map_err(|_| self.stack_dec())? + { + let call = Call::new(obj, Some(symbol), args); + stack.push(ExprOrOp::Expr(Expr::Call(call))); + } else { + let acc = Accessor::attr(obj, Local::new(symbol)); + 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 => { + self.restore(other); + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); + return Err(()); + } } - Some(ExprOrOp::Expr(expr)) => { - let extra = stack.pop().unwrap(); - let loc = match extra { - ExprOrOp::Expr(expr) => expr.loc(), - ExprOrOp::Op(op) => op.loc(), - }; - self.warns - .push(ParseError::compiler_bug(0, loc, fn_name!(), line!())); - self.level -= 1; - Ok(expr) + } + Some(t) if t.is(Comma) && winding => { + let first_elem = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); + let tup = self + .try_reduce_tuple(first_elem) + .map_err(|_| self.stack_dec())?; + self.level -= 1; + return Ok(Expr::Tuple(tup)); + } + _ => { + if stack.len() <= 1 { + break; } - Some(ExprOrOp::Op(op)) => { - self.level -= 1; - self.errs - .push(ParseError::compiler_bug(0, op.loc(), fn_name!(), line!())); - Err(()) + // else if stack.len() == 2 { switch_unreachable!() } + else { + while stack.len() >= 3 { + let rhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); + let op = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Op:(_))); + let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_))); + let bin = BinOp::new(op, lhs, rhs); + stack.push(ExprOrOp::Expr(Expr::BinOp(bin))); + } } - _ => switch_unreachable!(), } } } + match stack.pop() { + Some(ExprOrOp::Expr(expr)) if stack.is_empty() => { + self.level -= 1; + Ok(expr) + } + Some(ExprOrOp::Expr(expr)) => { + let extra = stack.pop().unwrap(); + let loc = match extra { + ExprOrOp::Expr(expr) => expr.loc(), + ExprOrOp::Op(op) => op.loc(), + }; + self.warns + .push(ParseError::compiler_bug(0, loc, fn_name!(), line!())); + self.level -= 1; + Ok(expr) + } + Some(ExprOrOp::Op(op)) => { + self.level -= 1; + self.errs + .push(ParseError::compiler_bug(0, op.loc(), fn_name!(), line!())); + Err(()) + } + _ => switch_unreachable!(), + } } /// "LHS" is the smallest unit that can be the left-hand side of an BinOp. @@ -2040,7 +1960,7 @@ impl Parser { self.level -= 1; Ok(BraceContainer::Record(record)) } - Expr::Decl(_) => todo!(), // invalid syntax + Expr::TypeAsc(_) => todo!(), // invalid syntax other => { let set = self .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 { + 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 { + debug_call_info!(self); + todo!() + } + + fn convert_accessor_to_var_sig(&mut self, _accessor: Accessor) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_array_to_array_pat(&mut self, _array: Array) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_tuple_to_tuple_pat(&mut self, _tuple: Tuple) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_type_asc_to_sig(&mut self, _tasc: TypeAscription) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_rhs_to_lambda_sig(&mut self, rhs: Expr) -> ParseResult { + 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 { + debug_call_info!(self); + todo!() + } + + fn convert_tuple_to_params(&mut self, _tuple: Tuple) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_array_to_param_pat(&mut self, _array: Array) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_record_to_param_pat(&mut self, _record: Record) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_type_asc_to_lambda_sig( + &mut self, + _tasc: TypeAscription, + ) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_rhs_to_type_spec(&mut self, rhs: Expr) -> ParseResult { + 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 { + debug_call_info!(self); + todo!() + } + + fn convert_call_to_predecl_type_spec(&mut self, _call: Call) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_lambda_to_subr_type_spec(&mut self, _lambda: Lambda) -> ParseResult { + debug_call_info!(self); + todo!() + } + + fn convert_array_to_array_type_spec(&mut self, _array: Array) -> ParseResult { + debug_call_info!(self); + todo!() + } }