mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-27 12:17:35 +03:00
merge testnet3
This commit is contained in:
commit
a15fce710c
@ -18,9 +18,9 @@ use crate::GroupLiteral;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// A literal expression.
|
||||
/// A literal.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum LiteralExpression {
|
||||
pub enum Literal {
|
||||
// todo: deserialize values here
|
||||
/// An address literal, e.g., `aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9`.
|
||||
Address(String, #[serde(with = "leo_span::span_json")] Span),
|
||||
@ -41,7 +41,7 @@ pub enum LiteralExpression {
|
||||
String(String, #[serde(with = "leo_span::span_json")] Span),
|
||||
}
|
||||
|
||||
impl fmt::Display for LiteralExpression {
|
||||
impl fmt::Display for Literal {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match &self {
|
||||
Self::Address(address, _) => write!(f, "{}", address),
|
||||
@ -55,7 +55,7 @@ impl fmt::Display for LiteralExpression {
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for LiteralExpression {
|
||||
impl Node for Literal {
|
||||
fn span(&self) -> Span {
|
||||
match &self {
|
||||
Self::Address(_, span)
|
@ -44,8 +44,8 @@ pub use tuple_init::*;
|
||||
mod unary;
|
||||
pub use unary::*;
|
||||
|
||||
mod value;
|
||||
pub use value::*;
|
||||
mod literal;
|
||||
pub use literal::*;
|
||||
|
||||
/// Expression that evaluates to a value.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
@ -64,7 +64,7 @@ pub enum Expression {
|
||||
/// An identifier.
|
||||
Identifier(Identifier),
|
||||
/// A literal expression.
|
||||
Literal(LiteralExpression),
|
||||
Literal(Literal),
|
||||
/// A ternary conditional expression `cond ? if_expr : else_expr`.
|
||||
Ternary(TernaryExpression),
|
||||
/// A tuple expression e.g., `(foo, 42, true)`.
|
||||
|
@ -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::{Expression, GroupLiteral, IntegerType, LiteralExpression, Node, Type, UnaryOperation};
|
||||
use crate::{Expression, GroupLiteral, IntegerType, Literal, Node, Type, UnaryOperation};
|
||||
use leo_errors::{InputError, LeoError, Result};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -34,11 +34,11 @@ impl TryFrom<(Type, Expression)> for InputValue {
|
||||
fn try_from(value: (Type, Expression)) -> Result<Self> {
|
||||
Ok(match value {
|
||||
(type_, Expression::Literal(lit)) => match (type_, lit) {
|
||||
(Type::Address, LiteralExpression::Address(value, _)) => Self::Address(value),
|
||||
(Type::Boolean, LiteralExpression::Boolean(value, _)) => Self::Boolean(value),
|
||||
(Type::Field, LiteralExpression::Field(value, _)) => Self::Field(value),
|
||||
(Type::Group, LiteralExpression::Group(value)) => Self::Group(*value),
|
||||
(Type::IntegerType(expected), LiteralExpression::Integer(actual, value, span)) => {
|
||||
(Type::Address, Literal::Address(value, _)) => Self::Address(value),
|
||||
(Type::Boolean, Literal::Boolean(value, _)) => Self::Boolean(value),
|
||||
(Type::Field, Literal::Field(value, _)) => Self::Field(value),
|
||||
(Type::Group, Literal::Group(value)) => Self::Group(*value),
|
||||
(Type::IntegerType(expected), Literal::Integer(actual, value, span)) => {
|
||||
if expected == actual {
|
||||
Self::Integer(expected, value)
|
||||
} else {
|
||||
|
@ -109,7 +109,7 @@ pub trait ExpressionReconstructor {
|
||||
(Expression::Identifier(input), Default::default())
|
||||
}
|
||||
|
||||
fn reconstruct_literal(&mut self, input: LiteralExpression) -> (Expression, Self::AdditionalOutput) {
|
||||
fn reconstruct_literal(&mut self, input: Literal) -> (Expression, Self::AdditionalOutput) {
|
||||
(Expression::Literal(input), Default::default())
|
||||
}
|
||||
|
||||
|
@ -72,17 +72,6 @@ pub trait ExpressionVisitor<'a> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_err(&mut self, _input: &'a ErrExpression, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
fn visit_identifier(&mut self, _input: &'a Identifier, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_literal(&mut self, _input: &'a LiteralExpression, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_circuit_init(
|
||||
&mut self,
|
||||
_input: &'a CircuitExpression,
|
||||
@ -91,6 +80,18 @@ pub trait ExpressionVisitor<'a> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_err(&mut self, _input: &'a ErrExpression, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_identifier(&mut self, _input: &'a Identifier, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_literal(&mut self, _input: &'a Literal, _additional: &Self::AdditionalInput) -> Self::Output {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_ternary(&mut self, input: &'a TernaryExpression, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_expression(&input.condition, additional);
|
||||
self.visit_expression(&input.if_true, additional);
|
||||
|
@ -53,6 +53,7 @@ impl Type {
|
||||
///
|
||||
/// Flattens array syntax: `[[u8; 1]; 2] == [u8; (2, 1)] == true`
|
||||
///
|
||||
// TODO: Does not seem to flatten?
|
||||
pub fn eq_flat(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Type::Address, Type::Address)
|
||||
|
@ -120,7 +120,7 @@ impl<'a> ParserContext<'a> {
|
||||
|
||||
/// Emit the error `err`.
|
||||
pub(super) fn emit_err(&self, err: ParserError) {
|
||||
self.handler.emit_err(err.into());
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
|
||||
/// Emit the error `err`.
|
||||
|
@ -384,9 +384,7 @@ impl ParserContext<'_> {
|
||||
/// tuple initialization expression or an affine group literal.
|
||||
fn parse_tuple_expression(&mut self) -> Result<Expression> {
|
||||
if let Some(gt) = self.eat_group_partial().transpose()? {
|
||||
return Ok(Expression::Literal(LiteralExpression::Group(Box::new(
|
||||
GroupLiteral::Tuple(gt),
|
||||
))));
|
||||
return Ok(Expression::Literal(Literal::Group(Box::new(GroupLiteral::Tuple(gt)))));
|
||||
}
|
||||
|
||||
let (mut tuple, trailing, span) = self.parse_expr_tuple()?;
|
||||
@ -475,7 +473,7 @@ impl ParserContext<'_> {
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// circuit initialization expression.
|
||||
/// let foo = Foo { x: 1u8 };
|
||||
pub fn parse_circuit_expression(&mut self, identifier: Identifier) -> Result<Expression> {
|
||||
pub fn parse_circuit_init_expression(&mut self, identifier: Identifier) -> Result<Expression> {
|
||||
let (members, _, end) = self.parse_list(Delimiter::Brace, Some(Token::Comma), |p| {
|
||||
p.parse_circuit_member().map(Some)
|
||||
})?;
|
||||
@ -511,44 +509,42 @@ impl ParserContext<'_> {
|
||||
// Literal followed by `field`, e.g., `42field`.
|
||||
Some(Token::Field) => {
|
||||
assert_no_whitespace("field")?;
|
||||
Expression::Literal(LiteralExpression::Field(value, full_span))
|
||||
Expression::Literal(Literal::Field(value, full_span))
|
||||
}
|
||||
// Literal followed by `group`, e.g., `42group`.
|
||||
Some(Token::Group) => {
|
||||
assert_no_whitespace("group")?;
|
||||
Expression::Literal(LiteralExpression::Group(Box::new(GroupLiteral::Single(
|
||||
value, full_span,
|
||||
))))
|
||||
Expression::Literal(Literal::Group(Box::new(GroupLiteral::Single(value, full_span))))
|
||||
}
|
||||
// Literal followed by `scalar` e.g., `42scalar`.
|
||||
Some(Token::Scalar) => {
|
||||
assert_no_whitespace("scalar")?;
|
||||
Expression::Literal(LiteralExpression::Scalar(value, full_span))
|
||||
Expression::Literal(Literal::Scalar(value, full_span))
|
||||
}
|
||||
// Literal followed by other type suffix, e.g., `42u8`.
|
||||
Some(suffix) => {
|
||||
assert_no_whitespace(&suffix.to_string())?;
|
||||
let int_ty = Self::token_to_int_type(suffix).expect("unknown int type token");
|
||||
Expression::Literal(LiteralExpression::Integer(int_ty, value, full_span))
|
||||
Expression::Literal(Literal::Integer(int_ty, value, full_span))
|
||||
}
|
||||
None => return Err(ParserError::implicit_values_not_allowed(value, span).into()),
|
||||
}
|
||||
}
|
||||
Token::True => Expression::Literal(LiteralExpression::Boolean(true, span)),
|
||||
Token::False => Expression::Literal(LiteralExpression::Boolean(false, span)),
|
||||
Token::True => Expression::Literal(Literal::Boolean(true, span)),
|
||||
Token::False => Expression::Literal(Literal::Boolean(false, span)),
|
||||
Token::AddressLit(addr) => {
|
||||
if addr.parse::<Address<Testnet2>>().is_err() {
|
||||
self.emit_err(ParserError::invalid_address_lit(&addr, span));
|
||||
}
|
||||
Expression::Literal(LiteralExpression::Address(addr, span))
|
||||
Expression::Literal(Literal::Address(addr, span))
|
||||
}
|
||||
Token::StaticString(value) => Expression::Literal(LiteralExpression::String(value, span)),
|
||||
Token::StaticString(value) => Expression::Literal(Literal::String(value, span)),
|
||||
Token::Identifier(name) => {
|
||||
let ident = Identifier { name, span };
|
||||
if !self.disallow_circuit_construction && self.check(&Token::LeftCurly) {
|
||||
// Parse circuit and records inits as circuit expressions.
|
||||
// Enforce circuit or record type later at type checking.
|
||||
self.parse_circuit_expression(ident)?
|
||||
self.parse_circuit_init_expression(ident)?
|
||||
} else {
|
||||
Expression::Identifier(ident)
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
// Check return type.
|
||||
return Some(self.assert_and_return_type(core_instruction.return_type(), expected, access.span()));
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::invalid_access_expression(access, access.span()));
|
||||
self.emit_err(TypeCheckerError::invalid_core_circuit_call(access, access.span()));
|
||||
}
|
||||
}
|
||||
AccessExpression::Tuple(access) => {
|
||||
@ -118,13 +118,199 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
self.emit_err(TypeCheckerError::type_should_be(type_, "tuple", access.span()));
|
||||
}
|
||||
}
|
||||
self.emit_err(TypeCheckerError::invalid_core_circuit_call(access, access.span()));
|
||||
}
|
||||
}
|
||||
_expr => {} // todo: Add support for associated constants (u8::MAX).
|
||||
AccessExpression::Member(access) => {
|
||||
// Check that the type of `inner` in `inner.name` is a circuit.
|
||||
match self.visit_expression(&access.inner, &None) {
|
||||
Some(Type::Identifier(identifier)) => {
|
||||
// Retrieve the circuit definition associated with `identifier`.
|
||||
let circ = self.symbol_table.borrow().lookup_circuit(&identifier.name).cloned();
|
||||
if let Some(circ) = circ {
|
||||
// Check that `access.name` is a member of the circuit.
|
||||
match circ
|
||||
.members
|
||||
.iter()
|
||||
.find(|circuit_member| circuit_member.name() == access.name.name)
|
||||
{
|
||||
// Case where `access.name` is a member of the circuit.
|
||||
Some(CircuitMember::CircuitVariable(_, type_)) => return Some(type_.clone()),
|
||||
// Case where `access.name` is not a member of the circuit.
|
||||
None => {
|
||||
self.emit_err(TypeCheckerError::invalid_circuit_variable(
|
||||
&access.name,
|
||||
&circ,
|
||||
access.name.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::invalid_circuit(&access.inner, access.inner.span()));
|
||||
}
|
||||
}
|
||||
Some(type_) => {
|
||||
self.emit_err(TypeCheckerError::type_should_be(type_, "circuit", access.inner.span()));
|
||||
}
|
||||
None => {
|
||||
self.emit_err(TypeCheckerError::could_not_determine_type(
|
||||
&access.inner,
|
||||
access.inner.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
AccessExpression::AssociatedConstant(..) => {} // todo: Add support for associated constants (u8::MAX).
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn visit_circuit_init(
|
||||
&mut self,
|
||||
input: &'a CircuitExpression,
|
||||
additional: &Self::AdditionalInput,
|
||||
) -> Self::Output {
|
||||
let circ = self.symbol_table.borrow().lookup_circuit(&input.name.name).cloned();
|
||||
if let Some(circ) = circ {
|
||||
// Check circuit type name.
|
||||
let ret = self.check_expected_circuit(circ.identifier, additional, input.name.span());
|
||||
|
||||
// Check number of circuit members.
|
||||
if circ.members.len() != input.members.len() {
|
||||
self.emit_err(TypeCheckerError::incorrect_num_circuit_members(
|
||||
circ.members.len(),
|
||||
input.members.len(),
|
||||
input.span(),
|
||||
));
|
||||
}
|
||||
|
||||
// Check circuit member types.
|
||||
circ.members
|
||||
.iter()
|
||||
.for_each(|CircuitMember::CircuitVariable(name, ty)| {
|
||||
// Lookup circuit variable name.
|
||||
if let Some(actual) = input.members.iter().find(|member| member.identifier.name == name.name) {
|
||||
if let Some(expr) = &actual.expression {
|
||||
self.visit_expression(expr, &Some(ty.clone()));
|
||||
}
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::missing_circuit_member(
|
||||
circ.identifier,
|
||||
name,
|
||||
input.span(),
|
||||
));
|
||||
};
|
||||
});
|
||||
|
||||
Some(ret)
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::unknown_sym(
|
||||
"circuit",
|
||||
&input.name.name,
|
||||
input.name.span(),
|
||||
));
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_identifier(&mut self, var: &'a Identifier, expected: &Self::AdditionalInput) -> Self::Output {
|
||||
if let Some(circuit) = self.symbol_table.borrow().lookup_circuit(&var.name) {
|
||||
Some(self.assert_and_return_type(Type::Identifier(circuit.identifier), expected, var.span))
|
||||
} else if let Some(var) = self.symbol_table.borrow().lookup_variable(&var.name) {
|
||||
Some(self.assert_and_return_type(var.type_.clone(), expected, var.span))
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::unknown_sym("variable", var.name, var.span()));
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_literal(&mut self, input: &'a Literal, expected: &Self::AdditionalInput) -> Self::Output {
|
||||
Some(match input {
|
||||
Literal::Address(_, _) => self.assert_and_return_type(Type::Address, expected, input.span()),
|
||||
Literal::Boolean(_, _) => self.assert_and_return_type(Type::Boolean, expected, input.span()),
|
||||
Literal::Field(_, _) => self.assert_and_return_type(Type::Field, expected, input.span()),
|
||||
Literal::Integer(type_, str_content, _) => {
|
||||
match type_ {
|
||||
IntegerType::I8 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i8>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i8", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::I16 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i16>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i16", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::I32 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i32>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i32", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::I64 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i64>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i64", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::I128 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i128>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i128", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::U8 if str_content.parse::<u8>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u8", input.span()))
|
||||
}
|
||||
IntegerType::U16 if str_content.parse::<u16>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u16", input.span()))
|
||||
}
|
||||
IntegerType::U32 if str_content.parse::<u32>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u32", input.span()))
|
||||
}
|
||||
IntegerType::U64 if str_content.parse::<u64>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u64", input.span()))
|
||||
}
|
||||
IntegerType::U128 if str_content.parse::<u128>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u128", input.span()))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.assert_and_return_type(Type::IntegerType(*type_), expected, input.span())
|
||||
}
|
||||
Literal::Group(_) => self.assert_and_return_type(Type::Group, expected, input.span()),
|
||||
Literal::Scalar(_, _) => self.assert_and_return_type(Type::Scalar, expected, input.span()),
|
||||
Literal::String(_, _) => self.assert_and_return_type(Type::String, expected, input.span()),
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_binary(&mut self, input: &'a BinaryExpression, destination: &Self::AdditionalInput) -> Self::Output {
|
||||
match input.op {
|
||||
BinaryOperation::And | BinaryOperation::Or | BinaryOperation::Nand | BinaryOperation::Nor => {
|
||||
@ -350,13 +536,15 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
fn visit_call(&mut self, input: &'a CallExpression, expected: &Self::AdditionalInput) -> Self::Output {
|
||||
match &*input.function {
|
||||
Expression::Identifier(ident) => {
|
||||
// Note: The function symbol lookup is performed outside of the `if let Some(func) ...` block to avoid a RefCell lifetime bug in Rust.
|
||||
// Do not move it into the `if let Some(func) ...` block or it will keep `self.symbol_table` alive for the entire block and will be very memory inefficient!
|
||||
let func = self.symbol_table.borrow().lookup_fn(&ident.name).cloned();
|
||||
if let Some(func) = func {
|
||||
let ret = self.assert_and_return_type(func.output, expected, func.span);
|
||||
|
||||
// Check number of function arguments.
|
||||
if func.input.len() != input.arguments.len() {
|
||||
self.emit_err(TypeCheckerError::incorrect_num_args_to_call(
|
||||
self.handler.emit_err(TypeCheckerError::incorrect_num_args_to_call(
|
||||
func.input.len(),
|
||||
input.arguments.len(),
|
||||
input.span(),
|
||||
@ -377,152 +565,11 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
None
|
||||
}
|
||||
}
|
||||
// TODO: Is this case sufficient?
|
||||
expr => self.visit_expression(expr, expected),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_circuit_init(&mut self, input: &'a CircuitExpression, additional: &Self::AdditionalInput) -> Self::Output {
|
||||
let circ = self.symbol_table.borrow().lookup_circuit(&input.name.name).cloned();
|
||||
if let Some(circ) = circ {
|
||||
// Check circuit type name.
|
||||
let ret = self.check_expected_circuit(circ.identifier, additional, input.name.span());
|
||||
|
||||
// Check number of circuit members.
|
||||
if circ.members.len() != input.members.len() {
|
||||
self.emit_err(TypeCheckerError::incorrect_num_circuit_members(
|
||||
circ.members.len(),
|
||||
input.members.len(),
|
||||
input.span(),
|
||||
));
|
||||
}
|
||||
|
||||
// Check circuit member types.
|
||||
circ.members
|
||||
.iter()
|
||||
.for_each(|CircuitMember::CircuitVariable(name, ty)| {
|
||||
// Lookup circuit variable name.
|
||||
if let Some(actual) = input.members.iter().find(|member| member.identifier.name == name.name) {
|
||||
if let Some(expr) = &actual.expression {
|
||||
self.visit_expression(expr, &Some(ty.clone()));
|
||||
}
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::unknown_sym(
|
||||
"circuit member variable",
|
||||
name,
|
||||
name.span(),
|
||||
));
|
||||
};
|
||||
});
|
||||
|
||||
Some(ret)
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::unknown_sym(
|
||||
"circuit",
|
||||
&input.name.name,
|
||||
input.name.span(),
|
||||
));
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_identifier(&mut self, var: &'a Identifier, expected: &Self::AdditionalInput) -> Self::Output {
|
||||
if let Some(circuit) = self.symbol_table.borrow().lookup_circuit(&var.name) {
|
||||
Some(self.assert_and_return_type(Type::Identifier(circuit.identifier), expected, var.span))
|
||||
} else if let Some(var) = self.symbol_table.borrow().lookup_variable(&var.name) {
|
||||
Some(self.assert_and_return_type(var.type_.clone(), expected, var.span))
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::unknown_sym("variable", var.name, var.span()));
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_literal(&mut self, input: &'a LiteralExpression, expected: &Self::AdditionalInput) -> Self::Output {
|
||||
Some(match input {
|
||||
LiteralExpression::Address(_, _) => self.assert_and_return_type(Type::Address, expected, input.span()),
|
||||
LiteralExpression::Boolean(_, _) => self.assert_and_return_type(Type::Boolean, expected, input.span()),
|
||||
LiteralExpression::Field(_, _) => self.assert_and_return_type(Type::Field, expected, input.span()),
|
||||
LiteralExpression::Integer(type_, str_content, _) => {
|
||||
match type_ {
|
||||
IntegerType::I8 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i8>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i8", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::I16 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i16>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i16", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::I32 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i32>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i32", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::I64 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i64>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i64", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::I128 => {
|
||||
let int = if self.negate {
|
||||
format!("-{str_content}")
|
||||
} else {
|
||||
str_content.clone()
|
||||
};
|
||||
|
||||
if int.parse::<i128>().is_err() {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(int, "i128", input.span()));
|
||||
}
|
||||
}
|
||||
IntegerType::U8 if str_content.parse::<u8>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u8", input.span()))
|
||||
}
|
||||
IntegerType::U16 if str_content.parse::<u16>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u16", input.span()))
|
||||
}
|
||||
IntegerType::U32 if str_content.parse::<u32>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u32", input.span()))
|
||||
}
|
||||
IntegerType::U64 if str_content.parse::<u64>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u64", input.span()))
|
||||
}
|
||||
IntegerType::U128 if str_content.parse::<u128>().is_err() => {
|
||||
self.emit_err(TypeCheckerError::invalid_int_value(str_content, "u128", input.span()))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.assert_and_return_type(Type::IntegerType(*type_), expected, input.span())
|
||||
}
|
||||
LiteralExpression::Group(_) => self.assert_and_return_type(Type::Group, expected, input.span()),
|
||||
LiteralExpression::Scalar(_, _) => self.assert_and_return_type(Type::Scalar, expected, input.span()),
|
||||
LiteralExpression::String(_, _) => self.assert_and_return_type(Type::String, expected, input.span()),
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_ternary(&mut self, input: &'a TernaryExpression, expected: &Self::AdditionalInput) -> Self::Output {
|
||||
self.visit_expression(&input.condition, &Some(Type::Boolean));
|
||||
|
||||
|
@ -35,7 +35,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
self.parent = Some(input.name());
|
||||
input.input.iter().for_each(|i| {
|
||||
let input_var = i.get_variable();
|
||||
self.check_ident_type(&Some(input_var.type_.clone()));
|
||||
self.check_core_type_conflict(&Some(input_var.type_.clone()));
|
||||
|
||||
// Check for conflicting variable names.
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
|
||||
|
@ -26,9 +26,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
// we can safely unwrap all self.parent instances because
|
||||
// statements should always have some parent block
|
||||
let parent = self.parent.unwrap();
|
||||
|
||||
let return_type = &self.symbol_table.borrow().lookup_fn(&parent).map(|f| f.output.clone());
|
||||
self.check_ident_type(return_type);
|
||||
self.check_core_type_conflict(return_type);
|
||||
|
||||
self.has_return = true;
|
||||
|
||||
self.visit_expression(&input.expression, return_type);
|
||||
@ -42,7 +42,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
};
|
||||
|
||||
input.variable_names.iter().for_each(|v| {
|
||||
self.check_ident_type(&Some(input.type_.clone()));
|
||||
self.check_core_type_conflict(&Some(input.type_.clone()));
|
||||
|
||||
self.visit_expression(&input.value, &Some(input.type_.clone()));
|
||||
|
||||
@ -71,9 +71,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
let var_type = if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(&var_name.name) {
|
||||
// TODO: Check where this check is moved to in `improved-flattening`.
|
||||
match &var.declaration {
|
||||
Declaration::Const => self.emit_err(TypeCheckerError::cannont_assign_to_const_var(var_name, var.span)),
|
||||
Declaration::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)),
|
||||
Declaration::Input(ParamMode::Const) => {
|
||||
self.emit_err(TypeCheckerError::cannont_assign_to_const_input(var_name, var.span))
|
||||
self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -86,7 +86,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
};
|
||||
|
||||
if var_type.is_some() {
|
||||
self.check_ident_type(&var_type);
|
||||
self.check_core_type_conflict(&var_type);
|
||||
self.visit_expression(&input.value, &var_type);
|
||||
}
|
||||
}
|
||||
@ -101,7 +101,8 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
fn visit_iteration(&mut self, input: &'a IterationStatement) {
|
||||
let iter_type = &Some(input.type_.clone());
|
||||
self.check_ident_type(iter_type);
|
||||
self.assert_int_type(iter_type, input.variable.span);
|
||||
self.check_core_type_conflict(iter_type);
|
||||
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
|
||||
input.variable.name,
|
||||
@ -132,10 +133,10 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
fn visit_block(&mut self, input: &'a Block) {
|
||||
// Creates a new sub-scope since we are in a block.
|
||||
let scope_index = self.symbol_table.borrow_mut().insert_block();
|
||||
let prev_st = std::mem::take(&mut self.symbol_table);
|
||||
let previous_symbol_table = std::mem::take(&mut self.symbol_table);
|
||||
self.symbol_table
|
||||
.swap(prev_st.borrow().get_block_scope(scope_index).unwrap());
|
||||
self.symbol_table.borrow_mut().parent = Some(Box::new(prev_st.into_inner()));
|
||||
.swap(previous_symbol_table.borrow().get_block_scope(scope_index).unwrap());
|
||||
self.symbol_table.borrow_mut().parent = Some(Box::new(previous_symbol_table.into_inner()));
|
||||
|
||||
input.statements.iter().for_each(|stmt| {
|
||||
match stmt {
|
||||
@ -149,8 +150,10 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
};
|
||||
});
|
||||
|
||||
let prev_st = *self.symbol_table.borrow_mut().parent.take().unwrap();
|
||||
self.symbol_table.swap(prev_st.get_block_scope(scope_index).unwrap());
|
||||
self.symbol_table = RefCell::new(prev_st);
|
||||
let previous_symbol_table = *self.symbol_table.borrow_mut().parent.take().unwrap();
|
||||
// TODO: Is this swap necessary?
|
||||
self.symbol_table
|
||||
.swap(previous_symbol_table.get_block_scope(scope_index).unwrap());
|
||||
self.symbol_table = RefCell::new(previous_symbol_table);
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
|
||||
/// Emits a type checker error.
|
||||
pub fn emit_err(&self, err: TypeCheckerError) {
|
||||
self.handler.emit_err(err.into());
|
||||
pub(crate) fn emit_err(&self, err: TypeCheckerError) {
|
||||
self.handler.emit_err(err);
|
||||
}
|
||||
|
||||
/// Emits an error to the handler if the given type is invalid.
|
||||
@ -311,7 +311,7 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
|
||||
/// Emits an error if the given type conflicts with a core library type.
|
||||
pub(crate) fn check_ident_type(&self, type_: &Option<Type>) {
|
||||
pub(crate) fn check_core_type_conflict(&self, type_: &Option<Type>) {
|
||||
// todo: deprecate this method.
|
||||
if let Some(Type::Identifier(ident)) = type_ {
|
||||
if self.account_types.contains(&ident.name) || self.algorithms_types.contains(&ident.name) {
|
||||
|
@ -205,8 +205,8 @@ impl Handler {
|
||||
}
|
||||
|
||||
/// Emit the error `err`.
|
||||
pub fn emit_err(&self, err: LeoError) {
|
||||
self.inner.borrow_mut().emit_err(err);
|
||||
pub fn emit_err<E: Into<LeoError>>(&self, err: E) {
|
||||
self.inner.borrow_mut().emit_err(err.into());
|
||||
}
|
||||
|
||||
/// Emit the error `err`.
|
||||
@ -282,9 +282,9 @@ mod tests {
|
||||
let res: Result<(), _> = Handler::with(|h| {
|
||||
let s = Span::default();
|
||||
assert_eq!(h.err_count(), 0);
|
||||
h.emit_err(ParserError::invalid_import_list(s).into());
|
||||
h.emit_err(ParserError::invalid_import_list(s));
|
||||
assert_eq!(h.err_count(), 1);
|
||||
h.emit_err(ParserError::unexpected_eof(s).into());
|
||||
h.emit_err(ParserError::unexpected_eof(s));
|
||||
assert_eq!(h.err_count(), 2);
|
||||
Err(ParserError::spread_in_array_init(s).into())
|
||||
});
|
||||
@ -293,8 +293,8 @@ mod tests {
|
||||
|
||||
let res: Result<(), _> = Handler::with(|h| {
|
||||
let s = Span::default();
|
||||
h.emit_err(ParserError::invalid_import_list(s).into());
|
||||
h.emit_err(ParserError::unexpected_eof(s).into());
|
||||
h.emit_err(ParserError::invalid_import_list(s));
|
||||
h.emit_err(ParserError::unexpected_eof(s));
|
||||
Ok(())
|
||||
});
|
||||
assert_eq!(count_err(res.unwrap_err().to_string()), 2);
|
||||
|
@ -33,7 +33,7 @@ create_messages!(
|
||||
|
||||
/// For when the user tries to assign to a const input.
|
||||
@formatted
|
||||
cannont_assign_to_const_input {
|
||||
cannot_assign_to_const_input {
|
||||
args: (input: impl Display),
|
||||
msg: format!(
|
||||
"Cannot assign to const input `{input}`",
|
||||
@ -43,7 +43,7 @@ create_messages!(
|
||||
|
||||
/// For when the user tries to assign to a const input.
|
||||
@formatted
|
||||
cannont_assign_to_const_var {
|
||||
cannot_assign_to_const_var {
|
||||
args: (var: impl Display),
|
||||
msg: format!(
|
||||
"Cannot assign to const variable `{var}`",
|
||||
@ -61,6 +61,16 @@ create_messages!(
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when the type checker cannot determine the type of an expression.
|
||||
@formatted
|
||||
could_not_determine_type {
|
||||
args: (expr: impl Display),
|
||||
msg: format!(
|
||||
"Could not determine the type of `{expr}`",
|
||||
),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// The method name is known but not supported for the given type.
|
||||
@formatted
|
||||
type_method_not_supported {
|
||||
@ -201,12 +211,22 @@ create_messages!(
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when the user is missing a circuit member during initialization.
|
||||
@formatted
|
||||
missing_circuit_member {
|
||||
args: (circuit: impl Display, member: impl Display),
|
||||
msg: format!(
|
||||
"Circuit initialization expression for `{circuit}` is missing member `{member}`.",
|
||||
),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// An invalid access call is made e.g., `bool::MAX`
|
||||
@formatted
|
||||
invalid_access_expression {
|
||||
invalid_core_circuit_call {
|
||||
args: (expr: impl Display),
|
||||
msg: format!(
|
||||
"Invalid method call to {expr}."
|
||||
"{expr} is not a valid core circuit call."
|
||||
),
|
||||
help: None,
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
expectation: Fail
|
||||
inputs:
|
||||
- inline.in: |
|
||||
[main]
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372025]: Comparison `>` is not supported for the address type.\n --> compiler-test:6:12\n |\n 6 | return x > sender;\n | ^^^^^^^^^^\n"
|
||||
- "Error [ETYC0372027]: Comparison `>` is not supported for the address type.\n --> compiler-test:6:12\n |\n 6 | return x > sender;\n | ^^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372025]: Comparison `>=` is not supported for the address type.\n --> compiler-test:6:12\n |\n 6 | return x >= sender;\n | ^^^^^^^^^^^\n"
|
||||
- "Error [ETYC0372027]: Comparison `>=` is not supported for the address type.\n --> compiler-test:6:12\n |\n 6 | return x >= sender;\n | ^^^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372025]: Comparison `<` is not supported for the address type.\n --> compiler-test:6:12\n |\n 6 | return x < sender;\n | ^^^^^^^^^^\n"
|
||||
- "Error [ETYC0372027]: Comparison `<` is not supported for the address type.\n --> compiler-test:6:12\n |\n 6 | return x < sender;\n | ^^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372025]: Comparison `<=` is not supported for the address type.\n --> compiler-test:6:12\n |\n 6 | return x <= sender;\n | ^^^^^^^^^^^\n"
|
||||
- "Error [ETYC0372027]: Comparison `<=` is not supported for the address type.\n --> compiler-test:6:12\n |\n 6 | return x <= sender;\n | ^^^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372019]: Circuit Bar defined with more than one member with the same name.\n --> compiler-test:3:1\n |\n 3 | circuit Bar {\n 4 | x: u32,\n 5 | x: u32,\n 6 | }\n | ^\n"
|
||||
- "Error [ETYC0372021]: Circuit Bar defined with more than one member with the same name.\n --> compiler-test:3:1\n |\n 3 | circuit Bar {\n 4 | x: u32,\n 5 | x: u32,\n 6 | }\n | ^\n"
|
||||
|
@ -1,7 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: no input
|
||||
initial_ast: d040a3a4f2be00b8123a1cbdbfe08a651526c76f12b24e0378f4f11fa7ded820
|
||||
- "Error [ETYC0372006]: Unknown variable `b`\n --> compiler-test:10:13\n |\n 10 | return (b.x == a.x) == y;\n | ^\nError [ETYC0372004]: Could not determine the type of `b`\n --> compiler-test:10:13\n |\n 10 | return (b.x == a.x) == y;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372014]: The type ComputeKey is a reserved core type name.\n --> compiler-test:4:35\n |\n 4 | function main(public compute_key: ComputeKey, a: bool) -> bool {\n | ^^^^^^^^^^\n"
|
||||
- "Error [ETYC0372015]: The type ComputeKey is a reserved core type name.\n --> compiler-test:4:35\n |\n 4 | function main(public compute_key: ComputeKey, a: bool) -> bool {\n | ^^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372014]: The type PrivateKey is a reserved core type name.\n --> compiler-test:4:35\n |\n 4 | function main(public private_key: PrivateKey, a: bool) -> bool {\n | ^^^^^^^^^^\n"
|
||||
- "Error [ETYC0372015]: The type PrivateKey is a reserved core type name.\n --> compiler-test:4:35\n |\n 4 | function main(public private_key: PrivateKey, a: bool) -> bool {\n | ^^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372014]: The type Signature is a reserved core type name.\n --> compiler-test:4:33\n |\n 4 | function main(public signature: Signature, a: bool) -> bool {\n | ^^^^^^^^^\n"
|
||||
- "Error [ETYC0372015]: The type Signature is a reserved core type name.\n --> compiler-test:4:33\n |\n 4 | function main(public signature: Signature, a: bool) -> bool {\n | ^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372014]: The type ViewKey is a reserved core type name.\n --> compiler-test:4:32\n |\n 4 | function main(public view_key: ViewKey, a: bool) -> bool {\n | ^^^^^^^\n"
|
||||
- "Error [ETYC0372015]: The type ViewKey is a reserved core type name.\n --> compiler-test:4:32\n |\n 4 | function main(public view_key: ViewKey, a: bool) -> bool {\n | ^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372009]: Expected one type from `bool, i8, i16, i32, i64, u8, u16, u32, u64, string`, but got `u128`\n --> compiler-test:4:20\n |\n 4 | let a: group = Pedersen64::hash(1u128);\n | ^^^^^^^^^^^^^^^^^^^^^^^\n"
|
||||
- "Error [ETYC0372010]: Expected one type from `bool, i8, i16, i32, i64, u8, u16, u32, u64, string`, but got `u128`\n --> compiler-test:4:20\n |\n 4 | let a: group = Pedersen64::hash(1u128);\n | ^^^^^^^^^^^^^^^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372005]: Unknown variable `b`\n --> compiler-test:4:14\n |\n 4 | \tlet b: u8 = b;\n | ^\n"
|
||||
- "Error [ETYC0372006]: Unknown variable `b`\n --> compiler-test:4:14\n |\n 4 | \tlet b: u8 = b;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372015]: The function main has no return statement.\n --> compiler-test:3:1\n |\n 3 | function main() -> u8 {}\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n"
|
||||
- "Error [ETYC0372016]: The function main has no return statement.\n --> compiler-test:3:1\n |\n 3 | function main() -> u8 {}\n | ^^^^^^^^^^^^^^^^^^^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372009]: Expected one type from `scalar`, but got `group`\n --> compiler-test:4:26\n |\n 4 | return (_, _)group * a;\n | ^\n"
|
||||
- "Error [ETYC0372010]: Expected one type from `scalar`, but got `group`\n --> compiler-test:4:26\n |\n 4 | return (_, _)group * a;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372024]: The field `balance` in a `record` must have type `u64`.\n --> compiler-test:4:1\n |\n 4 | record Token {\n 5 | balance: address,\n 6 | owner: address,\n 7 | }\n | ^\n"
|
||||
- "Error [ETYC0372026]: The field `balance` in a `record` must have type `u64`.\n --> compiler-test:4:1\n |\n 4 | record Token {\n 5 | balance: address,\n 6 | owner: address,\n 7 | }\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372020]: Record Token defined with more than one variable with the same name.\n --> compiler-test:3:1\n |\n 3 | record Token {\n 4 | // The token owner.\n 5 | owner: address,\n 6 | // The token owner.\n 7 | owner: address, // Cannot define two record variables with the same name.\n 8 | // The Aleo balance (in gates).\n 9 | balance: u64,\n 10 | // The token amount.\n 11 | amount: u64,\n 12 | }\n | ^\n"
|
||||
- "Error [ETYC0372022]: Record Token defined with more than one variable with the same name.\n --> compiler-test:3:1\n |\n 3 | record Token {\n 4 | // The token owner.\n 5 | owner: address,\n 6 | // The token owner.\n 7 | owner: address, // Cannot define two record variables with the same name.\n 8 | // The Aleo balance (in gates).\n 9 | balance: u64,\n 10 | // The token amount.\n 11 | amount: u64,\n 12 | }\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372005]: Unknown circuit member variable `owner`\n --> compiler-test:5:5\n |\n 5 | owner: address,\n | ^^^^^\n"
|
||||
- "Error [ETYC0372019]: Circuit initialization expression for `Token` is missing member `owner`.\n --> compiler-test:13:12\n |\n 13 | return Token {\n 14 | sender: r0, // This variable should be named `owner`.\n 15 | balance: 0u64,\n 16 | amount: r1,\n 17 | };\n | ^^^^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372023]: The `record` type requires the variable `owner: address`.\n --> compiler-test:4:1\n |\n 4 | record Token {\n 5 | // The Aleo balance (in gates).\n 6 | balance: u64,\n 7 | // The token amount.\n 8 | amount: u64,\n 9 | }\n | ^\n"
|
||||
- "Error [ETYC0372025]: The `record` type requires the variable `owner: address`.\n --> compiler-test:4:1\n |\n 4 | record Token {\n 5 | // The Aleo balance (in gates).\n 6 | balance: u64,\n 7 | // The token amount.\n 8 | amount: u64,\n 9 | }\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372024]: The field `owner` in a `record` must have type `address`.\n --> compiler-test:4:1\n |\n 4 | record Token {\n 5 | balance: u64,\n 6 | owner: bool,\n 7 | }\n | ^\n"
|
||||
- "Error [ETYC0372026]: The field `owner` in a `record` must have type `address`.\n --> compiler-test:4:1\n |\n 4 | record Token {\n 5 | balance: u64,\n 6 | owner: bool,\n 7 | }\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:4:20\n |\n 4 | let b: bool = -a == -1u8;\n | ^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:4:26\n |\n 4 | let b: bool = -a == -1u8;\n | ^^^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:5:20\n |\n 5 | let c: bool = -a > -1u8;\n | ^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:5:25\n |\n 5 | let c: bool = -a > -1u8;\n | ^^^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:6:20\n |\n 6 | let d: bool = -a < -1u8;\n | ^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:6:25\n |\n 6 | let d: bool = -a < -1u8;\n | ^^^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:7:20\n |\n 7 | let e: bool = -a >= -1u8;\n | ^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:7:26\n |\n 7 | let e: bool = -a >= -1u8;\n | ^^^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:8:20\n |\n 8 | let f: bool = -a <= -1u8;\n | ^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:8:26\n |\n 8 | let f: bool = -a <= -1u8;\n | ^^^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:9:18\n |\n 9 | let g: u8 = -a * -1u8;\n | ^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:9:23\n |\n 9 | let g: u8 = -a * -1u8;\n | ^^^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:10:18\n |\n 10 | let h: u8 = -a ** -1u8;\n | ^\nError [ETYC0372009]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:10:24\n |\n 10 | let h: u8 = -a ** -1u8;\n | ^^^\n"
|
||||
- "Error [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:4:20\n |\n 4 | let b: bool = -a == -1u8;\n | ^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:4:26\n |\n 4 | let b: bool = -a == -1u8;\n | ^^^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:5:20\n |\n 5 | let c: bool = -a > -1u8;\n | ^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:5:25\n |\n 5 | let c: bool = -a > -1u8;\n | ^^^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:6:20\n |\n 6 | let d: bool = -a < -1u8;\n | ^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:6:25\n |\n 6 | let d: bool = -a < -1u8;\n | ^^^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:7:20\n |\n 7 | let e: bool = -a >= -1u8;\n | ^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:7:26\n |\n 7 | let e: bool = -a >= -1u8;\n | ^^^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:8:20\n |\n 8 | let f: bool = -a <= -1u8;\n | ^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:8:26\n |\n 8 | let f: bool = -a <= -1u8;\n | ^^^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:9:18\n |\n 9 | let g: u8 = -a * -1u8;\n | ^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:9:23\n |\n 9 | let g: u8 = -a * -1u8;\n | ^^^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:10:18\n |\n 10 | let h: u8 = -a ** -1u8;\n | ^\nError [ETYC0372010]: Expected one type from `field, group, i8, i16, i32, i64, i128`, but got `u8`\n --> compiler-test:10:24\n |\n 10 | let h: u8 = -a ** -1u8;\n | ^^^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372005]: Unknown variable `z`\n --> compiler-test:4:19\n |\n 4 | \tlet b: u8 = 1u8**z;\n | ^\n"
|
||||
- "Error [ETYC0372006]: Unknown variable `z`\n --> compiler-test:4:19\n |\n 4 | \tlet b: u8 = 1u8**z;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372005]: Unknown variable `x`\n --> compiler-test:4:14\n |\n 4 | \tlet b: u8 = x*z;\n | ^\nError [ETYC0372005]: Unknown variable `z`\n --> compiler-test:4:16\n |\n 4 | \tlet b: u8 = x*z;\n | ^\n"
|
||||
- "Error [ETYC0372006]: Unknown variable `x`\n --> compiler-test:4:14\n |\n 4 | \tlet b: u8 = x*z;\n | ^\nError [ETYC0372006]: Unknown variable `z`\n --> compiler-test:4:16\n |\n 4 | \tlet b: u8 = x*z;\n | ^\n"
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372028]: Tuple index `2` out of range for a tuple with length `2`\n --> compiler-test:6:21\n |\n 6 | return (t.0, t.2); // Index `t.2` is out of bounds.\n | ^\n"
|
||||
- "Error [ETYC0372030]: Tuple index `2` out of range for a tuple with length `2`\n --> compiler-test:6:21\n |\n 6 | return (t.0, t.2); // Index `t.2` is out of bounds.\n | ^\nError [ETYC0372020]: t.2 is not a valid core circuit call.\n --> compiler-test:6:21\n |\n 6 | return (t.0, t.2); // Index `t.2` is out of bounds.\n | ^\n"
|
||||
|
Loading…
Reference in New Issue
Block a user