check output register type == return value type + tests

This commit is contained in:
collin 2021-01-08 20:06:23 -05:00
parent 4eecd61f98
commit c48c39caaf
8 changed files with 83 additions and 4 deletions

View File

@ -14,7 +14,8 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{Error as FormattedError, Span}; use crate::errors::ValueError;
use leo_ast::{Error as FormattedError, Span, Type};
use std::path::Path; use std::path::Path;
@ -22,12 +23,16 @@ use std::path::Path;
pub enum OutputBytesError { pub enum OutputBytesError {
#[error("{}", _0)] #[error("{}", _0)]
Error(#[from] FormattedError), Error(#[from] FormattedError),
#[error("{}", _0)]
ValueError(#[from] ValueError),
} }
impl OutputBytesError { impl OutputBytesError {
pub fn set_path(&mut self, path: &Path) { pub fn set_path(&mut self, path: &Path) {
match self { match self {
OutputBytesError::Error(error) => error.set_path(path), OutputBytesError::Error(error) => error.set_path(path),
OutputBytesError::ValueError(error) => error.set_path(path),
} }
} }
@ -40,4 +45,13 @@ impl OutputBytesError {
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }
pub fn mismatched_output_types(left: Type, right: Type, span: Span) -> Self {
let message = format!(
"Mismatched types. Expected register output type `{}`, found type `{}`.",
left, right
);
Self::new_from_span(message, span)
}
} }

View File

@ -51,7 +51,7 @@ impl OutputBytes {
// Return an error if we do not have enough return registers // Return an error if we do not have enough return registers
if register_values.len() < return_values.len() { if register_values.len() < return_values.len() {
return Err(OutputBytesError::not_enough_registers(span)); return Err(OutputBytesError::not_enough_registers(span.clone()));
} }
// Manually construct result string // Manually construct result string
@ -63,10 +63,22 @@ impl OutputBytes {
// format: "token_id: u64 = 1u64;" // format: "token_id: u64 = 1u64;"
for (parameter, value) in register_values.into_iter().zip(return_values.into_iter()) { for (parameter, value) in register_values.into_iter().zip(return_values.into_iter()) {
let name = parameter.variable.name; let name = parameter.variable.name;
let type_ = parameter.type_;
// Check register type == return value type.
let register_type = parameter.type_;
let return_value_type = value.to_type(&span)?;
if register_type != return_value_type {
return Err(OutputBytesError::mismatched_output_types(
register_type,
return_value_type,
span,
));
}
let value = value.to_string(); let value = value.to_string();
let format = format!("{}: {} = {};\n", name, type_, value,); let format = format!("{}: {} = {};\n", name, register_type, value,);
string.push_str(&format); string.push_str(&format);
} }

View File

@ -16,4 +16,5 @@
mod program_input; mod program_input;
mod program_input_and_program_state; mod program_input_and_program_state;
mod program_registers;
mod program_state; mod program_state;

View File

@ -0,0 +1,4 @@
[main]
[registers]
r: u8 = 0u8;

View File

@ -0,0 +1,40 @@
// Copyright (C) 2019-2020 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::{assert_satisfied, expect_compiler_error, get_output, parse_program_with_input};
#[test]
fn test_registers_pass() {
let program_string = include_str!("registers_pass.leo");
let input_string = include_str!("input/main.in");
let expected = include_bytes!("output/registers_pass.out");
let program = parse_program_with_input(program_string, input_string).unwrap();
let actual = get_output(program);
assert!(expected.eq(actual.bytes().as_slice()));
}
#[test]
fn test_registers_fail() {
let program_string = include_str!("registers_fail.leo");
let input_string = include_str!("input/main.in");
let program = parse_program_with_input(program_string, input_string).unwrap();
expect_compiler_error(program);
}

View File

@ -0,0 +1,2 @@
[registers]
r: u8 = 1;

View File

@ -0,0 +1,3 @@
function main() -> bool {
return false
}

View File

@ -0,0 +1,3 @@
function main() -> u8 {
return 1u8
}