Skip to content

Commit

Permalink
Add MIMC stdlib (#208)
Browse files Browse the repository at this point in the history
* add mimc stdlib
  • Loading branch information
katat authored Oct 28, 2024
1 parent eb1def1 commit 83e3491
Show file tree
Hide file tree
Showing 10 changed files with 423 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub enum ErrorKind {
GenericValueExpected(String),

#[error("conflict generic values during binding for `{0}`: `{1}` and `{2}`")]
ConflictGenericValue(String, u32, u32),
ConflictGenericValue(String, String, String),

#[error("unexpected generic parameter: `{0}`")]
UnexpectedGenericParameter(String),
Expand Down
42 changes: 21 additions & 21 deletions src/mast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,27 @@ pub struct ExprMonoInfo {

#[derive(Debug, Clone)]
pub enum PropagatedConstant {
Single(u32),
Single(BigUint),
Array(Vec<PropagatedConstant>),
Custom(HashMap<Ident, PropagatedConstant>),
}

impl PropagatedConstant {
pub fn as_single(&self) -> u32 {
pub fn as_single(&self) -> BigUint {
match self {
PropagatedConstant::Single(v) => *v,
PropagatedConstant::Single(v) => v.clone(),
_ => panic!("expected single value"),
}
}

pub fn as_array(&self) -> Vec<u32> {
pub fn as_array(&self) -> Vec<BigUint> {
match self {
PropagatedConstant::Array(v) => v.iter().map(|c| c.as_single()).collect(),
_ => panic!("expected array value"),
}
}

pub fn as_custom(&self) -> HashMap<Ident, u32> {
pub fn as_custom(&self) -> HashMap<Ident, BigUint> {
match self {
PropagatedConstant::Custom(v) => {
v.iter().map(|(k, c)| (k.clone(), c.as_single())).collect()
Expand All @@ -67,8 +67,8 @@ impl PropagatedConstant {
}

/// impl From trait for single value
impl From<u32> for PropagatedConstant {
fn from(v: u32) -> Self {
impl From<BigUint> for PropagatedConstant {
fn from(v: BigUint) -> Self {
PropagatedConstant::Single(v)
}
}
Expand Down Expand Up @@ -224,7 +224,10 @@ impl FnSig {
TyKind::Array(ty, size) => TyKind::Array(Box::new(self.resolve_type(ty, ctx)), *size),
TyKind::GenericSizedArray(ty, sym) => {
let val = sym.eval(&self.generics, &ctx.tast);
TyKind::Array(Box::new(self.resolve_type(ty, ctx)), val)
TyKind::Array(
Box::new(self.resolve_type(ty, ctx)),
val.to_u32().expect("array size exceeded u32"),
)
}
_ => typ.clone(),
}
Expand Down Expand Up @@ -381,9 +384,9 @@ impl<B: Backend> MastCtx<B> {

impl Symbolic {
/// Evaluate symbolic size to an integer.
pub fn eval<B: Backend>(&self, gens: &GenericParameters, tast: &TypeChecker<B>) -> u32 {
pub fn eval<B: Backend>(&self, gens: &GenericParameters, tast: &TypeChecker<B>) -> BigUint {
match self {
Symbolic::Concrete(v) => *v,
Symbolic::Concrete(v) => v.clone(),
Symbolic::Constant(var) => {
let qualified = FullyQualified::local(var.value.clone());
let cst = tast.const_info(&qualified).expect("constant not found");
Expand Down Expand Up @@ -805,11 +808,7 @@ fn monomorphize_expr<B: Backend>(
Some(v) => {
let mexpr = expr.to_mast(ctx, &ExprKind::BigUInt(v.clone()));

ExprMonoInfo::new(
mexpr,
typ,
Some(PropagatedConstant::from(v.to_u32().unwrap())),
)
ExprMonoInfo::new(mexpr, typ, Some(PropagatedConstant::from(v)))
}
// keep as is
_ => {
Expand Down Expand Up @@ -846,13 +845,12 @@ fn monomorphize_expr<B: Backend>(
}

ExprKind::BigUInt(inner) => {
let cst: u32 = inner.try_into().expect("biguint too large");
let mexpr = expr.to_mast(ctx, &ExprKind::BigUInt(inner.clone()));

ExprMonoInfo::new(
mexpr,
Some(TyKind::Field { constant: true }),
Some(PropagatedConstant::from(cst)),
Some(PropagatedConstant::from(inner.clone())),
)
}

Expand Down Expand Up @@ -892,13 +890,12 @@ fn monomorphize_expr<B: Backend>(
// if it's a variable,
// check if it's a constant first
let bigint: BigUint = cst.value[0].into();
let cst: u32 = bigint.clone().try_into().expect("biguint too large");
let mexpr = expr.to_mast(ctx, &ExprKind::BigUInt(bigint));
let mexpr = expr.to_mast(ctx, &ExprKind::BigUInt(bigint.clone()));

ExprMonoInfo::new(
mexpr,
Some(TyKind::Field { constant: true }),
Some(PropagatedConstant::from(cst)),
Some(PropagatedConstant::from(bigint)),
)
} else {
// otherwise it's a local variable
Expand Down Expand Up @@ -1090,7 +1087,10 @@ fn monomorphize_expr<B: Backend>(
);

if let Some(cst) = size_mono.constant {
let arr_typ = TyKind::Array(Box::new(item_typ), cst.as_single());
let arr_typ = TyKind::Array(
Box::new(item_typ),
cst.as_single().to_u32().expect("array size too large"),
);
ExprMonoInfo::new(mexpr, Some(arr_typ), None)
} else {
return Err(error(ErrorKind::InvalidArraySize, expr.span));
Expand Down
30 changes: 20 additions & 10 deletions src/parser/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use educe::Educe;
use num_bigint::BigUint;
use std::{
collections::{HashMap, HashSet},
fmt::Display,
Expand All @@ -7,15 +8,14 @@ use std::{
};

use ark_ff::Field;
use num_traits::ToPrimitive;
use num_traits::FromPrimitive;
use serde::{Deserialize, Serialize};

use crate::{
cli::packages::UserRepo,
constants::Span,
error::{Error, ErrorKind, Result},
lexer::{Keyword, Token, TokenKind, Tokens},
mast::ExprMonoInfo,
stdlib::builtins::BUILTIN_FN_NAMES,
syntax::{is_generic_parameter, is_type},
};
Expand Down Expand Up @@ -181,7 +181,7 @@ pub enum ModulePath {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Symbolic {
/// A literal number
Concrete(u32),
Concrete(BigUint),
/// Point to a constant variable
Constant(Ident),
/// Generic parameter
Expand Down Expand Up @@ -230,7 +230,7 @@ impl Symbolic {
/// Parse from an expression node recursively.
pub fn parse(node: &Expr) -> Result<Self> {
match &node.kind {
ExprKind::BigUInt(n) => Ok(Symbolic::Concrete(n.to_u32().unwrap())),
ExprKind::BigUInt(n) => Ok(Symbolic::Concrete(n.clone())),
ExprKind::Variable { module: _, name } => {
if is_generic_parameter(&name.value) {
Ok(Symbolic::Generic(name.clone()))
Expand Down Expand Up @@ -571,7 +571,11 @@ impl FnSig {
// resolve the generic parameter
match sym {
Symbolic::Generic(ident) => {
self.generics.assign(&ident.value, *observed_size, span)?;
self.generics.assign(
&ident.value,
BigUint::from_u32(*observed_size).unwrap(),
span,
)?;
}
_ => unreachable!("no operation allowed on symbolic size in function argument"),
}
Expand Down Expand Up @@ -633,7 +637,7 @@ impl FnSig {

let generics = generics
.iter()
.map(|(name, value)| format!("{}={}", name, value.unwrap()))
.map(|(name, value)| format!("{}={}", name, value.as_ref().unwrap()))
.collect::<Vec<_>>()
.join("#");

Expand Down Expand Up @@ -742,7 +746,7 @@ pub struct ResolvedSig {
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
/// Generic parameters for a function signature
pub struct GenericParameters {
pub parameters: HashMap<String, Option<u32>>,
pub parameters: HashMap<String, Option<BigUint>>,
pub resolved_sig: Option<ResolvedSig>,
}

Expand All @@ -758,11 +762,13 @@ impl GenericParameters {
}

/// Get the value of a generic parameter
pub fn get(&self, name: &str) -> u32 {
pub fn get(&self, name: &str) -> BigUint {
self.parameters
.get(name)
.expect("generic parameter not found")
.as_ref()
.expect("generic value not assigned")
.clone()
}

/// Returns whether the generic parameters are empty
Expand All @@ -771,7 +777,7 @@ impl GenericParameters {
}

/// Bind a generic parameter to a value
pub fn assign(&mut self, name: &String, value: u32, span: Span) -> Result<()> {
pub fn assign(&mut self, name: &String, value: BigUint, span: Span) -> Result<()> {
let existing = self.parameters.get(name);
match existing {
Some(Some(v)) => {
Expand All @@ -781,7 +787,11 @@ impl GenericParameters {

Err(Error::new(
"mast",
ErrorKind::ConflictGenericValue(name.to_string(), *v, value),
ErrorKind::ConflictGenericValue(
name.to_string(),
v.to_str_radix(10),
value.to_str_radix(10),
),
span,
))
}
Expand Down
2 changes: 1 addition & 1 deletion src/stdlib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub fn init_stdlib_dep<B: Backend>(
path_prefix: &str,
) -> usize {
// list the stdlib dependency in order
let libs = vec!["bits", "comparator", "multiplexer", "int"];
let libs = vec!["bits", "comparator", "multiplexer", "mimc", "int"];

let mut node_id = node_id;

Expand Down
Loading

0 comments on commit 83e3491

Please sign in to comment.