mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-09 20:38:46 +03:00
Add console.assert
This commit is contained in:
parent
1d55322276
commit
615cc61e9e
@ -216,6 +216,7 @@ pub trait StatementReconstructor: ExpressionReconstructor {
|
||||
fn reconstruct_console(&mut self, input: ConsoleStatement) -> Statement {
|
||||
Statement::Console(ConsoleStatement {
|
||||
function: match input.function {
|
||||
ConsoleFunction::Assert(expr) => ConsoleFunction::Assert(self.reconstruct_expression(expr).0),
|
||||
ConsoleFunction::AssertEq(left, right) => ConsoleFunction::AssertEq(
|
||||
self.reconstruct_expression(left).0,
|
||||
self.reconstruct_expression(right).0,
|
||||
|
@ -154,6 +154,9 @@ pub trait StatementVisitor<'a>: ExpressionVisitor<'a> {
|
||||
|
||||
fn visit_console(&mut self, input: &'a ConsoleStatement) {
|
||||
match &input.function {
|
||||
ConsoleFunction::Assert(expr) => {
|
||||
self.visit_expression(expr, &Default::default());
|
||||
}
|
||||
ConsoleFunction::AssertEq(left, right) => {
|
||||
self.visit_expression(left, &Default::default());
|
||||
self.visit_expression(right, &Default::default());
|
||||
|
@ -22,11 +22,11 @@ use std::fmt;
|
||||
/// A console logging function to invoke.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub enum ConsoleFunction {
|
||||
/// A `console.assert_eq(expr1, expr2)` call to invoke,
|
||||
/// asserting that the operands are equal.
|
||||
/// A `console.assert(expr)` call to invoke, asserting that the operands are equal
|
||||
Assert(Expression),
|
||||
/// A `console.assert_eq(expr1, expr2)` call to invoke, asserting that the operands are equal.
|
||||
AssertEq(Expression, Expression),
|
||||
/// A `console.assert_neq(expr1, expr2)` call to invoke,
|
||||
/// asserting that the operands are not equal.
|
||||
/// A `console.assert_neq(expr1, expr2)` call to invoke, asserting that the operands are not equal.
|
||||
AssertNeq(Expression, Expression),
|
||||
/// Dummy statement for the parser.
|
||||
Dummy,
|
||||
@ -35,6 +35,7 @@ pub enum ConsoleFunction {
|
||||
impl fmt::Display for ConsoleFunction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ConsoleFunction::Assert(expr) => write!(f, "assert({})", expr),
|
||||
ConsoleFunction::AssertEq(expr1, expr2) => write!(f, "assert_eq({}, {})", expr1, expr2),
|
||||
ConsoleFunction::AssertNeq(expr1, expr2) => write!(f, "assert_neq({}, {})", expr1, expr2),
|
||||
ConsoleFunction::Dummy => write!(f, "dummy"),
|
||||
|
@ -78,7 +78,7 @@ impl fmt::Display for Type {
|
||||
Type::Boolean => write!(f, "boolean"),
|
||||
Type::Field => write!(f, "field"),
|
||||
Type::Group => write!(f, "group"),
|
||||
Type::Identifier(ref variable) => write!(f, "circuit {}", variable),
|
||||
Type::Identifier(ref variable) => write!(f, "{}", variable),
|
||||
Type::Integer(ref integer_type) => write!(f, "{}", integer_type),
|
||||
Type::Scalar => write!(f, "scalar"),
|
||||
Type::String => write!(f, "string"),
|
||||
|
@ -178,6 +178,12 @@ impl ParserContext<'_> {
|
||||
self.expect(&Token::Dot)?;
|
||||
let identifier = self.expect_identifier()?;
|
||||
let (span, function) = match identifier.name {
|
||||
sym::assert => {
|
||||
self.expect(&Token::LeftParen)?;
|
||||
let expr = self.parse_expression()?;
|
||||
self.expect(&Token::RightParen)?;
|
||||
(keyword + expr.span(), ConsoleFunction::Assert(expr))
|
||||
}
|
||||
sym::assert_eq => {
|
||||
self.expect(&Token::LeftParen)?;
|
||||
let left = self.parse_expression()?;
|
||||
|
@ -89,7 +89,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
let mut generate_assert_instruction = |name: &str, left: &'a Expression, right: &'a Expression| {
|
||||
let (left_operand, left_instructions) = self.visit_expression(left);
|
||||
let (right_operand, right_instructions) = self.visit_expression(right);
|
||||
let assert_instruction = format!(" {} {}, {});", name, left_operand, right_operand);
|
||||
let assert_instruction = format!(" {} {} {};", name, left_operand, right_operand);
|
||||
|
||||
// Concatenate the instructions.
|
||||
let mut instructions = left_instructions;
|
||||
@ -99,6 +99,13 @@ impl<'a> CodeGenerator<'a> {
|
||||
instructions
|
||||
};
|
||||
match &input.function {
|
||||
ConsoleFunction::Assert(expr) => {
|
||||
let (operand, mut instructions) = self.visit_expression(expr);
|
||||
let assert_instruction = format!(" assert.eq {} true;", operand);
|
||||
|
||||
instructions.push_str(&assert_instruction);
|
||||
instructions
|
||||
}
|
||||
ConsoleFunction::AssertEq(left, right) => generate_assert_instruction("assert.eq", left, right),
|
||||
ConsoleFunction::AssertNeq(left, right) => generate_assert_instruction("assert.neq", left, right),
|
||||
ConsoleFunction::Dummy => String::new(),
|
||||
|
@ -192,6 +192,10 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
fn visit_console(&mut self, input: &'a ConsoleStatement) {
|
||||
match &input.function {
|
||||
ConsoleFunction::Assert(expr) => {
|
||||
let type_ = self.visit_expression(expr, &Some(Type::Boolean));
|
||||
self.assert_bool_type(&type_, expr.span());
|
||||
}
|
||||
ConsoleFunction::AssertEq(left, right) | ConsoleFunction::AssertNeq(left, right) => {
|
||||
let t1 = self.visit_expression(left, &None);
|
||||
let t2 = self.visit_expression(right, &None);
|
||||
|
@ -106,7 +106,9 @@ impl<'a> TypeChecker<'a> {
|
||||
/// Emits an error if the two given types are not equal.
|
||||
pub(crate) fn check_eq_types(&self, t1: &Option<Type>, t2: &Option<Type>, span: Span) {
|
||||
match (t1, t2) {
|
||||
(Some(t1), Some(t2)) if t1 != t2 => self.emit_err(TypeCheckerError::type_should_be(t1, t2, span)),
|
||||
(Some(t1), Some(t2)) if !Type::eq_flat(t1, t2) => {
|
||||
self.emit_err(TypeCheckerError::type_should_be(t1, t2, span))
|
||||
}
|
||||
(Some(type_), None) | (None, Some(type_)) => {
|
||||
self.emit_err(TypeCheckerError::type_should_be("no type", type_, span))
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/dummy.in
|
||||
*/
|
||||
|
||||
@program
|
||||
function main(y: bool) -> bool {
|
||||
console.error("hello error");
|
||||
return y == true;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/dummy.in
|
||||
*/
|
||||
|
||||
@program
|
||||
function main(y: bool) -> bool {
|
||||
console.log("hello world");
|
||||
return y == true;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file:
|
||||
- inputs/input_unequal.in
|
||||
- inputs/input_equal.in
|
||||
*/
|
||||
|
||||
// Conditionally add two u32 integers and log the result to the console.
|
||||
@program
|
||||
function main(a: u32, b: u32) -> bool {
|
||||
if a == b {
|
||||
console.log("{}=={}", a, b); // This line should not fail.
|
||||
}
|
||||
|
||||
return a == b;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
function main() {
|
||||
console.log( hello );
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/dummy.in
|
||||
*/
|
||||
|
||||
@program
|
||||
function main(y: bool) -> bool {
|
||||
console.log("a = {}", y);
|
||||
return y == true;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/dummy.in
|
||||
*/
|
||||
|
||||
@program
|
||||
function main(y: bool) -> bool {
|
||||
console.log("{}", 1u32);
|
||||
return y == true;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/dummy.in
|
||||
*/
|
||||
|
||||
@program
|
||||
function main(y: bool) -> bool {
|
||||
console.log("{} {}", 1u32, true);
|
||||
return y == true;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
function main() {
|
||||
console.log("{}", a);
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
input_file: inputs/dummy.in
|
||||
*/
|
||||
|
||||
function main(y: bool) -> bool {
|
||||
let hello: string = "hello world";
|
||||
console.log(hello);
|
||||
return y == true;
|
||||
}
|
Loading…
Reference in New Issue
Block a user