implement basic log statement
This commit is contained in:
parent
a08d49b7e5
commit
5ea93bb677
22 changed files with 70 additions and 8 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, ""),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -168,6 +168,7 @@ impl<T: Field> Folder<T> for RedefinitionOptimizer<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Statement::Log(l) => vec![Statement::Log(l)],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2024,6 +2024,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
}),
|
||||
}.map_err(|e| vec![e])
|
||||
}
|
||||
Statement::Log(l) => Ok(TypedStatement::Log(l)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ impl<T: Field> FlatStatement<T> {
|
|||
.collect(),
|
||||
..d
|
||||
})),
|
||||
FlatStatement::Log(l) => Some(FlatStatement::Log(l)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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![],
|
||||
};
|
||||
|
|
|
@ -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 {}/{}::<{}>",
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue