1
0
Fork 0
mirror of synced 2025-09-23 20:28:36 +00:00

implement basic log statement

This commit is contained in:
schaeff 2022-06-20 17:51:44 +02:00
parent a08d49b7e5
commit 5ea93bb677
22 changed files with 70 additions and 8 deletions

View file

@ -159,7 +159,7 @@ fn cli_compute<T: Field, I: Iterator<Item = ir::Statement<T>>>(
let interpreter = ir::Interpreter::default(); let interpreter = ir::Interpreter::default();
let witness = interpreter let witness = interpreter
.execute(ir_prog, &arguments.encode()) .execute(ir_prog, &arguments.encode(), &mut std::io::stdout())
.map_err(|e| format!("Execution failed: {}", e))?; .map_err(|e| format!("Execution failed: {}", e))?;
use zokrates_abi::Decode; use zokrates_abi::Decode;

View file

@ -256,6 +256,7 @@ fn statements_from_statement(statement: pest::Statement) -> Vec<absy::StatementN
pest::Statement::Iteration(s) => vec![absy::StatementNode::from(s)], pest::Statement::Iteration(s) => vec![absy::StatementNode::from(s)],
pest::Statement::Assertion(s) => vec![absy::StatementNode::from(s)], pest::Statement::Assertion(s) => vec![absy::StatementNode::from(s)],
pest::Statement::Return(s) => vec![absy::StatementNode::from(s)], pest::Statement::Return(s) => vec![absy::StatementNode::from(s)],
pest::Statement::Log(l) => vec![absy::StatementNode::from(l)],
} }
} }
@ -351,6 +352,14 @@ fn statements_from_definition(definition: pest::DefinitionStatement) -> Vec<absy
} }
} }
impl<'ast> From<pest::LogStatement<'ast>> for absy::StatementNode<'ast> {
fn from(statement: pest::LogStatement<'ast>) -> absy::StatementNode<'ast> {
use crate::absy::NodeValue;
absy::Statement::Log(statement.content.inner).span(statement.span)
}
}
impl<'ast> From<pest::ReturnStatement<'ast>> for absy::StatementNode<'ast> { impl<'ast> From<pest::ReturnStatement<'ast>> for absy::StatementNode<'ast> {
fn from(statement: pest::ReturnStatement<'ast>) -> absy::StatementNode<'ast> { fn from(statement: pest::ReturnStatement<'ast>) -> absy::StatementNode<'ast> {
use crate::absy::NodeValue; use crate::absy::NodeValue;

View file

@ -395,6 +395,7 @@ pub enum Statement<'ast> {
Vec<StatementNode<'ast>>, Vec<StatementNode<'ast>>,
), ),
MultipleDefinition(Vec<AssigneeNode<'ast>>, ExpressionNode<'ast>), MultipleDefinition(Vec<AssigneeNode<'ast>>, ExpressionNode<'ast>),
Log(String),
} }
pub type StatementNode<'ast> = Node<Statement<'ast>>; pub type StatementNode<'ast> = Node<Statement<'ast>>;
@ -428,6 +429,7 @@ impl<'ast> fmt::Display for Statement<'ast> {
} }
write!(f, " = {}", rhs) write!(f, " = {}", rhs)
} }
Statement::Log(ref l) => write!(f, "log!({})", l),
} }
} }
} }

View file

@ -159,6 +159,7 @@ pub enum FlatStatement<T> {
Condition(FlatExpression<T>, FlatExpression<T>, RuntimeError), Condition(FlatExpression<T>, FlatExpression<T>, RuntimeError),
Definition(FlatVariable, FlatExpression<T>), Definition(FlatVariable, FlatExpression<T>),
Directive(FlatDirective<T>), Directive(FlatDirective<T>),
Log(String),
} }
impl<T: Field> fmt::Display for FlatStatement<T> { impl<T: Field> fmt::Display for FlatStatement<T> {
@ -169,6 +170,7 @@ impl<T: Field> fmt::Display for FlatStatement<T> {
write!(f, "{} == {} // {}", lhs, rhs, message) write!(f, "{} == {} // {}", lhs, rhs, message)
} }
FlatStatement::Directive(ref d) => write!(f, "{}", d), FlatStatement::Directive(ref d) => write!(f, "{}", d),
FlatStatement::Log(ref l) => write!(f, "log!({})", l),
} }
} }
} }
@ -206,6 +208,7 @@ impl<T: Field> FlatStatement<T> {
..d ..d
}) })
} }
FlatStatement::Log(l) => FlatStatement::Log(l),
} }
} }
} }

