Skip to content

Commit

Permalink
implement op
Browse files Browse the repository at this point in the history
  • Loading branch information
KeenS committed May 29, 2022
1 parent 8561ba6 commit c7ae321
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 22 deletions.
6 changes: 6 additions & 0 deletions src/ast/desugar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ impl Desugar {
D(DerivedExprKind::Seq { seq }) => self.transform_seq(span, seq),
D(DerivedExprKind::BindSeq { binds, ret }) => self.transform_bind_seq(span, binds, ret),
D(DerivedExprKind::String { value }) => self.transform_string(span, value),
D(DerivedExprKind::Op { name }) => self.transform_op(span, name),
};
UntypedCoreExpr {
ty: expr.ty,
Expand Down Expand Up @@ -469,6 +470,10 @@ impl Desugar {
.inner
}

fn transform_op(&mut self, _: Span, name: Symbol) -> UntypedCoreExprKind {
ExprKind::Symbol { name }
}

fn transform_pattern(&mut self, pattern: UntypedPattern) -> UntypedCorePattern {
use PatternKind::*;
let span = pattern.span;
Expand Down Expand Up @@ -513,6 +518,7 @@ impl Desugar {
.rfold(empty, |s, c| cons(span.clone(), s, c))
.inner
}
D(DerivedPatternKind::Op { name }) => UntypedCorePatternKind::Variable { name },
};
UntypedCorePattern::new(span, inner)
}
Expand Down
4 changes: 4 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ pub enum DerivedExprKind<Ty> {
String {
value: Vec<u32>,
},
Op {
name: Symbol,
},
}

pub type CorePattern<Ty> = Pattern<Ty, Nothing>;
Expand Down Expand Up @@ -277,6 +280,7 @@ pub enum PatternKind<Ty, DP = DerivedPatternKind> {
#[derive(Debug, Clone, PartialEq)]
pub enum DerivedPatternKind {
String { value: Vec<u32> },
Op { name: Symbol },
}

#[derive(Debug, Clone, PartialEq, Default)]
Expand Down
12 changes: 12 additions & 0 deletions src/ast/pp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,9 @@ impl<Ty: PP> PP for DerivedExprKind<Ty> {
String { value } => {
write!(w, "{:?}", value)?;
}
Op { name } => {
write!(w, "op {:indent$}", name, indent = indent)?;
}
}
Ok(())
}
Expand Down Expand Up @@ -643,6 +646,9 @@ impl<Ty: fmt::Display> fmt::Display for DerivedExprKind<Ty> {
String { value } => {
write!(f, "{:?}", value)?;
}
Op { name } => {
write!(f, "op {:indent$}", name, indent = indent)?;
}
}
Ok(())
}
Expand Down Expand Up @@ -740,6 +746,9 @@ impl PP for DerivedPatternKind {
.map(|&u| char::from_u32(u).unwrap())
.collect::<String>()
),
DerivedPatternKind::Op { name } => {
write!(w, "{}", name)
}
}
}
}
Expand All @@ -755,6 +764,9 @@ impl fmt::Display for DerivedPatternKind {
.map(|&u| char::from_u32(u).unwrap())
.collect::<String>()
),
DerivedPatternKind::Op { name } => {
write!(f, "{}", name)
}
}
}
}
Expand Down
63 changes: 41 additions & 22 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,14 @@ impl Parser {

fn decl_funbind(&self) -> impl Fn(Input) -> IResult<Input, (Symbol, Vec<UntypedPattern>)> + '_ {
move |i| {
// TODO: support infix ops
map(
tuple((
self.op_symbol_eq(),
self.space0(),
separated_list0(self.space1(), self.pattern_atmic()),
)),
|((_, name), _, pats)| (name, pats),
|((_, _, name), _, pats)| (name, pats),
)(i)
}
}
Expand Down Expand Up @@ -590,17 +591,14 @@ impl Parser {
fn expr1_sym(&self) -> impl Fn(Input) -> IResult<Input, UntypedExpr> + '_ {
move |i| {
// = is allowed to be used in expression exceptionally
map(
alt((
self.symbol(),
// perhups this is not needed
map(tag("="), |i: Input| {
let cur = current_location(&i);
(cur..cur, Symbol::new(*i.fragment()))
}),
)),
|(span, name)| Expr::new(span, ExprKind::Symbol { name }),
)(i)
map(self.op_symbol_eq(), |(span, op, name)| {
let kind = if op {
ExprKind::D(DerivedExprKind::Op { name })
} else {
ExprKind::Symbol { name }
};
Expr::new(span, kind)
})(i)
}
}

Expand Down Expand Up @@ -978,30 +976,45 @@ impl Parser {
move |i| alt((self.symbol_alphanumeric(), self.symbol_symbolic()))(i)
}

fn op_symbol_eq(&self) -> impl Fn(Input) -> IResult<Input, (Span, Symbol)> + '_ {
fn op_symbol_eq(&self) -> impl Fn(Input) -> IResult<Input, (Span, bool, Symbol)> + '_ {
move |i| alt((self.op_symbol_alphanumeric(), self.op_symbol_symbolic_eq()))(i)
}

