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:
Shunsuke Shibayama 2022-09-02 01:19:43 +09:00
parent 66451ad61a
commit 0844fb2f7a
6 changed files with 510 additions and 83 deletions

View file

@ -97,7 +97,7 @@ pub struct KwArg {
impl NestedDisplay for KwArg {
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)
}
}

View file

@ -95,12 +95,18 @@ impl PosArg {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct KwArg {
pub keyword: Token,
pub t_spec: Option<TypeSpec>,
pub expr: Expr,
}
impl NestedDisplay for KwArg {
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)
}
}
@ -109,8 +115,12 @@ impl_display_from_nested!(KwArg);
impl_locational!(KwArg, keyword, expr);
impl KwArg {
pub const fn new(keyword: Token, expr: Expr) -> Self {
Self { keyword, expr }
pub const fn new(keyword: Token, t_spec: Option<TypeSpec>, expr: Expr) -> Self {
Self {
keyword,
t_spec,
expr,
}
}
}
@ -1174,7 +1184,7 @@ pub struct ConstKwArg {
impl NestedDisplay for ConstKwArg {
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 {
write!(
f,
"({}, {}, |= {}) {} {}",
"({}, {}, := {}) {} {}",
fmt_vec(&self.non_defaults),
fmt_option!(pre "...", &self.var_args),
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)]
pub struct ParamRecordPattern {
l_brace: Token,
@ -2116,12 +2140,12 @@ pub enum ParamPattern {
VarArgsName(VarName),
Lit(Literal),
Array(ParamArrayPattern),
// Tuple(),
Tuple(ParamTuplePattern),
Record(ParamRecordPattern),
}
impl_display_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Record);
impl_locational_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, Tuple, Record);
impl ParamPattern {
pub const fn inspect(&self) -> Option<&Str> {
@ -2165,7 +2189,7 @@ impl NestedDisplay for ParamSignature {
if let Some(default_val) = &self.opt_default_val {
write!(
f,
"{}{} |= {}",
"{}{} := {}",
self.pat,
fmt_option!(pre ": ", self.t_spec),
default_val
@ -2180,7 +2204,9 @@ impl_display_from_nested!(ParamSignature);
impl Locational for ParamSignature {
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)
} else {
self.pat.loc()
@ -2237,6 +2263,8 @@ impl Locational for Params {
Location::concat(l, r)
} else if !self.non_defaults.is_empty() {
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() {
Location::concat(&self.defaults[0], self.defaults.last().unwrap())
} else {
@ -2525,6 +2553,15 @@ impl NestedDisplay for TypeAscription {
impl_display_from_nested!(TypeAscription);
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)]
pub struct DefBody {
pub op: Token,

View file

@ -664,7 +664,11 @@ impl Iterator for Lexer /*<'a>*/ {
_ => 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, "."),
},
Some(',') => self.accept(Comma, ","),
@ -673,6 +677,10 @@ impl Iterator for Lexer /*<'a>*/ {
self.consume();
self.accept(DblColon, "::")
}
Some('=') => {
self.consume();
self.accept(Walrus, ":=")
}
Some('>') => {
self.consume();
self.accept(SupertypeOf, ":>")
@ -694,10 +702,6 @@ impl Iterator for Lexer /*<'a>*/ {
self.consume();
self.accept(BitOr, "||")
}
Some('=') => {
self.consume();
self.accept(OrEqual, "|=")
}
_ => self.accept(VBar, "|"),
},
Some('^') => {

View file

@ -272,7 +272,7 @@ impl Parser {
Some(t) if t.is(Indent) || t.is(Dedent) => {
switch_unreachable!()
}
Some(_) => match self.try_reduce_expr(true) {
Some(_) => match self.try_reduce_chunk(true) {
Ok(expr) => {
chunks.push(expr);
}
@ -290,7 +290,7 @@ impl Parser {
let mut block = Block::with_capacity(2);
// single line block
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);
self.level -= 1;
return Ok(block);
@ -312,7 +312,7 @@ impl Parser {
} else if t.is(EOF) {
break;
}
match self.try_reduce_expr(true) {
match self.try_reduce_chunk(true) {
Ok(expr) => {
block.push(expr);
if self.cur_is(Dedent) {
@ -454,7 +454,7 @@ impl Parser {
Ok(acc)
}
fn _validate_const_expr(&mut self, expr: Expr) -> ParseResult<ConstExpr> {
fn validate_const_expr(&mut self, expr: Expr) -> ParseResult<ConstExpr> {
match expr {
Expr::Lit(l) => Ok(ConstExpr::Lit(l)),
Expr::Accessor(Accessor::Local(local)) => {
@ -480,12 +480,12 @@ impl Parser {
}
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))
}
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))
}
@ -599,8 +599,7 @@ impl Parser {
|| t.category_is(TC::Caret)
|| t.is(LParen)
|| t.is(LSqBr)
|| t.is(LBrace)
|| t.is(Colon) =>
|| t.is(LBrace) =>
{
Some(self.try_reduce_args())
}
@ -733,28 +732,33 @@ impl Parser {
self.level -= 1;
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())?;
debug_power_assert!(self.cur_is(Colon));
if self.nth_is(1, Newline) {
self.level -= 1;
// colon style call
Ok(PosOrKwArg::Pos(PosArg::new(Expr::Accessor(acc))))
// TODO: type specification
debug_power_assert!(self.cur_is(Walrus));
self.skip();
let kw = if let Accessor::Local(n) = acc {
n.symbol
} else {
self.skip();
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.next_expr();
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 {
let expr = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
self.level -= 1;
@ -774,9 +778,9 @@ impl Parser {
debug_call_info!(self);
match self.peek() {
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())?;
debug_power_assert!(self.cur_is(Colon));
debug_power_assert!(self.cur_is(Walrus));
self.skip();
let keyword = if let Accessor::Local(n) = acc {
n.symbol
@ -787,9 +791,19 @@ impl Parser {
.push(ParseError::simple_syntax_error(0, acc.loc()));
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(KwArg::new(keyword, expr))
Ok(KwArg::new(keyword, t_spec, expr))
} else {
let loc = t.loc();
self.level -= 1;
@ -863,8 +877,7 @@ impl Parser {
}
}
/// winding: true => parse paren-less tuple
fn try_reduce_expr(&mut self, winding: bool) -> ParseResult<Expr> {
fn try_reduce_chunk(&mut self, winding: bool) -> ParseResult<Expr> {
debug_call_info!(self);
let mut stack = Vec::<ExprOrOp>::new();
stack.push(ExprOrOp::Expr(
@ -896,6 +909,16 @@ impl Parser {
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 {
@ -985,8 +1008,149 @@ impl Parser {
let tup = self
.try_reduce_tuple(first_elem)
.map_err(|_| self.stack_dec())?;
self.level -= 1;
return Ok(Expr::Tuple(tup));
stack.push(ExprOrOp::Expr(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 {
@ -1131,10 +1295,8 @@ impl Parser {
fn try_reduce_call_or_acc(&mut self) -> ParseResult<Expr> {
debug_call_info!(self);
let acc = self.try_reduce_acc().map_err(|_| self.stack_dec())?;
log!(err "{acc}");
if let Some(res) = self.opt_reduce_args() {
let args = res.map_err(|_| self.stack_dec())?;
log!(err "{args}");
let (obj, method_name) = match acc {
Accessor::Attr(attr) => (*attr.obj, Some(attr.name.symbol)),
Accessor::Local(local) => (Expr::Accessor(Accessor::Local(local)), None),
@ -1144,7 +1306,6 @@ impl Parser {
self.level -= 1;
Ok(Expr::Call(call))
} else {
log!(err "not args");
self.level -= 1;
Ok(Expr::Accessor(acc))
}
@ -1296,17 +1457,6 @@ impl Parser {
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;
}
@ -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> {
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> {
@ -1404,16 +1564,214 @@ impl Parser {
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);
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);
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> {
debug_call_info!(self);
match rhs {
@ -1469,9 +1827,28 @@ impl Parser {
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);
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> {
@ -1493,6 +1870,7 @@ impl Parser {
}
fn convert_rhs_to_type_spec(&mut self, rhs: Expr) -> ParseResult<TypeSpec> {
debug_call_info!(self);
match rhs {
Expr::Accessor(acc) => {
let predecl = self
@ -1528,10 +1906,18 @@ impl Parser {
fn convert_accessor_to_predecl_type_spec(
&mut self,
_accessor: Accessor,
accessor: Accessor,
) -> ParseResult<PreDeclTypeSpec> {
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> {

View file

@ -105,8 +105,8 @@ pub enum TokenKind {
CrossOp,
/// =
Equal,
/// |=
OrEqual,
/// :=
Walrus,
/// ->
FuncArrow,
/// =>
@ -175,7 +175,7 @@ pub enum TokenCategory {
LEnclosure,
/// ) } } Dedent
REnclosure,
/// , : :: :> <: . |> |=
/// , : :: :> <: . |> :=
SpecialBinOp,
/// =
DefOp,
@ -212,7 +212,7 @@ impl TokenKind {
| InfLit => TokenCategory::Literal,
PrePlus | PreMinus | PreBitNot | Mutate => TokenCategory::UnaryOp,
Try => TokenCategory::PostfixOp,
Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | OrEqual => {
Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | Walrus => {
TokenCategory::SpecialBinOp
}
Equal => TokenCategory::DefOp,
@ -250,7 +250,7 @@ impl TokenKind {
FuncArrow | ProcArrow => 60, // -> =>
Colon | SupertypeOf | SubtypeOf => 50, // : :> <:
Comma => 40, // ,
Equal | OrEqual => 20, // = |=
Equal | Walrus => 20, // = :=
Newline | Semi => 10, // \n ;
LParen | LBrace | LSqBr | Indent => 0, // ( { [ Indent
_ => return None,

View file

@ -704,7 +704,7 @@ impl LimitedDisplay for SubrType {
var_params.typ().limited_fmt(f, limit - 1)?;
}
for pt in self.default_params.iter() {
write!(f, ", {} |= ", pt.name().unwrap())?;
write!(f, ", {} := ", pt.name().unwrap())?;
pt.typ().limited_fmt(f, limit - 1)?;
}
write!(f, ") {} ", self.kind.arrow())?;
@ -1075,7 +1075,7 @@ impl fmt::Display for ArgsOwnership {
write!(f, ", ...{o:?}")?;
}
for (name, o) in self.defaults.iter() {
write!(f, ", {name} |= {o:?}")?;
write!(f, ", {name} := {o:?}")?;
}
write!(f, ")")?;
Ok(())