mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Change Parser
's parsing algorithm
The LHS value is first parsed as the RHS value, and when `=` or `->` comes in, it is converted as the LHS value.
This commit is contained in:
parent
66451ad61a
commit
0844fb2f7a
6 changed files with 510 additions and 83 deletions
|
@ -97,7 +97,7 @@ pub struct KwArg {
|
||||||
|
|
||||||
impl NestedDisplay for KwArg {
|
impl NestedDisplay for KwArg {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
writeln!(f, "{}:", self.keyword)?;
|
writeln!(f, "{} := ", self.keyword)?;
|
||||||
self.expr.fmt_nest(f, level + 1)
|
self.expr.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,12 +95,18 @@ impl PosArg {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct KwArg {
|
pub struct KwArg {
|
||||||
pub keyword: Token,
|
pub keyword: Token,
|
||||||
|
pub t_spec: Option<TypeSpec>,
|
||||||
pub expr: Expr,
|
pub expr: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for KwArg {
|
impl NestedDisplay for KwArg {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
writeln!(f, "{}: ", self.keyword.content)?;
|
writeln!(
|
||||||
|
f,
|
||||||
|
"{}{} := ",
|
||||||
|
self.keyword.content,
|
||||||
|
fmt_option!(pre ": ", self.t_spec)
|
||||||
|
)?;
|
||||||
self.expr.fmt_nest(f, level + 1)
|
self.expr.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,8 +115,12 @@ impl_display_from_nested!(KwArg);
|
||||||
impl_locational!(KwArg, keyword, expr);
|
impl_locational!(KwArg, keyword, expr);
|
||||||
|
|
||||||
impl KwArg {
|
impl KwArg {
|
||||||
pub const fn new(keyword: Token, expr: Expr) -> Self {
|
pub const fn new(keyword: Token, t_spec: Option<TypeSpec>, expr: Expr) -> Self {
|
||||||
Self { keyword, expr }
|
Self {
|
||||||
|
keyword,
|
||||||
|
t_spec,
|
||||||
|
expr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1174,7 +1184,7 @@ pub struct ConstKwArg {
|
||||||
|
|
||||||
impl NestedDisplay for ConstKwArg {
|
impl NestedDisplay for ConstKwArg {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
write!(f, "{}: {}", self.keyword.content, self.expr)
|
write!(f, "{} := {}", self.keyword.content, self.expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1422,7 +1432,7 @@ 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,
|
||||||
"({}, {}, |= {}) {} {}",
|
"({}, {}, := {}) {} {}",
|
||||||
fmt_vec(&self.non_defaults),
|
fmt_vec(&self.non_defaults),
|
||||||
fmt_option!(pre "...", &self.var_args),
|
fmt_option!(pre "...", &self.var_args),
|
||||||
fmt_vec(&self.defaults),
|
fmt_vec(&self.defaults),
|
||||||
|
@ -2079,6 +2089,20 @@ impl ParamArrayPattern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ParamTuplePattern {
|
||||||
|
pub elems: Params,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for ParamTuplePattern {
|
||||||
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
|
write!(f, "({})", self.elems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(ParamTuplePattern);
|
||||||
|
impl_locational!(ParamTuplePattern, elems);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ParamRecordPattern {
|
pub struct ParamRecordPattern {
|
||||||
l_brace: Token,
|
l_brace: Token,
|
||||||
|
@ -2116,12 +2140,12 @@ pub enum ParamPattern {
|
||||||
VarArgsName(VarName),
|
VarArgsName(VarName),
|
||||||
Lit(Literal),
|
Lit(Literal),
|
||||||
Array(ParamArrayPattern),
|
Array(ParamArrayPattern),
|
||||||
// Tuple(),
|
Tuple(ParamTuplePattern),
|
||||||
Record(ParamRecordPattern),
|
Record(ParamRecordPattern),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Record);
|
impl_display_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Tuple Record);
|
||||||
impl_locational_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Record);
|
impl_locational_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Tuple, Record);
|
||||||
|
|
||||||
impl ParamPattern {
|
impl ParamPattern {
|
||||||
pub const fn inspect(&self) -> Option<&Str> {
|
pub const fn inspect(&self) -> Option<&Str> {
|
||||||
|
@ -2165,7 +2189,7 @@ impl NestedDisplay for ParamSignature {
|
||||||
if let Some(default_val) = &self.opt_default_val {
|
if let Some(default_val) = &self.opt_default_val {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}{} |= {}",
|
"{}{} := {}",
|
||||||
self.pat,
|
self.pat,
|
||||||
fmt_option!(pre ": ", self.t_spec),
|
fmt_option!(pre ": ", self.t_spec),
|
||||||
default_val
|
default_val
|
||||||
|
@ -2180,7 +2204,9 @@ impl_display_from_nested!(ParamSignature);
|
||||||
|
|
||||||
impl Locational for ParamSignature {
|
impl Locational for ParamSignature {
|
||||||
fn loc(&self) -> Location {
|
fn loc(&self) -> Location {
|
||||||
if let Some(t_spec) = &self.t_spec {
|
if let Some(default) = &self.opt_default_val {
|
||||||
|
Location::concat(&self.pat, default)
|
||||||
|
} else if let Some(t_spec) = &self.t_spec {
|
||||||
Location::concat(&self.pat, t_spec)
|
Location::concat(&self.pat, t_spec)
|
||||||
} else {
|
} else {
|
||||||
self.pat.loc()
|
self.pat.loc()
|
||||||
|
@ -2237,6 +2263,8 @@ impl Locational for Params {
|
||||||
Location::concat(l, r)
|
Location::concat(l, r)
|
||||||
} else if !self.non_defaults.is_empty() {
|
} else if !self.non_defaults.is_empty() {
|
||||||
Location::concat(&self.non_defaults[0], self.non_defaults.last().unwrap())
|
Location::concat(&self.non_defaults[0], self.non_defaults.last().unwrap())
|
||||||
|
} else if let Some(var_args) = &self.var_args {
|
||||||
|
Location::concat(var_args.as_ref(), self.defaults.last().unwrap())
|
||||||
} else if !self.defaults.is_empty() {
|
} else if !self.defaults.is_empty() {
|
||||||
Location::concat(&self.defaults[0], self.defaults.last().unwrap())
|
Location::concat(&self.defaults[0], self.defaults.last().unwrap())
|
||||||
} else {
|
} else {
|
||||||
|
@ -2525,6 +2553,15 @@ impl NestedDisplay for TypeAscription {
|
||||||
impl_display_from_nested!(TypeAscription);
|
impl_display_from_nested!(TypeAscription);
|
||||||
impl_locational!(TypeAscription, expr, t_spec);
|
impl_locational!(TypeAscription, expr, t_spec);
|
||||||
|
|
||||||
|
impl TypeAscription {
|
||||||
|
pub fn new(expr: Expr, t_spec: TypeSpec) -> Self {
|
||||||
|
Self {
|
||||||
|
expr: Box::new(expr),
|
||||||
|
t_spec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct DefBody {
|
pub struct DefBody {
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
|
|
@ -664,7 +664,11 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
_ => self.accept(Closed, ".."),
|
_ => self.accept(Closed, ".."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(c) if c.is_ascii_digit() => Some(self.lex_ratio(".".into())),
|
// prev_token is Symbol => TupleAttribute
|
||||||
|
// else: RatioLit (e.g. .0)
|
||||||
|
Some(c) if c.is_ascii_digit() && !self.prev_token.is(Symbol) => {
|
||||||
|
Some(self.lex_ratio(".".into()))
|
||||||
|
}
|
||||||
_ => self.accept(Dot, "."),
|
_ => self.accept(Dot, "."),
|
||||||
},
|
},
|
||||||
Some(',') => self.accept(Comma, ","),
|
Some(',') => self.accept(Comma, ","),
|
||||||
|
@ -673,6 +677,10 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
self.consume();
|
self.consume();
|
||||||
self.accept(DblColon, "::")
|
self.accept(DblColon, "::")
|
||||||
}
|
}
|
||||||
|
Some('=') => {
|
||||||
|
self.consume();
|
||||||
|
self.accept(Walrus, ":=")
|
||||||
|
}
|
||||||
Some('>') => {
|
Some('>') => {
|
||||||
self.consume();
|
self.consume();
|
||||||
self.accept(SupertypeOf, ":>")
|
self.accept(SupertypeOf, ":>")
|
||||||
|
@ -694,10 +702,6 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
self.consume();
|
self.consume();
|
||||||
self.accept(BitOr, "||")
|
self.accept(BitOr, "||")
|
||||||
}
|
}
|
||||||
Some('=') => {
|
|
||||||
self.consume();
|
|
||||||
self.accept(OrEqual, "|=")
|
|
||||||
}
|
|
||||||
_ => self.accept(VBar, "|"),
|
_ => self.accept(VBar, "|"),
|
||||||
},
|
},
|
||||||
Some('^') => {
|
Some('^') => {
|
||||||
|
|
|
@ -272,7 +272,7 @@ impl Parser {
|
||||||
Some(t) if t.is(Indent) || t.is(Dedent) => {
|
Some(t) if t.is(Indent) || t.is(Dedent) => {
|
||||||
switch_unreachable!()
|
switch_unreachable!()
|
||||||
}
|
}
|
||||||
Some(_) => match self.try_reduce_expr(true) {
|
Some(_) => match self.try_reduce_chunk(true) {
|
||||||
Ok(expr) => {
|
Ok(expr) => {
|
||||||
chunks.push(expr);
|
chunks.push(expr);
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ impl Parser {
|
||||||
let mut block = Block::with_capacity(2);
|
let mut block = Block::with_capacity(2);
|
||||||
// single line block
|
// single line block
|
||||||
if !self.cur_is(Newline) {
|
if !self.cur_is(Newline) {
|
||||||
let chunk = self.try_reduce_expr(true).map_err(|_| self.stack_dec())?;
|
let chunk = self.try_reduce_chunk(true).map_err(|_| self.stack_dec())?;
|
||||||
block.push(chunk);
|
block.push(chunk);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
return Ok(block);
|
return Ok(block);
|
||||||
|
@ -312,7 +312,7 @@ impl Parser {
|
||||||
} else if t.is(EOF) {
|
} else if t.is(EOF) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match self.try_reduce_expr(true) {
|
match self.try_reduce_chunk(true) {
|
||||||
Ok(expr) => {
|
Ok(expr) => {
|
||||||
block.push(expr);
|
block.push(expr);
|
||||||
if self.cur_is(Dedent) {
|
if self.cur_is(Dedent) {
|
||||||
|
@ -454,7 +454,7 @@ impl Parser {
|
||||||
Ok(acc)
|
Ok(acc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _validate_const_expr(&mut self, expr: Expr) -> ParseResult<ConstExpr> {
|
fn validate_const_expr(&mut self, expr: Expr) -> ParseResult<ConstExpr> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Lit(l) => Ok(ConstExpr::Lit(l)),
|
Expr::Lit(l) => Ok(ConstExpr::Lit(l)),
|
||||||
Expr::Accessor(Accessor::Local(local)) => {
|
Expr::Accessor(Accessor::Local(local)) => {
|
||||||
|
@ -480,12 +480,12 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _validate_const_pos_arg(&mut self, arg: PosArg) -> ParseResult<ConstPosArg> {
|
fn _validate_const_pos_arg(&mut self, arg: PosArg) -> ParseResult<ConstPosArg> {
|
||||||
let expr = self._validate_const_expr(arg.expr)?;
|
let expr = self.validate_const_expr(arg.expr)?;
|
||||||
Ok(ConstPosArg::new(expr))
|
Ok(ConstPosArg::new(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _validate_const_kw_arg(&mut self, arg: KwArg) -> ParseResult<ConstKwArg> {
|
fn _validate_const_kw_arg(&mut self, arg: KwArg) -> ParseResult<ConstKwArg> {
|
||||||
let expr = self._validate_const_expr(arg.expr)?;
|
let expr = self.validate_const_expr(arg.expr)?;
|
||||||
Ok(ConstKwArg::new(arg.keyword, expr))
|
Ok(ConstKwArg::new(arg.keyword, expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,8 +599,7 @@ impl Parser {
|
||||||
|| t.category_is(TC::Caret)
|
|| t.category_is(TC::Caret)
|
||||||
|| t.is(LParen)
|
|| t.is(LParen)
|
||||||
|| t.is(LSqBr)
|
|| t.is(LSqBr)
|
||||||
|| t.is(LBrace)
|
|| t.is(LBrace) =>
|
||||||
|| t.is(Colon) =>
|
|
||||||
{
|
{
|
||||||
Some(self.try_reduce_args())
|
Some(self.try_reduce_args())
|
||||||
}
|
}
|
||||||
|
@ -733,28 +732,33 @@ impl Parser {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
return Ok(PosOrKwArg::Pos(PosArg::new(Expr::Lambda(lambda))));
|
return Ok(PosOrKwArg::Pos(PosArg::new(Expr::Lambda(lambda))));
|
||||||
}
|
}
|
||||||
if self.nth_is(1, Colon) {
|
if self.nth_is(1, Walrus) {
|
||||||
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
||||||
debug_power_assert!(self.cur_is(Colon));
|
// TODO: type specification
|
||||||
if self.nth_is(1, Newline) {
|
debug_power_assert!(self.cur_is(Walrus));
|
||||||
self.level -= 1;
|
self.skip();
|
||||||
// colon style call
|
let kw = if let Accessor::Local(n) = acc {
|
||||||
Ok(PosOrKwArg::Pos(PosArg::new(Expr::Accessor(acc))))
|
n.symbol
|
||||||
} else {
|
} else {
|
||||||
self.skip();
|
self.next_expr();
|
||||||
let kw = if let Accessor::Local(n) = acc {
|
|
||||||
n.symbol
|
|
||||||
} else {
|
|
||||||
self.next_expr();
|
|
||||||
self.level -= 1;
|
|
||||||
let err = ParseError::simple_syntax_error(0, acc.loc());
|
|
||||||
self.errs.push(err);
|
|
||||||
return Err(());
|
|
||||||
};
|
|
||||||
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(PosOrKwArg::Kw(KwArg::new(kw, expr)))
|
let err = ParseError::simple_syntax_error(0, acc.loc());
|
||||||
}
|
self.errs.push(err);
|
||||||
|
return Err(());
|
||||||
|
};
|
||||||
|
let t_spec = if self.cur_is(Colon) {
|
||||||
|
self.skip();
|
||||||
|
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||||
|
let t_spec = self
|
||||||
|
.convert_rhs_to_type_spec(expr)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
Some(t_spec)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(PosOrKwArg::Kw(KwArg::new(kw, t_spec, expr)))
|
||||||
} else {
|
} else {
|
||||||
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -774,9 +778,9 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Symbol) => {
|
Some(t) if t.is(Symbol) => {
|
||||||
if self.nth_is(1, Colon) {
|
if self.nth_is(1, Walrus) {
|
||||||
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
||||||
debug_power_assert!(self.cur_is(Colon));
|
debug_power_assert!(self.cur_is(Walrus));
|
||||||
self.skip();
|
self.skip();
|
||||||
let keyword = if let Accessor::Local(n) = acc {
|
let keyword = if let Accessor::Local(n) = acc {
|
||||||
n.symbol
|
n.symbol
|
||||||
|
@ -787,9 +791,19 @@ impl Parser {
|
||||||
.push(ParseError::simple_syntax_error(0, acc.loc()));
|
.push(ParseError::simple_syntax_error(0, acc.loc()));
|
||||||
return Err(());
|
return Err(());
|
||||||
};
|
};
|
||||||
|
let t_spec = if self.cur_is(Colon) {
|
||||||
|
self.skip();
|
||||||
|
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||||
|
let t_spec = self
|
||||||
|
.convert_rhs_to_type_spec(expr)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
Some(t_spec)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(KwArg::new(keyword, expr))
|
Ok(KwArg::new(keyword, t_spec, expr))
|
||||||
} else {
|
} else {
|
||||||
let loc = t.loc();
|
let loc = t.loc();
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -863,8 +877,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// winding: true => parse paren-less tuple
|
fn try_reduce_chunk(&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();
|
||||||
stack.push(ExprOrOp::Expr(
|
stack.push(ExprOrOp::Expr(
|
||||||
|
@ -896,6 +909,16 @@ impl Parser {
|
||||||
self.counter,
|
self.counter,
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
Some(op) if op.is(Colon) => {
|
||||||
|
let _op = self.lpop();
|
||||||
|
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
|
let t_spec = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||||
|
let t_spec = self
|
||||||
|
.convert_rhs_to_type_spec(t_spec)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let expr = Expr::TypeAsc(TypeAscription::new(lhs, t_spec));
|
||||||
|
stack.push(ExprOrOp::Expr(expr));
|
||||||
|
}
|
||||||
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 {
|
||||||
|
@ -985,8 +1008,149 @@ impl Parser {
|
||||||
let tup = self
|
let tup = self
|
||||||
.try_reduce_tuple(first_elem)
|
.try_reduce_tuple(first_elem)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
||||||
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// winding: true => parse paren-less tuple
|
||||||
|
fn try_reduce_expr(&mut self, winding: bool) -> ParseResult<Expr> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let mut stack = Vec::<ExprOrOp>::new();
|
||||||
|
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::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.is(Colon) => {
|
||||||
|
let _op = self.lpop();
|
||||||
|
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
|
let t_spec = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||||
|
let t_spec = self
|
||||||
|
.convert_rhs_to_type_spec(t_spec)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let expr = Expr::TypeAsc(TypeAscription::new(lhs, t_spec));
|
||||||
|
stack.push(ExprOrOp::Expr(expr));
|
||||||
|
}
|
||||||
|
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::Op(self.lpop()));
|
||||||
|
stack.push(ExprOrOp::Expr(
|
||||||
|
self.try_reduce_bin_lhs().map_err(|_| self.stack_dec())?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Some(t) if t.is(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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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())?;
|
||||||
|
stack.push(ExprOrOp::Expr(Expr::Tuple(tup)));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if stack.len() <= 1 {
|
if stack.len() <= 1 {
|
||||||
|
@ -1131,10 +1295,8 @@ impl Parser {
|
||||||
fn try_reduce_call_or_acc(&mut self) -> ParseResult<Expr> {
|
fn try_reduce_call_or_acc(&mut self) -> ParseResult<Expr> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
|
||||||
log!(err "{acc}");
|
|
||||||
if let Some(res) = self.opt_reduce_args() {
|
if let Some(res) = self.opt_reduce_args() {
|
||||||
let args = res.map_err(|_| self.stack_dec())?;
|
let args = res.map_err(|_| self.stack_dec())?;
|
||||||
log!(err "{args}");
|
|
||||||
let (obj, method_name) = match acc {
|
let (obj, method_name) = match acc {
|
||||||
Accessor::Attr(attr) => (*attr.obj, Some(attr.name.symbol)),
|
Accessor::Attr(attr) => (*attr.obj, Some(attr.name.symbol)),
|
||||||
Accessor::Local(local) => (Expr::Accessor(Accessor::Local(local)), None),
|
Accessor::Local(local) => (Expr::Accessor(Accessor::Local(local)), None),
|
||||||
|
@ -1144,7 +1306,6 @@ impl Parser {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Expr::Call(call))
|
Ok(Expr::Call(call))
|
||||||
} else {
|
} else {
|
||||||
log!(err "not args");
|
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Expr::Accessor(acc))
|
Ok(Expr::Accessor(acc))
|
||||||
}
|
}
|
||||||
|
@ -1296,17 +1457,6 @@ impl Parser {
|
||||||
PosOrKwArg::Kw(_arg) => todo!(),
|
PosOrKwArg::Kw(_arg) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(t) if t.is(Newline) => {
|
|
||||||
while self.cur_is(Newline) {
|
|
||||||
self.skip();
|
|
||||||
}
|
|
||||||
match self.try_reduce_arg().map_err(|_| self.stack_dec())? {
|
|
||||||
PosOrKwArg::Pos(arg) => {
|
|
||||||
args.push_pos(arg);
|
|
||||||
}
|
|
||||||
PosOrKwArg::Kw(_arg) => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1384,14 +1534,24 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
fn convert_accessor_to_var_sig(&mut self, _accessor: Accessor) -> ParseResult<VarSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
todo!()
|
match _accessor {
|
||||||
|
Accessor::Local(local) => {
|
||||||
|
let pat = VarPattern::Ident(Identifier::new(None, VarName::new(local.symbol)));
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(VarSignature::new(pat, None))
|
||||||
|
}
|
||||||
|
Accessor::Public(public) => {
|
||||||
|
let pat = VarPattern::Ident(Identifier::new(
|
||||||
|
Some(public.dot),
|
||||||
|
VarName::new(public.symbol),
|
||||||
|
));
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(VarSignature::new(pat, None))
|
||||||
|
}
|
||||||
|
other => todo!("{other}"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_array_to_array_pat(&mut self, _array: Array) -> ParseResult<VarArrayPattern> {
|
fn convert_array_to_array_pat(&mut self, _array: Array) -> ParseResult<VarArrayPattern> {
|
||||||
|
@ -1404,16 +1564,214 @@ impl Parser {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_tuple_to_tuple_pat(&mut self, _tuple: Tuple) -> ParseResult<VarTuplePattern> {
|
fn convert_tuple_to_tuple_pat(&mut self, tuple: Tuple) -> ParseResult<VarTuplePattern> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let mut vars = Vars::empty();
|
||||||
|
match tuple {
|
||||||
|
Tuple::Normal(tup) => {
|
||||||
|
let (pos_args, _kw_args, paren) = tup.elems.deconstruct();
|
||||||
|
for arg in pos_args {
|
||||||
|
let sig = self
|
||||||
|
.convert_rhs_to_sig(arg.expr)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
match sig {
|
||||||
|
Signature::Var(var) => {
|
||||||
|
vars.push(var);
|
||||||
|
}
|
||||||
|
other => todo!("{other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let tuple = VarTuplePattern::new(paren, vars);
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(tuple)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_type_asc_to_sig(&mut self, tasc: TypeAscription) -> ParseResult<Signature> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let sig = self
|
||||||
|
.convert_rhs_to_sig(*tasc.expr)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let sig = match sig {
|
||||||
|
Signature::Var(var) => {
|
||||||
|
let var = VarSignature::new(var.pat, Some(tasc.t_spec));
|
||||||
|
Signature::Var(var)
|
||||||
|
}
|
||||||
|
Signature::Subr(subr) => {
|
||||||
|
let subr = SubrSignature::new(
|
||||||
|
subr.decorators,
|
||||||
|
subr.ident,
|
||||||
|
subr.params,
|
||||||
|
Some(tasc.t_spec),
|
||||||
|
subr.bounds,
|
||||||
|
);
|
||||||
|
Signature::Subr(subr)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_call_to_subr_sig(&mut self, call: Call) -> ParseResult<SubrSignature> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let ident = match *call.obj {
|
||||||
|
Expr::Accessor(acc) => self
|
||||||
|
.convert_accessor_to_ident(acc)
|
||||||
|
.map_err(|_| self.stack_dec())?,
|
||||||
|
other => todo!("{other}"), // Error
|
||||||
|
};
|
||||||
|
let params = self
|
||||||
|
.convert_args_to_params(call.args)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let sig = SubrSignature::new(set! {}, ident, params, None, TypeBoundSpecs::empty());
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_accessor_to_ident(&mut self, _accessor: Accessor) -> ParseResult<Identifier> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let ident = match _accessor {
|
||||||
|
Accessor::Local(local) => Identifier::new(None, VarName::new(local.symbol)),
|
||||||
|
Accessor::Public(public) => {
|
||||||
|
Identifier::new(Some(public.dot), VarName::new(public.symbol))
|
||||||
|
}
|
||||||
|
other => todo!("{other}"), // Error
|
||||||
|
};
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(ident)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_args_to_params(&mut self, args: Args) -> ParseResult<Params> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let (pos_args, kw_args, parens) = args.deconstruct();
|
||||||
|
let mut params = Params::new(vec![], None, vec![], parens);
|
||||||
|
for arg in pos_args.into_iter() {
|
||||||
|
let nd_param = self
|
||||||
|
.convert_pos_arg_to_non_default_param(arg)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
params.non_defaults.push(nd_param);
|
||||||
|
}
|
||||||
|
// TODO: varargs
|
||||||
|
for arg in kw_args.into_iter() {
|
||||||
|
let d_param = self
|
||||||
|
.convert_kw_arg_to_default_param(arg)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
params.defaults.push(d_param);
|
||||||
|
}
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_pos_arg_to_non_default_param(&mut self, arg: PosArg) -> ParseResult<ParamSignature> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let param = self
|
||||||
|
.convert_rhs_to_param(arg.expr)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_rhs_to_param(&mut self, expr: Expr) -> ParseResult<ParamSignature> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
match expr {
|
||||||
|
Expr::Accessor(Accessor::Local(local)) => {
|
||||||
|
let name = VarName::new(local.symbol);
|
||||||
|
let pat = ParamPattern::VarName(name);
|
||||||
|
let param = ParamSignature::new(pat, None, None);
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
Expr::Lit(lit) => {
|
||||||
|
let pat = ParamPattern::Lit(lit);
|
||||||
|
let param = ParamSignature::new(pat, None, None);
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
Expr::Array(array) => {
|
||||||
|
let array_pat = self
|
||||||
|
.convert_array_to_param_array_pat(array)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let pat = ParamPattern::Array(array_pat);
|
||||||
|
let param = ParamSignature::new(pat, None, None);
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
Expr::Record(record) => {
|
||||||
|
let record_pat = self
|
||||||
|
.convert_record_to_param_record_pat(record)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let pat = ParamPattern::Record(record_pat);
|
||||||
|
let param = ParamSignature::new(pat, None, None);
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
Expr::Tuple(tuple) => {
|
||||||
|
let tuple_pat = self
|
||||||
|
.convert_tuple_to_param_tuple_pat(tuple)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let pat = ParamPattern::Tuple(tuple_pat);
|
||||||
|
let param = ParamSignature::new(pat, None, None);
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
Expr::TypeAsc(tasc) => {
|
||||||
|
let param = self
|
||||||
|
.convert_type_asc_to_param_pattern(tasc)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
other => todo!("{other}"), // Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_kw_arg_to_default_param(&mut self, arg: KwArg) -> ParseResult<ParamSignature> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let pat = ParamPattern::VarName(VarName::new(arg.keyword));
|
||||||
|
let expr = self.validate_const_expr(arg.expr)?;
|
||||||
|
let param = ParamSignature::new(pat, arg.t_spec, Some(expr));
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_array_to_param_array_pat(
|
||||||
|
&mut self,
|
||||||
|
_array: Array,
|
||||||
|
) -> ParseResult<ParamArrayPattern> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_type_asc_to_sig(&mut self, _tasc: TypeAscription) -> ParseResult<Signature> {
|
fn convert_record_to_param_record_pat(
|
||||||
|
&mut self,
|
||||||
|
_record: Record,
|
||||||
|
) -> ParseResult<ParamRecordPattern> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_tuple_to_param_tuple_pat(
|
||||||
|
&mut self,
|
||||||
|
_tuple: Tuple,
|
||||||
|
) -> ParseResult<ParamTuplePattern> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_type_asc_to_param_pattern(
|
||||||
|
&mut self,
|
||||||
|
tasc: TypeAscription,
|
||||||
|
) -> ParseResult<ParamSignature> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let param = self
|
||||||
|
.convert_rhs_to_param(*tasc.expr)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let param = ParamSignature::new(param.pat, Some(tasc.t_spec), None);
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(param)
|
||||||
|
}
|
||||||
|
|
||||||
fn convert_rhs_to_lambda_sig(&mut self, rhs: Expr) -> ParseResult<LambdaSignature> {
|
fn convert_rhs_to_lambda_sig(&mut self, rhs: Expr) -> ParseResult<LambdaSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match rhs {
|
match rhs {
|
||||||
|
@ -1469,9 +1827,28 @@ impl Parser {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_tuple_to_params(&mut self, _tuple: Tuple) -> ParseResult<Params> {
|
fn convert_tuple_to_params(&mut self, tuple: Tuple) -> ParseResult<Params> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
todo!()
|
match tuple {
|
||||||
|
Tuple::Normal(tup) => {
|
||||||
|
let (pos_args, kw_args, paren) = tup.elems.deconstruct();
|
||||||
|
let mut params = Params::new(vec![], None, vec![], paren);
|
||||||
|
for arg in pos_args {
|
||||||
|
let param = self
|
||||||
|
.convert_pos_arg_to_non_default_param(arg)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
params.non_defaults.push(param);
|
||||||
|
}
|
||||||
|
for arg in kw_args {
|
||||||
|
let param = self
|
||||||
|
.convert_kw_arg_to_default_param(arg)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
params.defaults.push(param);
|
||||||
|
}
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(params)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_array_to_param_pat(&mut self, _array: Array) -> ParseResult<ParamArrayPattern> {
|
fn convert_array_to_param_pat(&mut self, _array: Array) -> ParseResult<ParamArrayPattern> {
|
||||||
|
@ -1493,6 +1870,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_rhs_to_type_spec(&mut self, rhs: Expr) -> ParseResult<TypeSpec> {
|
fn convert_rhs_to_type_spec(&mut self, rhs: Expr) -> ParseResult<TypeSpec> {
|
||||||
|
debug_call_info!(self);
|
||||||
match rhs {
|
match rhs {
|
||||||
Expr::Accessor(acc) => {
|
Expr::Accessor(acc) => {
|
||||||
let predecl = self
|
let predecl = self
|
||||||
|
@ -1528,10 +1906,18 @@ impl Parser {
|
||||||
|
|
||||||
fn convert_accessor_to_predecl_type_spec(
|
fn convert_accessor_to_predecl_type_spec(
|
||||||
&mut self,
|
&mut self,
|
||||||
_accessor: Accessor,
|
accessor: Accessor,
|
||||||
) -> ParseResult<PreDeclTypeSpec> {
|
) -> ParseResult<PreDeclTypeSpec> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
todo!()
|
let t_spec = match accessor {
|
||||||
|
Accessor::Local(local) => PreDeclTypeSpec::Simple(SimpleTypeSpec::new(
|
||||||
|
VarName::new(local.symbol),
|
||||||
|
ConstArgs::empty(),
|
||||||
|
)),
|
||||||
|
other => todo!("{other}"),
|
||||||
|
};
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(t_spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_call_to_predecl_type_spec(&mut self, _call: Call) -> ParseResult<PreDeclTypeSpec> {
|
fn convert_call_to_predecl_type_spec(&mut self, _call: Call) -> ParseResult<PreDeclTypeSpec> {
|
||||||
|
|
|
@ -105,8 +105,8 @@ pub enum TokenKind {
|
||||||
CrossOp,
|
CrossOp,
|
||||||
/// =
|
/// =
|
||||||
Equal,
|
Equal,
|
||||||
/// |=
|
/// :=
|
||||||
OrEqual,
|
Walrus,
|
||||||
/// ->
|
/// ->
|
||||||
FuncArrow,
|
FuncArrow,
|
||||||
/// =>
|
/// =>
|
||||||
|
@ -175,7 +175,7 @@ pub enum TokenCategory {
|
||||||
LEnclosure,
|
LEnclosure,
|
||||||
/// ) } } Dedent
|
/// ) } } Dedent
|
||||||
REnclosure,
|
REnclosure,
|
||||||
/// , : :: :> <: . |> |=
|
/// , : :: :> <: . |> :=
|
||||||
SpecialBinOp,
|
SpecialBinOp,
|
||||||
/// =
|
/// =
|
||||||
DefOp,
|
DefOp,
|
||||||
|
@ -212,7 +212,7 @@ impl TokenKind {
|
||||||
| InfLit => TokenCategory::Literal,
|
| InfLit => TokenCategory::Literal,
|
||||||
PrePlus | PreMinus | PreBitNot | Mutate => TokenCategory::UnaryOp,
|
PrePlus | PreMinus | PreBitNot | Mutate => TokenCategory::UnaryOp,
|
||||||
Try => TokenCategory::PostfixOp,
|
Try => TokenCategory::PostfixOp,
|
||||||
Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | OrEqual => {
|
Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | Walrus => {
|
||||||
TokenCategory::SpecialBinOp
|
TokenCategory::SpecialBinOp
|
||||||
}
|
}
|
||||||
Equal => TokenCategory::DefOp,
|
Equal => TokenCategory::DefOp,
|
||||||
|
@ -250,7 +250,7 @@ impl TokenKind {
|
||||||
FuncArrow | ProcArrow => 60, // -> =>
|
FuncArrow | ProcArrow => 60, // -> =>
|
||||||
Colon | SupertypeOf | SubtypeOf => 50, // : :> <:
|
Colon | SupertypeOf | SubtypeOf => 50, // : :> <:
|
||||||
Comma => 40, // ,
|
Comma => 40, // ,
|
||||||
Equal | OrEqual => 20, // = |=
|
Equal | Walrus => 20, // = :=
|
||||||
Newline | Semi => 10, // \n ;
|
Newline | Semi => 10, // \n ;
|
||||||
LParen | LBrace | LSqBr | Indent => 0, // ( { [ Indent
|
LParen | LBrace | LSqBr | Indent => 0, // ( { [ Indent
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
|
|
@ -704,7 +704,7 @@ impl LimitedDisplay for SubrType {
|
||||||
var_params.typ().limited_fmt(f, limit - 1)?;
|
var_params.typ().limited_fmt(f, limit - 1)?;
|
||||||
}
|
}
|
||||||
for pt in self.default_params.iter() {
|
for pt in self.default_params.iter() {
|
||||||
write!(f, ", {} |= ", pt.name().unwrap())?;
|
write!(f, ", {} := ", pt.name().unwrap())?;
|
||||||
pt.typ().limited_fmt(f, limit - 1)?;
|
pt.typ().limited_fmt(f, limit - 1)?;
|
||||||
}
|
}
|
||||||
write!(f, ") {} ", self.kind.arrow())?;
|
write!(f, ") {} ", self.kind.arrow())?;
|
||||||
|
@ -1075,7 +1075,7 @@ impl fmt::Display for ArgsOwnership {
|
||||||
write!(f, ", ...{o:?}")?;
|
write!(f, ", ...{o:?}")?;
|
||||||
}
|
}
|
||||||
for (name, o) in self.defaults.iter() {
|
for (name, o) in self.defaults.iter() {
|
||||||
write!(f, ", {name} |= {o:?}")?;
|
write!(f, ", {name} := {o:?}")?;
|
||||||
}
|
}
|
||||||
write!(f, ")")?;
|
write!(f, ")")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue