mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
161 lines
3.9 KiB
Rust
161 lines
3.9 KiB
Rust
use self::BinOp::*;
|
|
use std::cmp::Ordering;
|
|
use std::fmt;
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
pub enum CalledVia {
|
|
/// Calling with space, e.g. (foo bar)
|
|
Space,
|
|
|
|
/// Calling with an operator, e.g. (bar |> foo) or (1 + 2)
|
|
BinOp(BinOp),
|
|
|
|
/// Calling with a unary operator, e.g. (!foo bar baz) or (-foo bar baz)
|
|
UnaryOp(UnaryOp),
|
|
|
|
/// This call is the result of desugaring string interpolation,
|
|
/// e.g. "\(first) \(last)" is transformed into Str.concat (Str.concat first " ") last.
|
|
StringInterpolation,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
pub enum UnaryOp {
|
|
/// (-), e.g. (-x)
|
|
Negate,
|
|
/// (!), e.g. (!x)
|
|
Not,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
pub enum BinOp {
|
|
// highest precedence
|
|
Caret,
|
|
Star,
|
|
Slash,
|
|
DoubleSlash,
|
|
Percent,
|
|
Plus,
|
|
Minus,
|
|
Equals,
|
|
NotEquals,
|
|
LessThan,
|
|
GreaterThan,
|
|
LessThanOrEq,
|
|
GreaterThanOrEq,
|
|
And,
|
|
Or,
|
|
Pizza,
|
|
Assignment,
|
|
IsAliasType,
|
|
IsOpaqueType,
|
|
Backpassing,
|
|
// lowest precedence
|
|
}
|
|
|
|
impl BinOp {
|
|
/// how wide this operator is when typed out
|
|
pub fn width(self) -> u16 {
|
|
match self {
|
|
Caret | Star | Slash | Percent | Plus | Minus | LessThan | GreaterThan => 1,
|
|
DoubleSlash | Equals | NotEquals | LessThanOrEq | GreaterThanOrEq | And | Or
|
|
| Pizza => 2,
|
|
Assignment | IsAliasType | IsOpaqueType | Backpassing => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub enum ArgSide {
|
|
Left,
|
|
Right,
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
pub enum Associativity {
|
|
/// left-associative operators:
|
|
///
|
|
/// arithmetic: * / // % + -
|
|
/// application: |>
|
|
LeftAssociative,
|
|
|
|
/// right-associative operators:
|
|
///
|
|
/// exponentiation: ^
|
|
/// boolean: && ||
|
|
/// application: <|
|
|
RightAssociative,
|
|
|
|
/// non-associative operators:
|
|
///
|
|
/// comparison: == > >= < <=
|
|
NonAssociative,
|
|
}
|
|
|
|
impl BinOp {
|
|
pub fn associativity(self) -> Associativity {
|
|
use self::Associativity::*;
|
|
|
|
match self {
|
|
Pizza | Star | Slash | DoubleSlash | Percent | Plus | Minus => LeftAssociative,
|
|
And | Or | Caret => RightAssociative,
|
|
Equals | NotEquals | LessThan | GreaterThan | LessThanOrEq | GreaterThanOrEq => {
|
|
NonAssociative
|
|
}
|
|
Assignment | IsAliasType | IsOpaqueType | Backpassing => unreachable!(),
|
|
}
|
|
}
|
|
|
|
fn precedence(self) -> u8 {
|
|
match self {
|
|
Caret => 7,
|
|
Star | Slash | DoubleSlash | Percent => 6,
|
|
Plus | Minus => 5,
|
|
Equals | NotEquals | LessThan | GreaterThan | LessThanOrEq | GreaterThanOrEq => 4,
|
|
And => 3,
|
|
Or => 2,
|
|
Pizza => 1,
|
|
Assignment | IsAliasType | IsOpaqueType | Backpassing => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PartialOrd for BinOp {
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl Ord for BinOp {
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
self.precedence().cmp(&other.precedence())
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for BinOp {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
let as_str = match self {
|
|
Caret => "^",
|
|
Star => "*",
|
|
Slash => "/",
|
|
DoubleSlash => "//",
|
|
Percent => "%",
|
|
Plus => "+",
|
|
Minus => "-",
|
|
Equals => "==",
|
|
NotEquals => "!=",
|
|
LessThan => "<",
|
|
GreaterThan => ">",
|
|
LessThanOrEq => "<=",
|
|
GreaterThanOrEq => ">=",
|
|
And => "&&",
|
|
Or => "||",
|
|
Pizza => "|>",
|
|
Assignment => "=",
|
|
IsAliasType => ":",
|
|
IsOpaqueType => ":=",
|
|
Backpassing => "<-",
|
|
};
|
|
|
|
write!(f, "{}", as_str)
|
|
}
|
|
}
|