1mod cli;
2mod error;
3pub mod num;
4mod parser;
5mod value;
6
7pub use self::cli::CliVariable;
8pub use self::error::*;
9pub use self::num::{FormatSpecifier, Number, NumberFormat, ParseNumberError};
10pub use self::value::{Value, ValueType};
11
12use litcheck::variables;
13
14use crate::common::*;
15
16pub type VariableName = variables::VariableName<Symbol>;
17pub type Variable<'a> = variables::Variable<Symbol, Value<'a>>;
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub(crate) struct Var<'a> {
21 pub name: VariableName,
22 pub value: Value<'a>,
23}
24
25#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
26pub struct TypedVariable {
27 pub name: VariableName,
28 pub ty: ValueType,
29}
30
31#[derive(Debug, Clone)]
32pub enum Expr {
33 Num(Number),
34 Var(VariableName),
35 Binary {
36 span: SourceSpan,
37 op: BinaryOp,
38 lhs: Box<Expr>,
39 rhs: Box<Expr>,
40 },
41}
42impl Spanned for Expr {
43 fn span(&self) -> SourceSpan {
44 match self {
45 Self::Num(spanned) => spanned.span(),
46 Self::Var(spanned) => spanned.span(),
47 Self::Binary { span, .. } => *span,
48 }
49 }
50}
51impl Expr {
52 pub fn from_call(
53 interner: &mut StringInterner,
54 span: SourceSpan,
55 callee: Span<Symbol>,
56 mut args: Vec<Expr>,
57 ) -> Result<Self, InvalidCallExprError> {
58 match args.len() {
59 2 => {
60 let op = match interner.resolve(callee.into_inner()) {
61 "add" => BinaryOp::Add,
62 "sub" => BinaryOp::Sub,
63 "mul" => BinaryOp::Mul,
64 "div" => BinaryOp::Div,
65 "min" => BinaryOp::Min,
66 "max" => BinaryOp::Max,
67 callee => {
68 return Err(InvalidCallExprError::Undefined {
69 span,
70 callee: callee.to_string(),
71 })
72 }
73 };
74 let rhs = Box::new(args.pop().unwrap());
75 let lhs = Box::new(args.pop().unwrap());
76 Ok(Self::Binary { span, op, lhs, rhs })
77 }
78 arity => match interner.resolve(*callee) {
79 callee @ ("add" | "sub" | "mul" | "div" | "min" | "max") => {
80 Err(InvalidCallExprError::InvalidArity {
81 span,
82 callee: callee.to_string(),
83 expected: 2,
84 given: arity as u8,
85 })
86 }
87 callee => Err(InvalidCallExprError::Undefined {
88 span,
89 callee: callee.to_string(),
90 }),
91 },
92 }
93 }
94}
95impl Eq for Expr {}
96impl PartialEq for Expr {
97 fn eq(&self, other: &Self) -> bool {
98 match (self, other) {
99 (Self::Num(a), Self::Num(b)) => a == b,
100 (Self::Var(a), Self::Var(b)) => a == b,
101 (
102 Self::Binary {
103 op: aop,
104 lhs: al,
105 rhs: ar,
106 ..
107 },
108 Self::Binary {
109 op: bop,
110 lhs: bl,
111 rhs: br,
112 ..
113 },
114 ) => aop == bop && al == bl && ar == br,
115 _ => false,
116 }
117 }
118}
119impl PartialOrd for Expr {
120 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
121 Some(self.cmp(other))
122 }
123}
124impl Ord for Expr {
125 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
126 use core::cmp::Ordering;
127 match (self, other) {
128 (Self::Num(l), Self::Num(r)) => l.cmp(r),
129 (Self::Num(_), _) => Ordering::Less,
130 (_, Self::Num(_)) => Ordering::Greater,
131 (Self::Var(l), Self::Var(r)) => l.cmp(r),
132 (Self::Var(_), _) => Ordering::Less,
133 (_, Self::Var(_)) => Ordering::Greater,
134 (
135 Self::Binary {
136 op: lop,
137 lhs: ll,
138 rhs: lr,
139 ..
140 },
141 Self::Binary {
142 op: rop,
143 lhs: rl,
144 rhs: rr,
145 ..
146 },
147 ) => lop
148 .cmp(rop)
149 .then_with(|| ll.cmp(rl))
150 .then_with(|| lr.cmp(rr)),
151 }
152 }
153}
154
155#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
156pub enum BinaryOp {
157 Eq,
158 Add,
159 Sub,
160 Mul,
161 Div,
162 Min,
163 Max,
164}