mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-19 07:32:26 +03:00
use more clear type checking methods
This commit is contained in:
parent
02e3313d59
commit
831e011f42
@ -231,30 +231,30 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
let t2 = self.visit_expression(&input.right, &None);
|
||||
|
||||
// Allow `group` * `scalar` multiplication.
|
||||
match (t1.as_ref(), t2.as_ref()) {
|
||||
(Some(Type::Group), Some(other)) => {
|
||||
self.visitor.assert_type(Type::Group, destination, input.left.span());
|
||||
match (t1, t2) {
|
||||
(Some(Type::Group), other) => {
|
||||
self.visitor.assert_type_exact(destination, &Type::Group, input.span());
|
||||
self.visitor
|
||||
.assert_type(*other, &Some(Type::Scalar), input.right.span());
|
||||
.assert_type_exact(&other, &Type::Scalar, input.right.span());
|
||||
Some(Type::Group)
|
||||
}
|
||||
(Some(other), Some(Type::Group)) => {
|
||||
self.visitor.assert_type(*other, &Some(Type::Scalar), input.left.span());
|
||||
self.visitor.assert_type(Type::Group, destination, input.right.span());
|
||||
(other, Some(Type::Group)) => {
|
||||
self.visitor.assert_type_exact(destination, &Type::Group, input.span());
|
||||
self.visitor.assert_type_exact(&other, &Type::Scalar, input.left.span());
|
||||
Some(Type::Group)
|
||||
}
|
||||
(Some(t1), Some(t2)) => {
|
||||
// Assert equal field or integer types.
|
||||
self.visitor.assert_type(*t1, destination, input.left.span());
|
||||
self.visitor.assert_type(*t2, destination, input.right.span());
|
||||
return_incorrect_type(Some(*t1), Some(*t2), destination)
|
||||
self.visitor.assert_type(t1, destination, input.left.span());
|
||||
self.visitor.assert_type(t2, destination, input.right.span());
|
||||
return_incorrect_type(Some(t1), Some(t2), destination)
|
||||
}
|
||||
(Some(type_), None) => {
|
||||
self.visitor.assert_type(*type_, destination, input.left.span());
|
||||
self.visitor.assert_type(type_, destination, input.left.span());
|
||||
None
|
||||
}
|
||||
(None, Some(type_)) => {
|
||||
self.visitor.assert_type(*type_, destination, input.right.span());
|
||||
self.visitor.assert_type(type_, destination, input.right.span());
|
||||
None
|
||||
}
|
||||
(None, None) => None,
|
||||
@ -279,25 +279,25 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
// Allow field * field.
|
||||
match (t1, t2) {
|
||||
(Some(Type::Field), type_) => {
|
||||
self.visitor.assert_type(Type::Field, &type_, input.left.span());
|
||||
self.visitor.assert_type(Type::Field, destination, input.left.span());
|
||||
self.visitor.assert_type_exact(&type_, &Type::Field, input.right.span());
|
||||
self.visitor.assert_type_exact(destination, &Type::Field, input.span());
|
||||
Some(Type::Field)
|
||||
}
|
||||
(type_, Some(Type::Field)) => {
|
||||
self.visitor.assert_type(Type::Field, &type_, input.right.span());
|
||||
self.visitor.assert_type(Type::Field, destination, input.right.span());
|
||||
self.visitor.assert_type_exact(&type_, &Type::Field, input.left.span());
|
||||
self.visitor.assert_type_exact(destination, &Type::Field, input.span());
|
||||
Some(Type::Field)
|
||||
}
|
||||
(Some(t1), t2) => {
|
||||
// Allow integer magnitude (u8, u16, u32)
|
||||
self.visitor.assert_magnitude_type(&t2, input.left.span());
|
||||
Some(self.visitor.assert_type(t1, destination, input.left.span()))
|
||||
// Allow integer t2 magnitude (u8, u16, u32)
|
||||
self.visitor.assert_magnitude_type(&t2, input.right.span());
|
||||
self.visitor.assert_type_exact(destination, &t1, input.span());
|
||||
Some(t1)
|
||||
}
|
||||
(t1, t2) => {
|
||||
// Allow integer magnitude (u8, u16, u32)
|
||||
self.visitor.assert_magnitude_type(&t2, input.span());
|
||||
self.visitor.assert_eq_types(t1, *destination, input.span());
|
||||
t1
|
||||
(None, t2) => {
|
||||
// Allow integer t2 magnitude (u8, u16, u32)
|
||||
self.visitor.assert_magnitude_type(&t2, input.right.span());
|
||||
*destination
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -312,7 +312,8 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
}
|
||||
BinaryOperation::Lt | BinaryOperation::Gt | BinaryOperation::Le | BinaryOperation::Ge => {
|
||||
// Assert the destination type is boolean.
|
||||
self.visitor.assert_type(Type::Boolean, destination, input.span());
|
||||
self.visitor
|
||||
.assert_type_exact(destination, &Type::Boolean, input.span());
|
||||
|
||||
// Assert left and right are equal field, scalar, or integer types.
|
||||
let t1 = self.visit_expression(&input.left, &None);
|
||||
|
@ -117,6 +117,7 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
|
||||
/// Returns the given type if it equals the expected type or the expected type is none.
|
||||
/// Use this method if the expected type is an unknown Option.
|
||||
pub(crate) fn assert_type(&mut self, type_: Type, expected: &Option<Type>, span: Span) -> Type {
|
||||
if let Some(expected) = expected {
|
||||
if &type_ != expected {
|
||||
@ -128,6 +129,17 @@ impl<'a> TypeChecker<'a> {
|
||||
type_
|
||||
}
|
||||
|
||||
/// Emits an error if the given type_ does not match the expected type.
|
||||
/// Use this method if the expected type is known.
|
||||
pub(crate) fn assert_type_exact(&mut self, type_: &Option<Type>, expected: &Type, span: Span) {
|
||||
if let Some(type_) = type_ {
|
||||
if type_ != expected {
|
||||
self.handler
|
||||
.emit_err(TypeCheckerError::type_should_be(type_, expected, span).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits an error to the error handler if the given type is not equal to any of the expected types.
|
||||
pub(crate) fn assert_one_of_types(&self, type_: &Option<Type>, expected: &[Type], span: Span) {
|
||||
if let Some(type_) = type_ {
|
||||
|
@ -137,7 +137,7 @@ symbols! {
|
||||
sub_wrapped,
|
||||
xor,
|
||||
|
||||
// arity three operators 33-44
|
||||
// algorithm operator names 33-44
|
||||
bhp256,
|
||||
bhp512,
|
||||
bhp768,
|
||||
|
@ -7,5 +7,5 @@ input_file:
|
||||
|
||||
function main(a: field) -> bool {
|
||||
const negOneField: field = -1field;
|
||||
return negOneField ** 2i8 == 1field;
|
||||
return negOneField ** 2field == 1field;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file:
|
||||
- inputs/fields.in
|
||||
*/
|
||||
|
||||
function main(a: field) -> bool {
|
||||
const negOneField: field = -1field;
|
||||
return negOneField ** 2u8 == 1field;
|
||||
}
|
@ -1,10 +1,8 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/pow.in
|
||||
expectation: Fail
|
||||
|
||||
# This test might take to long to fully compile.
|
||||
# If necessary we could move it to disabled_tests.
|
||||
# The exponent must be u8, u16, or u32
|
||||
*/
|
||||
|
||||
function main(a: u128, b: u128, c: u128) -> bool {
|
||||
|
@ -1,10 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
expectation: Fail
|
||||
input_file: inputs/pow.in
|
||||
|
||||
# This test might take to long to fully compile.
|
||||
# If necessary we could move it to disabled_tests.
|
||||
# The exponent must be u8, u16, or u32
|
||||
*/
|
||||
|
||||
function main(a: u64, b: u64, c: u64) -> bool {
|
||||
|
8
tests/expectations/compiler/compiler/field/pow.leo.out
Normal file
8
tests/expectations/compiler/compiler/field/pow.leo.out
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: ff3a3f5067b97fc7ac387dbfbb940a8c04f5755783dbf848f661d1962a594bb3
|
||||
initial_ast: 7d70280165206bb1163aa18f521a649b83d6193ecec6328bf329074f32c308f7
|
||||
symbol_table: 3b803544d5d80d914d6d8a04d9fd0dea5ee371845d5c03af5899d751187f8201
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 195a6921720db473ae0b5093da0353391308e0e31a698e5ef105127e94113ff6
|
||||
initial_ast: 66e17dd0b33e9a4f2e4312c5d6605a5d63e5bdf537df5f08f1a2fdc30f24c3f5
|
||||
symbol_table: 5e271a21555ca024865f1857d212de20903c307db62862b7a0ba486fd77854e3
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: 195a6921720db473ae0b5093da0353391308e0e31a698e5ef105127e94113ff6
|
||||
initial_ast: b4e5d9d62d4ed1e5f963b0d957c9be73b8ebe09e749d1658396672ea7d938454
|
||||
symbol_table: 34a7c1477e5cb3d23a4ce2fbc78487444e3a8ff3e6948b620fec27ac7b439c24
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372010]: The second operand must be a unsigned int but got type `i128`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
- "Error [ETYC0372008]: Expected one type from `u8,u16,u32,`, but got `i128`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372010]: The second operand must be a unsigned int but got type `i16`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
- "Error [ETYC0372008]: Expected one type from `u8,u16,u32,`, but got `i16`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372010]: The second operand must be a unsigned int but got type `i32`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
- "Error [ETYC0372008]: Expected one type from `u8,u16,u32,`, but got `i32`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372010]: The second operand must be a unsigned int but got type `i64`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
- "Error [ETYC0372008]: Expected one type from `u8,u16,u32,`, but got `i64`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372010]: The second operand must be a unsigned int but got type `i8`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
- "Error [ETYC0372008]: Expected one type from `u8,u16,u32,`, but got `i8`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
|
@ -1,8 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: f7022770406b07fcb59e741b04516838beabbaf118f1cf2c72501cf477a695ef
|
||||
initial_ast: 5c54a5764d818cb3c119b4a11838429264a322b6b5e0f3704023d0c3b574fca1
|
||||
symbol_table: 0116b72430652b485c5d4280152302b99593576ff5b7d12e8aeff94716e4fac3
|
||||
- "Error [ETYC0372008]: Expected one type from `u8,u16,u32,`, but got `u128`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
|
@ -1,8 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: dc741dca85c7ced073969a884df08515f767765ad7dcc43f285b77a87cb97de7
|
||||
initial_ast: 1f704360566c3d8bfc9b0ac406fa21fdb19e03c5cf35371b7cfa40568d23dc65
|
||||
symbol_table: 654d7f1e81fea92b17f7b5b232c9ebc63a471df086b31450036a3cc312f24c42
|
||||
- "Error [ETYC0372008]: Expected one type from `u8,u16,u32,`, but got `u64`\n --> compiler-test:4:17\n |\n 4 | return a ** b == c;\n | ^\n"
|
||||
|
Loading…
Reference in New Issue
Block a user