leo_ast/interpreter_value/
core_function.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use std::collections::HashMap;
18
19use rand::Rng as _;
20use rand_chacha::ChaCha20Rng;
21
22use crate::{
23    CoreFunction,
24    Expression,
25    interpreter_value::{ExpectTc, Value},
26    tc_fail2,
27};
28use leo_errors::{InterpreterHalt, Result};
29use leo_span::{Span, Symbol};
30
31use super::*;
32
33/// A context in which we can evaluate core functions.
34///
35/// This is intended to be implemented by `Cursor`, which will be used during
36/// execution of the interpreter, and by `Vec<Value>`, which will be used
37/// during compile time evaluation for constant folding.
38///
39/// The default implementations for `rng`, `set_block_height`, and mapping lookup
40/// do nothing, as those features will not be available during compile time
41/// evaluation.
42pub trait CoreFunctionHelper {
43    fn pop_value_impl(&mut self) -> Option<Value>;
44
45    fn pop_value(&mut self) -> Result<Value> {
46        match self.pop_value_impl() {
47            Some(v) => Ok(v),
48            None => {
49                Err(InterpreterHalt::new("value expected - this may be a bug in the Leo interpreter".to_string())
50                    .into())
51            }
52        }
53    }
54
55    fn set_block_height(&mut self, _height: u32) {}
56
57    fn lookup_mapping(&self, _program: Option<Symbol>, _name: Symbol) -> Option<&HashMap<Value, Value>> {
58        None
59    }
60
61    fn lookup_mapping_mut(&mut self, _program: Option<Symbol>, _name: Symbol) -> Option<&mut HashMap<Value, Value>> {
62        None
63    }
64
65    fn mapping_get(&self, program: Option<Symbol>, name: Symbol, key: &Value) -> Option<Value> {
66        self.lookup_mapping(program, name).and_then(|map| map.get(key).cloned())
67    }
68
69    fn mapping_set(&mut self, program: Option<Symbol>, name: Symbol, key: Value, value: Value) -> Option<()> {
70        self.lookup_mapping_mut(program, name).map(|map| {
71            map.insert(key, value);
72        })
73    }
74
75    fn mapping_remove(&mut self, program: Option<Symbol>, name: Symbol, key: &Value) -> Option<()> {
76        self.lookup_mapping_mut(program, name).map(|map| {
77            map.remove(key);
78        })
79    }
80
81    fn rng(&mut self) -> Option<&mut ChaCha20Rng> {
82        None
83    }
84}
85
86impl CoreFunctionHelper for Vec<Value> {
87    fn pop_value_impl(&mut self) -> Option<Value> {
88        self.pop()
89    }
90}
91
92pub fn evaluate_core_function(
93    helper: &mut dyn CoreFunctionHelper,
94    core_function: CoreFunction,
95    arguments: &[Expression],
96    span: Span,
97) -> Result<Option<Value>> {
98    use snarkvm::{
99        prelude::LiteralType,
100        synthesizer::program::{CommitVariant, HashVariant},
101    };
102
103    let dohash = |helper: &mut dyn CoreFunctionHelper, variant: HashVariant, typ: LiteralType| -> Result<Value> {
104        let input = helper.pop_value()?.try_into().expect_tc(span)?;
105        let value = snarkvm::synthesizer::program::evaluate_hash(
106            variant,
107            &input,
108            &snarkvm::prelude::PlaintextType::Literal(typ),
109        )?;
110        Ok(value.into())
111    };
112
113    let docommit = |helper: &mut dyn CoreFunctionHelper, variant: CommitVariant, typ: LiteralType| -> Result<Value> {
114        let randomizer: Scalar = helper.pop_value()?.try_into().expect_tc(span)?;
115        let input: SvmValue = helper.pop_value()?.try_into().expect_tc(span)?;
116        let value = snarkvm::synthesizer::program::evaluate_commit(variant, &input, &randomizer, typ)?;
117        Ok(value.into())
118    };
119
120    macro_rules! random {
121        ($ty: ident) => {{
122            let Some(rng) = helper.rng() else {
123                return Ok(None);
124            };
125            let value: $ty = rng.r#gen();
126            value.into()
127        }};
128    }
129
130    let value = match core_function {
131        CoreFunction::BHP256CommitToAddress => docommit(helper, CommitVariant::CommitBHP256, LiteralType::Address)?,
132        CoreFunction::BHP256CommitToField => docommit(helper, CommitVariant::CommitBHP256, LiteralType::Field)?,
133        CoreFunction::BHP256CommitToGroup => docommit(helper, CommitVariant::CommitBHP256, LiteralType::Group)?,
134        CoreFunction::BHP256HashToAddress => dohash(helper, HashVariant::HashBHP256, LiteralType::Address)?,
135        CoreFunction::BHP256HashToField => dohash(helper, HashVariant::HashBHP256, LiteralType::Field)?,
136        CoreFunction::BHP256HashToGroup => dohash(helper, HashVariant::HashBHP256, LiteralType::Group)?,
137        CoreFunction::BHP256HashToI8 => dohash(helper, HashVariant::HashBHP256, LiteralType::I8)?,
138        CoreFunction::BHP256HashToI16 => dohash(helper, HashVariant::HashBHP256, LiteralType::I16)?,
139        CoreFunction::BHP256HashToI32 => dohash(helper, HashVariant::HashBHP256, LiteralType::I32)?,
140        CoreFunction::BHP256HashToI64 => dohash(helper, HashVariant::HashBHP256, LiteralType::I64)?,
141        CoreFunction::BHP256HashToI128 => dohash(helper, HashVariant::HashBHP256, LiteralType::I128)?,
142        CoreFunction::BHP256HashToU8 => dohash(helper, HashVariant::HashBHP256, LiteralType::U8)?,
143        CoreFunction::BHP256HashToU16 => dohash(helper, HashVariant::HashBHP256, LiteralType::U16)?,
144        CoreFunction::BHP256HashToU32 => dohash(helper, HashVariant::HashBHP256, LiteralType::U32)?,
145        CoreFunction::BHP256HashToU64 => dohash(helper, HashVariant::HashBHP256, LiteralType::U64)?,
146        CoreFunction::BHP256HashToU128 => dohash(helper, HashVariant::HashBHP256, LiteralType::U128)?,
147        CoreFunction::BHP256HashToScalar => dohash(helper, HashVariant::HashBHP256, LiteralType::Scalar)?,
148        CoreFunction::BHP512CommitToAddress => docommit(helper, CommitVariant::CommitBHP512, LiteralType::Address)?,
149        CoreFunction::BHP512CommitToField => docommit(helper, CommitVariant::CommitBHP512, LiteralType::Field)?,
150        CoreFunction::BHP512CommitToGroup => docommit(helper, CommitVariant::CommitBHP512, LiteralType::Group)?,
151        CoreFunction::BHP512HashToAddress => dohash(helper, HashVariant::HashBHP512, LiteralType::Address)?,
152        CoreFunction::BHP512HashToField => dohash(helper, HashVariant::HashBHP512, LiteralType::Field)?,
153        CoreFunction::BHP512HashToGroup => dohash(helper, HashVariant::HashBHP512, LiteralType::Group)?,
154        CoreFunction::BHP512HashToI8 => dohash(helper, HashVariant::HashBHP512, LiteralType::I8)?,
155        CoreFunction::BHP512HashToI16 => dohash(helper, HashVariant::HashBHP512, LiteralType::I16)?,
156        CoreFunction::BHP512HashToI32 => dohash(helper, HashVariant::HashBHP512, LiteralType::I32)?,
157        CoreFunction::BHP512HashToI64 => dohash(helper, HashVariant::HashBHP512, LiteralType::I64)?,
158        CoreFunction::BHP512HashToI128 => dohash(helper, HashVariant::HashBHP512, LiteralType::I128)?,
159        CoreFunction::BHP512HashToU8 => dohash(helper, HashVariant::HashBHP512, LiteralType::U8)?,
160        CoreFunction::BHP512HashToU16 => dohash(helper, HashVariant::HashBHP512, LiteralType::U16)?,
161        CoreFunction::BHP512HashToU32 => dohash(helper, HashVariant::HashBHP512, LiteralType::U32)?,
162        CoreFunction::BHP512HashToU64 => dohash(helper, HashVariant::HashBHP512, LiteralType::U64)?,
163        CoreFunction::BHP512HashToU128 => dohash(helper, HashVariant::HashBHP512, LiteralType::U128)?,
164        CoreFunction::BHP512HashToScalar => dohash(helper, HashVariant::HashBHP512, LiteralType::Scalar)?,
165        CoreFunction::BHP768CommitToAddress => docommit(helper, CommitVariant::CommitBHP768, LiteralType::Address)?,
166        CoreFunction::BHP768CommitToField => docommit(helper, CommitVariant::CommitBHP768, LiteralType::Field)?,
167        CoreFunction::BHP768CommitToGroup => docommit(helper, CommitVariant::CommitBHP768, LiteralType::Group)?,
168        CoreFunction::BHP768HashToAddress => dohash(helper, HashVariant::HashBHP768, LiteralType::Address)?,
169        CoreFunction::BHP768HashToField => dohash(helper, HashVariant::HashBHP768, LiteralType::Field)?,
170        CoreFunction::BHP768HashToGroup => dohash(helper, HashVariant::HashBHP768, LiteralType::Group)?,
171        CoreFunction::BHP768HashToI8 => dohash(helper, HashVariant::HashBHP768, LiteralType::I8)?,
172        CoreFunction::BHP768HashToI16 => dohash(helper, HashVariant::HashBHP768, LiteralType::I16)?,
173        CoreFunction::BHP768HashToI32 => dohash(helper, HashVariant::HashBHP768, LiteralType::I32)?,
174        CoreFunction::BHP768HashToI64 => dohash(helper, HashVariant::HashBHP768, LiteralType::I64)?,
175        CoreFunction::BHP768HashToI128 => dohash(helper, HashVariant::HashBHP768, LiteralType::I128)?,
176        CoreFunction::BHP768HashToU8 => dohash(helper, HashVariant::HashBHP768, LiteralType::U8)?,
177        CoreFunction::BHP768HashToU16 => dohash(helper, HashVariant::HashBHP768, LiteralType::U16)?,
178        CoreFunction::BHP768HashToU32 => dohash(helper, HashVariant::HashBHP768, LiteralType::U32)?,
179        CoreFunction::BHP768HashToU64 => dohash(helper, HashVariant::HashBHP768, LiteralType::U64)?,
180        CoreFunction::BHP768HashToU128 => dohash(helper, HashVariant::HashBHP768, LiteralType::U128)?,
181        CoreFunction::BHP768HashToScalar => dohash(helper, HashVariant::HashBHP768, LiteralType::Scalar)?,
182        CoreFunction::BHP1024CommitToAddress => docommit(helper, CommitVariant::CommitBHP1024, LiteralType::Address)?,
183        CoreFunction::BHP1024CommitToField => docommit(helper, CommitVariant::CommitBHP1024, LiteralType::Field)?,
184        CoreFunction::BHP1024CommitToGroup => docommit(helper, CommitVariant::CommitBHP1024, LiteralType::Group)?,
185        CoreFunction::BHP1024HashToAddress => dohash(helper, HashVariant::HashBHP1024, LiteralType::Address)?,
186        CoreFunction::BHP1024HashToField => dohash(helper, HashVariant::HashBHP1024, LiteralType::Field)?,
187        CoreFunction::BHP1024HashToGroup => dohash(helper, HashVariant::HashBHP1024, LiteralType::Group)?,
188        CoreFunction::BHP1024HashToI8 => dohash(helper, HashVariant::HashBHP1024, LiteralType::I8)?,
189        CoreFunction::BHP1024HashToI16 => dohash(helper, HashVariant::HashBHP1024, LiteralType::I16)?,
190        CoreFunction::BHP1024HashToI32 => dohash(helper, HashVariant::HashBHP1024, LiteralType::I32)?,
191        CoreFunction::BHP1024HashToI64 => dohash(helper, HashVariant::HashBHP1024, LiteralType::I64)?,
192        CoreFunction::BHP1024HashToI128 => dohash(helper, HashVariant::HashBHP1024, LiteralType::I128)?,
193        CoreFunction::BHP1024HashToU8 => dohash(helper, HashVariant::HashBHP1024, LiteralType::U8)?,
194        CoreFunction::BHP1024HashToU16 => dohash(helper, HashVariant::HashBHP1024, LiteralType::U16)?,
195        CoreFunction::BHP1024HashToU32 => dohash(helper, HashVariant::HashBHP1024, LiteralType::U32)?,
196        CoreFunction::BHP1024HashToU64 => dohash(helper, HashVariant::HashBHP1024, LiteralType::U64)?,
197        CoreFunction::BHP1024HashToU128 => dohash(helper, HashVariant::HashBHP1024, LiteralType::U128)?,
198        CoreFunction::BHP1024HashToScalar => dohash(helper, HashVariant::HashBHP1024, LiteralType::Scalar)?,
199        CoreFunction::Keccak256HashToAddress => dohash(helper, HashVariant::HashKeccak256, LiteralType::Address)?,
200        CoreFunction::Keccak256HashToField => dohash(helper, HashVariant::HashKeccak256, LiteralType::Field)?,
201        CoreFunction::Keccak256HashToGroup => dohash(helper, HashVariant::HashKeccak256, LiteralType::Group)?,
202        CoreFunction::Keccak256HashToI8 => dohash(helper, HashVariant::HashKeccak256, LiteralType::I8)?,
203        CoreFunction::Keccak256HashToI16 => dohash(helper, HashVariant::HashKeccak256, LiteralType::I16)?,
204        CoreFunction::Keccak256HashToI32 => dohash(helper, HashVariant::HashKeccak256, LiteralType::I32)?,
205        CoreFunction::Keccak256HashToI64 => dohash(helper, HashVariant::HashKeccak256, LiteralType::I64)?,
206        CoreFunction::Keccak256HashToI128 => dohash(helper, HashVariant::HashKeccak256, LiteralType::I128)?,
207        CoreFunction::Keccak256HashToU8 => dohash(helper, HashVariant::HashKeccak256, LiteralType::U8)?,
208        CoreFunction::Keccak256HashToU16 => dohash(helper, HashVariant::HashKeccak256, LiteralType::U16)?,
209        CoreFunction::Keccak256HashToU32 => dohash(helper, HashVariant::HashKeccak256, LiteralType::U32)?,
210        CoreFunction::Keccak256HashToU64 => dohash(helper, HashVariant::HashKeccak256, LiteralType::U64)?,
211        CoreFunction::Keccak256HashToU128 => dohash(helper, HashVariant::HashKeccak256, LiteralType::U128)?,
212        CoreFunction::Keccak256HashToScalar => dohash(helper, HashVariant::HashKeccak256, LiteralType::Scalar)?,
213        CoreFunction::Keccak384HashToAddress => dohash(helper, HashVariant::HashKeccak384, LiteralType::Address)?,
214        CoreFunction::Keccak384HashToField => dohash(helper, HashVariant::HashKeccak384, LiteralType::Field)?,
215        CoreFunction::Keccak384HashToGroup => dohash(helper, HashVariant::HashKeccak384, LiteralType::Group)?,
216        CoreFunction::Keccak384HashToI8 => dohash(helper, HashVariant::HashKeccak384, LiteralType::I8)?,
217        CoreFunction::Keccak384HashToI16 => dohash(helper, HashVariant::HashKeccak384, LiteralType::I16)?,
218        CoreFunction::Keccak384HashToI32 => dohash(helper, HashVariant::HashKeccak384, LiteralType::I32)?,
219        CoreFunction::Keccak384HashToI64 => dohash(helper, HashVariant::HashKeccak384, LiteralType::I64)?,
220        CoreFunction::Keccak384HashToI128 => dohash(helper, HashVariant::HashKeccak384, LiteralType::I128)?,
221        CoreFunction::Keccak384HashToU8 => dohash(helper, HashVariant::HashKeccak384, LiteralType::U8)?,
222        CoreFunction::Keccak384HashToU16 => dohash(helper, HashVariant::HashKeccak384, LiteralType::U16)?,
223        CoreFunction::Keccak384HashToU32 => dohash(helper, HashVariant::HashKeccak384, LiteralType::U32)?,
224        CoreFunction::Keccak384HashToU64 => dohash(helper, HashVariant::HashKeccak384, LiteralType::U64)?,
225        CoreFunction::Keccak384HashToU128 => dohash(helper, HashVariant::HashKeccak384, LiteralType::U128)?,
226        CoreFunction::Keccak384HashToScalar => dohash(helper, HashVariant::HashKeccak384, LiteralType::Scalar)?,
227        CoreFunction::Keccak512HashToAddress => dohash(helper, HashVariant::HashKeccak512, LiteralType::Address)?,
228        CoreFunction::Keccak512HashToField => dohash(helper, HashVariant::HashKeccak512, LiteralType::Field)?,
229        CoreFunction::Keccak512HashToGroup => dohash(helper, HashVariant::HashKeccak512, LiteralType::Group)?,
230        CoreFunction::Keccak512HashToI8 => dohash(helper, HashVariant::HashKeccak512, LiteralType::I8)?,
231        CoreFunction::Keccak512HashToI16 => dohash(helper, HashVariant::HashKeccak512, LiteralType::I16)?,
232        CoreFunction::Keccak512HashToI32 => dohash(helper, HashVariant::HashKeccak512, LiteralType::I32)?,
233        CoreFunction::Keccak512HashToI64 => dohash(helper, HashVariant::HashKeccak512, LiteralType::I64)?,
234        CoreFunction::Keccak512HashToI128 => dohash(helper, HashVariant::HashKeccak512, LiteralType::I128)?,
235        CoreFunction::Keccak512HashToU8 => dohash(helper, HashVariant::HashKeccak512, LiteralType::U8)?,
236        CoreFunction::Keccak512HashToU16 => dohash(helper, HashVariant::HashKeccak512, LiteralType::U16)?,
237        CoreFunction::Keccak512HashToU32 => dohash(helper, HashVariant::HashKeccak512, LiteralType::U32)?,
238        CoreFunction::Keccak512HashToU64 => dohash(helper, HashVariant::HashKeccak512, LiteralType::U64)?,
239        CoreFunction::Keccak512HashToU128 => dohash(helper, HashVariant::HashKeccak512, LiteralType::U128)?,
240        CoreFunction::Keccak512HashToScalar => dohash(helper, HashVariant::HashKeccak512, LiteralType::Scalar)?,
241        CoreFunction::Pedersen64CommitToAddress => docommit(helper, CommitVariant::CommitPED64, LiteralType::Address)?,
242        CoreFunction::Pedersen64CommitToField => docommit(helper, CommitVariant::CommitPED64, LiteralType::Field)?,
243        CoreFunction::Pedersen64CommitToGroup => docommit(helper, CommitVariant::CommitPED64, LiteralType::Group)?,
244        CoreFunction::Pedersen64HashToAddress => dohash(helper, HashVariant::HashPED64, LiteralType::Address)?,
245        CoreFunction::Pedersen64HashToField => dohash(helper, HashVariant::HashPED64, LiteralType::Field)?,
246        CoreFunction::Pedersen64HashToGroup => dohash(helper, HashVariant::HashPED64, LiteralType::Group)?,
247        CoreFunction::Pedersen64HashToI8 => dohash(helper, HashVariant::HashPED64, LiteralType::I8)?,
248        CoreFunction::Pedersen64HashToI16 => dohash(helper, HashVariant::HashPED64, LiteralType::I16)?,
249        CoreFunction::Pedersen64HashToI32 => dohash(helper, HashVariant::HashPED64, LiteralType::I32)?,
250        CoreFunction::Pedersen64HashToI64 => dohash(helper, HashVariant::HashPED64, LiteralType::I64)?,
251        CoreFunction::Pedersen64HashToI128 => dohash(helper, HashVariant::HashPED64, LiteralType::I128)?,
252        CoreFunction::Pedersen64HashToU8 => dohash(helper, HashVariant::HashPED64, LiteralType::U8)?,
253        CoreFunction::Pedersen64HashToU16 => dohash(helper, HashVariant::HashPED64, LiteralType::U16)?,
254        CoreFunction::Pedersen64HashToU32 => dohash(helper, HashVariant::HashPED64, LiteralType::U32)?,
255        CoreFunction::Pedersen64HashToU64 => dohash(helper, HashVariant::HashPED64, LiteralType::U64)?,
256        CoreFunction::Pedersen64HashToU128 => dohash(helper, HashVariant::HashPED64, LiteralType::U128)?,
257        CoreFunction::Pedersen64HashToScalar => dohash(helper, HashVariant::HashPED64, LiteralType::Scalar)?,
258        CoreFunction::Pedersen128CommitToAddress => {
259            docommit(helper, CommitVariant::CommitPED128, LiteralType::Address)?
260        }
261        CoreFunction::Pedersen128CommitToField => docommit(helper, CommitVariant::CommitPED128, LiteralType::Field)?,
262        CoreFunction::Pedersen128CommitToGroup => docommit(helper, CommitVariant::CommitPED128, LiteralType::Group)?,
263        CoreFunction::Pedersen128HashToAddress => dohash(helper, HashVariant::HashPED128, LiteralType::Address)?,
264        CoreFunction::Pedersen128HashToField => dohash(helper, HashVariant::HashPED128, LiteralType::Field)?,
265        CoreFunction::Pedersen128HashToGroup => dohash(helper, HashVariant::HashPED128, LiteralType::Group)?,
266        CoreFunction::Pedersen128HashToI8 => dohash(helper, HashVariant::HashPED128, LiteralType::I8)?,
267        CoreFunction::Pedersen128HashToI16 => dohash(helper, HashVariant::HashPED128, LiteralType::I16)?,
268        CoreFunction::Pedersen128HashToI32 => dohash(helper, HashVariant::HashPED128, LiteralType::I32)?,
269        CoreFunction::Pedersen128HashToI64 => dohash(helper, HashVariant::HashPED128, LiteralType::I64)?,
270        CoreFunction::Pedersen128HashToI128 => dohash(helper, HashVariant::HashPED128, LiteralType::I128)?,
271        CoreFunction::Pedersen128HashToU8 => dohash(helper, HashVariant::HashPED128, LiteralType::U8)?,
272        CoreFunction::Pedersen128HashToU16 => dohash(helper, HashVariant::HashPED128, LiteralType::U16)?,
273        CoreFunction::Pedersen128HashToU32 => dohash(helper, HashVariant::HashPED128, LiteralType::U32)?,
274        CoreFunction::Pedersen128HashToU64 => dohash(helper, HashVariant::HashPED128, LiteralType::U64)?,
275        CoreFunction::Pedersen128HashToU128 => dohash(helper, HashVariant::HashPED128, LiteralType::U128)?,
276        CoreFunction::Pedersen128HashToScalar => dohash(helper, HashVariant::HashPED128, LiteralType::Scalar)?,
277        CoreFunction::Poseidon2HashToAddress => dohash(helper, HashVariant::HashPSD2, LiteralType::Address)?,
278        CoreFunction::Poseidon2HashToField => dohash(helper, HashVariant::HashPSD2, LiteralType::Field)?,
279        CoreFunction::Poseidon2HashToGroup => dohash(helper, HashVariant::HashPSD2, LiteralType::Group)?,
280        CoreFunction::Poseidon2HashToI8 => dohash(helper, HashVariant::HashPSD2, LiteralType::I8)?,
281        CoreFunction::Poseidon2HashToI16 => dohash(helper, HashVariant::HashPSD2, LiteralType::I16)?,
282        CoreFunction::Poseidon2HashToI32 => dohash(helper, HashVariant::HashPSD2, LiteralType::I32)?,
283        CoreFunction::Poseidon2HashToI64 => dohash(helper, HashVariant::HashPSD2, LiteralType::I64)?,
284        CoreFunction::Poseidon2HashToI128 => dohash(helper, HashVariant::HashPSD2, LiteralType::I128)?,
285        CoreFunction::Poseidon2HashToU8 => dohash(helper, HashVariant::HashPSD2, LiteralType::U8)?,
286        CoreFunction::Poseidon2HashToU16 => dohash(helper, HashVariant::HashPSD2, LiteralType::U16)?,
287        CoreFunction::Poseidon2HashToU32 => dohash(helper, HashVariant::HashPSD2, LiteralType::U32)?,
288        CoreFunction::Poseidon2HashToU64 => dohash(helper, HashVariant::HashPSD2, LiteralType::U64)?,
289        CoreFunction::Poseidon2HashToU128 => dohash(helper, HashVariant::HashPSD2, LiteralType::U128)?,
290        CoreFunction::Poseidon2HashToScalar => dohash(helper, HashVariant::HashPSD2, LiteralType::Scalar)?,
291        CoreFunction::Poseidon4HashToAddress => dohash(helper, HashVariant::HashPSD4, LiteralType::Address)?,
292        CoreFunction::Poseidon4HashToField => dohash(helper, HashVariant::HashPSD4, LiteralType::Field)?,
293        CoreFunction::Poseidon4HashToGroup => dohash(helper, HashVariant::HashPSD4, LiteralType::Group)?,
294        CoreFunction::Poseidon4HashToI8 => dohash(helper, HashVariant::HashPSD4, LiteralType::I8)?,
295        CoreFunction::Poseidon4HashToI16 => dohash(helper, HashVariant::HashPSD4, LiteralType::I16)?,
296        CoreFunction::Poseidon4HashToI32 => dohash(helper, HashVariant::HashPSD4, LiteralType::I32)?,
297        CoreFunction::Poseidon4HashToI64 => dohash(helper, HashVariant::HashPSD4, LiteralType::I64)?,
298        CoreFunction::Poseidon4HashToI128 => dohash(helper, HashVariant::HashPSD4, LiteralType::I128)?,
299        CoreFunction::Poseidon4HashToU8 => dohash(helper, HashVariant::HashPSD4, LiteralType::U8)?,
300        CoreFunction::Poseidon4HashToU16 => dohash(helper, HashVariant::HashPSD4, LiteralType::U16)?,
301        CoreFunction::Poseidon4HashToU32 => dohash(helper, HashVariant::HashPSD4, LiteralType::U32)?,
302        CoreFunction::Poseidon4HashToU64 => dohash(helper, HashVariant::HashPSD4, LiteralType::U64)?,
303        CoreFunction::Poseidon4HashToU128 => dohash(helper, HashVariant::HashPSD4, LiteralType::U128)?,
304        CoreFunction::Poseidon4HashToScalar => dohash(helper, HashVariant::HashPSD4, LiteralType::Scalar)?,
305        CoreFunction::Poseidon8HashToAddress => dohash(helper, HashVariant::HashPSD8, LiteralType::Address)?,
306        CoreFunction::Poseidon8HashToField => dohash(helper, HashVariant::HashPSD8, LiteralType::Field)?,
307        CoreFunction::Poseidon8HashToGroup => dohash(helper, HashVariant::HashPSD8, LiteralType::Group)?,
308        CoreFunction::Poseidon8HashToI8 => dohash(helper, HashVariant::HashPSD8, LiteralType::I8)?,
309        CoreFunction::Poseidon8HashToI16 => dohash(helper, HashVariant::HashPSD8, LiteralType::I16)?,
310        CoreFunction::Poseidon8HashToI32 => dohash(helper, HashVariant::HashPSD8, LiteralType::I32)?,
311        CoreFunction::Poseidon8HashToI64 => dohash(helper, HashVariant::HashPSD8, LiteralType::I64)?,
312        CoreFunction::Poseidon8HashToI128 => dohash(helper, HashVariant::HashPSD8, LiteralType::I128)?,
313        CoreFunction::Poseidon8HashToU8 => dohash(helper, HashVariant::HashPSD8, LiteralType::U8)?,
314        CoreFunction::Poseidon8HashToU16 => dohash(helper, HashVariant::HashPSD8, LiteralType::U16)?,
315        CoreFunction::Poseidon8HashToU32 => dohash(helper, HashVariant::HashPSD8, LiteralType::U32)?,
316        CoreFunction::Poseidon8HashToU64 => dohash(helper, HashVariant::HashPSD8, LiteralType::U64)?,
317        CoreFunction::Poseidon8HashToU128 => dohash(helper, HashVariant::HashPSD8, LiteralType::U128)?,
318        CoreFunction::Poseidon8HashToScalar => dohash(helper, HashVariant::HashPSD8, LiteralType::Scalar)?,
319        CoreFunction::SHA3_256HashToAddress => dohash(helper, HashVariant::HashSha3_256, LiteralType::Address)?,
320        CoreFunction::SHA3_256HashToField => dohash(helper, HashVariant::HashSha3_256, LiteralType::Field)?,
321        CoreFunction::SHA3_256HashToGroup => dohash(helper, HashVariant::HashSha3_256, LiteralType::Group)?,
322        CoreFunction::SHA3_256HashToI8 => dohash(helper, HashVariant::HashSha3_256, LiteralType::I8)?,
323        CoreFunction::SHA3_256HashToI16 => dohash(helper, HashVariant::HashSha3_256, LiteralType::I16)?,
324        CoreFunction::SHA3_256HashToI32 => dohash(helper, HashVariant::HashSha3_256, LiteralType::I32)?,
325        CoreFunction::SHA3_256HashToI64 => dohash(helper, HashVariant::HashSha3_256, LiteralType::I64)?,
326        CoreFunction::SHA3_256HashToI128 => dohash(helper, HashVariant::HashSha3_256, LiteralType::I128)?,
327        CoreFunction::SHA3_256HashToU8 => dohash(helper, HashVariant::HashSha3_256, LiteralType::U8)?,
328        CoreFunction::SHA3_256HashToU16 => dohash(helper, HashVariant::HashSha3_256, LiteralType::U16)?,
329        CoreFunction::SHA3_256HashToU32 => dohash(helper, HashVariant::HashSha3_256, LiteralType::U32)?,
330        CoreFunction::SHA3_256HashToU64 => dohash(helper, HashVariant::HashSha3_256, LiteralType::U64)?,
331        CoreFunction::SHA3_256HashToU128 => dohash(helper, HashVariant::HashSha3_256, LiteralType::U128)?,
332        CoreFunction::SHA3_256HashToScalar => dohash(helper, HashVariant::HashSha3_256, LiteralType::Scalar)?,
333        CoreFunction::SHA3_384HashToAddress => dohash(helper, HashVariant::HashSha3_384, LiteralType::Address)?,
334        CoreFunction::SHA3_384HashToField => dohash(helper, HashVariant::HashSha3_384, LiteralType::Field)?,
335        CoreFunction::SHA3_384HashToGroup => dohash(helper, HashVariant::HashSha3_384, LiteralType::Group)?,
336        CoreFunction::SHA3_384HashToI8 => dohash(helper, HashVariant::HashSha3_384, LiteralType::I8)?,
337        CoreFunction::SHA3_384HashToI16 => dohash(helper, HashVariant::HashSha3_384, LiteralType::I16)?,
338        CoreFunction::SHA3_384HashToI32 => dohash(helper, HashVariant::HashSha3_384, LiteralType::I32)?,
339        CoreFunction::SHA3_384HashToI64 => dohash(helper, HashVariant::HashSha3_384, LiteralType::I64)?,
340        CoreFunction::SHA3_384HashToI128 => dohash(helper, HashVariant::HashSha3_384, LiteralType::I128)?,
341        CoreFunction::SHA3_384HashToU8 => dohash(helper, HashVariant::HashSha3_384, LiteralType::U8)?,
342        CoreFunction::SHA3_384HashToU16 => dohash(helper, HashVariant::HashSha3_384, LiteralType::U16)?,
343        CoreFunction::SHA3_384HashToU32 => dohash(helper, HashVariant::HashSha3_384, LiteralType::U32)?,
344        CoreFunction::SHA3_384HashToU64 => dohash(helper, HashVariant::HashSha3_384, LiteralType::U64)?,
345        CoreFunction::SHA3_384HashToU128 => dohash(helper, HashVariant::HashSha3_384, LiteralType::U128)?,
346        CoreFunction::SHA3_384HashToScalar => dohash(helper, HashVariant::HashSha3_384, LiteralType::Scalar)?,
347        CoreFunction::SHA3_512HashToAddress => dohash(helper, HashVariant::HashSha3_512, LiteralType::Address)?,
348        CoreFunction::SHA3_512HashToField => dohash(helper, HashVariant::HashSha3_512, LiteralType::Field)?,
349        CoreFunction::SHA3_512HashToGroup => dohash(helper, HashVariant::HashSha3_512, LiteralType::Group)?,
350        CoreFunction::SHA3_512HashToI8 => dohash(helper, HashVariant::HashSha3_512, LiteralType::I8)?,
351        CoreFunction::SHA3_512HashToI16 => dohash(helper, HashVariant::HashSha3_512, LiteralType::I16)?,
352        CoreFunction::SHA3_512HashToI32 => dohash(helper, HashVariant::HashSha3_512, LiteralType::I32)?,
353        CoreFunction::SHA3_512HashToI64 => dohash(helper, HashVariant::HashSha3_512, LiteralType::I64)?,
354        CoreFunction::SHA3_512HashToI128 => dohash(helper, HashVariant::HashSha3_512, LiteralType::I128)?,
355        CoreFunction::SHA3_512HashToU8 => dohash(helper, HashVariant::HashSha3_512, LiteralType::U8)?,
356        CoreFunction::SHA3_512HashToU16 => dohash(helper, HashVariant::HashSha3_512, LiteralType::U16)?,
357        CoreFunction::SHA3_512HashToU32 => dohash(helper, HashVariant::HashSha3_512, LiteralType::U32)?,
358        CoreFunction::SHA3_512HashToU64 => dohash(helper, HashVariant::HashSha3_512, LiteralType::U64)?,
359        CoreFunction::SHA3_512HashToU128 => dohash(helper, HashVariant::HashSha3_512, LiteralType::U128)?,
360        CoreFunction::SHA3_512HashToScalar => dohash(helper, HashVariant::HashSha3_512, LiteralType::Scalar)?,
361        CoreFunction::GroupToXCoordinate => {
362            let g: Group = helper.pop_value()?.try_into().expect_tc(span)?;
363            g.to_x_coordinate().into()
364        }
365        CoreFunction::GroupToYCoordinate => {
366            let g: Group = helper.pop_value()?.try_into().expect_tc(span)?;
367            g.to_y_coordinate().into()
368        }
369        CoreFunction::ChaChaRandAddress => random!(Address),
370        CoreFunction::ChaChaRandBool => random!(Boolean),
371        CoreFunction::ChaChaRandField => random!(Field),
372        CoreFunction::ChaChaRandGroup => random!(Group),
373        CoreFunction::ChaChaRandI8 => random!(i8),
374        CoreFunction::ChaChaRandI16 => random!(i16),
375        CoreFunction::ChaChaRandI32 => random!(i32),
376        CoreFunction::ChaChaRandI64 => random!(i64),
377        CoreFunction::ChaChaRandI128 => random!(i128),
378        CoreFunction::ChaChaRandU8 => random!(u8),
379        CoreFunction::ChaChaRandU16 => random!(u16),
380        CoreFunction::ChaChaRandU32 => random!(u32),
381        CoreFunction::ChaChaRandU64 => random!(u64),
382        CoreFunction::ChaChaRandU128 => random!(u128),
383        CoreFunction::ChaChaRandScalar => random!(Scalar),
384        CoreFunction::CheatCodePrintMapping => {
385            let (program, name) = match &arguments[0] {
386                Expression::Path(id) => (None, id.identifier().name),
387                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
388                _ => tc_fail2!(),
389            };
390            if let Some(mapping) = helper.lookup_mapping(program, name) {
391                // TODO: What is the appropriate way to print this to the console.
392                // Print the name of the mapping.
393                println!(
394                    "Mapping: {}",
395                    if let Some(program) = program { format!("{program}/{name}") } else { name.to_string() }
396                );
397                // Print the contents of the mapping.
398                for (key, value) in mapping {
399                    println!("  {key} -> {value}");
400                }
401            } else {
402                tc_fail2!();
403            }
404            Value { id: None, contents: ValueVariants::Unit }
405        }
406        CoreFunction::CheatCodeSetBlockHeight => {
407            let height: u32 = helper.pop_value()?.try_into().expect_tc(span)?;
408            helper.set_block_height(height);
409            Value { id: None, contents: ValueVariants::Unit }
410        }
411        CoreFunction::MappingGet => {
412            let key = helper.pop_value().expect_tc(span)?;
413            let (program, name) = match &arguments[0] {
414                Expression::Path(path) => (None, path.identifier().name),
415                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
416                _ => tc_fail2!(),
417            };
418            helper.mapping_get(program, name, &key).expect_tc(span)?.clone()
419        }
420        CoreFunction::MappingGetOrUse => {
421            let use_value = helper.pop_value().expect_tc(span)?;
422            let key = helper.pop_value().expect_tc(span)?;
423            let (program, name) = match &arguments[0] {
424                Expression::Path(path) => (None, path.identifier().name),
425                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
426                _ => tc_fail2!(),
427            };
428            helper.mapping_get(program, name, &key).unwrap_or(use_value)
429        }
430        CoreFunction::MappingSet => {
431            let value = helper.pop_value().expect_tc(span)?;
432            let key = helper.pop_value().expect_tc(span)?;
433            let (program, name) = match &arguments[0] {
434                Expression::Path(path) => (None, path.identifier().name),
435                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
436                _ => tc_fail2!(),
437            };
438            helper.mapping_set(program, name, key, value).expect_tc(span)?;
439            Value::make_unit()
440        }
441        CoreFunction::MappingRemove => {
442            let key = helper.pop_value().expect_tc(span)?;
443            let (program, name) = match &arguments[0] {
444                Expression::Path(path) => (None, path.identifier().name),
445                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
446                _ => tc_fail2!(),
447            };
448            helper.mapping_remove(program, name, &key).expect_tc(span)?;
449            Value::make_unit()
450        }
451        CoreFunction::MappingContains => {
452            let key = helper.pop_value().expect_tc(span)?;
453            let (program, name) = match &arguments[0] {
454                Expression::Path(path) => (None, path.identifier().name),
455                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
456                _ => tc_fail2!(),
457            };
458            helper.mapping_get(program, name, &key).is_some().into()
459        }
460        CoreFunction::SignatureVerify => todo!(),
461        CoreFunction::FutureAwait => panic!("await must be handled elsewhere"),
462
463        CoreFunction::ProgramChecksum => {
464            // TODO: This is a placeholder. The actual implementation should look up the program in the global context and get its checksum.
465            return Ok(None);
466        }
467        CoreFunction::ProgramEdition => {
468            // TODO: This is a placeholder. The actual implementation should look up the program in the global context and get its edition.
469            return Ok(None);
470        }
471        CoreFunction::ProgramOwner => {
472            // TODO: This is a placeholder. The actual implementation should look up the program in the global context and get its owner.
473            return Ok(None);
474        }
475    };
476
477    Ok(Some(value))
478}