fn op_symbol_alphanumeric(&self) -> impl Fn(Input) -> IResult<Input, (Span, Symbol)> + '_ {
fn op_symbol(&self) -> impl Fn(Input) -> IResult<Input, (Span, bool, Symbol)> + '_ {
move |i| alt((self.op_symbol_alphanumeric(), self.op_symbol_symbolic()))(i)
}

fn op_symbol_alphanumeric(
&self,
) -> impl Fn(Input) -> IResult<Input, (Span, bool, Symbol)> + '_ {
move |i| {
let start = current_location(&i);
let (i, _) = opt(tuple((tag("op"), self.space1())))(i)?;
let (i, op) = opt(tuple((tag("op"), self.space1())))(i)?;
let (i, (loc, sym)) = self.symbol_alphanumeric()(i)?;
Ok((i, (start..loc.end, sym)))
Ok((i, (start..loc.end, op.is_some(), sym)))
}
}

fn op_symbol_symbolic_eq(&self) -> impl Fn(Input) -> IResult<Input, (Span, Symbol)> + '_ {
fn op_symbol_symbolic(&self) -> impl Fn(Input) -> IResult<Input, (Span, bool, Symbol)> + '_ {
move |i| {
let start = current_location(&i);
let (i, _) = opt(tuple((tag("op"), self.space0())))(i)?;
let (i, op) = opt(tuple((tag("op"), self.space1())))(i)?;
let (i, (loc, sym)) = self.symbol_symbolic()(i)?;
Ok((i, (start..loc.end, op.is_some(), sym)))
}
}

fn op_symbol_symbolic_eq(&self) -> impl Fn(Input) -> IResult<Input, (Span, bool, Symbol)> + '_ {
move |i| {
let start = current_location(&i);
let (i, op) = opt(tuple((tag("op"), self.space0())))(i)?;
let cur = current_location(&i);
let (i, (loc, sym)) = alt((
self.symbol_symbolic(),
// FIXME: calculate correct span
value((cur..cur, Symbol::new("=")), tag("=")),
))(i)?;
Ok((i, (start..loc.end, sym)))
Ok((i, (start..loc.end, op.is_some(), sym)))
}
}

Expand Down Expand Up @@ -1205,7 +1218,8 @@ impl Parser {
E(e) => e,
App { span, f, arg } => {
let name = match convert(*f).inner {
PatternKind::Variable { name } => name,
PatternKind::Variable { name }
| PatternKind::D(DerivedPatternKind::Op { name }) => name,
_ => panic!("non symbol infix operator"),
};
let arg = convert(*arg);
Expand Down Expand Up @@ -1240,8 +1254,13 @@ impl Parser {

fn pattern_var(&self) -> impl Fn(Input) -> IResult<Input, UntypedPattern> + '_ {
move |i| {
map(self.symbol(), |(span, name)| {
Pattern::new(span, PatternKind::Variable { name })
map(self.op_symbol(), |(span, op, name)| {
let kind = if op {
PatternKind::D(DerivedPatternKind::Op { name })
} else {
PatternKind::Variable { name }
};
Pattern::new(span, kind)
})(i)
}
}
Expand Down
61 changes: 61 additions & 0 deletions tests/tests/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,67 @@ fn parse_nofix() {
)
}

#[test]
fn parse_op() {
let input = r#"infix 6 + val x = op+(1, 2)"#;
let ast = parse(input).unwrap();
assert_eq!(
ast,
AST(vec![
Declaration::D(DerivedDeclaration::Infix {
priority: Some(6),
names: vec![Symbol::new("+")],
}),
Declaration::Val {
rec: false,
pattern: Pattern {
ty: Empty {},
span: Location::new(1, 15)..Location::new(1, 16),
inner: PatternKind::Variable {
name: Symbol::new("x"),
}
},
expr: Expr {
ty: Empty {},
span: Location::new(1, 19)..Location::new(1, 28),
inner: ExprKind::App {
fun: Expr {
ty: Empty {},
span: Location::new(1, 19)..Location::new(1, 22),
inner: ExprKind::D(DerivedExprKind::Op {
name: Symbol::new("+")
})
}
.boxed(),
arg: Expr {
ty: Empty {},
span: Location::new(1, 22)..Location::new(1, 28),
inner: ExprKind::Tuple {
tuple: vec![
Expr {
ty: Empty {},
span: Location::new(1, 23)..Location::new(1, 24),
inner: ExprKind::Literal {
value: Literal::Int(1),
}
},
Expr {
ty: Empty {},
span: Location::new(1, 26)..Location::new(1, 27),
inner: ExprKind::Literal {
value: Literal::Int(2),
}
}
]
}
}
.boxed()
}
}
},
])
)
}
#[test]
fn parse_binop_space() {
let input = r#"infix 6 + val x = 1+2"#;
Expand Down

0 comments on commit c7ae321

Please sign in to comment.