Added --debug flag, eval returns Result
This commit is contained in:
parent
55e7ef0a04
commit
5830904a45
@ -1,8 +1,11 @@
|
||||
[package]
|
||||
name = "cpc"
|
||||
version = "0.1.0"
|
||||
authors = ["Kasper <kasperkh.kh@gmail.com>"]
|
||||
description = "evaluates math expressions, with support for units and conversion between units"
|
||||
readme = 'README.md'
|
||||
authors = ["Kasper Henningsen"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/probablykasper/cpc"
|
||||
|
||||
[dependencies]
|
||||
decimal = "2.0.4"
|
||||
|
||||
30
README.md
30
README.md
@ -3,6 +3,23 @@ calculation + conversion
|
||||
|
||||
cpc parses and evaluates strings of math, with support for units and conversion. 128-bit decimal floating points are used for high accuracy.
|
||||
|
||||
cpc lets you mix units, so for example `1 km - 1m` results in `Number { value: 999, unit: Meter }`.
|
||||
|
||||
## Usage
|
||||
```rs
|
||||
use cpc::{eval, Unit::*}
|
||||
|
||||
match eval("3m + 1cm", true, Celcius) {
|
||||
Ok(answer) => {
|
||||
// answer: Number { value: 301, unit: Unit::cm }
|
||||
println!("Evaluated value: {} {:?}", answer.value, answer.unit)
|
||||
},
|
||||
Err(e) => {
|
||||
println!(e)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
```
|
||||
3 + 4 * 2
|
||||
@ -20,7 +37,6 @@ cpc parses and evaluates strings of math, with support for units and conversion.
|
||||
round(sqrt(2)^4)! liters
|
||||
|
||||
10% of abs(sin(pi)) horsepower to watts
|
||||
|
||||
```
|
||||
|
||||
## Supported unit types
|
||||
@ -41,7 +57,10 @@ round(sqrt(2)^4)! liters
|
||||
cpc Uses 128-bit Decimal Floating Point (d128) numbers instead of Binary Coded Decimals for better accuracy. The result cpc gives will still not always be 100% accurate. I would recommend rounding the result to 20 decimals or less.
|
||||
|
||||
## Performance
|
||||
In my case, I can expect `eval()` to take 100-200ms, and this scales pretty alright. However, putting numbers with a lot of digits into functions result in pretty poor performance. `log(e)` is one of the worst, and takes 500ms.
|
||||
In my case, I can expect `eval()` to take 100-200ms, and this scales pretty alright. However, putting numbers with a lot of digits into functions result in pretty poor performance. `log(e)` is one of the worst, and takes 500ms for me.
|
||||
|
||||
## Errors
|
||||
cpc returns `Result`s with basic strings as errors. Just to be safe, you may want to handle panics (You can do that using `std::panic::catch_unwind`).
|
||||
|
||||
# Dev Instructions
|
||||
|
||||
@ -54,6 +73,11 @@ Run cpc with a CLI argument as input:
|
||||
cargo run -- '100ms to s'
|
||||
```
|
||||
|
||||
Run with debugging, which shows some extra logs:
|
||||
```
|
||||
cargo run -- '100ms to s' --debug
|
||||
```
|
||||
|
||||
Run tests:
|
||||
```
|
||||
cargo test
|
||||
@ -99,7 +123,7 @@ match string {
|
||||
// ...
|
||||
```
|
||||
|
||||
# Potential Improvements
|
||||
## Potential Improvements
|
||||
### General
|
||||
- Support for math in `6'4"` syntax, like `3'+2'4"`. Currently needs to be written like `3'+3'+4"`
|
||||
- The functions in units.rs have a lot of manual if statements. This could probably be replaced with a pretty advanced macro.
|
||||
|
||||
39
src/main.rs
39
src/main.rs
@ -91,14 +91,27 @@ mod lookup;
|
||||
fn main() {
|
||||
use std::env;
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let mut debug = false;
|
||||
if args.iter().any(|i| i=="--debug") {
|
||||
debug = true;
|
||||
}
|
||||
if args.len() >= 2 {
|
||||
eval(&args[1], true, Unit::Celcius);
|
||||
match eval(&args[1], true, Unit::Celcius, debug) {
|
||||
Ok(answer) => {
|
||||
if !debug {
|
||||
println!("Evaluated value: {} {:?}", answer.value, answer.unit)
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
println!("{}", e)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
println!("No argument supplied");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval(input: &str, allow_trailing_operators: bool, default_degree: Unit) {
|
||||
pub fn eval(input: &str, allow_trailing_operators: bool, default_degree: Unit, debug: bool) -> Result<units::Number, String> {
|
||||
|
||||
let lex_start = Instant::now();
|
||||
|
||||
@ -116,24 +129,26 @@ pub fn eval(input: &str, allow_trailing_operators: bool, default_degree: Unit) {
|
||||
Ok(answer) => {
|
||||
let eval_time = Instant::now().duration_since(eval_start).as_nanos() as f32;
|
||||
|
||||
println!("Lexed TokenVector: {:?}", tokens);
|
||||
println!("Parsed AstNode: {:#?}", ast);
|
||||
if debug == true {
|
||||
println!("Lexed TokenVector: {:?}", tokens);
|
||||
println!("Parsed AstNode: {:#?}", ast);
|
||||
println!("Evaluated value: {} {:?}", answer.value, answer.unit);
|
||||
println!("\u{23f1} {:.3}ms lexing", lex_time/1000.0/1000.0);
|
||||
println!("\u{23f1} {:.3}ms parsing", parse_time/1000.0/1000.0);
|
||||
println!("\u{23f1} {:.3}ms evaluation", eval_time/1000.0/1000.0);
|
||||
}
|
||||
|
||||
println!("Evaluated value: {} {:?}", answer.value, answer.unit);
|
||||
|
||||
println!("\u{23f1} {:.3}ms lexing", lex_time/1000.0/1000.0);
|
||||
println!("\u{23f1} {:.3}ms parsing", parse_time/1000.0/1000.0);
|
||||
println!("\u{23f1} {:.3}ms evaluation", eval_time/1000.0/1000.0);
|
||||
return Ok(answer)
|
||||
},
|
||||
Err(e) => println!("Eval error: {}", e),
|
||||
Err(e) => Err(format!("Eval error: {}", e)),
|
||||
}
|
||||
|
||||
},
|
||||
Err(e) => println!("Parsing error: {}", e),
|
||||
Err(e) => Err(format!("Parsing error: {}", e)),
|
||||
}
|
||||
|
||||
},
|
||||
Err(e) => println!("Lexing error: {}", e),
|
||||
Err(e) => Err(format!("Lexing error: {}", e)),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user