Initial commit

This commit is contained in:
Tove 2025-01-10 21:36:26 +01:00
commit bc9203eadc
Signed by: TudbuT
GPG key ID: B3CF345217F202D3
6 changed files with 163 additions and 0 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use nix

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
/.direnv/

16
Cargo.lock generated Normal file
View 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
View 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
View 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
View 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()
);
}