impl let statements

This commit is contained in:
collin 2020-05-02 19:03:50 -07:00
parent 219f90cb17
commit fa4f786f22
10 changed files with 84 additions and 43 deletions

View File

@ -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]
}

View File

@ -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),
}
}
}

View File

@ -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

View File

@ -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> {

View File

@ -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,
);
}

View File

@ -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 = {

View File

@ -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>),

View File

@ -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) => {

View File

@ -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),
)
}

View File

@ -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);
}