View file

@ -1234,6 +1234,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
inputs: new_inputs, inputs: new_inputs,
}) })
} }
FlatStatement::Log(l) => FlatStatement::Log(l),
}); });
statements_flattened.extend(statements); statements_flattened.extend(statements);
@ -2572,6 +2573,9 @@ impl<'ast, T: Field> Flattener<'ast, T> {
} }
} }
} }
ZirStatement::Log(l) => {
statements_flattened.push_back(FlatStatement::Log(l));
}
} }
} }

View file

@ -58,6 +58,7 @@ pub fn fold_statement<T: Field, F: Folder<T>>(f: &mut F, s: Statement<T>) -> Vec
message, message,
)], )],
Statement::Directive(dir) => vec![Statement::Directive(f.fold_directive(dir))], Statement::Directive(dir) => vec![Statement::Directive(f.fold_directive(dir))],
Statement::Log(l) => vec![Statement::Log(l)],
} }
} }

View file

@ -74,6 +74,7 @@ impl<T: Field> From<FlatStatement<T>> for Statement<T> {
e => Statement::Constraint(LinComb::from(e).into(), var.into(), None), e => Statement::Constraint(LinComb::from(e).into(), var.into(), None),
}, },
FlatStatement::Directive(ds) => Statement::Directive(ds.into()), FlatStatement::Directive(ds) => Statement::Directive(ds.into()),
FlatStatement::Log(l) => Statement::Log(l),
} }
} }
} }

View file

@ -25,10 +25,11 @@ impl Interpreter {
} }
impl Interpreter { impl Interpreter {
pub fn execute<T: Field, I: IntoIterator<Item = Statement<T>>>( pub fn execute<W: std::io::Write, T: Field, I: IntoIterator<Item = Statement<T>>>(
&self, &self,
program: ProgIterator<T, I>, program: ProgIterator<T, I>,
inputs: &[T], inputs: &[T],
log_stream: &mut W,
) -> ExecutionResult<T> { ) -> ExecutionResult<T> {
self.check_inputs(&program, inputs)?; self.check_inputs(&program, inputs)?;
let mut witness = BTreeMap::new(); let mut witness = BTreeMap::new();
@ -75,6 +76,9 @@ impl Interpreter {
witness.insert(*o, res[i].clone()); witness.insert(*o, res[i].clone());
} }
} }
Statement::Log(l) => {
writeln!(log_stream, "{}", l).map_err(|_| Error::LogStream)?;
}
} }
} }
@ -273,6 +277,7 @@ pub enum Error {
UnsatisfiedConstraint { error: Option<RuntimeError> }, UnsatisfiedConstraint { error: Option<RuntimeError> },
Solver, Solver,
WrongInputCount { expected: usize, received: usize }, WrongInputCount { expected: usize, received: usize },
LogStream,
} }
impl fmt::Display for Error { impl fmt::Display for Error {
@ -305,6 +310,7 @@ impl fmt::Display for Error {
received, received,
if received == 1 { "" } else { "s" } if received == 1 { "" } else { "s" }
), ),
Error::LogStream => write!(f, "Error writing a log to the log stream"),
} }
} }
} }

View file

@ -26,6 +26,7 @@ pub use self::witness::Witness;
pub enum Statement<T> { pub enum Statement<T> {
Constraint(QuadComb<T>, LinComb<T>, Option<RuntimeError>), Constraint(QuadComb<T>, LinComb<T>, Option<RuntimeError>),
Directive(Directive<T>), Directive(Directive<T>),
Log(String),
} }
impl<T: Field> Statement<T> { impl<T: Field> Statement<T> {
@ -70,6 +71,7 @@ impl<T: Field> fmt::Display for Statement<T> {
match *self { match *self {
Statement::Constraint(ref quad, ref lin, _) => write!(f, "{} == {}", quad, lin), Statement::Constraint(ref quad, ref lin, _) => write!(f, "{} == {}", quad, lin),
Statement::Directive(ref s) => write!(f, "{}", s), Statement::Directive(ref s) => write!(f, "{}", s),
Statement::Log(ref s) => write!(f, "{}", s),
} }
} }
} }

