mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Move calc.nan
to float.nan
and add float.inf
(#4733)
This commit is contained in:
parent
0edd8ec93d
commit
c43997de0a
@ -13,11 +13,26 @@ pub fn scope(_: TokenStream, item: syn::Item) -> Result<TokenStream> {
|
|||||||
|
|
||||||
let self_ty = &item.self_ty;
|
let self_ty = &item.self_ty;
|
||||||
|
|
||||||
|
let mut primitive_ident_ext = None;
|
||||||
|
if let syn::Type::Path(syn::TypePath { path, .. }) = self_ty.as_ref() {
|
||||||
|
if let Some(ident) = path.get_ident() {
|
||||||
|
if is_primitive(ident) {
|
||||||
|
let ident_ext = quote::format_ident!("{ident}Ext");
|
||||||
|
primitive_ident_ext = Some(ident_ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let self_ty_expr = match &primitive_ident_ext {
|
||||||
|
None => quote! { #self_ty },
|
||||||
|
Some(ident_ext) => quote! { <#self_ty as #ident_ext> },
|
||||||
|
};
|
||||||
|
|
||||||
let mut definitions = vec![];
|
let mut definitions = vec![];
|
||||||
let mut constructor = quote! { None };
|
let mut constructor = quote! { None };
|
||||||
for child in &mut item.items {
|
for child in &mut item.items {
|
||||||
let def = match child {
|
let def = match child {
|
||||||
syn::ImplItem::Const(item) => handle_const(self_ty, item)?,
|
syn::ImplItem::Const(item) => handle_const(&self_ty_expr, item)?,
|
||||||
syn::ImplItem::Fn(item) => match handle_fn(self_ty, item)? {
|
syn::ImplItem::Fn(item) => match handle_fn(self_ty, item)? {
|
||||||
FnKind::Member(tokens) => tokens,
|
FnKind::Member(tokens) => tokens,
|
||||||
FnKind::Constructor(tokens) => {
|
FnKind::Constructor(tokens) => {
|
||||||
@ -33,14 +48,10 @@ pub fn scope(_: TokenStream, item: syn::Item) -> Result<TokenStream> {
|
|||||||
|
|
||||||
item.items.retain(|item| !matches!(item, syn::ImplItem::Verbatim(_)));
|
item.items.retain(|item| !matches!(item, syn::ImplItem::Verbatim(_)));
|
||||||
|
|
||||||
let mut base = quote! { #item };
|
let base = match &primitive_ident_ext {
|
||||||
if let syn::Type::Path(syn::TypePath { path, .. }) = self_ty.as_ref() {
|
None => quote! { #item },
|
||||||
if let Some(ident) = path.get_ident() {
|
Some(ident_ext) => rewrite_primitive_base(&item, ident_ext),
|
||||||
if is_primitive(ident) {
|
};
|
||||||
base = rewrite_primitive_base(&item, ident);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#base
|
#base
|
||||||
@ -60,7 +71,7 @@ pub fn scope(_: TokenStream, item: syn::Item) -> Result<TokenStream> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Process a const item and returns its definition.
|
/// Process a const item and returns its definition.
|
||||||
fn handle_const(self_ty: &syn::Type, item: &syn::ImplItemConst) -> Result<TokenStream> {
|
fn handle_const(self_ty: &TokenStream, item: &syn::ImplItemConst) -> Result<TokenStream> {
|
||||||
let ident = &item.ident;
|
let ident = &item.ident;
|
||||||
let name = ident.to_string().to_kebab_case();
|
let name = ident.to_string().to_kebab_case();
|
||||||
Ok(quote! { scope.define(#name, #self_ty::#ident) })
|
Ok(quote! { scope.define(#name, #self_ty::#ident) })
|
||||||
@ -117,11 +128,12 @@ fn is_primitive(ident: &syn::Ident) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Rewrite an impl block for a primitive into a trait + trait impl.
|
/// Rewrite an impl block for a primitive into a trait + trait impl.
|
||||||
fn rewrite_primitive_base(item: &syn::ItemImpl, ident: &syn::Ident) -> TokenStream {
|
fn rewrite_primitive_base(item: &syn::ItemImpl, ident_ext: &syn::Ident) -> TokenStream {
|
||||||
let mut sigs = vec![];
|
let mut sigs = vec![];
|
||||||
let mut items = vec![];
|
let mut items = vec![];
|
||||||
for sub in &item.items {
|
for sub in &item.items {
|
||||||
let syn::ImplItem::Fn(mut func) = sub.clone() else { continue };
|
match sub.clone() {
|
||||||
|
syn::ImplItem::Fn(mut func) => {
|
||||||
func.vis = syn::Visibility::Inherited;
|
func.vis = syn::Visibility::Inherited;
|
||||||
items.push(func.clone());
|
items.push(func.clone());
|
||||||
|
|
||||||
@ -141,7 +153,14 @@ fn rewrite_primitive_base(item: &syn::ItemImpl, ident: &syn::Ident) -> TokenStre
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident_ext = quote::format_ident!("{ident}Ext");
|
syn::ImplItem::Const(cons) => {
|
||||||
|
sigs.push(quote! { #cons });
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let self_ty = &item.self_ty;
|
let self_ty = &item.self_ty;
|
||||||
quote! {
|
quote! {
|
||||||
trait #ident_ext {
|
trait #ident_ext {
|
||||||
|
@ -50,7 +50,6 @@ pub fn module() -> Module {
|
|||||||
scope.define_func::<rem_euclid>();
|
scope.define_func::<rem_euclid>();
|
||||||
scope.define_func::<quo>();
|
scope.define_func::<quo>();
|
||||||
scope.define("inf", f64::INFINITY);
|
scope.define("inf", f64::INFINITY);
|
||||||
scope.define("nan", f64::NAN);
|
|
||||||
scope.define("pi", std::f64::consts::PI);
|
scope.define("pi", std::f64::consts::PI);
|
||||||
scope.define("tau", std::f64::consts::TAU);
|
scope.define("tau", std::f64::consts::TAU);
|
||||||
scope.define("e", std::f64::consts::E);
|
scope.define("e", std::f64::consts::E);
|
||||||
|
@ -13,6 +13,9 @@ use crate::layout::Ratio;
|
|||||||
///
|
///
|
||||||
/// You can convert a value to a float with this type's constructor.
|
/// You can convert a value to a float with this type's constructor.
|
||||||
///
|
///
|
||||||
|
/// NaN and positive infinity are available as `{float.nan}` and `{float.inf}`
|
||||||
|
/// respectively.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```example
|
/// ```example
|
||||||
/// #3.14 \
|
/// #3.14 \
|
||||||
@ -24,6 +27,13 @@ type f64;
|
|||||||
|
|
||||||
#[scope]
|
#[scope]
|
||||||
impl f64 {
|
impl f64 {
|
||||||
|
/// Positive infinity.
|
||||||
|
const INF: f64 = f64::INFINITY;
|
||||||
|
|
||||||
|
/// A NaN value, as defined by the
|
||||||
|
/// [IEEE 754 standard](https://en.wikipedia.org/wiki/IEEE_754).
|
||||||
|
const NAN: f64 = f64::NAN;
|
||||||
|
|
||||||
/// Converts a value to a float.
|
/// Converts a value to a float.
|
||||||
///
|
///
|
||||||
/// - Booleans are converted to `0.0` or `1.0`.
|
/// - Booleans are converted to `0.0` or `1.0`.
|
||||||
@ -58,7 +68,7 @@ impl f64 {
|
|||||||
/// ```example
|
/// ```example
|
||||||
/// #float.is-nan(0) \
|
/// #float.is-nan(0) \
|
||||||
/// #float.is-nan(1) \
|
/// #float.is-nan(1) \
|
||||||
/// #float.is-nan(calc.nan)
|
/// #float.is-nan(float.nan)
|
||||||
/// ```
|
/// ```
|
||||||
#[func]
|
#[func]
|
||||||
pub fn is_nan(self) -> bool {
|
pub fn is_nan(self) -> bool {
|
||||||
@ -73,7 +83,7 @@ impl f64 {
|
|||||||
/// ```example
|
/// ```example
|
||||||
/// #float.is-infinite(0) \
|
/// #float.is-infinite(0) \
|
||||||
/// #float.is-infinite(1) \
|
/// #float.is-infinite(1) \
|
||||||
/// #float.is-infinite(calc.inf)
|
/// #float.is-infinite(float.inf)
|
||||||
/// ```
|
/// ```
|
||||||
#[func]
|
#[func]
|
||||||
pub fn is_infinite(self) -> bool {
|
pub fn is_infinite(self) -> bool {
|
||||||
@ -84,13 +94,13 @@ impl f64 {
|
|||||||
///
|
///
|
||||||
/// - If the number is positive (including `{+0.0}`), returns `{1.0}`.
|
/// - If the number is positive (including `{+0.0}`), returns `{1.0}`.
|
||||||
/// - If the number is negative (including `{-0.0}`), returns `{-1.0}`.
|
/// - If the number is negative (including `{-0.0}`), returns `{-1.0}`.
|
||||||
/// - If the number is `{calc.nan}`, returns `{calc.nan}`.
|
/// - If the number is `{float.nan}`, returns `{float.nan}`.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
/// #(5.0).signum() \
|
/// #(5.0).signum() \
|
||||||
/// #(-5.0).signum() \
|
/// #(-5.0).signum() \
|
||||||
/// #(0.0).signum() \
|
/// #(0.0).signum() \
|
||||||
/// #calc.nan.signum()
|
/// #float.nan.signum()
|
||||||
/// ```
|
/// ```
|
||||||
#[func]
|
#[func]
|
||||||
pub fn signum(self) -> f64 {
|
pub fn signum(self) -> f64 {
|
||||||
|
@ -76,7 +76,7 @@ pub fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
|
|||||||
/// unit, all with a single allocation.
|
/// unit, all with a single allocation.
|
||||||
///
|
///
|
||||||
/// The returned string is always valid Typst code. As such, it might not be a
|
/// The returned string is always valid Typst code. As such, it might not be a
|
||||||
/// float literal. For example, it may return `"calc.inf"`.
|
/// float literal. For example, it may return `"float.inf"`.
|
||||||
pub fn format_float(
|
pub fn format_float(
|
||||||
mut value: f64,
|
mut value: f64,
|
||||||
precision: Option<u8>,
|
precision: Option<u8>,
|
||||||
@ -91,10 +91,10 @@ pub fn format_float(
|
|||||||
// when necessary.
|
// when necessary.
|
||||||
let unit_multiplication = if unit.is_empty() { "" } else { " * 1" };
|
let unit_multiplication = if unit.is_empty() { "" } else { " * 1" };
|
||||||
if value.is_nan() {
|
if value.is_nan() {
|
||||||
eco_format!("calc.nan{unit_multiplication}{unit}")
|
eco_format!("float.nan{unit_multiplication}{unit}")
|
||||||
} else if value.is_infinite() {
|
} else if value.is_infinite() {
|
||||||
let sign = if value < 0.0 { "-" } else { "" };
|
let sign = if value < 0.0 { "-" } else { "" };
|
||||||
eco_format!("{sign}calc.inf{unit_multiplication}{unit}")
|
eco_format!("{sign}float.inf{unit_multiplication}{unit}")
|
||||||
} else if force_separator {
|
} else if force_separator {
|
||||||
eco_format!("{value:?}{unit}")
|
eco_format!("{value:?}{unit}")
|
||||||
} else {
|
} else {
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
--- float-is-nan ---
|
--- float-is-nan ---
|
||||||
// Test float `is-nan()`.
|
// Test float `is-nan()`.
|
||||||
#test(float(calc.nan).is-nan(), true)
|
#test(float(float.nan).is-nan(), true)
|
||||||
#test(float(10).is-nan(), false)
|
#test(float(10).is-nan(), false)
|
||||||
#test(float(calc.inf).is-nan(), false)
|
#test(float(calc.inf).is-nan(), false)
|
||||||
#test(float(-calc.inf).is-nan(), false)
|
#test(float(-calc.inf).is-nan(), false)
|
||||||
@ -29,7 +29,7 @@
|
|||||||
#test(float(-calc.inf).is-infinite(), true)
|
#test(float(-calc.inf).is-infinite(), true)
|
||||||
#test(float(10).is-infinite(), false)
|
#test(float(10).is-infinite(), false)
|
||||||
#test(float(-10).is-infinite(), false)
|
#test(float(-10).is-infinite(), false)
|
||||||
#test(float(calc.nan).is-infinite(), false)
|
#test(float(float.nan).is-infinite(), false)
|
||||||
|
|
||||||
--- float-signum ---
|
--- float-signum ---
|
||||||
// Test float `signum()`
|
// Test float `signum()`
|
||||||
@ -40,7 +40,7 @@
|
|||||||
#test(float(-10.0).signum(), -1.0)
|
#test(float(-10.0).signum(), -1.0)
|
||||||
#test(float(calc.inf).signum(), 1.0)
|
#test(float(calc.inf).signum(), 1.0)
|
||||||
#test(float(-calc.inf).signum(), -1.0)
|
#test(float(-calc.inf).signum(), -1.0)
|
||||||
#test(float(calc.nan).signum().is-nan(), true)
|
#test(float(float.nan).signum().is-nan(), true)
|
||||||
|
|
||||||
--- float-repr ---
|
--- float-repr ---
|
||||||
// Test the `repr` function with floats.
|
// Test the `repr` function with floats.
|
||||||
@ -55,9 +55,9 @@
|
|||||||
#repr(-0987654321.0) \
|
#repr(-0987654321.0) \
|
||||||
#repr(-3.14) \
|
#repr(-3.14) \
|
||||||
#repr(4.0 - 8.0) \
|
#repr(4.0 - 8.0) \
|
||||||
#repr(calc.inf) \
|
#repr(float.inf) \
|
||||||
#repr(-calc.inf) \
|
#repr(-float.inf) \
|
||||||
#repr(calc.nan)
|
#repr(float.nan)
|
||||||
|
|
||||||
--- float-display ---
|
--- float-display ---
|
||||||
// Test floats.
|
// Test floats.
|
||||||
@ -72,6 +72,6 @@
|
|||||||
#(-0987654321.0) \
|
#(-0987654321.0) \
|
||||||
#(-3.14) \
|
#(-3.14) \
|
||||||
#(4.0 - 8.0) \
|
#(4.0 - 8.0) \
|
||||||
#calc.inf \
|
#float.inf \
|
||||||
#(-calc.inf) \
|
#(-float.inf) \
|
||||||
#calc.nan
|
#float.nan
|
||||||
|
@ -335,7 +335,7 @@
|
|||||||
#(1em <= 10pt)
|
#(1em <= 10pt)
|
||||||
|
|
||||||
--- ops-compare-normal-float-with-nan ---
|
--- ops-compare-normal-float-with-nan ---
|
||||||
// Error: 3-22 cannot compare 2.2 with calc.nan
|
// Error: 3-22 cannot compare 2.2 with float.nan
|
||||||
#(2.2 <= float("nan"))
|
#(2.2 <= float("nan"))
|
||||||
|
|
||||||
--- ops-compare-int-and-str ---
|
--- ops-compare-int-and-str ---
|
||||||
@ -343,7 +343,7 @@
|
|||||||
#((0, 1, 3) > (0, 1, "a"))
|
#((0, 1, 3) > (0, 1, "a"))
|
||||||
|
|
||||||
--- ops-compare-array-nested-failure ---
|
--- ops-compare-array-nested-failure ---
|
||||||
// Error: 3-42 cannot compare 3.5 with calc.nan
|
// Error: 3-42 cannot compare 3.5 with float.nan
|
||||||
#((0, "a", 3.5) <= (0, "a", float("nan")))
|
#((0, "a", 3.5) <= (0, "a", float("nan")))
|
||||||
|
|
||||||
--- ops-divide-by-zero-float ---
|
--- ops-divide-by-zero-float ---
|
||||||
|
Loading…
x
Reference in New Issue
Block a user