input, output and compiler tests

This commit is contained in:
gluax 2021-05-13 07:16:59 -04:00
parent 0ef7ca3d8e
commit 29cd920075
14 changed files with 140 additions and 71 deletions

View File

@ -38,7 +38,7 @@ use std::fmt;
pub enum InputValue {
Address(String),
Boolean(bool),
Char(String),
Char(char),
Field(String),
Group(GroupValue),
Integer(IntegerType, String),
@ -63,8 +63,9 @@ impl InputValue {
Ok(InputValue::Boolean(boolean))
}
fn from_char(character: CharValue) -> Self {
InputValue::Char(character.value)
fn from_char(character: CharValue) -> Result<Self, InputParserError> {
let character = character.value.inner()?;
Ok(InputValue::Char(character))
}
fn from_number(integer_type: IntegerType, number: String) -> Self {
@ -94,7 +95,7 @@ impl InputValue {
match (data_type, value) {
(DataType::Address(_), Value::Address(address)) => Ok(InputValue::from_address_value(address)),
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
(DataType::Char(_), Value::Char(character)) => Ok(InputValue::from_char(character)),
(DataType::Char(_), Value::Char(character)) => InputValue::from_char(character),
(DataType::Integer(integer_type), Value::Integer(integer)) => {
Ok(InputValue::from_number(integer_type, integer.to_string()))
}

View File

@ -18,7 +18,7 @@
use crate::{
address::Address,
errors::{CharError, FunctionError},
errors::FunctionError,
program::ConstrainedProgram,
value::{
boolean::input::bool_from_input,
@ -83,17 +83,11 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
match (type_, input) {
(Type::Address, InputValue::Address(addr)) => Ok(ConstrainedValue::Address(Address::constant(addr, span)?)),
(Type::Boolean, InputValue::Boolean(value)) => Ok(ConstrainedValue::Boolean(Boolean::constant(value))),
(Type::Char, InputValue::Char(value)) => {
if let Some(character) = value.chars().nth(1) {
Ok(ConstrainedValue::Char(Char::constant(
character,
format!("{}", character as u32),
span,
)?))
} else {
Err(FunctionError::from(CharError::invalid_char(value, span)))
}
}
(Type::Char, InputValue::Char(character)) => Ok(ConstrainedValue::Char(Char::constant(
character,
format!("{}", character as u32),
span,
)?)),
(Type::Field, InputValue::Field(value)) => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
(Type::Group, InputValue::Group(value)) => Ok(ConstrainedValue::Group(G::constant(&value.into(), span)?)),
(Type::Integer(integer_type), InputValue::Integer(_, value)) => Ok(ConstrainedValue::Integer(

View File

@ -50,12 +50,8 @@ pub(crate) fn char_from_input<'a, F: PrimeField, G: GroupType<F>, CS: Constraint
// Check that the parameter value is the correct type
let option = match input_value {
Some(input) => {
if let InputValue::Char(string) = input {
if let Some(character) = string.chars().nth(1) {
(character, Some((character as u32).to_string()))
} else {
return Err(CharError::invalid_char(string, span));
}
if let InputValue::Char(character) = input {
(character, Some((character as u32).to_string()))
} else {
return Err(CharError::invalid_char(input.to_string(), span));
}

View File

@ -1,7 +1,9 @@
circuit Foo {
a: char;
b: char;
c: char;
}
function main() {
const f = Foo { a: 'a' };
function main(a: char, b: char, c: char) {
let f = Foo { a, b, c };
}

View File

@ -1,3 +1,4 @@
[main]
a: char = '\u{2764}';
b: char = 'a';
a: char = 'a';
b: char = '\'';
c: char = '\u{2764}';

View File

@ -1,2 +1,2 @@
[registers]
r: char = '\n';
r: char = 'a';

View File

@ -14,13 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{
assert_satisfied,
get_output,
parse_program,
parse_program_with_input,
EdwardsTestCompiler,
};
use crate::{assert_satisfied, get_output, parse_program, parse_program_with_input, EdwardsTestCompiler};
pub fn output_char(program: EdwardsTestCompiler) {
let expected = include_bytes!("output/output_char.out");
@ -29,26 +23,6 @@ pub fn output_char(program: EdwardsTestCompiler) {
assert_eq!(expected, actual.bytes().as_slice());
}
#[test]
fn test_input_pass() {
let program_string = include_str!("input.leo");
let input_string = include_str!("input/char.in");
let program = parse_program_with_input(program_string, input_string).unwrap();
assert_satisfied(program);
}
// #[test]
// fn test_input_fail() {
// let program_string = include_str!("assert_eq_input.leo");
// let input_string = include_str!("input/true_false.in");
// let program = parse_program_with_input(program_string, input_string).unwrap();
// expect_compiler_error(program);
// }
#[test]
fn test_registers() {
let program_string = include_str!("output_register.leo");
@ -94,8 +68,10 @@ fn test_function() {
#[test]
fn test_circuit() {
let program_string = include_str!("function.leo");
let program = parse_program(program_string).unwrap();
let program_string = include_str!("circuit.leo");
let char_input_string = include_str!("input/char.in");
let program = parse_program_with_input(program_string, char_input_string).unwrap();
assert_satisfied(program);
}
}

View File

@ -1,2 +1,2 @@
[registers]
r: char = '\n';
r: char = a;

View File

@ -83,6 +83,12 @@ impl InputParserError {
Self::new_from_span(message, span)
}
pub fn invalid_char(character: String, span: &Span) -> Self {
let message = format!("Expected valid character found `{}`", character);
Self::new_from_span(message, span)
}
pub fn implicit_type(data_type: DataType, implicit: NumberValue) -> Self {
let message = format!("expected `{}`, found `{}`", data_type, implicit);

View File

@ -133,17 +133,19 @@ number_negative = @{ "-" ~ ASCII_DIGIT+ }
// Declared in values/number_positive.rs
number_positive = @{ ASCII_DIGIT+ }
// Decalred in values/char_types.rs
// ANY is equivalent to '\u{00}'..'\u{10FFFF}'
basic_char = { ANY }
escaped_char = @{ "\\" ~ ("\"" | "\'" | "\\" | "/" | "b" | "f" | "n" | "r" | "t") }
hex_char = @{ "\\" ~ "u" ~ "{" ~ ASCII_HEX_DIGIT{4} ~ "}" }
char_types = {
escaped_char
| hex_char
| basic_char
}
// Declared in values/char_value.rs
// ANY is equivalent to '\u{00}'..'\u{10FFFF}'
// TODO FIX
// value_char = {
// !("\'" | "\\") ~ ANY
// | "\\" ~ ("\"" | "\'" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
// | "\\" ~ ("u" ~ ASCII_HEX_DIGIT(4))
// }
value_char = { "'" ~ "\\"? ~ ANY ~ "'" }
value_char = { "\'" ~ char_types ~ "\'" }
// Declared in values/integer_value.rs
value_integer = { value_integer_signed | value_integer_unsigned}

View File

@ -0,0 +1,89 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{
ast::{span_into_string, Rule},
errors::InputParserError,
};
use pest::Span;
use pest_ast::FromPest;
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::basic_char))]
pub struct BasicChar<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::escaped_char))]
pub struct EscapedChar<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::hex_char))]
pub struct HexChar<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::char_types))]
pub enum CharTypes<'ast> {
Basic(BasicChar<'ast>),
Escaped(EscapedChar<'ast>),
Hex(HexChar<'ast>),
}
impl<'ast> CharTypes<'ast> {
pub fn inner(self) -> Result<char, InputParserError> {
match self {
Self::Basic(character) => {
if let Some(character) = character.value.chars().next() {
return Ok(character);
}
Err(InputParserError::invalid_char(character.value, &character.span))
}
Self::Escaped(character) => {
if let Some(character) = character.value.chars().nth(1) {
return Ok(character);
}
Err(InputParserError::invalid_char(character.value, &character.span))
}
Self::Hex(character) => {
let hex_string_number = character.value[3..=6].to_string();
if let Ok(hex) = u32::from_str_radix(&hex_string_number, 16) {
if let Some(unicode) = std::char::from_u32(hex) {
return Ok(unicode);
}
}
Err(InputParserError::invalid_char(character.value, &character.span))
}
}
}
}

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::ast::{span_into_string, Rule};
use crate::{ast::Rule, values::CharTypes};
use pest::Span;
use pest_ast::FromPest;
@ -23,14 +23,13 @@ use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
#[pest_ast(rule(Rule::value_char))]
pub struct CharValue<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
pub value: CharTypes<'ast>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for CharValue<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
write!(f, "{:?}", self.value)
}
}

View File

@ -26,6 +26,9 @@ pub use address_value::*;
pub mod boolean_value;
pub use boolean_value::*;
pub mod char_types;
pub use char_types::*;
pub mod char_value;
pub use char_value::*;