git.delta.rocks / jrsonnet / refs/commits / 7af406eaa740

difftreelog

feat return NumValue directly from parser

rlsuqplzYaroslav Bolyukin2026-04-25parent: #eee6c62.patch.diff
in: master

15 files changed

modifiedbindings/jsonnet/src/val_make.rsdiffbeforeafterboth
5 os::raw::{c_char, c_double, c_int},5 os::raw::{c_char, c_double, c_int},
6};6};
77
8use jrsonnet_evaluator::{8use jrsonnet_evaluator::{NumValue, ObjValue, Val};
9 ObjValue, Val,
10 val::{ArrValue, NumValue},
11};
129
13use crate::VM;10use crate::VM;
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
3use jrsonnet_gcmodule::{Acyclic, Trace};3use jrsonnet_gcmodule::{Acyclic, Trace};
4use jrsonnet_interner::IStr;4use jrsonnet_interner::IStr;
5use jrsonnet_ir::{BinaryOpType, Source, SourcePath, Span, Spanned, UnaryOpType};5use jrsonnet_ir::{
6 BinaryOpType, ConvertNumValueError, Source, SourcePath, Span, Spanned, UnaryOpType,
7};
6use jrsonnet_types::ValType;8use jrsonnet_types::ValType;
7use thiserror::Error;9use thiserror::Error;
11 function::{CallLocation, FunctionSignature, ParamName},13 function::{CallLocation, FunctionSignature, ParamName},
12 stdlib::format::FormatError,14 stdlib::format::FormatError,
13 typed::TypeLocError,15 typed::TypeLocError,
14 val::ConvertNumValueError,
15};16};
1617
17#[derive(Debug, Clone)]18#[derive(Debug, Clone)]
228 Self::new(e)229 Self::new(e)
229 }230 }
230}231}
232impl From<ConvertNumValueError> for Error {
233 fn from(e: ConvertNumValueError) -> Self {
234 Self::new(ErrorKind::ConvertNumValue(e))
235 }
236}
231237
232impl From<Infallible> for Error {238impl From<Infallible> for Error {
233 fn from(_value: Infallible) -> Self {239 fn from(_value: Infallible) -> Self {
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
21 function::{CallLocation, FuncDesc, FuncVal, PreparedFuncVal},21 function::{CallLocation, FuncDesc, FuncVal, PreparedFuncVal},
22 in_frame,22 in_frame,
23 typed::{FromUntyped, IntoUntyped as _, Typed},23 typed::{FromUntyped, IntoUntyped as _, Typed},
24 val::{CachedUnbound, IndexableVal, NumValue, StrValue, Thunk},24 val::{CachedUnbound, IndexableVal, StrValue, Thunk},
25 with_state,25 with_state,
26};26};
27pub mod destructure;27pub mod destructure;
58 }58 }
59 Some(match expr {59 Some(match expr {
60 Expr::Str(s) => Val::string(s.clone()),60 Expr::Str(s) => Val::string(s.clone()),
61 Expr::Num(n) => {61 Expr::Num(n) => Val::Num(*n),
62 Val::Num(NumValue::new(*n).expect("parser will not allow non-finite values"))
63 }
64 Expr::Literal(LiteralType::False) => Val::Bool(false),62 Expr::Literal(LiteralType::False) => Val::Bool(false),
65 Expr::Literal(LiteralType::True) => Val::Bool(true),63 Expr::Literal(LiteralType::True) => Val::Bool(true),
66 Expr::Literal(LiteralType::Null) => Val::Null,64 Expr::Literal(LiteralType::Null) => Val::Null,
modifiedcrates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth
1use std::borrow::Cow;1use std::borrow::Cow;
22
3use jrsonnet_interner::{IBytes, IStr};3use jrsonnet_interner::{IBytes, IStr};
4use jrsonnet_ir::NumValue;
4use serde::{5use serde::{
5 Deserialize, Serialize, Serializer,6 Deserialize, Serialize, Serializer,
6 de::{self, Visitor},7 de::{self, Visitor},
1213
13use crate::{14use crate::{
14 Error as JrError, ObjValue, ObjValueBuilder, Result, Val, in_description_frame, runtime_error,15 Error as JrError, ObjValue, ObjValueBuilder, Result, Val, in_description_frame, runtime_error,
15 val::NumValue,
16};16};
1717
18impl<'de> Deserialize<'de> for Val {18impl<'de> Deserialize<'de> for Val {
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
42use jrsonnet_gcmodule::{Cc, Trace, cc_dyn};42use jrsonnet_gcmodule::{Cc, Trace, cc_dyn};
43pub use jrsonnet_interner::{IBytes, IStr};43pub use jrsonnet_interner::{IBytes, IStr};
44pub use jrsonnet_ir as parser;44pub use jrsonnet_ir as parser;
45pub use jrsonnet_ir::NumValue;
45use jrsonnet_ir::{Expr, Source, SourcePath};46use jrsonnet_ir::{Expr, Source, SourcePath};
46#[doc(hidden)]47#[doc(hidden)]
47pub use jrsonnet_macros;48pub use jrsonnet_macros;
modifiedcrates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth
829#[cfg(test)]829#[cfg(test)]
830pub mod test_format {830pub mod test_format {
831 use super::*;831 use super::*;
832 use crate::val::NumValue;832 use crate::NumValue;
833833
834 #[test]834 #[test]
835 fn parse() {835 fn parse() {
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
22
3use jrsonnet_gcmodule::Trace;3use jrsonnet_gcmodule::Trace;
4use jrsonnet_interner::{IBytes, IStr};4use jrsonnet_interner::{IBytes, IStr};
5use jrsonnet_ir::NumValue;
6pub use jrsonnet_ir::{MAX_SAFE_INTEGER, MIN_SAFE_INTEGER};
5use jrsonnet_types::{ComplexValType, ValType};7use jrsonnet_types::{ComplexValType, ValType};
68
7use crate::{9use crate::{
10 bail,12 bail,
11 function::FuncVal,13 function::FuncVal,
12 typed::CheckType,14 typed::CheckType,
13 val::{IndexableVal, NumValue, StrValue, ThunkMapper},15 val::{IndexableVal, StrValue, ThunkMapper},
14};16};
1517
16#[doc(hidden)]18#[doc(hidden)]
220 }222 }
221}223}
222
223#[expect(clippy::cast_precision_loss, reason = "checked to not overflow")]
224pub const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS)) - 1) as f64;
225#[expect(clippy::cast_precision_loss, reason = "checked to not overflow")]
226pub const MIN_SAFE_INTEGER: f64 = (-((1i64 << (f64::MANTISSA_DIGITS)) - 1)) as f64;
227224
228macro_rules! impl_int {225macro_rules! impl_int {
229 ($($ty:ty)*) => {$(226 ($($ty:ty)*) => {$(
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
5 marker::PhantomData,5 marker::PhantomData,
6 mem::replace,6 mem::replace,
7 num::NonZeroU32,7 num::NonZeroU32,
8 ops::Deref,
9 rc::Rc,8 rc::Rc,
10};9};
1110
14pub use jrsonnet_macros::Thunk;13pub use jrsonnet_macros::Thunk;
15use jrsonnet_types::ValType;14use jrsonnet_types::ValType;
16use rustc_hash::FxHashMap;15use rustc_hash::FxHashMap;
17use thiserror::Error;
1816
19pub use crate::arr::{ArrValue, ArrayLike};17pub use crate::arr::{ArrValue, ArrayLike};
20use crate::{18use crate::{
21 ObjValue, Result, SupThis, Unbound, WeakSupThis, bail,19 NumValue, ObjValue, Result, SupThis, Unbound, WeakSupThis, bail,
22 error::{Error, ErrorKind::*},20 error::{Error, ErrorKind::*},
23 function::FuncVal,21 function::FuncVal,
24 gc::WithCapacityExt as _,22 gc::WithCapacityExt as _,
25 manifest::{ManifestFormat, ToStringFormat},23 manifest::{ManifestFormat, ToStringFormat},
26 typed::{BoundedUsize, MAX_SAFE_INTEGER, MIN_SAFE_INTEGER},24 typed::BoundedUsize,
27};25};
2826
29pub trait ThunkValue: Trace {27pub trait ThunkValue: Trace {
442 }440 }
443}441}
444
445/// Represents jsonnet number
446/// Jsonnet numbers are finite f64, with NaNs disallowed
447#[derive(Trace, Clone, Copy)]
448#[repr(transparent)]
449pub struct NumValue(f64);
450impl NumValue {
451 /// Creates a [`NumValue`], if value is finite and not NaN
452 pub fn new(v: f64) -> Option<Self> {
453 if !v.is_finite() {
454 return None;
455 }
456 Some(Self(v))
457 }
458 #[inline]
459 pub const fn get(&self) -> f64 {
460 self.0
461 }
462 pub(crate) fn truncate_for_bitwise(self) -> Result<i64> {
463 if self.0 < MIN_SAFE_INTEGER || self.0 > MAX_SAFE_INTEGER {
464 bail!("numberic value outside of safe integer range for bitwise operation");
465 }
466 #[expect(clippy::cast_possible_truncation, reason = "intended")]
467 Ok(self.0 as i64)
468 }
469}
470impl PartialEq for NumValue {
471 fn eq(&self, other: &Self) -> bool {
472 self.0 == other.0
473 }
474}
475impl Eq for NumValue {}
476impl Ord for NumValue {
477 #[inline]
478 fn cmp(&self, other: &Self) -> Ordering {
479 // Can't use `total_cmp`: its behavior for `-0` and `0`
480 // is not following wanted.
481 unsafe { self.0.partial_cmp(&other.0).unwrap_unchecked() }
482 }
483}
484impl PartialOrd for NumValue {
485 #[inline]
486 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
487 Some(self.cmp(other))
488 }
489}
490impl Debug for NumValue {
491 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492 Debug::fmt(&self.0, f)
493 }
494}
495impl Display for NumValue {
496 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
497 Display::fmt(&self.0, f)
498 }
499}
500impl Deref for NumValue {
501 type Target = f64;
502
503 #[inline]
504 fn deref(&self) -> &Self::Target {
505 &self.0
506 }
507}
508macro_rules! impl_num {
509 ($($ty:ty),+) => {$(
510 impl From<$ty> for NumValue {
511 #[inline]
512 fn from(value: $ty) -> Self {
513 Self(value.into())
514 }
515 }
516 )+};
517}
518impl_num!(i8, u8, i16, u16, i32, u32);
519
520#[derive(Clone, Copy, Debug, Error, Trace)]
521pub enum ConvertNumValueError {
522 #[error("overflow")]
523 Overflow,
524 #[error("underflow")]
525 Underflow,
526 #[error("non-finite")]
527 NonFinite,
528}
529impl From<ConvertNumValueError> for Error {
530 fn from(e: ConvertNumValueError) -> Self {
531 Self::new(e.into())
532 }
533}
534
535macro_rules! impl_try_num {
536 ($($ty:ty),+) => {$(
537 impl TryFrom<$ty> for NumValue {
538 type Error = ConvertNumValueError;
539 #[inline]
540 fn try_from(value: $ty) -> Result<Self, ConvertNumValueError> {
541 #[expect(clippy::cast_precision_loss, reason = "precision loss is explicitly handled")]
542 let value = value as f64;
543 if value < MIN_SAFE_INTEGER {
544 return Err(ConvertNumValueError::Underflow)
545 } else if value > MAX_SAFE_INTEGER {
546 return Err(ConvertNumValueError::Overflow)
547 }
548 // Number is finite.
549 Ok(Self(value))
550 }
551 }
552 )+};
553}
554impl_try_num!(usize, isize, i64, u64);
555
556impl TryFrom<f64> for NumValue {
557 type Error = ConvertNumValueError;
558
559 #[inline]
560 fn try_from(value: f64) -> Result<Self, Self::Error> {
561 Self::new(value).ok_or(ConvertNumValueError::NonFinite)
562 }
563}
564impl TryFrom<f32> for NumValue {
565 type Error = ConvertNumValueError;
566
567 #[inline]
568 fn try_from(value: f32) -> Result<Self, Self::Error> {
569 Self::new(f64::from(value)).ok_or(ConvertNumValueError::NonFinite)
570 }
571}
572442
573/// Represents any valid Jsonnet value.443/// Represents any valid Jsonnet value.
574#[derive(Debug, Clone, Trace, Default)]444#[derive(Debug, Clone, Trace, Default)]
modifiedcrates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth
4use jrsonnet_ir::{4use jrsonnet_ir::{
5 ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec, Destruct, Expr,5 ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec, Destruct, Expr,
6 ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IfElse, IfSpecData,6 ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IfElse, IfSpecData,
7 ImportKind, IndexPart, LiteralType, Member, ObjBody, ObjComp, ObjMembers, Slice, SliceDesc,7 ImportKind, IndexPart, LiteralType, Member, NumValue, ObjBody, ObjComp, ObjMembers, Slice,
8 Source, Span, Spanned, UnaryOpType, Visibility, unescape,8 SliceDesc, Source, Span, Spanned, UnaryOpType, Visibility, unescape,
9};9};
10use jrsonnet_lexer::{Lexeme, Lexer, Span as LexSpan, SyntaxKind, T, collect_lexed_str_block};10use jrsonnet_lexer::{Lexeme, Lexer, Span as LexSpan, SyntaxKind, T, collect_lexed_str_block};
1111
202 )202 )
203}203}
204204
205fn parse_number(p: &mut Parser<'_>) -> Result<f64> {205fn parse_number(p: &mut Parser<'_>) -> Result<NumValue> {
206 let text = p.text();206 let text = p.text();
207 let n: f64 = text207 let n: f64 = text
208 .replace('_', "")208 .replace('_', "")
209 .parse()209 .parse()
210 .map_err(|_| p.error(format!("invalid number literal: {text}")))?;210 .map_err(|_| p.error(format!("invalid number literal: {text}")))?;
211
211 if !n.is_finite() {212 let v = match NumValue::try_from(n) {
212 return Err(p.error("numbers are finite".into()));213 Ok(v) => v,
214 Err(e) => return Err(p.error(format!("invalid number value: {e}"))),
213 }215 };
216
214 p.eat_any();217 p.eat_any();
218
215 Ok(n)219 Ok(v)
216}220}
217221
218fn ident(p: &mut Parser<'_>) -> Result<IStr> {222fn ident(p: &mut Parser<'_>) -> Result<IStr> {
modifiedcrates/jrsonnet-ir/Cargo.tomldiffbeforeafterboth
19static_assertions.workspace = true19static_assertions.workspace = true
2020
21peg.workspace = true21peg.workspace = true
22thiserror.workspace = true
2223
23[dev-dependencies]24[dev-dependencies]
24insta.workspace = true25insta.workspace = true
modifiedcrates/jrsonnet-ir/src/expr.rsdiffbeforeafterboth
8use jrsonnet_interner::IStr;8use jrsonnet_interner::IStr;
99
10use crate::{10use crate::{
11 NumValue,
11 function::{FunctionSignature, ParamDefault, ParamName, ParamParse},12 function::{FunctionSignature, ParamDefault, ParamName, ParamParse},
12 source::Source,13 source::Source,
13};14};
398 /// String value: "hello"399 /// String value: "hello"
399 Str(IStr),400 Str(IStr),
400 /// Number: 1, 2.0, 2e+20401 /// Number: 1, 2.0, 2e+20
401 Num(f64),402 Num(NumValue),
402 /// Variable name: test403 /// Variable name: test
403 Var(Spanned<IStr>),404 Var(Spanned<IStr>),
404405
modifiedcrates/jrsonnet-ir/src/lib.rsdiffbeforeafterboth
1#![allow(clippy::redundant_closure_call, clippy::derive_partial_eq_without_eq)]1#![allow(clippy::redundant_closure_call, clippy::derive_partial_eq_without_eq)]
22
3mod expr;3mod expr;
4use std::{cmp::Ordering, fmt, ops::Deref};
5
4pub use expr::*;6pub use expr::*;
7use jrsonnet_gcmodule::Acyclic;
5pub use jrsonnet_interner::IStr;8pub use jrsonnet_interner::IStr;
6pub mod function;9pub mod function;
7mod location;10mod location;
15 SourcePathT, SourceVirtual,18 SourcePathT, SourceVirtual,
16};19};
20
21// It seels to be a wrong place for this kind of stuff, but as it would also be used for static analysis and
22// is already wanted for NumValue, I don't know a better place.
23#[expect(clippy::cast_precision_loss, reason = "checked to not overflow")]
24pub const MAX_SAFE_INTEGER: f64 = ((1u64 << (f64::MANTISSA_DIGITS)) - 1) as f64;
25#[expect(clippy::cast_precision_loss, reason = "checked to not overflow")]
26pub const MIN_SAFE_INTEGER: f64 = (-((1i64 << (f64::MANTISSA_DIGITS)) - 1)) as f64;
27
28/// Represents jsonnet number
29/// Jsonnet numbers are finite f64, with NaNs disallowed
30#[derive(Acyclic, Clone, Copy)]
31pub struct NumValue(f64);
32impl NumValue {
33 /// Creates a [`NumValue`], if value is finite and not NaN
34 pub fn new(v: f64) -> Option<Self> {
35 if !v.is_finite() {
36 return None;
37 }
38 Some(Self(v))
39 }
40 #[inline]
41 pub const fn get(&self) -> f64 {
42 self.0
43 }
44 pub fn truncate_for_bitwise(self) -> Result<i64, ConvertNumValueError> {
45 if self.0 < MIN_SAFE_INTEGER || self.0 > MAX_SAFE_INTEGER {
46 return Err(ConvertNumValueError::BitwiseSafeRange);
47 }
48 #[expect(clippy::cast_possible_truncation, reason = "intended")]
49 Ok(self.0 as i64)
50 }
51}
52impl PartialEq for NumValue {
53 fn eq(&self, other: &Self) -> bool {
54 self.0 == other.0
55 }
56}
57impl Eq for NumValue {}
58impl Ord for NumValue {
59 #[inline]
60 fn cmp(&self, other: &Self) -> Ordering {
61 // Can't use `total_cmp`: its behavior for `-0` and `0`
62 // is not following wanted.
63 unsafe { self.0.partial_cmp(&other.0).unwrap_unchecked() }
64 }
65}
66impl PartialOrd for NumValue {
67 #[inline]
68 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
69 Some(self.cmp(other))
70 }
71}
72impl fmt::Debug for NumValue {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 fmt::Debug::fmt(&self.0, f)
75 }
76}
77impl fmt::Display for NumValue {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 fmt::Display::fmt(&self.0, f)
80 }
81}
82impl Deref for NumValue {
83 type Target = f64;
84
85 #[inline]
86 fn deref(&self) -> &Self::Target {
87 &self.0
88 }
89}
90macro_rules! impl_num {
91 ($($ty:ty),+) => {$(
92 impl From<$ty> for NumValue {
93 #[inline]
94 fn from(value: $ty) -> Self {
95 Self(value.into())
96 }
97 }
98 )+};
99}
100impl_num!(i8, u8, i16, u16, i32, u32);
101
102#[derive(Clone, Copy, Debug, thiserror::Error, Acyclic)]
103pub enum ConvertNumValueError {
104 #[error("overflow")]
105 Overflow,
106 #[error("underflow")]
107 Underflow,
108 #[error("non-finite")]
109 NonFinite,
110 #[error("float out of safe int range")]
111 BitwiseSafeRange,
112}
113
114macro_rules! impl_try_num {
115 ($($ty:ty),+) => {$(
116 impl TryFrom<$ty> for NumValue {
117 type Error = ConvertNumValueError;
118 #[inline]
119 fn try_from(value: $ty) -> Result<Self, ConvertNumValueError> {
120 #[expect(clippy::cast_precision_loss, reason = "precision loss is explicitly handled")]
121 let value = value as f64;
122 if value < MIN_SAFE_INTEGER {
123 return Err(ConvertNumValueError::Underflow)
124 } else if value > MAX_SAFE_INTEGER {
125 return Err(ConvertNumValueError::Overflow)
126 }
127 // Number is finite.
128 Ok(Self(value))
129 }
130 }
131 )+};
132}
133impl_try_num!(usize, isize, i64, u64);
134
135impl TryFrom<f64> for NumValue {
136 type Error = ConvertNumValueError;
137
138 #[inline]
139 fn try_from(value: f64) -> Result<Self, Self::Error> {
140 Self::new(value).ok_or(ConvertNumValueError::NonFinite)
141 }
142}
143impl TryFrom<f32> for NumValue {
144 type Error = ConvertNumValueError;
145
146 #[inline]
147 fn try_from(value: f32) -> Result<Self, Self::Error> {
148 Self::new(f64::from(value)).ok_or(ConvertNumValueError::NonFinite)
149 }
150}
17151
modifiedcrates/jrsonnet-peg-parser/src/lib.rsdiffbeforeafterboth
4use jrsonnet_ir::{4use jrsonnet_ir::{
5 ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BindSpec, CompSpec, Destruct, DestructRest, Expr,5 ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BindSpec, CompSpec, Destruct, DestructRest, Expr,
6 ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IfElse, IfSpecData,6 ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IfElse, IfSpecData,
7 ImportKind, IndexPart, LiteralType, Member, ObjBody, ObjComp, ObjMembers, Slice, SliceDesc,7 ImportKind, IndexPart, LiteralType, Member, NumValue, ObjBody, ObjComp, ObjMembers, Slice,
8 Source, Span, Spanned, Visibility, unescape,8 SliceDesc, Source, Span, Spanned, Visibility, unescape,
9};9};
10use peg::parser;10use peg::parser;
52 /// Sequence of digits52 /// Sequence of digits
53 rule uint_str() -> &'input str = a:$(digit()+ ("_" digit()+)*) { a }53 rule uint_str() -> &'input str = a:$(digit()+ ("_" digit()+)*) { a }
54 /// Number in scientific notation format54 /// Number in scientific notation format
55 rule number() -> f64 = quiet!{a:$(uint_str() ("." uint_str())? (['e'|'E'] (s:['+'|'-'])? uint_str())?) {? a.replace("_","").parse().map_err(|_| "<number>") }} / expected!("<number>")55 rule number() -> f64 = quiet!{a:$(uint_str() ("." uint_str())? (['e'|'E'] (s:['+'|'-'])? uint_str())?) {? a.replace('_',"").parse().map_err(|_| "<number>") }} / expected!("<number>")
5656
57 /// Reserved word followed by any non-alphanumberic57 /// Reserved word followed by any non-alphanumberic
58 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "importbin" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()58 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "importbin" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()
267 Expr::ArrComp(Rc::new(expr), specs)267 Expr::ArrComp(Rc::new(expr), specs)
268 }268 }
269 pub rule number_expr(s: &ParserSettings) -> Expr269 pub rule number_expr(s: &ParserSettings) -> Expr
270 = n:number() {? if n.is_finite() {270 = n:number() {? if let Some(n) = NumValue::new(n) {
271 Ok(Expr::Num(n))271 Ok(Expr::Num(n))
272 } else {272 } else {
273 Err("!!!numbers are finite")273 Err("!!!numbers are finite")
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
12pub use encoding::*;12pub use encoding::*;
13pub use hash::*;13pub use hash::*;
14use jrsonnet_evaluator::{14use jrsonnet_evaluator::{
15 ContextBuilder, IStr, ObjValue, ObjValueBuilder, Thunk, Val,15 ContextBuilder, IStr, NumValue, ObjValue, ObjValueBuilder, Thunk, Val,
16 error::Result,16 error::Result,
17 function::{CallLocation, FuncVal, builtin_id},17 function::{CallLocation, FuncVal, builtin_id},
18 tla::TlaArg,18 tla::TlaArg,
19 trace::PathResolver,19 trace::PathResolver,
20 typed::SerializeTypedObj as _,20 typed::SerializeTypedObj as _,
21 val::NumValue,
22};21};
23use jrsonnet_gcmodule::{Acyclic, Cc, Trace};22use jrsonnet_gcmodule::{Acyclic, Cc, Trace};
24use jrsonnet_ir::Source;23use jrsonnet_ir::Source;
modifiedcrates/jrsonnet-stdlib/src/operator.rsdiffbeforeafterboth
2//! However, in our case we instead implement them in native, and implement native functions on top of core for backwards compatibility2//! However, in our case we instead implement them in native, and implement native functions on top of core for backwards compatibility
33
4use jrsonnet_evaluator::{4use jrsonnet_evaluator::{
5 IStr, Result, Val,5 IStr, NumValue, Result, Val,
6 function::builtin,6 function::builtin,
7 operator::evaluate_mod_op,7 operator::evaluate_mod_op,
8 stdlib::std_format,8 stdlib::std_format,
9 typed::{Either, Either2},9 typed::{Either, Either2},
10 val::{NumValue, equals, primitive_equals},10 val::{equals, primitive_equals},
11};11};
1212
13#[builtin]13#[builtin]