use crate::{
core::{
actually_used_field::ActuallyUsedField,
expressions::{expr::Expr, field_expr::FieldExpr},
global_value::global_expr_store::with_global_expr_store_as_local,
},
utils::field::{BaseField, ScalarField},
};
use std::marker::PhantomData;
#[derive(Clone, Copy, Debug)]
pub struct FieldValue<F: ActuallyUsedField> {
pub(super) id: usize,
pub(super) marker: PhantomData<F>,
}
impl<F: ActuallyUsedField> FieldValue<F> {
pub fn new(expr: FieldExpr<F, FieldValue<F>>) -> FieldValue<F> {
let id = with_global_expr_store_as_local(|expr_store| {
expr_store.new_expr(F::field_expr_to_expr(
expr.clone().apply(|dep: FieldValue<F>| dep.id),
))
});
FieldValue {
id,
marker: PhantomData,
}
}
pub fn get_id(&self) -> usize {
self.id
}
pub fn from_id(id: usize) -> FieldValue<F> {
#[cfg(debug_assertions)]
with_global_expr_store_as_local(|expr_store| {
assert!(expr_store.contains_expr_id(id));
let _ = F::bounds_to_field_bounds(*expr_store.get_bounds(id));
});
FieldValue {
id,
marker: PhantomData,
}
}
pub fn from_expr(expr: Expr<usize>) -> FieldValue<F> {
let id = with_global_expr_store_as_local(|expr_store| {
let id = expr_store.new_expr(expr);
#[cfg(debug_assertions)]
let _ = F::bounds_to_field_bounds(*expr_store.get_bounds(id));
id
});
FieldValue {
id,
marker: PhantomData,
}
}
}
impl From<FieldValue<BaseField>> for BaseField {
fn from(value: FieldValue<BaseField>) -> Self {
if let Expr::Base(FieldExpr::Val(v)) = value.expr() {
v
} else {
panic!("non-constant instance of FieldValue<BaseField>");
}
}
}
impl From<FieldValue<ScalarField>> for ScalarField {
fn from(value: FieldValue<ScalarField>) -> Self {
if let Expr::Scalar(FieldExpr::Val(v)) = value.expr() {
v
} else {
panic!("non-constant instance of FieldValue<ScalarField>");
}
}
}