mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +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 {
|
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 {
|
||||||
|
|
|
@ -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!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue