Skip to content

Commit

Permalink
chore: remove the as_field and from_field built-ins (#6845)
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite authored Dec 19, 2024
1 parent 021d62c commit 0558607
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 90 deletions.
2 changes: 0 additions & 2 deletions compiler/noirc_evaluator/src/acir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2760,8 +2760,6 @@ impl<'a> Context<'a> {
unreachable!("Expected static_assert to be removed by this point")
}
Intrinsic::StrAsBytes => unreachable!("Expected as_bytes to be removed by this point"),
Intrinsic::FromField => unreachable!("Expected from_field to be removed by this point"),
Intrinsic::AsField => unreachable!("Expected as_field to be removed by this point"),
Intrinsic::IsUnconstrained => {
unreachable!("Expected is_unconstrained to be removed by this point")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,9 +635,7 @@ impl<'block> BrilligBlock<'block> {
let array = array.extract_register();
self.brillig_context.load_instruction(destination, array);
}
Intrinsic::FromField
| Intrinsic::AsField
| Intrinsic::IsUnconstrained
Intrinsic::IsUnconstrained
| Intrinsic::DerivePedersenGenerators
| Intrinsic::ApplyRangeConstraint
| Intrinsic::StrAsBytes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,9 @@ impl DependencyContext {
Intrinsic::ArrayLen
| Intrinsic::ArrayRefCount
| Intrinsic::ArrayAsStrUnchecked
| Intrinsic::AsField
| Intrinsic::AsSlice
| Intrinsic::BlackBox(..)
| Intrinsic::DerivePedersenGenerators
| Intrinsic::FromField
| Intrinsic::Hint(..)
| Intrinsic::SlicePushBack
| Intrinsic::SlicePushFront
Expand Down Expand Up @@ -574,12 +572,10 @@ impl Context {
Intrinsic::ArrayLen
| Intrinsic::ArrayAsStrUnchecked
| Intrinsic::ArrayRefCount
| Intrinsic::AsField
| Intrinsic::AsSlice
| Intrinsic::BlackBox(..)
| Intrinsic::Hint(Hint::BlackBox)
| Intrinsic::DerivePedersenGenerators
| Intrinsic::FromField
| Intrinsic::SliceInsert
| Intrinsic::SlicePushBack
| Intrinsic::SlicePushFront
Expand Down
8 changes: 0 additions & 8 deletions compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ pub(crate) enum Intrinsic {
ToRadix(Endian),
BlackBox(BlackBoxFunc),
Hint(Hint),
FromField,
AsField,
AsWitness,
IsUnconstrained,
DerivePedersenGenerators,
Expand Down Expand Up @@ -97,8 +95,6 @@ impl std::fmt::Display for Intrinsic {
Intrinsic::ToRadix(Endian::Little) => write!(f, "to_le_radix"),
Intrinsic::BlackBox(function) => write!(f, "{function}"),
Intrinsic::Hint(Hint::BlackBox) => write!(f, "black_box"),
Intrinsic::FromField => write!(f, "from_field"),
Intrinsic::AsField => write!(f, "as_field"),
Intrinsic::AsWitness => write!(f, "as_witness"),
Intrinsic::IsUnconstrained => write!(f, "is_unconstrained"),
Intrinsic::DerivePedersenGenerators => write!(f, "derive_pedersen_generators"),
Expand Down Expand Up @@ -140,8 +136,6 @@ impl Intrinsic {
| Intrinsic::SlicePushFront
| Intrinsic::SliceInsert
| Intrinsic::StrAsBytes
| Intrinsic::FromField
| Intrinsic::AsField
| Intrinsic::IsUnconstrained
| Intrinsic::DerivePedersenGenerators
| Intrinsic::FieldLessThan => false,
Expand Down Expand Up @@ -213,8 +207,6 @@ impl Intrinsic {
"to_be_radix" => Some(Intrinsic::ToRadix(Endian::Big)),
"to_le_bits" => Some(Intrinsic::ToBits(Endian::Little)),
"to_be_bits" => Some(Intrinsic::ToBits(Endian::Big)),
"from_field" => Some(Intrinsic::FromField),
"as_field" => Some(Intrinsic::AsField),
"as_witness" => Some(Intrinsic::AsWitness),
"is_unconstrained" => Some(Intrinsic::IsUnconstrained),
"derive_pedersen_generators" => Some(Intrinsic::DerivePedersenGenerators),
Expand Down
25 changes: 0 additions & 25 deletions compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,31 +330,6 @@ pub(super) fn simplify_call(
Intrinsic::BlackBox(bb_func) => {
simplify_black_box_func(bb_func, arguments, dfg, block, call_stack)
}
Intrinsic::AsField => {
let instruction = Instruction::Cast(arguments[0], NumericType::NativeField);
SimplifyResult::SimplifiedToInstruction(instruction)
}
Intrinsic::FromField => {
let incoming_type = Type::field();
let target_type = return_type.clone().unwrap();

let truncate = Instruction::Truncate {
value: arguments[0],
bit_size: target_type.bit_size(),
max_bit_size: incoming_type.bit_size(),
};
let truncated_value = dfg
.insert_instruction_and_results(
truncate,
block,
Some(vec![incoming_type]),
call_stack,
)
.first();

let instruction = Instruction::Cast(truncated_value, target_type.unwrap_numeric());
SimplifyResult::SimplifiedToInstruction(instruction)
}
Intrinsic::AsWitness => SimplifyResult::None,
Intrinsic::IsUnconstrained => SimplifyResult::None,
Intrinsic::DerivePedersenGenerators => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,6 @@ impl Context {
| Intrinsic::ToRadix(_)
| Intrinsic::BlackBox(_)
| Intrinsic::Hint(Hint::BlackBox)
| Intrinsic::FromField
| Intrinsic::AsField
| Intrinsic::AsSlice
| Intrinsic::AsWitness
| Intrinsic::IsUnconstrained
Expand Down
2 changes: 0 additions & 2 deletions compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,6 @@ fn slice_capacity_change(
| Intrinsic::StrAsBytes
| Intrinsic::BlackBox(_)
| Intrinsic::Hint(Hint::BlackBox)
| Intrinsic::FromField
| Intrinsic::AsField
| Intrinsic::AsWitness
| Intrinsic::IsUnconstrained
| Intrinsic::DerivePedersenGenerators
Expand Down
23 changes: 0 additions & 23 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"array_len" => array_len(interner, arguments, location),
"array_refcount" => Ok(Value::U32(0)),
"assert_constant" => Ok(Value::Bool(true)),
"as_field" => as_field(interner, arguments, location),
"as_slice" => as_slice(interner, arguments, location),
"ctstring_eq" => ctstring_eq(arguments, location),
"ctstring_hash" => ctstring_hash(arguments, location),
Expand Down Expand Up @@ -117,7 +116,6 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"field_less_than" => field_less_than(arguments, location),
"fmtstr_as_ctstring" => fmtstr_as_ctstring(interner, arguments, location),
"fmtstr_quoted_contents" => fmtstr_quoted_contents(interner, arguments, location),
"from_field" => from_field(interner, arguments, return_type, location),
"fresh_type_variable" => fresh_type_variable(interner),
"function_def_add_attribute" => function_def_add_attribute(self, arguments, location),
"function_def_body" => function_def_body(interner, arguments, location),
Expand Down Expand Up @@ -292,16 +290,6 @@ fn array_as_str_unchecked(
Ok(Value::String(Rc::new(string)))
}

// fn as_field<T>(x: T) -> Field {}
fn as_field(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let (value, value_location) = check_one_argument(arguments, location)?;
Interpreter::evaluate_cast_one_step(&Type::FieldElement, value_location, value, interner)
}

fn as_slice(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
Expand Down Expand Up @@ -2236,17 +2224,6 @@ fn fmtstr_quoted_contents(
Ok(Value::Quoted(Rc::new(tokens)))
}

// fn from_field<T>(x: Field) -> T {}
fn from_field(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
return_type: Type,
location: Location,
) -> IResult<Value> {
let (value, value_location) = check_one_argument(arguments, location)?;
Interpreter::evaluate_cast_one_step(&return_type, value_location, value, interner)
}

// fn fresh_type_variable() -> Type
fn fresh_type_variable(interner: &NodeInterner) -> IResult<Value> {
Ok(Value::Type(interner.next_type_variable_with_kind(Kind::Any)))
Expand Down
48 changes: 48 additions & 0 deletions noir_stdlib/src/convert.nr
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,51 @@ impl From<bool> for Field {
}
}
// docs:end:from-impls

/// A generic interface for casting between primitive types,
/// equivalent of using the `as` keyword between values.
///
/// # Example
///
/// ```
/// let x: Field = 1234567890;
/// let y: u8 = x as u8;
/// let z: u8 = x.as_();
/// assert_eq(y, z);
/// ```
pub trait AsPrimitive<T> {
/// The equivalent of doing `self as T`.
fn as_(self) -> T;
}

#[generate_as_primitive_impls]
comptime fn generate_as_primitive_impls(_: FunctionDefinition) -> Quoted {
let types = [
quote { bool },
quote { u8 },
quote { u16 },
quote { u32 },
quote { u64 },
quote { i8 },
quote { i16 },
quote { i32 },
quote { i64 },
quote { Field },
];

let mut impls = &[];
for type1 in types {
for type2 in types {
impls = impls.push_back(
quote {
impl AsPrimitive<$type1> for $type2 {
fn as_(self) -> $type1 {
self as $type1
}
}
},
);
}
}
impls.join(quote {})
}
37 changes: 20 additions & 17 deletions noir_stdlib/src/lib.nr
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub mod mem;
pub mod panic;
pub mod hint;

use convert::AsPrimitive;

// Oracle calls are required to be wrapped in an unconstrained function
// Thus, the only argument to the `println` oracle is expected to always be an ident
#[oracle(print)]
Expand Down Expand Up @@ -89,28 +91,29 @@ pub fn assert_constant<T>(x: T) {}
#[builtin(static_assert)]
pub fn static_assert<let N: u32>(predicate: bool, message: str<N>) {}

// from_field and as_field are private since they are not valid for every type.
// `as` should be the default for users to cast between primitive types, and in the future
// traits can be used to work with generic types.
#[builtin(from_field)]
fn from_field<T>(x: Field) -> T {}

#[builtin(as_field)]
fn as_field<T>(x: T) -> Field {}

pub fn wrapping_add<T>(x: T, y: T) -> T {
crate::from_field(crate::as_field(x) + crate::as_field(y))
pub fn wrapping_add<T>(x: T, y: T) -> T
where
T: AsPrimitive<Field>,
Field: AsPrimitive<T>,
{
AsPrimitive::as_(x.as_() + y.as_())
}

pub fn wrapping_sub<T>(x: T, y: T) -> T {
pub fn wrapping_sub<T>(x: T, y: T) -> T
where
T: AsPrimitive<Field>,
Field: AsPrimitive<T>,
{
//340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow
crate::from_field(
crate::as_field(x) + 340282366920938463463374607431768211456 - crate::as_field(y),
)
AsPrimitive::as_(x.as_() + 340282366920938463463374607431768211456 - y.as_())
}

pub fn wrapping_mul<T>(x: T, y: T) -> T {
crate::from_field(crate::as_field(x) * crate::as_field(y))
pub fn wrapping_mul<T>(x: T, y: T) -> T
where
T: AsPrimitive<Field>,
Field: AsPrimitive<T>,
{
AsPrimitive::as_(x.as_() * y.as_())
}

#[builtin(as_witness)]
Expand Down
15 changes: 11 additions & 4 deletions noir_stdlib/src/uint128.nr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::cmp::{Eq, Ord, Ordering};
use crate::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Not, Rem, Shl, Shr, Sub};
use super::convert::AsPrimitive;

global pow64: Field = 18446744073709551616; //2^64;
global pow63: Field = 9223372036854775808; // 2^63;
Expand Down Expand Up @@ -139,17 +140,23 @@ impl U128 {
}
}

pub fn from_integer<T>(i: T) -> U128 {
let f = crate::as_field(i);
pub fn from_integer<T>(i: T) -> U128
where
T: AsPrimitive<Field>,
{
let f = i.as_();
// Reject values which would overflow a u128
f.assert_max_bit_size::<128>();
let lo = f as u64 as Field;
let hi = (f - lo) / pow64;
U128 { lo, hi }
}

pub fn to_integer<T>(self) -> T {
crate::from_field(self.lo + self.hi * pow64)
pub fn to_integer<T>(self) -> T
where
Field: AsPrimitive<T>,
{
AsPrimitive::as_(self.lo + self.hi * pow64)
}

fn wrapping_mul(self: Self, b: U128) -> U128 {
Expand Down

0 comments on commit 0558607

Please sign in to comment.