expressions/
expressions.rs1use orx_imp_vec::*;
2use std::{
3 fmt::Display,
4 ops::{Add, Sub},
5};
6
7#[derive(Default)]
9struct Scope<'a> {
10 expressions: ImpVec<Expr<'a>>,
11}
12
13impl<'a> Scope<'a> {
14 fn symbol(&'a self, name: &'static str) -> ExprInScope<'a> {
16 let expr = Expr::Symbol(name);
17 self.expressions.imp_push(expr);
18 ExprInScope {
19 scope: self,
20 expr: &self.expressions[self.expressions.len() - 1],
21 }
22 }
23}
24
25enum Expr<'a> {
27 Symbol(&'static str),
28 Addition(&'a Expr<'a>, &'a Expr<'a>),
29 Subtraction(&'a Expr<'a>, &'a Expr<'a>),
30}
31
32impl<'a> Display for Expr<'a> {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 match self {
35 Expr::Symbol(x) => write!(f, "{}", x),
36 Expr::Addition(x, y) => write!(f, "{} + {}", x, y),
37 Expr::Subtraction(x, y) => write!(f, "{} - {}", x, y),
38 }
39 }
40}
41
42#[derive(Clone, Copy)]
48struct ExprInScope<'a> {
49 scope: &'a Scope<'a>,
50 expr: &'a Expr<'a>,
51}
52
53impl<'a> ExprInScope<'a> {
54 fn belongs_to_same_scope(&self, other: Self) -> bool {
57 let self_scope = self.scope as *const Scope;
58 let other_scope = other.scope as *const Scope;
59 self_scope == other_scope
60 }
61}
62impl<'a> Display for ExprInScope<'a> {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 write!(f, "{}", self.expr)
65 }
66}
67
68impl<'a> Add for ExprInScope<'a> {
69 type Output = ExprInScope<'a>;
70
71 fn add(self, rhs: Self) -> Self::Output {
82 assert!(self.belongs_to_same_scope(rhs));
83 let expressions = &self.scope.expressions;
84 let expr = Expr::Addition(self.expr, rhs.expr);
85 expressions.imp_push(expr);
86 ExprInScope {
87 scope: self.scope,
88 expr: &expressions[expressions.len() - 1],
89 }
90 }
91}
92
93impl<'a> Sub for ExprInScope<'a> {
94 type Output = ExprInScope<'a>;
95
96 fn sub(self, rhs: Self) -> Self::Output {
107 assert!(self.belongs_to_same_scope(rhs));
108 let expressions = &self.scope.expressions;
109 let expr = Expr::Subtraction(self.expr, rhs.expr);
110 expressions.imp_push(expr);
111 ExprInScope {
112 scope: self.scope,
113 expr: &expressions[expressions.len() - 1],
114 }
115 }
116}
117
118fn main() {
119 let scope = Scope::default();
120
121 let x = scope.symbol("x");
123 let y = scope.symbol("y");
124 assert_eq!(&x.to_string(), "x");
125 assert_eq!(&y.to_string(), "y");
126
127 let p = x + y;
129 assert_eq!(&p.to_string(), "x + y");
130
131 let q = x - y;
132 assert_eq!(&q.to_string(), "x - y");
133
134 let t = p + q;
136 assert_eq!(&t.to_string(), "x + y + x - y");
137
138 let all_expressions: Vec<_> = scope.expressions.iter().map(|x| x.to_string()).collect();
141 assert_eq!(
142 all_expressions,
143 ["x", "y", "x + y", "x - y", "x + y + x - y"]
144 );
145}