mirror of https://github.com/rm-dr/daisy
Added constant generation
parent
86a3f506ba
commit
9fdabb80d3
1
TODO.md
1
TODO.md
|
@ -60,7 +60,6 @@
|
|||
- Show base units on error
|
||||
|
||||
## Units
|
||||
- Abbreviations: kWh, bps, fps, dot/in, px/in, parts-per-x(ppm, ppb, ppt, ppq), percent(pct)
|
||||
- Selective prefixes: tonne (k M G), Byte (TiB, etc), calorie (kcal)
|
||||
- Print units with powers instead of /
|
||||
- HMS for degrees
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
use std::io::Write;
|
||||
use std::fs::OpenOptions;
|
||||
use std::path::Path;
|
||||
use toml::Table;
|
||||
|
||||
|
||||
|
||||
pub fn write(target: &Path) {
|
||||
let constants = include_str!("constants.toml").parse::<Table>().unwrap();
|
||||
let toml::Value::Array(constants) = &constants["constant"] else {panic!()};
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(target)
|
||||
.unwrap();
|
||||
|
||||
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"#[derive(Debug)]\n",
|
||||
"#[derive(Copy, Clone)]\n",
|
||||
"pub enum Constant {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for c in constants {
|
||||
writeln!(file,
|
||||
"\t{},",
|
||||
c["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "}}\n").unwrap();
|
||||
|
||||
// ToString
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"impl ToString for Constant {{\n",
|
||||
"\tfn to_string(&self) -> String {{\n",
|
||||
"\t\tString::from(match self {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for c in constants {
|
||||
if c["strings"].is_array() {
|
||||
writeln!(file,
|
||||
"\t\t\tConstant::{e} => \"{s}\",",
|
||||
e = c["enum_name"].as_str().unwrap(),
|
||||
s = c["strings"].as_array().unwrap()[0].as_str().unwrap()
|
||||
).unwrap();
|
||||
} else {
|
||||
writeln!(file,
|
||||
"\t\t\tConstant::{e} => \"{s}\",",
|
||||
e = c["enum_name"].as_str().unwrap(),
|
||||
s = c["strings"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t}})\n\t}}\n}}\n").unwrap();
|
||||
|
||||
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"impl Constant {{\n",
|
||||
"\tpub fn from_string(s: &str) -> Option<Constant> {{\n",
|
||||
"\t\tmatch s {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for c in constants {
|
||||
if c["strings"].is_array() {
|
||||
for s in c["strings"].as_array().unwrap() {
|
||||
writeln!(file,
|
||||
"\t\t\t\"{s}\" => Some(Constant::{e}),",
|
||||
e = c["enum_name"].as_str().unwrap(),
|
||||
s = s.as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
} else {
|
||||
writeln!(file,
|
||||
"\t\t\t\"{s}\" => Some(Constant::{e}),",
|
||||
e = c["enum_name"].as_str().unwrap(),
|
||||
s = c["strings"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t\t_ => None\n\t\t}}\n\t}}\n").unwrap();
|
||||
|
||||
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"\tpub fn value(&self) -> Token {{\n",
|
||||
"\t\tmatch self {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for c in constants {
|
||||
writeln!(file,
|
||||
"\t\t\tConstant::{e} => parse(&String::from(\"{s}\")).unwrap(),",
|
||||
e = c["enum_name"].as_str().unwrap(),
|
||||
s = c["value"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t}}\n\t}}\n}}").unwrap();
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
[[constant]]
|
||||
enum_name = "Pi"
|
||||
strings = ["π", "pi"]
|
||||
value = "3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067"
|
||||
|
||||
[[constant]]
|
||||
enum_name = "Phi"
|
||||
strings = ["φ", "phi"]
|
||||
value = "1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137"
|
||||
|
||||
[[constant]]
|
||||
enum_name = "Euler"
|
||||
strings = "e"
|
||||
value = "2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427"
|
||||
|
||||
[[constant]]
|
||||
enum_name = "MPG"
|
||||
strings = "mpg"
|
||||
value = "mile/gallon"
|
||||
unit = true
|
||||
|
||||
|
||||
[[constant]]
|
||||
enum_name = "MPH"
|
||||
strings = "mph"
|
||||
value = "mile/hour"
|
||||
unit = true
|
||||
|
||||
[[constant]]
|
||||
enum_name = "DPI"
|
||||
strings = "dpi"
|
||||
value = "dot/inch"
|
||||
unit = true
|
||||
|
||||
[[constant]]
|
||||
enum_name = "PPI"
|
||||
strings = "ppi"
|
||||
value = "pixel/inch"
|
||||
unit = true
|
||||
|
||||
[[constant]]
|
||||
enum_name = "FPS"
|
||||
strings = "fps"
|
||||
value = "frame/second"
|
||||
unit = true
|
||||
|
||||
[[constant]]
|
||||
enum_name = "PCT"
|
||||
strings = "pct"
|
||||
value = "0.01"
|
||||
unit = true
|
||||
|
||||
[[constant]]
|
||||
enum_name = "PPM"
|
||||
strings = "ppm"
|
||||
value = "1e-6"
|
||||
unit = true
|
||||
|
||||
[[constant]]
|
||||
enum_name = "PPB"
|
||||
strings = "ppb"
|
||||
value = "1e-9"
|
||||
unit = true
|
||||
|
||||
[[constant]]
|
||||
enum_name = "PPT"
|
||||
strings = "ppt"
|
||||
value = "1e-12"
|
||||
unit = true
|
||||
|
||||
[[constant]]
|
||||
enum_name = "PPQ"
|
||||
strings = "ppq"
|
||||
value = "1e-15"
|
||||
unit = true
|
|
@ -1,278 +1,21 @@
|
|||
use std::env;
|
||||
use std::io::Write;
|
||||
use std::fs::OpenOptions;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use toml::Table;
|
||||
use toml::Value;
|
||||
|
||||
|
||||
|
||||
|
||||
/// Create WholeUnit enum with
|
||||
/// basic impls. Should only be run once.
|
||||
fn write_wholeunit_main(mut file: &File, units: &Vec<Value>) {
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"#[derive(Hash)]\n",
|
||||
"#[derive(Debug)]\n",
|
||||
"#[derive(Copy, Clone)]\n",
|
||||
"#[derive(Eq, PartialEq)]\n",
|
||||
"pub enum WholeUnit {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
writeln!(file,
|
||||
"\t{},",
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "}}\n").unwrap();
|
||||
|
||||
// ToString
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"impl ToString for WholeUnit {{\n",
|
||||
"\tfn to_string(&self) -> String {{\n",
|
||||
"\t\tString::from(match self {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
writeln!(file,
|
||||
"\t\t\tWholeUnit::{e} => \"{s}\",",
|
||||
s = u["print"].as_str().unwrap(),
|
||||
e = u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t}})\n\t}}\n}}\n").unwrap();
|
||||
|
||||
|
||||
// Properties
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"impl WholeUnit {{\n",
|
||||
"\tfn no_space(&self) -> bool {{\n",
|
||||
"\t\tmatch self {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
if u.as_table().unwrap().contains_key("no_space") {
|
||||
if u.as_table().unwrap()["no_space"].as_bool().unwrap() {
|
||||
writeln!(file,
|
||||
"\t\t\tWholeUnit::{} => true,",
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t\t_ => false\n\t\t}}\n\t}}\n}}").unwrap();
|
||||
}
|
||||
|
||||
|
||||
/// Create WholeUnit::base_factor().
|
||||
/// Should only be run once.
|
||||
fn write_wholeunit_base_factor(mut file: &File, units: &Vec<Value>) {
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"impl WholeUnit {{\n",
|
||||
"\tfn base_factor(&self) -> Option<Quantity> {{\n",
|
||||
"\t\tmatch self {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
|
||||
|
||||
if { // Base units should return None
|
||||
u.as_table().unwrap().contains_key("base") &&
|
||||
u["base"].as_bool().unwrap()
|
||||
} {
|
||||
writeln!(file,
|
||||
"\t\t\tWholeUnit::{} => None,",
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
writeln!(file,
|
||||
"\t\t\tWholeUnit::{} => Some(Quantity{{",
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
|
||||
match u["base_value_type"].as_str().unwrap() {
|
||||
"exact" => {
|
||||
writeln!(file,
|
||||
"\t\t\t\tscalar: Scalar::new_rational_from_string(\"{}\").unwrap(),",
|
||||
u["base_value"].as_str().unwrap(),
|
||||
).unwrap();
|
||||
},
|
||||
|
||||
"fract" => {
|
||||
writeln!(file,
|
||||
"\t\t\t\tscalar: Scalar::new_rational_from_frac({}, {}).unwrap(),",
|
||||
u["base_value"].as_array().unwrap()[0].as_integer().unwrap(),
|
||||
u["base_value"].as_array().unwrap()[1].as_integer().unwrap(),
|
||||
).unwrap();
|
||||
},
|
||||
|
||||
"approx" => {
|
||||
writeln!(file,
|
||||
"\t\t\t\tscalar: Scalar::new_float_from_string(\"{}\").unwrap(),",
|
||||
u["base_value"].as_str().unwrap(),
|
||||
).unwrap();
|
||||
},
|
||||
|
||||
_ => panic!()
|
||||
};
|
||||
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"\t\t\t\tunit: Unit::from_array(&[\n",
|
||||
"\t\t\t\t\t(FreeUnit{{whole: WholeUnit::{}, prefix: Prefix::None}}, Scalar::new_rational(-1f64).unwrap()),",
|
||||
),
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
|
||||
for b in u["base_units"].as_array().unwrap() {
|
||||
writeln!(file,
|
||||
"\t\t\t\t\t(FreeUnit{{whole: WholeUnit::{u}, prefix: Prefix::None}}, Scalar::new_rational({p}f64).unwrap()),",
|
||||
u = b.as_table().unwrap()["u"].as_str().unwrap(),
|
||||
p = b.as_table().unwrap()["p"].as_integer().unwrap(),
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"\t\t\t\t])\n",
|
||||
"\t\t\t}}),"
|
||||
),
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t}}\n\t}}\n}}").unwrap();
|
||||
}
|
||||
|
||||
|
||||
/// Write all SI prefixes.
|
||||
/// Used inside freeunit_from_string().
|
||||
fn prefix_si(mut file: &File, enum_name: &str, s: &str) {
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"\t\t", "\"{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::None}}),\n",
|
||||
"\t\t", "\"Q{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Quetta}}),\n",
|
||||
"\t\t", "\"R{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Ronna}}),\n",
|
||||
"\t\t", "\"Y{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Yotta}}),\n",
|
||||
"\t\t", "\"Z{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Zetta}}),\n",
|
||||
"\t\t", "\"E{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Exa}}),\n",
|
||||
"\t\t", "\"P{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Peta}}),\n",
|
||||
"\t\t", "\"T{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Tera}}),\n",
|
||||
"\t\t", "\"G{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Giga}}),\n",
|
||||
"\t\t", "\"M{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Mega}}),\n",
|
||||
"\t\t", "\"k{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Kilo}}),\n",
|
||||
"\t\t", "\"h{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Hecto}}),\n",
|
||||
"\t\t", "\"da{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Deka}}),\n",
|
||||
"\t\t", "\"d{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Deci}}),\n",
|
||||
"\t\t", "\"c{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Centi}}),\n",
|
||||
"\t\t", "\"m{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Milli}}),\n",
|
||||
"\t\t", "\"u{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Micro}}),\n",
|
||||
"\t\t", "\"n{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Nano}}),\n",
|
||||
"\t\t", "\"p{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Pico}}),\n",
|
||||
"\t\t", "\"f{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Femto}}),\n",
|
||||
"\t\t", "\"a{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Atto}}),\n",
|
||||
"\t\t", "\"z{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Zepto}}),\n",
|
||||
"\t\t", "\"y{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Yocto}}),\n",
|
||||
"\t\t", "\"r{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Ronto}}),\n",
|
||||
"\t\t", "\"q{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Quecto}}),",
|
||||
),
|
||||
e = enum_name,
|
||||
s = s
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
|
||||
/// Create freeunit_from_string().
|
||||
/// Should only be run once.
|
||||
fn write_freeunit_from_string(mut file: &File, units: &Vec<Value>) {
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"#[inline(always)]\n",
|
||||
"fn freeunit_from_string(s: &str) -> Option<FreeUnit> {{\n",
|
||||
"\tmatch s {{"
|
||||
),
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
if u.as_table().unwrap().contains_key("parse") {
|
||||
for s in u["parse"].as_array().unwrap() {
|
||||
writeln!(file,
|
||||
"\t\t\"{}\" => Some(FreeUnit{{whole: WholeUnit::{}, prefix: Prefix::None}}),",
|
||||
s.as_str().unwrap(),
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if u.as_table().unwrap().contains_key("parse_with_prefix") {
|
||||
if u.as_table().unwrap()["parse_with_prefix"].is_array() {
|
||||
for p in u["parse_with_prefix"].as_array().unwrap() {
|
||||
prefix_si(
|
||||
&file,
|
||||
u["enum_name"].as_str().unwrap(),
|
||||
p.as_str().unwrap()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
prefix_si(
|
||||
&file,
|
||||
u["enum_name"].as_str().unwrap(),
|
||||
u["parse_with_prefix"].as_str().unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(file, "").unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t_ => None\n\t}}\n}}").unwrap();
|
||||
}
|
||||
|
||||
|
||||
mod units;
|
||||
mod constants;
|
||||
|
||||
|
||||
fn main() -> Result<(), ()>{
|
||||
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let dest_path = Path::new(&out_dir).join("units.rs");
|
||||
println!("cargo:rerun-if-changed=buildscript/build.rs");
|
||||
println!("cargo:rerun-if-changed=buildscript/constants.rs");
|
||||
println!("cargo:rerun-if-changed=buildscript/units.rs");
|
||||
println!("cargo:rerun-if-changed=buildscript/units.toml");
|
||||
println!("cargo:rerun-if-changed=buildscript/constants.toml");
|
||||
|
||||
let units = include_str!("units.toml").parse::<Table>().unwrap();
|
||||
let toml::Value::Array(units) = &units["unit"] else {panic!()};
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(dest_path)
|
||||
.unwrap();
|
||||
|
||||
|
||||
|
||||
write_wholeunit_main(&file, units);
|
||||
writeln!(file, "\n\n").unwrap();
|
||||
|
||||
write_wholeunit_base_factor(&file, units);
|
||||
writeln!(file, "\n\n").unwrap();
|
||||
|
||||
write_freeunit_from_string(&file, units);
|
||||
units::write(&Path::new(&out_dir).join("units.rs"));
|
||||
constants::write(&Path::new(&out_dir).join("constants.rs"));
|
||||
|
||||
return Ok(());
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
use toml::Table;
|
||||
use toml::Value;
|
||||
|
||||
|
||||
|
||||
/// Create WholeUnit enum with
|
||||
/// basic impls. Should only be run once.
|
||||
fn write_wholeunit_main(mut file: &File, units: &Vec<Value>) {
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"#[derive(Hash)]\n",
|
||||
"#[derive(Debug)]\n",
|
||||
"#[derive(Copy, Clone)]\n",
|
||||
"#[derive(Eq, PartialEq)]\n",
|
||||
"pub enum WholeUnit {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
writeln!(file,
|
||||
"\t{},",
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "}}\n").unwrap();
|
||||
|
||||
// ToString
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"impl ToString for WholeUnit {{\n",
|
||||
"\tfn to_string(&self) -> String {{\n",
|
||||
"\t\tString::from(match self {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
writeln!(file,
|
||||
"\t\t\tWholeUnit::{e} => \"{s}\",",
|
||||
s = u["print"].as_str().unwrap(),
|
||||
e = u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t}})\n\t}}\n}}\n").unwrap();
|
||||
|
||||
|
||||
// Properties
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"impl WholeUnit {{\n",
|
||||
"\tfn no_space(&self) -> bool {{\n",
|
||||
"\t\tmatch self {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
if u.as_table().unwrap().contains_key("no_space") {
|
||||
if u.as_table().unwrap()["no_space"].as_bool().unwrap() {
|
||||
writeln!(file,
|
||||
"\t\t\tWholeUnit::{} => true,",
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t\t_ => false\n\t\t}}\n\t}}\n}}").unwrap();
|
||||
}
|
||||
|
||||
|
||||
/// Create WholeUnit::base_factor().
|
||||
/// Should only be run once.
|
||||
fn write_wholeunit_base_factor(mut file: &File, units: &Vec<Value>) {
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"impl WholeUnit {{\n",
|
||||
"\tfn base_factor(&self) -> Option<Quantity> {{\n",
|
||||
"\t\tmatch self {{"
|
||||
)
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
|
||||
|
||||
if { // Base units should return None
|
||||
u.as_table().unwrap().contains_key("base") &&
|
||||
u["base"].as_bool().unwrap()
|
||||
} {
|
||||
writeln!(file,
|
||||
"\t\t\tWholeUnit::{} => None,",
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
writeln!(file,
|
||||
"\t\t\tWholeUnit::{} => Some(Quantity{{",
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
|
||||
match u["base_value_type"].as_str().unwrap() {
|
||||
"exact" => {
|
||||
writeln!(file,
|
||||
"\t\t\t\tscalar: Scalar::new_rational_from_string(\"{}\").unwrap(),",
|
||||
u["base_value"].as_str().unwrap(),
|
||||
).unwrap();
|
||||
},
|
||||
|
||||
"fract" => {
|
||||
writeln!(file,
|
||||
"\t\t\t\tscalar: Scalar::new_rational_from_frac({}, {}).unwrap(),",
|
||||
u["base_value"].as_array().unwrap()[0].as_integer().unwrap(),
|
||||
u["base_value"].as_array().unwrap()[1].as_integer().unwrap(),
|
||||
).unwrap();
|
||||
},
|
||||
|
||||
"approx" => {
|
||||
writeln!(file,
|
||||
"\t\t\t\tscalar: Scalar::new_float_from_string(\"{}\").unwrap(),",
|
||||
u["base_value"].as_str().unwrap(),
|
||||
).unwrap();
|
||||
},
|
||||
|
||||
_ => panic!()
|
||||
};
|
||||
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"\t\t\t\tunit: Unit::from_array(&[\n",
|
||||
"\t\t\t\t\t(FreeUnit{{whole: WholeUnit::{}, prefix: Prefix::None}}, Scalar::new_rational(-1f64).unwrap()),",
|
||||
),
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
|
||||
for b in u["base_units"].as_array().unwrap() {
|
||||
writeln!(file,
|
||||
"\t\t\t\t\t(FreeUnit{{whole: WholeUnit::{u}, prefix: Prefix::None}}, Scalar::new_rational({p}f64).unwrap()),",
|
||||
u = b.as_table().unwrap()["u"].as_str().unwrap(),
|
||||
p = b.as_table().unwrap()["p"].as_integer().unwrap(),
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"\t\t\t\t])\n",
|
||||
"\t\t\t}}),"
|
||||
),
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t}}\n\t}}\n}}").unwrap();
|
||||
}
|
||||
|
||||
|
||||
/// Write all SI prefixes.
|
||||
/// Used inside freeunit_from_string().
|
||||
fn prefix_si(mut file: &File, enum_name: &str, s: &str) {
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"\t\t", "\"{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::None}}),\n",
|
||||
"\t\t", "\"Q{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Quetta}}),\n",
|
||||
"\t\t", "\"R{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Ronna}}),\n",
|
||||
"\t\t", "\"Y{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Yotta}}),\n",
|
||||
"\t\t", "\"Z{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Zetta}}),\n",
|
||||
"\t\t", "\"E{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Exa}}),\n",
|
||||
"\t\t", "\"P{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Peta}}),\n",
|
||||
"\t\t", "\"T{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Tera}}),\n",
|
||||
"\t\t", "\"G{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Giga}}),\n",
|
||||
"\t\t", "\"M{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Mega}}),\n",
|
||||
"\t\t", "\"k{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Kilo}}),\n",
|
||||
"\t\t", "\"h{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Hecto}}),\n",
|
||||
"\t\t", "\"da{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Deka}}),\n",
|
||||
"\t\t", "\"d{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Deci}}),\n",
|
||||
"\t\t", "\"c{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Centi}}),\n",
|
||||
"\t\t", "\"m{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Milli}}),\n",
|
||||
"\t\t", "\"u{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Micro}}),\n",
|
||||
"\t\t", "\"n{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Nano}}),\n",
|
||||
"\t\t", "\"p{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Pico}}),\n",
|
||||
"\t\t", "\"f{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Femto}}),\n",
|
||||
"\t\t", "\"a{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Atto}}),\n",
|
||||
"\t\t", "\"z{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Zepto}}),\n",
|
||||
"\t\t", "\"y{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Yocto}}),\n",
|
||||
"\t\t", "\"r{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Ronto}}),\n",
|
||||
"\t\t", "\"q{s}\" => Some(FreeUnit{{whole: WholeUnit::{e}, prefix: Prefix::Quecto}}),",
|
||||
),
|
||||
e = enum_name,
|
||||
s = s
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
|
||||
/// Create freeunit_from_string().
|
||||
/// Should only be run once.
|
||||
fn write_freeunit_from_string(mut file: &File, units: &Vec<Value>) {
|
||||
writeln!(file,
|
||||
concat!(
|
||||
"#[inline(always)]\n",
|
||||
"fn freeunit_from_string(s: &str) -> Option<FreeUnit> {{\n",
|
||||
"\tmatch s {{"
|
||||
),
|
||||
).unwrap();
|
||||
|
||||
for u in units {
|
||||
if u.as_table().unwrap().contains_key("parse") {
|
||||
for s in u["parse"].as_array().unwrap() {
|
||||
writeln!(file,
|
||||
"\t\t\"{}\" => Some(FreeUnit{{whole: WholeUnit::{}, prefix: Prefix::None}}),",
|
||||
s.as_str().unwrap(),
|
||||
u["enum_name"].as_str().unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if u.as_table().unwrap().contains_key("parse_with_prefix") {
|
||||
if u.as_table().unwrap()["parse_with_prefix"].is_array() {
|
||||
for p in u["parse_with_prefix"].as_array().unwrap() {
|
||||
prefix_si(
|
||||
&file,
|
||||
u["enum_name"].as_str().unwrap(),
|
||||
p.as_str().unwrap()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
prefix_si(
|
||||
&file,
|
||||
u["enum_name"].as_str().unwrap(),
|
||||
u["parse_with_prefix"].as_str().unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(file, "").unwrap();
|
||||
}
|
||||
|
||||
writeln!(file, "\t\t_ => None\n\t}}\n}}").unwrap();
|
||||
}
|
||||
|
||||
pub fn write(target: &Path) {
|
||||
let units = include_str!("units.toml").parse::<Table>().unwrap();
|
||||
let toml::Value::Array(units) = &units["unit"] else {panic!()};
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(target)
|
||||
.unwrap();
|
||||
|
||||
|
||||
write_wholeunit_main(&file, units);
|
||||
writeln!(file, "\n\n").unwrap();
|
||||
|
||||
write_wholeunit_base_factor(&file, units);
|
||||
writeln!(file, "\n\n").unwrap();
|
||||
|
||||
write_freeunit_from_string(&file, units);
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
use crate::parser::Token;
|
||||
use crate::parser::Constant;
|
||||
use crate::quantity::Quantity;
|
||||
use crate::quantity::Unit;
|
||||
|
||||
use super::EvalError;
|
||||
|
||||
pub fn eval_constant(c: &Constant) -> Result<Token, EvalError> {
|
||||
Ok(match c {
|
||||
// Mathematical constants
|
||||
// 100 digits of each.
|
||||
Constant::Pi => { Token::Quantity(Quantity::new_float_from_string(
|
||||
"3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067"
|
||||
).unwrap())},
|
||||
|
||||
Constant::E => { Token::Quantity(Quantity::new_float_from_string(
|
||||
"2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427"
|
||||
).unwrap()) },
|
||||
|
||||
Constant::Phi => { Token::Quantity(Quantity::new_float_from_string(
|
||||
"1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137"
|
||||
).unwrap()) },
|
||||
|
||||
Constant::MPG => {
|
||||
let mut q = Quantity::new_float_from_string("1").unwrap();
|
||||
q.set_unit(
|
||||
(
|
||||
Unit::from_string("mile").unwrap() /
|
||||
Unit::from_string("gallon").unwrap()
|
||||
).unit
|
||||
);
|
||||
Token::Quantity(q)
|
||||
},
|
||||
|
||||
Constant::MPH => {
|
||||
let mut q = Quantity::new_float_from_string("1").unwrap();
|
||||
q.set_unit(
|
||||
(
|
||||
Unit::from_string("mile").unwrap() /
|
||||
Unit::from_string("hour").unwrap()
|
||||
).unit
|
||||
);
|
||||
Token::Quantity(q)
|
||||
},
|
||||
})
|
||||
}
|
|
@ -2,7 +2,6 @@ use crate::parser::Token;
|
|||
use crate::parser::Operator;
|
||||
|
||||
use super::operator::eval_operator;
|
||||
use super::constant::eval_constant;
|
||||
use super::function::eval_function;
|
||||
use super::EvalError;
|
||||
|
||||
|
@ -13,8 +12,8 @@ pub fn evaluate(t: &Token) -> Result<Token, EvalError> {
|
|||
coords.push(0);
|
||||
|
||||
'outer: loop {
|
||||
|
||||
let mut h = &mut g;
|
||||
|
||||
for t in coords.iter() {
|
||||
let inner = h.get_args_mut();
|
||||
|
||||
|
@ -32,7 +31,7 @@ pub fn evaluate(t: &Token) -> Result<Token, EvalError> {
|
|||
loop {
|
||||
e = match e {
|
||||
Token::Quantity(_) => { break; },
|
||||
Token::Constant(c) => { eval_constant(&c)? }
|
||||
Token::Constant(c) => { evaluate(&c.value()).unwrap() }
|
||||
Token::Operator(Operator::Function(f), v) => { eval_function(&f, &v)? }
|
||||
Token::Operator(o, v) => { eval_operator(&o, &v)? }
|
||||
};
|
||||
|
@ -50,22 +49,13 @@ pub fn evaluate(t: &Token) -> Result<Token, EvalError> {
|
|||
}
|
||||
|
||||
|
||||
|
||||
match h {
|
||||
Token::Operator(_,_) => {
|
||||
coords.push(0);
|
||||
continue 'outer;
|
||||
},
|
||||
|
||||
Token::Constant(_) => {
|
||||
coords.push(0);
|
||||
continue 'outer;
|
||||
},
|
||||
Token::Operator(_,_) => { coords.push(0); },
|
||||
Token::Constant(_) => { coords.push(0); },
|
||||
|
||||
Token::Quantity(_) => {
|
||||
let l = coords.pop().unwrap();
|
||||
coords.push(l + 1);
|
||||
continue 'outer;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -74,14 +74,7 @@ impl PreToken {
|
|||
},
|
||||
|
||||
PreToken::PreWord(l, s) => {
|
||||
let c = match &s[..] {
|
||||
"π"|"pi" => { Some(Constant::Pi)},
|
||||
"e" => { Some(Constant::E) },
|
||||
"phi"|"φ" => { Some(Constant::Phi) },
|
||||
"mpg" => { Some(Constant::MPG) },
|
||||
"mph" => { Some(Constant::MPH) },
|
||||
_ => { None }
|
||||
};
|
||||
let c = Constant::from_string(&s);
|
||||
|
||||
if c.is_some() {
|
||||
return Ok(Token::Constant(c.unwrap()));
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#[derive(Debug)]
|
||||
#[derive(Clone)]
|
||||
pub enum Constant {
|
||||
// Fake units
|
||||
MPG,
|
||||
MPH,
|
||||
|
||||
// Mathematics
|
||||
Pi,
|
||||
Phi,
|
||||
E,
|
||||
}
|
||||
|
||||
impl Constant {
|
||||
pub fn to_string(&self) -> String {
|
||||
match self {
|
||||
// Fake units
|
||||
Constant::MPG => { String::from("mpg") },
|
||||
Constant::MPH => { String::from("mph") },
|
||||
|
||||
// Mathematics
|
||||
Constant::Pi => { String::from("π") },
|
||||
Constant::Phi => { String::from("φ") },
|
||||
Constant::E => { String::from("e") }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
mod operator;
|
||||
mod function;
|
||||
mod token;
|
||||
mod constant;
|
||||
|
||||
pub use self::operator::Operator;
|
||||
pub use self::function::Function;
|
||||
pub use self::token::Token;
|
||||
pub use self::constant::Constant;
|
||||
|
||||
|
||||
use super::parse;
|
||||
include!(concat!(env!("OUT_DIR"), "/constants.rs"));
|
Loading…
Reference in New Issue