View file

@ -86,6 +86,7 @@ impl<T: Field> SMTLib2 for Statement<T> {
write!(f, " |~prime|))") write!(f, " |~prime|))")
} }
Statement::Directive(ref s) => s.to_smtlib2(f), Statement::Directive(ref s) => s.to_smtlib2(f),
Statement::Log(_) => write!(f, ""),
} }
} }
} }

View file

@ -61,6 +61,7 @@ pub fn visit_statement<T: Field, F: Visitor<T>>(f: &mut F, s: &Statement<T>) {
} }
} }
Statement::Directive(dir) => f.visit_directive(dir), Statement::Directive(dir) => f.visit_directive(dir),
Statement::Log(_) => {}
} }
} }

View file

@ -168,6 +168,7 @@ impl<T: Field> Folder<T> for RedefinitionOptimizer<T> {
} }
} }
} }
Statement::Log(l) => vec![Statement::Log(l)],
} }
} }

View file

@ -2024,6 +2024,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
}), }),
}.map_err(|e| vec![e]) }.map_err(|e| vec![e])
} }
Statement::Log(l) => Ok(TypedStatement::Log(l)),
} }
} }

View file

@ -75,6 +75,7 @@ impl<T: Field> FlatStatement<T> {
.collect(), .collect(),
..d ..d
})), })),
FlatStatement::Log(l) => Some(FlatStatement::Log(l)),
} }
} }
} }

View file

@ -474,6 +474,7 @@ fn fold_statement<'ast, T: Field>(
f.fold_expression_list(statements_buffer, elist), f.fold_expression_list(statements_buffer, elist),
)] )]
} }
typed_absy::TypedStatement::Log(l) => vec![zir::ZirStatement::Log(l)],
typed_absy::TypedStatement::PushCallLog(..) => vec![], typed_absy::TypedStatement::PushCallLog(..) => vec![],
typed_absy::TypedStatement::PopCallLog => vec![], typed_absy::TypedStatement::PopCallLog => vec![],
}; };

View file

@ -641,6 +641,7 @@ pub enum TypedStatement<'ast, T> {
Vec<TypedStatement<'ast, T>>, Vec<TypedStatement<'ast, T>>,
), ),
MultipleDefinition(Vec<TypedAssignee<'ast, T>>, TypedExpressionList<'ast, T>), MultipleDefinition(Vec<TypedAssignee<'ast, T>>, TypedExpressionList<'ast, T>),
Log(String),
// Aux // Aux
PushCallLog( PushCallLog(
DeclarationFunctionKey<'ast, T>, DeclarationFunctionKey<'ast, T>,
@ -707,6 +708,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
} }
write!(f, " = {}", rhs) write!(f, " = {}", rhs)
} }
TypedStatement::Log(ref l) => write!(f, "log!({})", l),
TypedStatement::PushCallLog(ref key, ref generics) => write!( TypedStatement::PushCallLog(ref key, ref generics) => write!(
f, f,
"// PUSH CALL TO {}/{}::<{}>", "// PUSH CALL TO {}/{}::<{}>",

View file

@ -122,6 +122,7 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
variables.into_iter().map(|v| f.fold_variable(v)).collect(), variables.into_iter().map(|v| f.fold_variable(v)).collect(),
f.fold_expression_list(elist), f.fold_expression_list(elist),
), ),
ZirStatement::Log(l) => ZirStatement::Log(l),
}; };
vec![res] vec![res]
} }

View file

@ -112,6 +112,7 @@ pub enum ZirStatement<'ast, T> {
), ),
Assertion(BooleanExpression<'ast, T>, RuntimeError), Assertion(BooleanExpression<'ast, T>, RuntimeError),
MultipleDefinition(Vec<ZirAssignee<'ast>>, ZirExpressionList<'ast, T>), MultipleDefinition(Vec<ZirAssignee<'ast>>, ZirExpressionList<'ast, T>),
Log(String),
} }
impl<'ast, T: fmt::Display> fmt::Display for ZirStatement<'ast, T> { impl<'ast, T: fmt::Display> fmt::Display for ZirStatement<'ast, T> {
@ -161,6 +162,7 @@ impl<'ast, T: fmt::Display> fmt::Display for ZirStatement<'ast, T> {
} }
write!(f, " = {}", rhs) write!(f, " = {}", rhs)
} }
ZirStatement::Log(ref l) => write!(f, "log!({})", l),
} }
} }
} }

