Support custom binops

This commit is contained in:
Greg Shuflin 2021-11-20 23:56:53 -08:00
parent 1a48e9b43a
commit 8d5858d3d2
3 changed files with 46 additions and 4 deletions

View File

@ -284,9 +284,32 @@ fn func_decl(input: Span) -> ParseResult<Declaration> {
//TODO handle operators
fn func_signature(input: Span) -> ParseResult<Signature> {
map(tuple((kw("fn"), identifier, formal_params, opt(type_anno))), |(_, name, params, type_anno)| {
Signature { name: rc_string(name.fragment()), operator: false, params, type_anno }
})(input)
let normal_fn = context("ordinary-fn", tuple((identifier, formal_params, opt(type_anno))));
let operator_fn = context(
"operator-fn",
tuple((delimited(tok(char('(')), operator, tok(char(')'))), formal_params, opt(type_anno))),
);
context(
"func-signature",
preceded(
kw("fn"),
cut(alt((
map(normal_fn, |(name, params, type_anno)| Signature {
name: rc_string(name.fragment()),
operator: false,
params,
type_anno,
}),
map(operator_fn, |(op, params, type_anno)| Signature {
name: rc_string(op.sigil()),
operator: true,
params,
type_anno,
}),
))),
),
)(input)
}
fn formal_params(input: Span) -> ParseResult<Vec<FormalParam>> {

View File

@ -112,10 +112,12 @@ peg::parser! {
rule func_declaration(parser: &mut Parser) -> Declaration =
_ sig:func_signature(parser) __ body:block(parser) { Declaration::FuncDecl(sig, body) }
//TODO handle operators
rule func_signature(parser: &mut Parser) -> Signature =
_ "fn" _ name:identifier() "(" _ params:formal_params(parser) _ ")" _ type_anno:type_anno()? { Signature {
name: rc_string(name), operator: false, params, type_anno
} } /
_ "fn" _ "(" op:operator() ")" _ "(" _ params:formal_params(parser) _ ")" _ type_anno:type_anno()? { Signature {
name: rc_string(op), operator: true, params, type_anno
} }
rule formal_params(parser: &mut Parser) -> Vec<FormalParam> =

View File

@ -856,6 +856,23 @@ fn functions() {
);
}
#[test]
fn custom_operator() {
let source = "fn (!!)(lhs,rhs)";
assert_ast!(
source,
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("!!"),
operator: true,
params: vec![
FormalParam { name: rc("lhs"), default: None, anno: None },
FormalParam { name: rc("rhs"), default: None, anno: None },
],
type_anno: None
})))]
);
}
#[test]
fn max_function_params() {
let mut buf = "fn longfunc(".to_string();