Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions starstream_compiler/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,13 @@ pub enum Expr {
NotEquals(Box<Self>, Box<Self>),
/// `a < b`
LessThan(Box<Self>, Box<Self>),
// TODO: GreaterThan, LessEq, GreaterEq
/// `a > b`
GreaterThan(Box<Self>, Box<Self>),
/// `a <= b`
LessEq(Box<Self>, Box<Self>),
/// `a >= b`
GreaterEq(Box<Self>, Box<Self>),
// Arithmetic operators
/// `-a`
Neg(Box<Self>),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason to drop Neg? Wasm has a floating-point neg instruction, and integer neg is easy to implement as ~x + 1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly because it was previously ~, and when I changed that I removed it. But it probably makes sense to keep it I guess.

So I added it back. I'm not really sure how much people actually use the unary negation in general though.

/// `a + b`
Add(Box<Self>, Box<Self>),
/// `a - b`
Expand All @@ -180,13 +183,26 @@ pub enum Expr {
Mul(Box<Self>, Box<Self>),
/// `a / b`
Div(Box<Self>, Box<Self>),
/// `a ** b`
Pow(Box<Self>, Box<Self>),
// TODO: Mod
/// `a % b`
Mod(Box<Self>, Box<Self>),
/// `-a`
Neg(Box<Self>),
// Bitwise operators
// TODO: BitNot, BitAnd, BitOr, BitXor, LShift, RShift
/// `~a`
BitNot(Box<Self>),
/// `a & b`
BitAnd(Box<Self>, Box<Self>),
/// `a | b`
BitOr(Box<Self>, Box<Self>),
/// `a ^ b`
BitXor(Box<Self>, Box<Self>),
/// `a << b`
LShift(Box<Self>, Box<Expr>),
/// `a >> b`
RShift(Box<Self>, Box<Expr>),
// Boolean operators
// TODO: Not
/// `!a`
Not(Box<Self>),
/// `a && b`
And(Box<Self>, Box<Self>),
/// `a || b`
Expand Down
73 changes: 55 additions & 18 deletions starstream_compiler/src/parser/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::ast::*;
use ariadne::{Color, Label, Report, ReportKind};
use chumsky::{
pratt::{infix, left, prefix, right},
pratt::{infix, left, prefix},
prelude::*,
};

Expand Down Expand Up @@ -324,7 +324,7 @@ fn optionally_typed_bindings<'a>(
fn expr<'a>(
block_parser: impl Parser<'a, &'a str, Block, extra::Err<Rich<'a, char>>> + Clone + 'a,
) -> impl Parser<'a, &'a str, Expr, extra::Err<Rich<'a, char>>> {
let op = |c| just(c).padded();
let op = |c: &'static str| just(c).padded();

recursive(|expr_parser| {
let function_call = expr_parser
Expand Down Expand Up @@ -358,37 +358,74 @@ fn expr<'a>(
.or(block_expr(expr_parser, block_parser).map(Expr::BlockExpr));

atom.pratt((
prefix(4, op('!'), |_, atom, _| Expr::Neg(Box::new(atom))),
infix(right(3), op('^'), |l, _, r, _| {
Expr::Pow(Box::new(l), Box::new(r))
}),
infix(left(2), op('*'), |l, _, r, _| {
// prec = 10
prefix(10, op("-"), |_, atom, _| Expr::Neg(Box::new(atom))),
prefix(10, op("!"), |_, atom, _| Expr::Not(Box::new(atom))),
prefix(10, op("~"), |_, atom, _| Expr::BitNot(Box::new(atom))),
// prec = 9
infix(left(9), op("*"), |l, _, r, _| {
Expr::Mul(Box::new(l), Box::new(r))
}),
infix(left(2), just("&&").padded(), |l, _, r, _| {
Expr::And(Box::new(l), Box::new(r))
infix(left(9), op("/"), |l, _, r, _| {
Expr::Div(Box::new(l), Box::new(r))
}),
infix(left(2), op('/'), |l, _, r, _| {
infix(left(9), op("%"), |l, _, r, _| {
Expr::Div(Box::new(l), Box::new(r))
}),
infix(left(1), op('+'), |l, _, r, _| {
// prec = 8
infix(left(8), op("+"), |l, _, r, _| {
Expr::Add(Box::new(l), Box::new(r))
}),
infix(left(1), just("||").padded(), |l, _, r, _| {
Expr::Or(Box::new(l), Box::new(r))
}),
infix(left(1), op('-'), |l, _, r, _| {
infix(left(8), op("-"), |l, _, r, _| {
Expr::Sub(Box::new(l), Box::new(r))
}),
infix(left(1), op('<'), |l, _, r, _| {
// prec = 7
infix(left(7), op("<<"), |l, _, r, _| {
Expr::LShift(Box::new(l), Box::new(r))
}),
infix(left(7), op(">>"), |l, _, r, _| {
Expr::RShift(Box::new(l), Box::new(r))
}),
// prec = 6
infix(left(6), op("<"), |l, _, r, _| {
Expr::LessThan(Box::new(l), Box::new(r))
}),
infix(left(6), op(">"), |l, _, r, _| {
Expr::GreaterThan(Box::new(l), Box::new(r))
}),
infix(left(6), op("<="), |l, _, r, _| {
Expr::LessEq(Box::new(l), Box::new(r))
}),
infix(left(6), op(">="), |l, _, r, _| {
Expr::LessThan(Box::new(l), Box::new(r))
}),
infix(left(1), just("==").padded(), |l, _, r, _| {
// prec = 5
infix(left(5), op("=="), |l, _, r, _| {
Expr::Equals(Box::new(l), Box::new(r))
}),
infix(left(1), just("!=").padded(), |l, _, r, _| {
infix(left(5), op("!="), |l, _, r, _| {
Expr::NotEquals(Box::new(l), Box::new(r))
}),
// prec = 4
infix(left(4), op("&"), |l, _, r, _| {
Expr::BitAnd(Box::new(l), Box::new(r))
}),
// prec = 3
infix(left(3), op("^"), |l, _, r, _| {
Expr::BitXor(Box::new(l), Box::new(r))
}),
// prec = 2
infix(left(2), op("|"), |l, _, r, _| {
Expr::BitOr(Box::new(l), Box::new(r))
}),
// prec = 1
infix(left(1), op("&&"), |l, _, r, _| {
Expr::And(Box::new(l), Box::new(r))
}),
// prec = 0
infix(left(0), just("||").padded(), |l, _, r, _| {
Expr::Or(Box::new(l), Box::new(r))
}),
))
.boxed()
})
Expand Down