1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +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 witness = interpreter
.execute(ir_prog, &arguments.encode())
.execute(ir_prog, &arguments.encode(), &mut std::io::stdout())
.map_err(|e| format!("Execution failed: {}", e))?;
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::Assertion(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> {
fn from(statement: pest::ReturnStatement<'ast>) -> absy::StatementNode<'ast> {
use crate::absy::NodeValue;

View file

@ -395,6 +395,7 @@ pub enum Statement<'ast> {
Vec<StatementNode<'ast>>,
),
MultipleDefinition(Vec<AssigneeNode<'ast>>, ExpressionNode<'ast>),
Log(String),
}
pub type StatementNode<'ast> = Node<Statement<'ast>>;
@ -428,6 +429,7 @@ impl<'ast> fmt::Display for Statement<'ast> {
}
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),
Definition(FlatVariable, FlatExpression<T>),
Directive(FlatDirective<T>),
Log(String),
}
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)
}
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
})
}
FlatStatement::Log(l) => FlatStatement::Log(l),
}
}
}

View file

@ -1234,6 +1234,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
inputs: new_inputs,
})
}
FlatStatement::Log(l) => FlatStatement::Log(l),
});
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,
)],
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),
},
FlatStatement::Directive(ds) => Statement::Directive(ds.into()),
FlatStatement::Log(l) => Statement::Log(l),
}
}
}

View file

@ -25,10 +25,11 @@ 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,
program: ProgIterator<T, I>,
inputs: &[T],
log_stream: &mut W,
) -> ExecutionResult<T> {
self.check_inputs(&program, inputs)?;
let mut witness = BTreeMap::new();
@ -75,6 +76,9 @@ impl Interpreter {
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> },
Solver,
WrongInputCount { expected: usize, received: usize },
LogStream,
}
impl fmt::Display for Error {
@ -305,6 +310,7 @@ impl fmt::Display for Error {
received,
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> {
Constraint(QuadComb<T>, LinComb<T>, Option<RuntimeError>),
Directive(Directive<T>),
Log(String),
}
impl<T: Field> Statement<T> {
@ -70,6 +71,7 @@ impl<T: Field> fmt::Display for Statement<T> {
match *self {
Statement::Constraint(ref quad, ref lin, _) => write!(f, "{} == {}", quad, lin),
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|))")
}
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::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])
}
Statement::Log(l) => Ok(TypedStatement::Log(l)),
}
}

View file

@ -75,6 +75,7 @@ impl<T: Field> FlatStatement<T> {
.collect(),
..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),
)]
}
typed_absy::TypedStatement::Log(l) => vec![zir::ZirStatement::Log(l)],
typed_absy::TypedStatement::PushCallLog(..) => vec![],
typed_absy::TypedStatement::PopCallLog => vec![],
};

View file

@ -641,6 +641,7 @@ pub enum TypedStatement<'ast, T> {
Vec<TypedStatement<'ast, T>>,
),
MultipleDefinition(Vec<TypedAssignee<'ast, T>>, TypedExpressionList<'ast, T>),
Log(String),
// Aux
PushCallLog(
DeclarationFunctionKey<'ast, T>,
@ -707,6 +708,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
}
write!(f, " = {}", rhs)
}
TypedStatement::Log(ref l) => write!(f, "log!({})", l),
TypedStatement::PushCallLog(ref key, ref generics) => write!(
f,
"// 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(),
f.fold_expression_list(elist),
),
ZirStatement::Log(l) => ZirStatement::Log(l),
};
vec![res]
}

View file

@ -112,6 +112,7 @@ pub enum ZirStatement<'ast, T> {
),
Assertion(BooleanExpression<'ast, T>, RuntimeError),
MultipleDefinition(Vec<ZirAssignee<'ast>>, ZirExpressionList<'ast, T>),
Log(String),
}
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)
}
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<_, _>>()?,
f.fold_expression_list(elist)?,
),
ZirStatement::Log(l) => ZirStatement::Log(l),
};
Ok(vec![res])
}

View file

@ -53,12 +53,15 @@ vis = { vis_private | vis_public }
// Statements
statement = { (return_statement // does not require subsequent newline
| (iteration_statement
| (log_statement
| iteration_statement
| definition_statement
| expression_statement
) ~ 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"}
return_statement = { "return" ~ expression_list}
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,
IdentifierExpression, IdentifierOrDecimal, IfElseExpression, ImportDirective, ImportSymbol,
InlineArrayExpression, InlineStructExpression, InlineStructMember, InlineTupleExpression,
IterationStatement, LiteralExpression, Parameter, PostfixExpression, Range, RangeOrExpression,
ReturnStatement, Span, Spread, SpreadOrExpression, Statement, StructDefinition, StructField,
SymbolDeclaration, TernaryExpression, ToExpression, Type, TypeDefinition, TypedIdentifier,
TypedIdentifierOrAssignee, UnaryExpression, UnaryOperator, Underscore, Visibility,
IterationStatement, LiteralExpression, LogStatement, Parameter, PostfixExpression, Range,
RangeOrExpression, ReturnStatement, Span, Spread, SpreadOrExpression, Statement,
StructDefinition, StructField, SymbolDeclaration, TernaryExpression, ToExpression, Type,
TypeDefinition, TypedIdentifier, TypedIdentifierOrAssignee, UnaryExpression, UnaryOperator,
Underscore, Visibility,
};
mod ast {
@ -365,6 +366,24 @@ mod ast {
Definition(DefinitionStatement<'ast>),
Assertion(AssertionStatement<'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)]

View file

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