mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
impl let statements
This commit is contained in:
parent
219f90cb17
commit
fa4f786f22
@ -1,7 +1,9 @@
|
||||
function main() -> () {
|
||||
assert_eq(45, 45);
|
||||
assert_eq(2fe, 2fe);
|
||||
assert_eq(true, true);
|
||||
function test() -> (u32, u32[2]) {
|
||||
return 1, [2, 3]
|
||||
}
|
||||
|
||||
return
|
||||
function main() -> (u32[3]) {
|
||||
let (a, b) = test();
|
||||
// a, u32[2] b = test() <- explicit type also works
|
||||
return [a, ...b]
|
||||
}
|
@ -879,8 +879,8 @@ pub struct MultipleAssignmentStatement<'ast> {
|
||||
#[derive(Clone, Debug, FromPest, PartialEq)]
|
||||
#[pest_ast(rule(Rule::statement_definition))]
|
||||
pub struct DefinitionStatement<'ast> {
|
||||
pub ty: Type<'ast>,
|
||||
pub variable: Variable<'ast>,
|
||||
pub ty: Option<Type<'ast>>,
|
||||
pub expression: Expression<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
pub span: Span<'ast>,
|
||||
@ -981,7 +981,10 @@ impl<'ast> fmt::Display for MultipleAssignmentStatement<'ast> {
|
||||
|
||||
impl<'ast> fmt::Display for DefinitionStatement<'ast> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} {} = {};", self.ty, self.variable, self.expression)
|
||||
match self.ty {
|
||||
Some(ref ty) => write!(f, "let {} : {} = {};", self.variable, ty, self.expression),
|
||||
None => write!(f, "let {} = {}", self.variable, self.expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{ast, Program, ResolvedProgram, ResolvedValue};
|
||||
use crate::errors::CompilerError;
|
||||
use crate::{ast, Program, ResolvedProgram, ResolvedValue};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
@ -28,15 +28,20 @@ impl<F: Field + PrimeField> Compiler<F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn evaluate_program<CS: ConstraintSystem<F>>(self, cs: &mut CS) -> Result<ResolvedValue<F>, CompilerError> {
|
||||
pub fn evaluate_program<CS: ConstraintSystem<F>>(
|
||||
self,
|
||||
cs: &mut CS,
|
||||
) -> Result<ResolvedValue<F>, CompilerError> {
|
||||
// Read in the main file as string
|
||||
let unparsed_file = fs::read_to_string(&self.main_file_path).map_err(|_| CompilerError::FileReadError(self.main_file_path.clone()))?;
|
||||
let unparsed_file = fs::read_to_string(&self.main_file_path)
|
||||
.map_err(|_| CompilerError::FileReadError(self.main_file_path.clone()))?;
|
||||
|
||||
// Parse the file using leo.pest
|
||||
let mut file = ast::parse(&unparsed_file).map_err(|_| CompilerError::FileParsingError)?;
|
||||
|
||||
// Build the abstract syntax tree
|
||||
let syntax_tree = ast::File::from_pest(&mut file).map_err(|_| CompilerError::SyntaxTreeError)?;
|
||||
let syntax_tree =
|
||||
ast::File::from_pest(&mut file).map_err(|_| CompilerError::SyntaxTreeError)?;
|
||||
log::debug!("{:#?}", syntax_tree);
|
||||
|
||||
// Build program from abstract syntax tree
|
||||
|
@ -7,7 +7,7 @@ use snarkos_models::curves::{Field, PrimeField};
|
||||
use snarkos_models::gadgets::utilities::eq::EqGadget;
|
||||
use snarkos_models::gadgets::{
|
||||
r1cs::ConstraintSystem,
|
||||
utilities::{alloc::AllocGadget, boolean::Boolean, eq::ConditionalEqGadget, uint32::UInt32},
|
||||
utilities::{alloc::AllocGadget, boolean::Boolean, uint32::UInt32},
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
|
@ -137,14 +137,22 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
assignee: Assignee<F>,
|
||||
expression: Expression<F>,
|
||||
) {
|
||||
let result_value = &mut self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expression,
|
||||
);
|
||||
// Check that assignee exists
|
||||
let name = self.resolve_assignee(function_scope.clone(), assignee.clone());
|
||||
|
||||
self.store_assignment(cs, file_scope, function_scope, assignee, result_value);
|
||||
match self.get(&name) {
|
||||
Some(_assignee) => {
|
||||
let result_value = &mut self.enforce_expression(
|
||||
cs,
|
||||
file_scope.clone(),
|
||||
function_scope.clone(),
|
||||
expression,
|
||||
);
|
||||
|
||||
self.store_assignment(cs, file_scope, function_scope, assignee, result_value);
|
||||
}
|
||||
None => unimplemented!("cannot assign to uninitialized variable {}", assignee),
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_definition_statement(
|
||||
@ -152,8 +160,8 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
cs: &mut CS,
|
||||
file_scope: String,
|
||||
function_scope: String,
|
||||
ty: Type<F>,
|
||||
assignee: Assignee<F>,
|
||||
ty: Option<Type<F>>,
|
||||
expression: Expression<F>,
|
||||
) {
|
||||
let result_value = &mut self.enforce_expression(
|
||||
@ -163,10 +171,17 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
expression,
|
||||
);
|
||||
|
||||
if result_value.match_type(&ty) {
|
||||
self.store_assignment(cs, file_scope, function_scope, assignee, result_value);
|
||||
} else {
|
||||
unimplemented!("incompatible types {} = {}", assignee, result_value)
|
||||
match ty {
|
||||
// Explicit type
|
||||
Some(ty) => {
|
||||
if result_value.match_type(&ty) {
|
||||
self.store_assignment(cs, file_scope, function_scope, assignee, result_value);
|
||||
} else {
|
||||
unimplemented!("incompatible types {} = {}", assignee, result_value)
|
||||
}
|
||||
}
|
||||
// Implicit type
|
||||
None => self.store_assignment(cs, file_scope, function_scope, assignee, result_value),
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,13 +397,13 @@ impl<F: Field + PrimeField, CS: ConstraintSystem<F>> ResolvedProgram<F, CS> {
|
||||
return_types,
|
||||
));
|
||||
}
|
||||
Statement::Definition(ty, assignee, expression) => {
|
||||
Statement::Definition(assignee, ty, expression) => {
|
||||
self.enforce_definition_statement(
|
||||
cs,
|
||||
file_scope,
|
||||
function_scope,
|
||||
ty,
|
||||
assignee,
|
||||
ty,
|
||||
expression,
|
||||
);
|
||||
}
|
||||
|
@ -160,9 +160,9 @@ conditional_nested_or_end = { statement_conditional | "{" ~ NEWLINE* ~ statement
|
||||
|
||||
/// Statements
|
||||
statement_return = { "return" ~ expression_tuple }
|
||||
statement_definition = { ty ~ variable ~ "=" ~ expression }
|
||||
statement_definition = { "let" ~ variable ~ (":" ~ ty)? ~ "=" ~ expression }
|
||||
statement_assign = { assignee ~ operation_assign ~ expression }
|
||||
statement_multiple_assignment = { optionally_typed_variable_tuple ~ "=" ~ variable ~ "(" ~ expression_tuple ~ ")" }
|
||||
statement_multiple_assignment = { "let" ~ "(" ~ optionally_typed_variable_tuple ~ ")" ~ "=" ~ variable ~ "(" ~ expression_tuple ~ ")" }
|
||||
statement_conditional = {"if" ~ "(" ~ expression ~ ")" ~ "{" ~ NEWLINE* ~ statement+ ~ "}" ~ ("else" ~ conditional_nested_or_end)?}
|
||||
statement_for = { "for" ~ variable ~ "in" ~ expression ~ ".." ~ expression ~ "{" ~ NEWLINE* ~ statement+ ~ "}"}
|
||||
statement_assert = {
|
||||
|
@ -125,7 +125,7 @@ pub struct ConditionalStatement<F: Field + PrimeField> {
|
||||
pub enum Statement<F: Field + PrimeField> {
|
||||
// Declaration(Variable),
|
||||
Return(Vec<Expression<F>>),
|
||||
Definition(Type<F>, Assignee<F>, Expression<F>),
|
||||
Definition(Assignee<F>, Option<Type<F>>, Expression<F>),
|
||||
Assign(Assignee<F>, Expression<F>),
|
||||
MultipleAssign(Vec<Assignee<F>>, Expression<F>),
|
||||
Conditional(ConditionalStatement<F>),
|
||||
|
@ -180,20 +180,22 @@ impl<F: Field + PrimeField> fmt::Display for Statement<F> {
|
||||
}
|
||||
write!(f, "\n")
|
||||
}
|
||||
Statement::Definition(ref ty, ref assignee, ref statement) => {
|
||||
write!(f, "{} {} = {};", ty, assignee, statement)
|
||||
}
|
||||
Statement::Definition(ref assignee, ref ty, ref expression) => match ty {
|
||||
Some(ref ty) => write!(f, "let {} : {} = {};", assignee, ty, expression),
|
||||
None => write!(f, "let {} = {};", assignee, expression),
|
||||
},
|
||||
Statement::Assign(ref variable, ref statement) => {
|
||||
write!(f, "{} = {};", variable, statement)
|
||||
}
|
||||
Statement::MultipleAssign(ref assignees, ref function) => {
|
||||
write!(f, "let (")?;
|
||||
for (i, id) in assignees.iter().enumerate() {
|
||||
write!(f, "{}", id)?;
|
||||
if i < assignees.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, " = {};", function)
|
||||
write!(f, ") = {};", function)
|
||||
}
|
||||
Statement::Conditional(ref statement) => write!(f, "{}", statement),
|
||||
Statement::For(ref var, ref start, ref stop, ref list) => {
|
||||
@ -223,20 +225,22 @@ impl<F: Field + PrimeField> fmt::Debug for Statement<F> {
|
||||
}
|
||||
write!(f, "\n")
|
||||
}
|
||||
Statement::Definition(ref ty, ref assignee, ref statement) => {
|
||||
write!(f, "{} {} = {};", ty, assignee, statement)
|
||||
}
|
||||
Statement::Definition(ref assignee, ref ty, ref expression) => match ty {
|
||||
Some(ref ty) => write!(f, "let {} : {} = {};", assignee, ty, expression),
|
||||
None => write!(f, "let {} = {};", assignee, expression),
|
||||
},
|
||||
Statement::Assign(ref variable, ref statement) => {
|
||||
write!(f, "{} = {};", variable, statement)
|
||||
}
|
||||
Statement::MultipleAssign(ref assignees, ref function) => {
|
||||
write!(f, "let (")?;
|
||||
for (i, id) in assignees.iter().enumerate() {
|
||||
write!(f, "{}", id)?;
|
||||
if i < assignees.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, " = {};", function)
|
||||
write!(f, ") = {};", function)
|
||||
}
|
||||
Statement::Conditional(ref statement) => write!(f, "{}", statement),
|
||||
Statement::For(ref var, ref start, ref stop, ref list) => {
|
||||
|
@ -373,8 +373,8 @@ impl<'ast, F: Field + PrimeField> From<ast::ReturnStatement<'ast>> for types::St
|
||||
impl<'ast, F: Field + PrimeField> From<ast::DefinitionStatement<'ast>> for types::Statement<F> {
|
||||
fn from(statement: ast::DefinitionStatement<'ast>) -> Self {
|
||||
types::Statement::Definition(
|
||||
types::Type::from(statement.ty),
|
||||
types::Assignee::from(statement.variable),
|
||||
statement.ty.map(|ty| types::Type::<F>::from(ty)),
|
||||
types::Expression::from(statement.expression),
|
||||
)
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ use leo_compiler::{compiler::Compiler, ResolvedValue};
|
||||
|
||||
use snarkos_curves::bls12_377::Fr;
|
||||
|
||||
use std::env::current_dir;
|
||||
use snarkos_models::gadgets::r1cs::{ConstraintSynthesizer, TestConstraintSystem};
|
||||
use snarkos_models::gadgets::utilities::uint32::UInt32;
|
||||
use std::env::current_dir;
|
||||
|
||||
const DIRECTORY_NAME: &str = "tests/u32/";
|
||||
|
||||
@ -38,7 +38,10 @@ fn test_zero() {
|
||||
assert!(cs.is_satisfied());
|
||||
|
||||
let output = output.unwrap();
|
||||
assert_eq!(ResolvedValue::<Fr>::Return(vec![ResolvedValue::<Fr>::U32(UInt32::constant(0))]), output);
|
||||
assert_eq!(
|
||||
ResolvedValue::<Fr>::Return(vec![ResolvedValue::<Fr>::U32(UInt32::constant(0))]),
|
||||
output
|
||||
);
|
||||
println!("{}", output);
|
||||
}
|
||||
|
||||
@ -50,7 +53,10 @@ fn test_one() {
|
||||
assert!(cs.is_satisfied());
|
||||
|
||||
let output = output.unwrap();
|
||||
assert_eq!(ResolvedValue::<Fr>::Return(vec![ResolvedValue::<Fr>::U32(UInt32::constant(1))]), output);
|
||||
assert_eq!(
|
||||
ResolvedValue::<Fr>::Return(vec![ResolvedValue::<Fr>::U32(UInt32::constant(1))]),
|
||||
output
|
||||
);
|
||||
println!("{}", output);
|
||||
}
|
||||
|
||||
@ -62,7 +68,10 @@ fn test_1_plus_1() {
|
||||
assert!(cs.is_satisfied());
|
||||
|
||||
let output = output.unwrap();
|
||||
assert_eq!(ResolvedValue::<Fr>::Return(vec![ResolvedValue::<Fr>::U32(UInt32::constant(2))]), output);
|
||||
assert_eq!(
|
||||
ResolvedValue::<Fr>::Return(vec![ResolvedValue::<Fr>::U32(UInt32::constant(2))]),
|
||||
output
|
||||
);
|
||||
println!("{}", output);
|
||||
}
|
||||
|
||||
@ -74,7 +83,10 @@ fn test_1_minus_1() {
|
||||
assert!(cs.is_satisfied());
|
||||
|
||||
let output = output.unwrap();
|
||||
assert_eq!(ResolvedValue::<Fr>::Return(vec![ResolvedValue::<Fr>::U32(UInt32::constant(0))]), output);
|
||||
assert_eq!(
|
||||
ResolvedValue::<Fr>::Return(vec![ResolvedValue::<Fr>::U32(UInt32::constant(0))]),
|
||||
output
|
||||
);
|
||||
println!("{}", output);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user