Initial commit
This commit is contained in:
commit
bc9203eadc
6 changed files with 163 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
use nix
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
/.direnv/
|
||||
16
Cargo.lock
generated
Normal file
16
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "calculatey"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"type-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "type-fn"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "204df419af3d8f4e9d597266dcb61672b915d7bff2727f96ad63e53657f794f8"
|
||||
7
Cargo.toml
Normal file
7
Cargo.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "calculatey"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
type-fn = "0.1.2"
|
||||
9
shell.nix
Normal file
9
shell.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{ pkgs ? import <nixpkgs> {} }:
|
||||
pkgs.mkShell {
|
||||
nativeBuildInputs = with pkgs; [
|
||||
cargo
|
||||
helix
|
||||
rust-analyzer
|
||||
cargo-watch
|
||||
];
|
||||
}
|
||||
128
src/main.rs
Normal file
128
src/main.rs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
static mut INDENTATION: u32 = 0;
|
||||
|
||||
fn indentation() -> String {
|
||||
unsafe {
|
||||
let mut s = String::new();
|
||||
for _ in 0..INDENTATION {
|
||||
s += "| ";
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
fn indent() {
|
||||
unsafe {
|
||||
INDENTATION += 1;
|
||||
}
|
||||
}
|
||||
fn unindent() {
|
||||
unsafe {
|
||||
INDENTATION -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub type BExpr = Box<Expression>;
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum Expression {
|
||||
Num(f64),
|
||||
Var(char),
|
||||
Add(BExpr, BExpr),
|
||||
Sub(BExpr, BExpr),
|
||||
Mul(BExpr, BExpr),
|
||||
Div(BExpr, BExpr),
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn simplify(self) -> Expression {
|
||||
println!("{}Simplifying {self:?}", indentation());
|
||||
indent();
|
||||
use Expression::*;
|
||||
let r = match self {
|
||||
Num(x) => Num(x),
|
||||
Var(x) => Var(x),
|
||||
Add(a, b) => match (a.simplify(), b.simplify()) {
|
||||
(Num(a), Num(0.)) => Num(a).simplify(),
|
||||
(Num(0.), Num(a)) => Num(a).simplify(),
|
||||
(Num(a), Num(b)) => Num(a + b).simplify(),
|
||||
(a, b) if a == b => Mul(Num(2.).wrap(), a.wrap()).simplify(),
|
||||
(a, Mul(b, c)) => match (b.simplify(), c.simplify()) {
|
||||
(b, Num(c)) if a == b => Mul(Num(c + 1.).wrap(), a.wrap()).simplify(),
|
||||
(Num(b), c) if a == c => Mul(Num(b + 1.).wrap(), a.wrap()).simplify(),
|
||||
(b, c) => Add(a.wrap(), Mul(b.wrap(), c.wrap()).wrap()),
|
||||
},
|
||||
(Mul(b, c), a) => match (b.simplify(), c.simplify()) {
|
||||
(b, Num(c)) if a == b => Mul(Num(c + 1.).wrap(), a.wrap()).simplify(),
|
||||
(Num(b), c) if a == c => Mul(Num(b + 1.).wrap(), a.wrap()).simplify(),
|
||||
(b, c) => Add(a.wrap(), Mul(b.wrap(), c.wrap()).wrap()),
|
||||
},
|
||||
(a, b) => Add(a.wrap(), b.wrap()),
|
||||
},
|
||||
Sub(a, b) => match (a.simplify(), b.simplify()) {
|
||||
(a, b) if a == b => Num(0.),
|
||||
(a, b) => Sub(a.wrap(), b.wrap()),
|
||||
},
|
||||
Mul(a, b) => match (a.simplify(), b.simplify()) {
|
||||
(Num(a), Num(b)) => Num(a * b),
|
||||
(Num(0.), b) => Num(0.),
|
||||
(a, Num(0.)) => Num(0.),
|
||||
(Num(1.), b) => b,
|
||||
(a, Num(1.)) => a,
|
||||
(a, b) => Mul(a.wrap(), b.wrap()),
|
||||
},
|
||||
Div(a, b) => match (a.simplify(), b.simplify()) {
|
||||
(a, Num(1.)) => a,
|
||||
(Num(0.), b) => Num(0.),
|
||||
(a, b) => Div(a.wrap(), b.wrap()),
|
||||
},
|
||||
};
|
||||
unindent();
|
||||
println!("{} => {r:?}", indentation());
|
||||
r
|
||||
}
|
||||
|
||||
pub fn wrap(self) -> Box<Self> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Expression {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
use Expression::*;
|
||||
match self {
|
||||
Num(x) => f.write_fmt(format_args!("{x}")),
|
||||
Var(x) => f.write_fmt(format_args!("{x}")),
|
||||
Add(a, b) => f.write_fmt(format_args!("({a} + {b})")),
|
||||
Sub(a, b) => f.write_fmt(format_args!("({a} - {b})")),
|
||||
Mul(a, b) => f.write_fmt(format_args!("{a} {b}")),
|
||||
Div(a, b) => f.write_fmt(format_args!("({a} / {b})")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use Expression::*;
|
||||
println!(
|
||||
"{}",
|
||||
// 5 * (((5 * 5) + 1) + ((a + (a + a)) + a))
|
||||
Mul(
|
||||
Num(5.).wrap(),
|
||||
Add(
|
||||
Add(Mul(Num(5.).wrap(), Num(5.).wrap()).wrap(), Num(1.).wrap()).wrap(),
|
||||
Add(
|
||||
Add(
|
||||
Var('a').wrap(),
|
||||
Add(Var('a').wrap(), Var('a').wrap()).wrap()
|
||||
)
|
||||
.wrap(),
|
||||
Var('a').wrap(),
|
||||
)
|
||||
.wrap()
|
||||
)
|
||||
.wrap()
|
||||
)
|
||||
.simplify()
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue