mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Improve: LHS are parsed once as RHS, then conv to LHS
This commit is contained in:
parent
29b395d96d
commit
d790063ec2
2 changed files with 487 additions and 287 deletions
|
@ -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 {
|
||||
fn from(attrs: Vec<Def>) -> 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<Token>,
|
||||
pub non_defaults: Vec<ParamTySpec>,
|
||||
|
@ -1412,7 +1418,7 @@ pub struct SubrTySpec {
|
|||
pub return_t: Box<TypeSpec>,
|
||||
}
|
||||
|
||||
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<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.
|
||||
/// * 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<TypeSpec>),
|
||||
// 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<ParamTySpec>,
|
||||
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<ParamTySpec>,
|
||||
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<TypeSpec>,
|
||||
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<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)]
|
||||
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 {
|
||||
|
|
|
@ -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<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) {
|
||||
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<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> {
|
||||
debug_call_info!(self);
|
||||
let do_symbol = self.lpop();
|
||||
|
@ -1721,28 +1616,35 @@ impl Parser {
|
|||
fn try_reduce_expr(&mut self, winding: bool) -> ParseResult<Expr> {
|
||||
debug_call_info!(self);
|
||||
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(
|
||||
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 {
|
||||
|
@ -1750,12 +1652,9 @@ impl Parser {
|
|||
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 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 {
|
||||
|
@ -1771,11 +1670,27 @@ impl Parser {
|
|||
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(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(());
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(Dot) => {
|
||||
self.skip();
|
||||
let dot = self.lpop();
|
||||
match self.lpop() {
|
||||
symbol if symbol.is(Symbol) => {
|
||||
let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() {
|
||||
|
@ -1798,6 +1713,13 @@ impl Parser {
|
|||
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;
|
||||
|
@ -1857,8 +1779,6 @@ impl Parser {
|
|||
_ => switch_unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// "LHS" is the smallest unit that can be the left-hand side of an BinOp.
|
||||
/// e.g. Call, Name, UnaryOp, Lambda
|
||||
|
@ -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<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!()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue