Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MIMC stdlib #208

Merged
merged 10 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use that UnexpectedError from #209 :o

)
}
_ => 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
6 changes: 5 additions & 1 deletion src/type_checker/checker.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashMap;

use num_traits::ToPrimitive;
use serde::{Deserialize, Serialize};

use crate::{
Expand Down Expand Up @@ -591,7 +592,10 @@ impl<B: Backend> TypeChecker<B> {
let sym = Symbolic::parse(size)?;
let res = if let Symbolic::Concrete(size) = sym {
// if sym is a concrete variant, then just return concrete array type
ExprTyInfo::new_anon(TyKind::Array(Box::new(item_node.typ), size))
ExprTyInfo::new_anon(TyKind::Array(
Box::new(item_node.typ),
size.to_u32().expect("array size too large"),
))
} else {
// use generic array as the size node might include generic parameters or constant vars
ExprTyInfo::new_anon(TyKind::GenericSizedArray(
Expand Down