View file

@ -147,6 +147,7 @@ pub fn fold_statement<'ast, T: Field, F: ResultFolder<'ast, T>>(
.collect::<Result<_, _>>()?, .collect::<Result<_, _>>()?,
f.fold_expression_list(elist)?, f.fold_expression_list(elist)?,
), ),
ZirStatement::Log(l) => ZirStatement::Log(l),
}; };
Ok(vec![res]) Ok(vec![res])
} }

View file

@ -53,12 +53,15 @@ vis = { vis_private | vis_public }
// Statements // Statements
statement = { (return_statement // does not require subsequent newline statement = { (return_statement // does not require subsequent newline
| (iteration_statement | (log_statement
| iteration_statement
| definition_statement | definition_statement
| expression_statement | expression_statement
) ~ NEWLINE ) ~ NEWLINE
) ~ NEWLINE* } ) ~ NEWLINE* }
log_statement = { "log!(\"" ~ log_statement_content ~ "\")"}
log_statement_content = { ASCII_ALPHANUMERIC* }
iteration_statement = { "for" ~ ty ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"} iteration_statement = { "for" ~ ty ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"}
return_statement = { "return" ~ expression_list} return_statement = { "return" ~ expression_list}
definition_statement = { typed_identifier_or_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement` definition_statement = { typed_identifier_or_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement`

View file

@ -15,10 +15,11 @@ pub use ast::{
File, FromExpression, FunctionDefinition, HexLiteralExpression, HexNumberExpression, File, FromExpression, FunctionDefinition, HexLiteralExpression, HexNumberExpression,
IdentifierExpression, IdentifierOrDecimal, IfElseExpression, ImportDirective, ImportSymbol, IdentifierExpression, IdentifierOrDecimal, IfElseExpression, ImportDirective, ImportSymbol,
InlineArrayExpression, InlineStructExpression, InlineStructMember, InlineTupleExpression, InlineArrayExpression, InlineStructExpression, InlineStructMember, InlineTupleExpression,
IterationStatement, LiteralExpression, Parameter, PostfixExpression, Range, RangeOrExpression, IterationStatement, LiteralExpression, LogStatement, Parameter, PostfixExpression, Range,
ReturnStatement, Span, Spread, SpreadOrExpression, Statement, StructDefinition, StructField, RangeOrExpression, ReturnStatement, Span, Spread, SpreadOrExpression, Statement,
SymbolDeclaration, TernaryExpression, ToExpression, Type, TypeDefinition, TypedIdentifier, StructDefinition, StructField, SymbolDeclaration, TernaryExpression, ToExpression, Type,
TypedIdentifierOrAssignee, UnaryExpression, UnaryOperator, Underscore, Visibility, TypeDefinition, TypedIdentifier, TypedIdentifierOrAssignee, UnaryExpression, UnaryOperator,
Underscore, Visibility,
}; };
mod ast { mod ast {
@ -365,6 +366,24 @@ mod ast {
Definition(DefinitionStatement<'ast>), Definition(DefinitionStatement<'ast>),
Assertion(AssertionStatement<'ast>), Assertion(AssertionStatement<'ast>),
Iteration(IterationStatement<'ast>), Iteration(IterationStatement<'ast>),
Log(LogStatement<'ast>),
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::log_statement))]
pub struct LogStatement<'ast> {
pub content: LogStatementContent<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::log_statement_content))]
pub struct LogStatementContent<'ast> {
#[pest_ast(outer(with(span_into_str)))]
pub inner: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
} }
#[derive(Debug, FromPest, PartialEq, Clone)] #[derive(Debug, FromPest, PartialEq, Clone)]

View file

@ -164,7 +164,7 @@ fn compile_and_run<T: Field>(t: Tests) {
.unwrap() .unwrap()
}; };
let output = interpreter.execute(bin.clone(), &input); let output = interpreter.execute(bin.clone(), &input, &mut std::io::sink());
use zokrates_abi::Decode; use zokrates_abi::Decode;
let output: Result<Output, ir::Error> = output.map(|witness| Output { let output: Result<Output, ir::Error> = output.map(|witness| Output {