1use std::cell::RefCell;
10use std::rc::Rc;
11use std::sync::Arc;
12
13use logicaffeine_base::algebraic::Algebraic;
14use logicaffeine_base::exact_real::ExactReal;
15use logicaffeine_base::germ::Germ;
16use logicaffeine_base::hypernatural::Hypernatural;
17use logicaffeine_base::hyperreal::Hyperreal;
18use logicaffeine_base::limit_value::{Converging, Depends, LimitRule};
19use logicaffeine_base::numeric::{rational_from_f64_exact, BigInt, Rational};
20use logicaffeine_base::ordinal::Ordinal;
21use logicaffeine_base::tower::{self, ExactRef, Shape, TowerValue, ValueAlgebra};
22
23pub use logicaffeine_base::tower::{Branch, HyperForm, HyperValue, NaturalValue, Op, Rel, Rounding, Scale};
24
25use crate::ast::stmt::BinaryOpKind;
26use crate::interpreter::{ListRepr, RuntimeValue};
27use crate::semantics::builtins::{call_builtin, BuiltinId};
28
29pub type DependsValue = tower::DependsValue<RuntimeValue>;
31
32pub fn from_algebraic(a: Algebraic) -> RuntimeValue {
34 tower::from_algebraic(a)
35}
36
37pub fn from_exact_real(x: ExactReal) -> RuntimeValue {
39 tower::from_exact_real(x)
40}
41
42pub fn from_hyper(value: Hyperreal, scale: &Arc<Scale>) -> RuntimeValue {
44 tower::from_hyper(value, scale)
45}
46
47pub fn from_germ(g: Germ, scale: &Arc<Scale>) -> RuntimeValue {
49 tower::from_germ(g, scale)
50}
51
52pub fn from_natural(value: Hypernatural, scale: &Arc<Scale>) -> RuntimeValue {
54 tower::from_natural(value, scale)
55}
56
57pub fn from_depends(value: Depends<Branch<RuntimeValue>>, scale: &Arc<Scale>) -> RuntimeValue {
59 tower::from_depends(value, scale)
60}
61
62pub fn from_ordinal(o: Ordinal) -> RuntimeValue {
64 tower::from_ordinal(o)
65}
66
67pub fn is_exact_value(v: &RuntimeValue) -> bool {
69 tower::is_exact_value(v)
70}
71
72pub fn arith(
74 op: Op,
75 left: &RuntimeValue,
76 right: &RuntimeValue,
77 recurse: &dyn Fn(Op, RuntimeValue, RuntimeValue) -> Result<RuntimeValue, String>,
78) -> Option<Result<RuntimeValue, String>> {
79 tower::arith(op, left, right, recurse)
80}
81
82pub fn germ_of(v: &RuntimeValue) -> Option<Germ> {
84 tower::germ_of(v)
85}
86
87pub fn relation(
89 rel: Rel,
90 left: &RuntimeValue,
91 right: &RuntimeValue,
92 recurse: &dyn Fn(Rel, RuntimeValue, RuntimeValue) -> Result<RuntimeValue, String>,
93) -> Option<Result<RuntimeValue, String>> {
94 tower::relation(rel, left, right, recurse)
95}
96
97pub fn structurally_equal(left: &RuntimeValue, right: &RuntimeValue) -> Option<bool> {
99 tower::structurally_equal(left, right)
100}
101
102pub fn display(v: &RuntimeValue) -> Option<String> {
104 tower::display(v)
105}
106
107pub fn standard_part(v: &RuntimeValue) -> Result<RuntimeValue, String> {
109 tower::standard_part(v)
110}
111
112pub fn integer_part(
114 v: &RuntimeValue,
115 mode: Rounding,
116 recurse: &dyn Fn(RuntimeValue) -> Result<RuntimeValue, String>,
117) -> Option<Result<RuntimeValue, String>> {
118 tower::integer_part(v, mode, recurse)
119}
120
121pub fn is_infinitesimal(v: &RuntimeValue) -> Result<RuntimeValue, String> {
123 tower::is_infinitesimal(v)
124}
125
126pub fn is_limited(v: &RuntimeValue) -> Result<RuntimeValue, String> {
128 tower::is_limited(v)
129}
130
131pub fn new_infinitesimal(name: &str, modulus: u64, allowed: &[u64]) -> Result<RuntimeValue, String> {
133 tower::new_infinitesimal(name, modulus, allowed)
134}
135
136pub fn new_ordered_infinitesimal(
139 name: &str,
140 larger: &RuntimeValue,
141 smaller: &RuntimeValue,
142 modulus: u64,
143 allowed: &[u64],
144) -> Result<RuntimeValue, String> {
145 tower::new_ordered_infinitesimal(name, larger, smaller, modulus, allowed)
146}
147
148pub fn generator_of(v: &RuntimeValue) -> Result<RuntimeValue, String> {
150 tower::generator_of(v)
151}
152
153pub fn limit_rule(name: &str) -> Result<LimitRule, String> {
155 tower::limit_rule(name)
156}
157
158pub fn apply_limit(v: &RuntimeValue, rule: LimitRule) -> Result<RuntimeValue, String> {
160 tower::apply_limit(v, rule)
161}
162
163pub fn provisional(value: RuntimeValue, steps: u64, revisions: u64) -> RuntimeValue {
165 tower::provisional(value, steps, revisions)
166}
167
168pub fn undecided_branch(v: &RuntimeValue) -> Option<String> {
170 tower::undecided_branch(v)
171}
172
173pub fn not(
175 v: &RuntimeValue,
176 recurse: &dyn Fn(RuntimeValue) -> Result<RuntimeValue, String>,
177) -> Option<Result<RuntimeValue, String>> {
178 tower::not(v, recurse)
179}
180
181pub fn exact_bytes(v: &RuntimeValue) -> Option<(u8, Vec<u8>)> {
183 tower::exact_bytes(v)
184}
185
186pub fn from_exact_bytes(kind: u8, bytes: &[u8]) -> Option<RuntimeValue> {
188 tower::from_exact_bytes(kind, bytes)
189}
190
191pub fn scale_parts(scale: &Scale) -> (String, Vec<u8>) {
193 tower::scale_parts(scale)
194}
195
196pub fn scale_from_parts(name: &str, residues: &[u8]) -> Option<Arc<Scale>> {
198 tower::scale_from_parts(name, residues)
199}
200
201pub fn scaled_bytes(v: &RuntimeValue) -> Option<(u8, String, Vec<u8>, Vec<u8>)> {
203 tower::scaled_bytes(v)
204}
205
206pub fn from_scaled_bytes(kind: u8, name: &str, residues: &[u8], bytes: &[u8]) -> Option<RuntimeValue> {
208 tower::from_scaled_bytes(kind, name, residues, bytes)
209}
210
211pub fn depends_from_parts(
213 name: &str,
214 residues: &[u8],
215 modulus: u64,
216 branches: Vec<Option<RuntimeValue>>,
217) -> Option<RuntimeValue> {
218 tower::depends_from_parts(name, residues, modulus, branches)
219}
220
221impl TowerValue for RuntimeValue {
222 fn exact(&self) -> Option<ExactRef<'_, Self>> {
223 Some(match self {
224 RuntimeValue::Algebraic(a) => ExactRef::Algebraic(a),
225 RuntimeValue::ExactReal(x) => ExactRef::Real(x),
226 RuntimeValue::Hyperreal(h) => ExactRef::Hyper(h),
227 RuntimeValue::Hypernatural(n) => ExactRef::Natural(n),
228 RuntimeValue::Ordinal(o) => ExactRef::Ordinal(o),
229 RuntimeValue::Depends(d) => ExactRef::Depends(d),
230 RuntimeValue::Converging(c) => ExactRef::Converging(c),
231 _ => return None,
232 })
233 }
234
235 fn standard_rational(&self) -> Option<Rational> {
236 match self {
237 RuntimeValue::Int(n) => Some(Rational::from_i64(*n)),
238 RuntimeValue::BigInt(b) => Some(Rational::from_bigint((**b).clone())),
239 RuntimeValue::Rational(r) => Some((**r).clone()),
240 RuntimeValue::Decimal(d) => Some(d.to_rational()),
241 RuntimeValue::Float(f) => rational_from_f64_exact(*f),
242 _ => None,
243 }
244 }
245
246 fn integer(&self) -> Option<BigInt> {
247 match self {
248 RuntimeValue::Int(n) => Some(BigInt::from_i64(*n)),
249 RuntimeValue::BigInt(b) => Some((**b).clone()),
250 _ => None,
251 }
252 }
253
254 fn exact_rational(&self) -> Option<Rational> {
255 match self {
256 RuntimeValue::Int(n) => Some(Rational::from_i64(*n)),
257 RuntimeValue::BigInt(b) => Some(Rational::from_bigint((**b).clone())),
258 RuntimeValue::Rational(r) => Some((**r).clone()),
259 _ => None,
260 }
261 }
262
263 fn is_standard_number(&self) -> bool {
264 matches!(
265 self,
266 RuntimeValue::Int(_)
267 | RuntimeValue::BigInt(_)
268 | RuntimeValue::Rational(_)
269 | RuntimeValue::Decimal(_)
270 | RuntimeValue::Float(_)
271 )
272 }
273
274 fn text(&self) -> Option<&str> {
275 match self {
276 RuntimeValue::Text(t) => Some(t.as_str()),
277 _ => None,
278 }
279 }
280
281 fn type_name(&self) -> String {
282 RuntimeValue::type_name(self).to_string()
283 }
284
285 fn display_string(&self) -> String {
286 self.to_display_string()
287 }
288
289 fn values_equal(&self, other: &Self) -> bool {
290 super::compare::values_equal(self, other)
291 }
292
293 fn is_nothing(&self) -> bool {
294 matches!(self, RuntimeValue::Nothing)
295 }
296
297 fn from_rational(r: Rational) -> Self {
298 RuntimeValue::from_rational(r)
299 }
300
301 fn from_bigint(b: BigInt) -> Self {
302 RuntimeValue::from_bigint(b)
303 }
304
305 fn boolean(b: bool) -> Self {
306 RuntimeValue::Bool(b)
307 }
308
309 fn nothing() -> Self {
310 RuntimeValue::Nothing
311 }
312
313 fn algebraic(a: Algebraic) -> Self {
314 RuntimeValue::Algebraic(Rc::new(a))
315 }
316
317 fn exact_real(x: ExactReal) -> Self {
318 RuntimeValue::ExactReal(Rc::new(x))
319 }
320
321 fn hyper(h: HyperValue) -> Self {
322 RuntimeValue::Hyperreal(Rc::new(h))
323 }
324
325 fn natural(n: NaturalValue) -> Self {
326 RuntimeValue::Hypernatural(Rc::new(n))
327 }
328
329 fn ordinal(o: Ordinal) -> Self {
330 RuntimeValue::Ordinal(Rc::new(o))
331 }
332
333 fn depends(d: DependsValue) -> Self {
334 RuntimeValue::Depends(Rc::new(d))
335 }
336
337 fn converging(c: Converging<Self>) -> Self {
338 RuntimeValue::Converging(Rc::new(c))
339 }
340}
341
342impl ValueAlgebra for RuntimeValue {
343 fn add(a: Self, b: Self) -> Result<Self, String> {
344 super::arith::add(a, b)
345 }
346
347 fn subtract(a: Self, b: Self) -> Result<Self, String> {
348 super::arith::subtract(a, b)
349 }
350
351 fn multiply(a: Self, b: Self) -> Result<Self, String> {
352 super::arith::multiply(a, b)
353 }
354
355 fn exact_divide(a: Self, b: Self) -> Result<Self, String> {
356 super::arith::exact_divide(a, b)
357 }
358
359 fn modulo(a: Self, b: Self) -> Result<Self, String> {
360 super::arith::modulo(a, b)
361 }
362
363 fn power(a: Self, b: Self) -> Result<Self, String> {
364 super::arith::power(a, b)
365 }
366
367 fn holds(rel: Rel, a: &Self, b: &Self) -> Result<bool, String> {
368 let op = match rel {
369 Rel::Lt => BinaryOpKind::Lt,
370 Rel::Gt => BinaryOpKind::Gt,
371 Rel::LtEq => BinaryOpKind::LtEq,
372 Rel::GtEq => BinaryOpKind::GtEq,
373 Rel::Eq => BinaryOpKind::Eq,
374 Rel::NotEq => BinaryOpKind::NotEq,
375 };
376 super::arith::binary_op(op, a.clone(), b.clone())?.decided_truth()
377 }
378
379 fn floor(v: Self) -> Result<Self, String> {
380 call_builtin(BuiltinId::Floor, vec![v])
381 }
382
383 fn ceil(v: Self) -> Result<Self, String> {
384 call_builtin(BuiltinId::Ceil, vec![v])
385 }
386
387 fn list(values: Vec<Self>) -> Self {
388 RuntimeValue::List(Rc::new(RefCell::new(ListRepr::from_values(values))))
389 }
390
391 fn shape(&self) -> Shape<Self> {
392 match self {
393 RuntimeValue::Bool(_) => Shape::Bool,
394 RuntimeValue::Int(n) => Shape::Int(*n),
395 RuntimeValue::Float(_) => Shape::Float,
396 RuntimeValue::BigInt(b) => Shape::BigInt((**b).clone()),
397 RuntimeValue::Rational(r) => Shape::Rational((**r).clone()),
398 RuntimeValue::Decimal(_) => Shape::Decimal,
399 RuntimeValue::Text(t) => Shape::Text(t.len()),
400 RuntimeValue::List(l) => Shape::List(l.borrow().to_values()),
401 RuntimeValue::Tuple(items) => Shape::Tuple(items.to_vec()),
402 _ => Shape::Other,
403 }
404 }
405}
406
407#[cfg(test)]
408#[path = "../../../logicaffeine_tests/unit/logicaffeine_compile/semantics/exact/tests.rs"]
409mod tests;