mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-18 07:11:53 +03:00
Merge pull request #1866 from AleoHQ/method-call-expr
Implement AVM instructions as Leo method calls
This commit is contained in:
commit
c95c920f04
@ -15,87 +15,132 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use leo_span::{sym, Symbol};
|
||||
|
||||
/// A binary operator.
|
||||
///
|
||||
/// Precedence is defined in the parser.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum BinaryOperation {
|
||||
/// Addition, i.e. `+`.
|
||||
/// Addition, i.e. `+`, `.add()`.
|
||||
Add,
|
||||
/// Subtraction, i.e. `-`.
|
||||
Sub,
|
||||
/// Multiplication, i.e. `*`.
|
||||
Mul,
|
||||
/// Division, i.e. `/`.
|
||||
Div,
|
||||
/// Exponentiation, i.e. `**` in `a ** b`.
|
||||
Pow,
|
||||
/// Logical-or, i.e., `||`.
|
||||
Or,
|
||||
/// Logical-and, i.e., `&&`.
|
||||
/// Wrapping addition, i.e. `.add_wrapped()`.
|
||||
AddWrapped,
|
||||
/// Logical AND, i.e. `&&`.
|
||||
And,
|
||||
/// Equality relation, i.e., `==`.
|
||||
/// Bitwise AND, i.e. `&`, `.and()`.
|
||||
BitwiseAnd,
|
||||
/// Division, i.e. `/`, `.div()`.
|
||||
Div,
|
||||
/// Wrapping division, i.e. `.div_wrapped()`.
|
||||
DivWrapped,
|
||||
/// Equality relation, i.e. `==`, `.eq()`.
|
||||
Eq,
|
||||
/// In-equality relation, i.e. `!=`.
|
||||
Ne,
|
||||
/// Greater-or-equal relation, i.e. `>=`.
|
||||
/// Greater-or-equal relation, i.e. `>=`, `.ge()`.
|
||||
Ge,
|
||||
/// Greater-than relation, i.e. `>=`.
|
||||
/// Greater-than relation, i.e. `>`, `.gt()`.
|
||||
Gt,
|
||||
/// Lesser-or-equal relation, i.e. `<=`.
|
||||
/// Lesser-or-equal relation, i.e. `<=`, `.le()`.
|
||||
Le,
|
||||
/// Lesser-than relation, i.e. `<`.
|
||||
/// Lesser-than relation, i.e. `<`, `.lt()`.
|
||||
Lt,
|
||||
}
|
||||
|
||||
/// The category a binary operation belongs to.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum BinaryOperationClass {
|
||||
/// A numeric one, that is, the result is numeric.
|
||||
Numeric,
|
||||
/// A boolean one, meaning the result is of type `bool`.
|
||||
Boolean,
|
||||
}
|
||||
|
||||
impl AsRef<str> for BinaryOperation {
|
||||
fn as_ref(&self) -> &'static str {
|
||||
match self {
|
||||
BinaryOperation::Add => "+",
|
||||
BinaryOperation::Sub => "-",
|
||||
BinaryOperation::Mul => "*",
|
||||
BinaryOperation::Div => "/",
|
||||
BinaryOperation::Pow => "**",
|
||||
BinaryOperation::Or => "||",
|
||||
BinaryOperation::And => "&&",
|
||||
BinaryOperation::Eq => "==",
|
||||
BinaryOperation::Ne => "!=",
|
||||
BinaryOperation::Ge => ">=",
|
||||
BinaryOperation::Gt => ">",
|
||||
BinaryOperation::Le => "<=",
|
||||
BinaryOperation::Lt => "<",
|
||||
}
|
||||
}
|
||||
/// Multiplication, i.e. `*`, `.mul()`.
|
||||
Mul,
|
||||
/// Wrapping multiplication, i.e. `.mul_wrapped()`.
|
||||
MulWrapped,
|
||||
/// Boolean NAND, i.e. `.nand()`.
|
||||
Nand,
|
||||
/// In-equality relation, i.e. `!=`, `.neq()`.
|
||||
Neq,
|
||||
/// Boolean NOR, i.e. `.nor()`.
|
||||
Nor,
|
||||
/// Logical OR, i.e. `||`.
|
||||
Or,
|
||||
/// Bitwise OR, i.e. `|`, `.or()`.
|
||||
BitwiseOr,
|
||||
/// Exponentiation, i.e. `**` in `a ** b`, `.pow()`.
|
||||
Pow,
|
||||
/// Wrapping exponentiation, i.e. `.pow_wrapped()`.
|
||||
PowWrapped,
|
||||
/// Shift left operation, i.e. `<<`, `.shl()`.
|
||||
Shl,
|
||||
/// Wrapping shift left operation, i.e. `<<`, `.shl_wrapped()`.
|
||||
ShlWrapped,
|
||||
/// Shift right operation, i.e. >>, `.shr()`.
|
||||
Shr,
|
||||
/// Wrapping shift right operation, i.e. >>, `.shr_wrapped()`.
|
||||
ShrWrapped,
|
||||
/// Subtraction, i.e. `-`, `.sub()`.
|
||||
Sub,
|
||||
/// Wrapped subtraction, i.e. `.sub_wrapped()`.
|
||||
SubWrapped,
|
||||
/// Bitwise XOR, i.e. `.xor()`.
|
||||
Xor,
|
||||
}
|
||||
|
||||
impl BinaryOperation {
|
||||
/// The class ("category") that the binary operation belongs to.
|
||||
/// For example, the `+` operator is numeric and `==` results in a boolean value.
|
||||
pub fn class(&self) -> BinaryOperationClass {
|
||||
/// Returns a `BinaryOperation` from the given `Symbol`.
|
||||
pub fn from_symbol(symbol: Symbol) -> Option<Self> {
|
||||
Some(match symbol {
|
||||
sym::add => Self::Add,
|
||||
sym::add_wrapped => Self::AddWrapped,
|
||||
sym::and => Self::BitwiseAnd,
|
||||
sym::div => Self::Div,
|
||||
sym::div_wrapped => Self::DivWrapped,
|
||||
sym::eq => Self::Eq,
|
||||
sym::ge => Self::Ge,
|
||||
sym::gt => Self::Gt,
|
||||
sym::le => Self::Le,
|
||||
sym::lt => Self::Lt,
|
||||
sym::mul => Self::Mul,
|
||||
sym::mul_wrapped => Self::MulWrapped,
|
||||
sym::nand => Self::Nand,
|
||||
sym::neq => Self::Neq,
|
||||
sym::nor => Self::Nor,
|
||||
sym::or => Self::BitwiseOr,
|
||||
sym::pow => Self::Pow,
|
||||
sym::pow_wrapped => Self::PowWrapped,
|
||||
sym::shl => Self::Shl,
|
||||
sym::shl_wrapped => Self::ShlWrapped,
|
||||
sym::shr => Self::Shr,
|
||||
sym::shr_wrapped => Self::ShrWrapped,
|
||||
sym::sub => Self::Sub,
|
||||
sym::sub_wrapped => Self::SubWrapped,
|
||||
sym::xor => Self::Xor,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Represents the operator as a string.
|
||||
fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
BinaryOperation::Add
|
||||
| BinaryOperation::Sub
|
||||
| BinaryOperation::Mul
|
||||
| BinaryOperation::Div
|
||||
| BinaryOperation::Pow => BinaryOperationClass::Numeric,
|
||||
BinaryOperation::Or
|
||||
| BinaryOperation::And
|
||||
| BinaryOperation::Eq
|
||||
| BinaryOperation::Ne
|
||||
| BinaryOperation::Ge
|
||||
| BinaryOperation::Gt
|
||||
| BinaryOperation::Le
|
||||
| BinaryOperation::Lt => BinaryOperationClass::Boolean,
|
||||
Self::Add => "add",
|
||||
Self::AddWrapped => "add_wrapped",
|
||||
Self::And => "&&",
|
||||
Self::BitwiseAnd => "and",
|
||||
Self::Div => "div",
|
||||
Self::DivWrapped => "div_wrapped",
|
||||
Self::Eq => "eq",
|
||||
Self::Ge => "ge",
|
||||
Self::Gt => "gt",
|
||||
Self::Le => "le",
|
||||
Self::Lt => "lt",
|
||||
Self::Mul => "mul",
|
||||
Self::MulWrapped => "mul_wrapped",
|
||||
Self::Nand => "nand",
|
||||
Self::Neq => "neq",
|
||||
Self::Nor => "nor",
|
||||
Self::Or => "||",
|
||||
Self::BitwiseOr => "or",
|
||||
Self::Pow => "pow",
|
||||
Self::PowWrapped => "pow_wrapped",
|
||||
Self::Shl => "shl",
|
||||
Self::ShlWrapped => "shl_wrapped",
|
||||
Self::Shr => "shr",
|
||||
Self::ShrWrapped => "shr_wrapped",
|
||||
Self::Sub => "sub",
|
||||
Self::SubWrapped => "sub_wrapped",
|
||||
Self::Xor => "xor",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,7 +161,7 @@ pub struct BinaryExpression {
|
||||
|
||||
impl fmt::Display for BinaryExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} {} {}", self.left, self.op.as_ref(), self.right)
|
||||
write!(f, "{}.{}({})", self.left, self.op.as_str(), self.right)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ pub enum Expression {
|
||||
Unary(UnaryExpression),
|
||||
/// A ternary conditional expression `cond ? if_expr : else_expr`.
|
||||
Ternary(TernaryExpression),
|
||||
/// A call expression like `my_fun(args)`.
|
||||
/// A call expression, e.g., `my_fun(args)`.
|
||||
Call(CallExpression),
|
||||
/// An expression of type "error".
|
||||
/// Will result in a compile error eventually.
|
||||
|
@ -15,22 +15,56 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use leo_span::{sym, Symbol};
|
||||
|
||||
/// A unary operator for a unary expression.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum UnaryOperation {
|
||||
/// The logical negation operator, i.e., `!`.
|
||||
/// For example, it transforms `true` to `false`.
|
||||
Not,
|
||||
/// The arithmetic negation operator, i.e., `-`.
|
||||
/// Absolute value checking for overflow, i.e. `.abs()`.
|
||||
Abs,
|
||||
/// Absolute value wrapping around at the boundary of the type, i.e. `.abs_wrapped()`.
|
||||
AbsWrapped,
|
||||
/// Double operation, i.e. `.double()`.
|
||||
Double,
|
||||
/// Multiplicative inverse, i.e. `.inv()`.
|
||||
Inverse,
|
||||
/// Negate operation, i.e. `.neg()`.
|
||||
Negate,
|
||||
/// Bitwise NOT, i.e. `!`, `.not()`.
|
||||
Not,
|
||||
/// Square operation, i.e. `.square()`.
|
||||
Square,
|
||||
/// Square root operation, i.e. `.sqrt()`.
|
||||
SquareRoot,
|
||||
}
|
||||
|
||||
impl AsRef<str> for UnaryOperation {
|
||||
fn as_ref(&self) -> &'static str {
|
||||
impl UnaryOperation {
|
||||
/// Returns a `UnaryOperation` from the given `Symbol`.
|
||||
pub fn from_symbol(symbol: Symbol) -> Option<Self> {
|
||||
Some(match symbol {
|
||||
sym::abs => Self::Abs,
|
||||
sym::abs_wrapped => Self::AbsWrapped,
|
||||
sym::double => Self::Double,
|
||||
sym::inv => Self::Inverse,
|
||||
sym::neg => Self::Negate,
|
||||
sym::not => Self::Not,
|
||||
sym::square => Self::Square,
|
||||
sym::sqrt => Self::SquareRoot,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Represents the opera.tor as a string.
|
||||
fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
UnaryOperation::Not => "!",
|
||||
UnaryOperation::Negate => "-",
|
||||
Self::Abs => "abs",
|
||||
Self::AbsWrapped => "abs_wrapped",
|
||||
Self::Double => "double",
|
||||
Self::Inverse => "inv",
|
||||
Self::Negate => "neg",
|
||||
Self::Not => "not",
|
||||
Self::Square => "square",
|
||||
Self::SquareRoot => "sqrt",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -39,7 +73,7 @@ impl AsRef<str> for UnaryOperation {
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct UnaryExpression {
|
||||
/// The inner expression `op` is applied to.
|
||||
pub inner: Box<Expression>,
|
||||
pub receiver: Box<Expression>,
|
||||
/// The unary operator to apply to `inner`.
|
||||
pub op: UnaryOperation,
|
||||
/// The span covering `op inner`.
|
||||
@ -48,7 +82,7 @@ pub struct UnaryExpression {
|
||||
|
||||
impl fmt::Display for UnaryExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}{}", self.op.as_ref(), self.inner)
|
||||
write!(f, "{}{}", self.op.as_str(), self.receiver)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ pub struct Function {
|
||||
pub identifier: Identifier,
|
||||
/// The function's parameters.
|
||||
pub input: Vec<FunctionInput>,
|
||||
/// The function return type, if explicitly specified, or `()` if not.
|
||||
/// The function's required return type.
|
||||
pub output: Type,
|
||||
/// Any mapping to the core library.
|
||||
/// Always `None` when initially parsed.
|
||||
|
@ -55,7 +55,7 @@ impl TryFrom<(Type, Expression)> for InputValue {
|
||||
}
|
||||
}
|
||||
(type_, Expression::Unary(unary)) if unary.op == UnaryOperation::Negate => {
|
||||
InputValue::try_from((type_, *unary.inner))?
|
||||
InputValue::try_from((type_, *unary.receiver))?
|
||||
}
|
||||
(_type_, expr) => return Err(InputError::illegal_expression(&expr, expr.span()).into()),
|
||||
})
|
||||
|
@ -93,9 +93,9 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
}
|
||||
|
||||
pub fn reduce_unary(&mut self, unary: &UnaryExpression) -> Result<UnaryExpression> {
|
||||
let inner = self.reduce_expression(&unary.inner)?;
|
||||
let inner = self.reduce_expression(&unary.receiver)?;
|
||||
|
||||
self.reducer.reduce_unary(unary, inner, unary.op.clone())
|
||||
self.reducer.reduce_unary(unary, inner, unary.op)
|
||||
}
|
||||
|
||||
pub fn reduce_ternary(&mut self, ternary: &TernaryExpression) -> Result<TernaryExpression> {
|
||||
|
@ -89,7 +89,7 @@ pub trait ReconstructingReducer {
|
||||
op: UnaryOperation,
|
||||
) -> Result<UnaryExpression> {
|
||||
Ok(UnaryExpression {
|
||||
inner: Box::new(inner),
|
||||
receiver: Box::new(inner),
|
||||
op,
|
||||
span: unary.span,
|
||||
})
|
||||
|
@ -72,7 +72,7 @@ pub trait ExpressionVisitorDirector<'a>: VisitorDirector<'a> {
|
||||
|
||||
fn visit_unary(&mut self, input: &'a UnaryExpression, additional: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
if let VisitResult::VisitChildren = self.visitor_ref().visit_unary(input) {
|
||||
self.visit_expression(&input.inner, additional);
|
||||
self.visit_expression(&input.receiver, additional);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -56,16 +56,16 @@ impl ParserContext<'_> {
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent
|
||||
/// a ternary expression. May or may not include circuit init expressions.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_disjunctive_expression`].
|
||||
/// Otherwise, tries to parse the next token using [`parse_boolean_or_expression`].
|
||||
pub(super) fn parse_conditional_expression(&mut self) -> Result<Expression> {
|
||||
// Try to parse the next expression. Try BinaryOperation::Or.
|
||||
let mut expr = self.parse_disjunctive_expression()?;
|
||||
let mut expr = self.parse_boolean_or_expression()?;
|
||||
|
||||
// Parse the rest of the ternary expression.
|
||||
if self.eat(&Token::Question) {
|
||||
let if_true = self.parse_expression()?;
|
||||
self.expect(&Token::Colon)?;
|
||||
let if_false = self.parse_conditional_expression()?;
|
||||
let if_false = self.parse_expression()?;
|
||||
expr = Expression::Ternary(TernaryExpression {
|
||||
span: expr.span() + if_false.span(),
|
||||
condition: Box::new(expr),
|
||||
@ -100,27 +100,27 @@ impl ParserContext<'_> {
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent
|
||||
/// a binary or expression.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_conjunctive_expression`].
|
||||
fn parse_disjunctive_expression(&mut self) -> Result<Expression> {
|
||||
self.parse_bin_expr(&[Token::Or], Self::parse_conjunctive_expression)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// binary and expression.
|
||||
/// binary AND expression.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_equality_expression`].
|
||||
fn parse_conjunctive_expression(&mut self) -> Result<Expression> {
|
||||
fn parse_boolean_and_expression(&mut self) -> Result<Expression> {
|
||||
self.parse_bin_expr(&[Token::And], Self::parse_equality_expression)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent
|
||||
/// a binary OR expression.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_boolean_and_expression`].
|
||||
fn parse_boolean_or_expression(&mut self) -> Result<Expression> {
|
||||
self.parse_bin_expr(&[Token::Or], Self::parse_boolean_and_expression)
|
||||
}
|
||||
|
||||
/// Eats one of binary operators matching any in `tokens`.
|
||||
fn eat_bin_op(&mut self, tokens: &[Token]) -> Option<BinaryOperation> {
|
||||
self.eat_any(tokens).then(|| match &self.prev_token.token {
|
||||
Token::Eq => BinaryOperation::Eq,
|
||||
Token::NotEq => BinaryOperation::Ne,
|
||||
Token::NotEq => BinaryOperation::Neq,
|
||||
Token::Lt => BinaryOperation::Lt,
|
||||
Token::LtEq => BinaryOperation::Le,
|
||||
Token::Gt => BinaryOperation::Gt,
|
||||
@ -131,11 +131,29 @@ impl ParserContext<'_> {
|
||||
Token::Div => BinaryOperation::Div,
|
||||
Token::Or => BinaryOperation::Or,
|
||||
Token::And => BinaryOperation::And,
|
||||
Token::BitwiseOr => BinaryOperation::BitwiseOr,
|
||||
Token::BitwiseAnd => BinaryOperation::BitwiseAnd,
|
||||
Token::Exp => BinaryOperation::Pow,
|
||||
Token::Shl => BinaryOperation::Shl,
|
||||
Token::Shr => BinaryOperation::Shr,
|
||||
Token::Xor => BinaryOperation::Xor,
|
||||
_ => unreachable!("`eat_bin_op` shouldn't produce this"),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// binary relational expression: less than, less than or equals, greater than, greater than or equals.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_additive_expression`].
|
||||
fn parse_ordering_expression(&mut self) -> Result<Expression> {
|
||||
let mut expr = self.parse_bitwise_exclusive_or_expression()?;
|
||||
if let Some(op) = self.eat_bin_op(&[Token::Lt, Token::LtEq, Token::Gt, Token::GtEq]) {
|
||||
let right = self.parse_bitwise_exclusive_or_expression()?;
|
||||
expr = Self::bin_expr(expr, right, op);
|
||||
}
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// binary equals or not equals expression.
|
||||
///
|
||||
@ -150,16 +168,35 @@ impl ParserContext<'_> {
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// binary relational expression: less than, less than or equals, greater than, greater than or equals.
|
||||
/// bitwise exclusive or expression.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_bitwise_inclusive_or_expression`].
|
||||
fn parse_bitwise_exclusive_or_expression(&mut self) -> Result<Expression> {
|
||||
self.parse_bin_expr(&[Token::Xor], Self::parse_bitwise_inclusive_or_expression)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// bitwise inclusive or expression.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_bitwise_and_expression`].
|
||||
fn parse_bitwise_inclusive_or_expression(&mut self) -> Result<Expression> {
|
||||
self.parse_bin_expr(&[Token::BitwiseOr], Self::parse_bitwise_and_expression)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// bitwise and expression.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_shift_expression`].
|
||||
fn parse_bitwise_and_expression(&mut self) -> Result<Expression> {
|
||||
self.parse_bin_expr(&[Token::BitwiseAnd], Self::parse_shift_expression)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// shift left or a shift right expression.
|
||||
///
|
||||
/// Otherwise, tries to parse the next token using [`parse_additive_expression`].
|
||||
fn parse_ordering_expression(&mut self) -> Result<Expression> {
|
||||
let mut expr = self.parse_additive_expression()?;
|
||||
if let Some(op) = self.eat_bin_op(&[Token::Lt, Token::LtEq, Token::Gt, Token::GtEq]) {
|
||||
let right = self.parse_additive_expression()?;
|
||||
expr = Self::bin_expr(expr, right, op);
|
||||
}
|
||||
Ok(expr)
|
||||
fn parse_shift_expression(&mut self) -> Result<Expression> {
|
||||
self.parse_bin_expr(&[Token::Shl, Token::Shr], Self::parse_additive_expression)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
@ -212,12 +249,49 @@ impl ParserContext<'_> {
|
||||
inner = Expression::Unary(UnaryExpression {
|
||||
span: op_span + inner.span(),
|
||||
op,
|
||||
inner: Box::new(inner),
|
||||
receiver: Box::new(inner),
|
||||
});
|
||||
}
|
||||
Ok(inner)
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent a
|
||||
/// method call expression.
|
||||
fn parse_method_call_expression(&mut self, receiver: Expression) -> Result<Expression> {
|
||||
// Parse the method name.
|
||||
let method = self.expect_ident()?;
|
||||
|
||||
// Parse the argument list.
|
||||
let (mut args, _, span) = self.parse_expr_tuple()?;
|
||||
let span = receiver.span() + span;
|
||||
|
||||
if let (true, Some(op)) = (args.is_empty(), UnaryOperation::from_symbol(method.name)) {
|
||||
// Found an unary operator and the argument list is empty.
|
||||
Ok(Expression::Unary(UnaryExpression {
|
||||
span,
|
||||
op,
|
||||
receiver: Box::new(receiver),
|
||||
}))
|
||||
} else if let (1, Some(op)) = (args.len(), BinaryOperation::from_symbol(method.name)) {
|
||||
// Found a binary operator and the argument list contains a single argument.
|
||||
Ok(Expression::Binary(BinaryExpression {
|
||||
span,
|
||||
op,
|
||||
left: Box::new(receiver),
|
||||
right: Box::new(args.swap_remove(0)),
|
||||
}))
|
||||
} else {
|
||||
// Either an invalid unary/binary operator, or more arguments given.
|
||||
self.emit_err(ParserError::expr_arbitrary_method_call(span));
|
||||
Ok(Expression::Err(ErrExpression { span }))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a tuple of expressions.
|
||||
fn parse_expr_tuple(&mut self) -> Result<(Vec<Expression>, bool, Span)> {
|
||||
self.parse_paren_comma_list(|p| p.parse_expression().map(Some))
|
||||
}
|
||||
|
||||
/// Returns an [`Expression`] AST node if the next tokens represent an
|
||||
/// array access, circuit member access, function call, or static function call expression.
|
||||
///
|
||||
@ -229,20 +303,21 @@ impl ParserContext<'_> {
|
||||
let mut expr = self.parse_primary_expression()?;
|
||||
loop {
|
||||
if self.eat(&Token::Dot) {
|
||||
let curr = &self.token;
|
||||
return Err(ParserError::unexpected_str(&curr.token, "int or ident", curr.span).into());
|
||||
// Eat a method call on a type
|
||||
expr = self.parse_method_call_expression(expr)?
|
||||
} else if self.check(&Token::LeftParen) {
|
||||
// Parse a function call that's by itself.
|
||||
let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
|
||||
expr = Expression::Call(CallExpression {
|
||||
span: expr.span() + span,
|
||||
function: Box::new(expr),
|
||||
arguments,
|
||||
});
|
||||
}
|
||||
|
||||
if !self.check(&Token::LeftParen) {
|
||||
// Check if next token is a dot to see if we are calling recursive method.
|
||||
if !self.check(&Token::Dot) {
|
||||
break;
|
||||
}
|
||||
|
||||
let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
|
||||
expr = Expression::Call(CallExpression {
|
||||
span: expr.span() + span,
|
||||
function: Box::new(expr),
|
||||
arguments,
|
||||
});
|
||||
}
|
||||
Ok(expr)
|
||||
}
|
||||
@ -256,10 +331,10 @@ impl ParserContext<'_> {
|
||||
)))));
|
||||
}
|
||||
|
||||
let (mut tuple, trailing, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
|
||||
let (mut tuple, trailing, span) = self.parse_expr_tuple()?;
|
||||
|
||||
if !trailing && tuple.len() == 1 {
|
||||
Ok(tuple.remove(0))
|
||||
Ok(tuple.swap_remove(0))
|
||||
} else {
|
||||
Err(ParserError::unexpected("A tuple expression.", "A valid expression.", span).into())
|
||||
}
|
||||
|
@ -192,16 +192,16 @@ impl Token {
|
||||
(1, els)
|
||||
})
|
||||
};
|
||||
// Consumes `on` again and produces `token` if found.
|
||||
let twice = |input: &mut Peekable<_>, on, token| {
|
||||
// Consumes a character followed by `on_1`, `on_2` or none. Outputs case_1, case_2, or els.
|
||||
let three_cases = |input: &mut Peekable<_>, on_1, case_1, on_2, case_2, els| {
|
||||
input.next();
|
||||
if input.next_if_eq(&on).is_some() {
|
||||
Ok((2, token))
|
||||
} else if let Some(found) = input.next() {
|
||||
Err(ParserError::lexer_expected_but_found(found, on).into())
|
||||
Ok(if input.next_if_eq(&on_1).is_some() {
|
||||
(2, case_1)
|
||||
} else if input.next_if_eq(&on_2).is_some() {
|
||||
(2, case_2)
|
||||
} else {
|
||||
Err(ParserError::lexer_empty_input().into())
|
||||
}
|
||||
(1, els)
|
||||
})
|
||||
};
|
||||
|
||||
match *input.peek().ok_or_else(ParserError::lexer_empty_input)? {
|
||||
@ -236,7 +236,7 @@ impl Token {
|
||||
x if x.is_ascii_digit() => return Self::eat_integer(&mut input),
|
||||
'!' => return followed_by(&mut input, '=', Token::NotEq, Token::Not),
|
||||
'?' => return single(&mut input, Token::Question),
|
||||
'&' => return twice(&mut input, '&', Token::And),
|
||||
'&' => return followed_by(&mut input, '&', Token::And, Token::BitwiseAnd),
|
||||
'(' => return single(&mut input, Token::LeftParen),
|
||||
')' => return single(&mut input, Token::RightParen),
|
||||
'_' => return single(&mut input, Token::Underscore),
|
||||
@ -292,14 +292,15 @@ impl Token {
|
||||
}
|
||||
':' => return single(&mut input, Token::Colon),
|
||||
';' => return single(&mut input, Token::Semicolon),
|
||||
'<' => return followed_by(&mut input, '=', Token::LtEq, Token::Lt),
|
||||
'>' => return followed_by(&mut input, '=', Token::GtEq, Token::Gt),
|
||||
'<' => return three_cases(&mut input, '=', Token::LtEq, '<', Token::Shl, Token::Lt),
|
||||
'>' => return three_cases(&mut input, '=', Token::GtEq, '>', Token::Shr, Token::Gt),
|
||||
'=' => return followed_by(&mut input, '=', Token::Eq, Token::Assign),
|
||||
'[' => return single(&mut input, Token::LeftSquare),
|
||||
']' => return single(&mut input, Token::RightSquare),
|
||||
'{' => return single(&mut input, Token::LeftCurly),
|
||||
'}' => return single(&mut input, Token::RightCurly),
|
||||
'|' => return twice(&mut input, '|', Token::Or),
|
||||
'|' => return followed_by(&mut input, '|', Token::Or, Token::BitwiseOr),
|
||||
'^' => return single(&mut input, Token::Xor),
|
||||
_ => (),
|
||||
}
|
||||
if let Some(ident) = eat_identifier(&mut input) {
|
||||
|
@ -38,6 +38,8 @@ pub enum Token {
|
||||
Not,
|
||||
And,
|
||||
Or,
|
||||
BitwiseAnd,
|
||||
BitwiseOr,
|
||||
Eq,
|
||||
NotEq,
|
||||
Lt,
|
||||
@ -63,7 +65,10 @@ pub enum Token {
|
||||
Colon,
|
||||
Question,
|
||||
Arrow,
|
||||
Shl,
|
||||
Shr,
|
||||
Underscore,
|
||||
Xor,
|
||||
|
||||
// Syntactic Grammar
|
||||
// Types
|
||||
@ -200,6 +205,8 @@ impl fmt::Display for Token {
|
||||
Not => write!(f, "!"),
|
||||
And => write!(f, "&&"),
|
||||
Or => write!(f, "||"),
|
||||
BitwiseAnd => write!(f, "&"),
|
||||
BitwiseOr => write!(f, "|"),
|
||||
Eq => write!(f, "=="),
|
||||
NotEq => write!(f, "!="),
|
||||
Lt => write!(f, "<"),
|
||||
@ -225,7 +232,10 @@ impl fmt::Display for Token {
|
||||
Colon => write!(f, ":"),
|
||||
Question => write!(f, "?"),
|
||||
Arrow => write!(f, "->"),
|
||||
Shl => write!(f, "<<"),
|
||||
Shr => write!(f, ">>"),
|
||||
Underscore => write!(f, "_"),
|
||||
Xor => write!(f, "^"),
|
||||
|
||||
Address => write!(f, "address"),
|
||||
Bool => write!(f, "bool"),
|
||||
|
@ -64,7 +64,7 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
fn visit_identifier(&mut self, input: &'a Identifier, expected: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
if let VisitResult::VisitChildren = self.visitor.visit_identifier(input) {
|
||||
return if let Some(var) = self.visitor.symbol_table.clone().lookup_variable(&input.name) {
|
||||
Some(self.visitor.assert_type(*var.type_, expected, var.span))
|
||||
Some(self.visitor.assert_expected_option(*var.type_, expected, input.span))
|
||||
} else {
|
||||
self.visitor
|
||||
.handler
|
||||
@ -79,9 +79,17 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
fn visit_value(&mut self, input: &'a ValueExpression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
if let VisitResult::VisitChildren = self.visitor.visit_value(input) {
|
||||
return Some(match input {
|
||||
ValueExpression::Address(_, _) => self.visitor.assert_type(Type::Address, expected, input.span()),
|
||||
ValueExpression::Boolean(_, _) => self.visitor.assert_type(Type::Boolean, expected, input.span()),
|
||||
ValueExpression::Field(_, _) => self.visitor.assert_type(Type::Field, expected, input.span()),
|
||||
ValueExpression::Address(_, _) => {
|
||||
self.visitor
|
||||
.assert_expected_option(Type::Address, expected, input.span())
|
||||
}
|
||||
ValueExpression::Boolean(_, _) => {
|
||||
self.visitor
|
||||
.assert_expected_option(Type::Boolean, expected, input.span())
|
||||
}
|
||||
ValueExpression::Field(_, _) => {
|
||||
self.visitor.assert_expected_option(Type::Field, expected, input.span())
|
||||
}
|
||||
ValueExpression::Integer(type_, str_content, _) => {
|
||||
match type_ {
|
||||
IntegerType::I8 => {
|
||||
@ -172,143 +180,234 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
_ => {}
|
||||
}
|
||||
self.visitor
|
||||
.assert_type(Type::IntegerType(*type_), expected, input.span())
|
||||
.assert_expected_option(Type::IntegerType(*type_), expected, input.span())
|
||||
}
|
||||
ValueExpression::Group(_) => self.visitor.assert_expected_option(Type::Group, expected, input.span()),
|
||||
ValueExpression::Scalar(_, _) => {
|
||||
self.visitor
|
||||
.assert_expected_option(Type::Scalar, expected, input.span())
|
||||
}
|
||||
ValueExpression::String(_, _) => {
|
||||
self.visitor
|
||||
.assert_expected_option(Type::String, expected, input.span())
|
||||
}
|
||||
ValueExpression::Group(_) => self.visitor.assert_type(Type::Group, expected, input.span()),
|
||||
ValueExpression::Scalar(_, _) => self.visitor.assert_type(Type::Scalar, expected, input.span()),
|
||||
ValueExpression::String(_, _) => self.visitor.assert_type(Type::String, expected, input.span()),
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn visit_binary(&mut self, input: &'a BinaryExpression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
fn visit_binary(
|
||||
&mut self,
|
||||
input: &'a BinaryExpression,
|
||||
destination: &Self::AdditionalInput,
|
||||
) -> Option<Self::Output> {
|
||||
if let VisitResult::VisitChildren = self.visitor.visit_binary(input) {
|
||||
return match input.op {
|
||||
BinaryOperation::And | BinaryOperation::Or => {
|
||||
self.visitor.assert_type(Type::Boolean, expected, input.span());
|
||||
let t1 = self.visit_expression(&input.left, expected);
|
||||
let t2 = self.visit_expression(&input.right, expected);
|
||||
BinaryOperation::And | BinaryOperation::Or | BinaryOperation::Nand | BinaryOperation::Nor => {
|
||||
// Assert equal boolean types.
|
||||
self.visitor
|
||||
.assert_expected_option(Type::Boolean, destination, input.span());
|
||||
let t1 = self.visit_expression(&input.left, destination);
|
||||
let t2 = self.visit_expression(&input.right, destination);
|
||||
|
||||
return_incorrect_type(t1, t2, expected)
|
||||
return_incorrect_type(t1, t2, destination)
|
||||
}
|
||||
BinaryOperation::BitwiseAnd | BinaryOperation::BitwiseOr | BinaryOperation::Xor => {
|
||||
// Assert equal boolean or integer types.
|
||||
self.visitor.assert_bool_int_type(destination, input.span());
|
||||
let t1 = self.visit_expression(&input.left, destination);
|
||||
let t2 = self.visit_expression(&input.right, destination);
|
||||
|
||||
return_incorrect_type(t1, t2, destination)
|
||||
}
|
||||
BinaryOperation::Add => {
|
||||
self.visitor.assert_field_group_scalar_int_type(expected, input.span());
|
||||
let t1 = self.visit_expression(&input.left, expected);
|
||||
let t2 = self.visit_expression(&input.right, expected);
|
||||
// Assert equal field, group, scalar, or integer types.
|
||||
self.visitor
|
||||
.assert_field_group_scalar_int_type(destination, input.span());
|
||||
let t1 = self.visit_expression(&input.left, destination);
|
||||
let t2 = self.visit_expression(&input.right, destination);
|
||||
|
||||
return_incorrect_type(t1, t2, expected)
|
||||
return_incorrect_type(t1, t2, destination)
|
||||
}
|
||||
BinaryOperation::Sub => {
|
||||
self.visitor.assert_field_group_int_type(expected, input.span());
|
||||
let t1 = self.visit_expression(&input.left, expected);
|
||||
let t2 = self.visit_expression(&input.right, expected);
|
||||
// Assert equal field, group, or integer types.
|
||||
self.visitor.assert_field_group_int_type(destination, input.span());
|
||||
let t1 = self.visit_expression(&input.left, destination);
|
||||
let t2 = self.visit_expression(&input.right, destination);
|
||||
|
||||
return_incorrect_type(t1, t2, expected)
|
||||
return_incorrect_type(t1, t2, destination)
|
||||
}
|
||||
BinaryOperation::Mul => {
|
||||
self.visitor.assert_field_group_int_type(expected, input.span());
|
||||
// Assert field, group or integer types.
|
||||
self.visitor.assert_field_group_int_type(destination, input.span());
|
||||
|
||||
let t1 = self.visit_expression(&input.left, &None);
|
||||
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, expected, input.left.span());
|
||||
match (t1, t2) {
|
||||
(Some(Type::Group), other) => {
|
||||
self.visitor
|
||||
.assert_type(*other, &Some(Type::Scalar), input.right.span());
|
||||
Some(Type::Group)
|
||||
.assert_expected_type(&other, Type::Scalar, input.right.span());
|
||||
Some(
|
||||
self.visitor
|
||||
.assert_expected_type(destination, Type::Group, input.span()),
|
||||
)
|
||||
}
|
||||
(Some(other), Some(Type::Group)) => {
|
||||
self.visitor.assert_type(*other, &Some(Type::Scalar), input.left.span());
|
||||
self.visitor.assert_type(Type::Group, expected, input.right.span());
|
||||
Some(Type::Group)
|
||||
(other, Some(Type::Group)) => {
|
||||
self.visitor
|
||||
.assert_expected_type(&other, Type::Scalar, input.left.span());
|
||||
Some(
|
||||
self.visitor
|
||||
.assert_expected_type(destination, Type::Group, input.span()),
|
||||
)
|
||||
}
|
||||
(Some(t1), Some(t2)) => {
|
||||
self.visitor.assert_type(*t1, expected, input.left.span());
|
||||
self.visitor.assert_type(*t2, expected, input.right.span());
|
||||
return_incorrect_type(Some(*t1), Some(*t2), expected)
|
||||
(t1, t2) => {
|
||||
// Assert equal field or integer types.
|
||||
self.visitor.assert_field_int_type(destination, input.span());
|
||||
|
||||
return_incorrect_type(t1, t2, destination)
|
||||
}
|
||||
(Some(type_), None) => {
|
||||
self.visitor.assert_type(*type_, expected, input.left.span());
|
||||
None
|
||||
}
|
||||
(None, Some(type_)) => {
|
||||
self.visitor.assert_type(*type_, expected, input.right.span());
|
||||
None
|
||||
}
|
||||
(None, None) => None,
|
||||
}
|
||||
}
|
||||
BinaryOperation::Div => {
|
||||
self.visitor.assert_field_int_type(expected, input.span());
|
||||
// Assert equal field or integer types.
|
||||
self.visitor.assert_field_int_type(destination, input.span());
|
||||
|
||||
let t1 = self.visit_expression(&input.left, expected);
|
||||
let t2 = self.visit_expression(&input.right, expected);
|
||||
let t1 = self.visit_expression(&input.left, destination);
|
||||
let t2 = self.visit_expression(&input.right, destination);
|
||||
|
||||
return_incorrect_type(t1, t2, expected)
|
||||
return_incorrect_type(t1, t2, destination)
|
||||
}
|
||||
BinaryOperation::Pow => {
|
||||
// Assert field or integer types.
|
||||
self.visitor.assert_field_int_type(destination, input.span());
|
||||
|
||||
let t1 = self.visit_expression(&input.left, &None);
|
||||
let t2 = self.visit_expression(&input.right, &None);
|
||||
|
||||
match (t1.as_ref(), t2.as_ref()) {
|
||||
// Type A must be an int.
|
||||
// Type B must be a unsigned int.
|
||||
(Some(Type::IntegerType(_)), Some(Type::IntegerType(itype))) if !itype.is_signed() => {
|
||||
self.visitor.assert_type(t1.unwrap(), expected, input.left.span());
|
||||
}
|
||||
// Type A was an int.
|
||||
// But Type B was not a unsigned int.
|
||||
(Some(Type::IntegerType(_)), Some(t)) => {
|
||||
self.visitor.handler.emit_err(
|
||||
TypeCheckerError::incorrect_pow_exponent_type("unsigned int", t, input.right.span())
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
// Type A must be a field.
|
||||
// Type B must be an int.
|
||||
(Some(Type::Field), Some(Type::IntegerType(_))) => {
|
||||
self.visitor.assert_type(Type::Field, expected, input.left.span());
|
||||
}
|
||||
// Type A was a field.
|
||||
// But Type B was not an int.
|
||||
(Some(Type::Field), Some(t)) => {
|
||||
self.visitor.handler.emit_err(
|
||||
TypeCheckerError::incorrect_pow_exponent_type("int", t, input.right.span()).into(),
|
||||
);
|
||||
}
|
||||
// The base is some type thats not an int or field.
|
||||
(Some(t), _) if !matches!(t, Type::IntegerType(_) | Type::Field) => {
|
||||
// Allow field * field.
|
||||
match (t1, t2) {
|
||||
(Some(Type::Field), type_) => {
|
||||
self.visitor
|
||||
.handler
|
||||
.emit_err(TypeCheckerError::incorrect_pow_base_type(t, input.left.span()).into());
|
||||
.assert_expected_type(&type_, Type::Field, input.right.span());
|
||||
Some(
|
||||
self.visitor
|
||||
.assert_expected_type(destination, Type::Field, input.span()),
|
||||
)
|
||||
}
|
||||
(type_, Some(Type::Field)) => {
|
||||
self.visitor
|
||||
.assert_expected_type(&type_, Type::Field, input.left.span());
|
||||
Some(
|
||||
self.visitor
|
||||
.assert_expected_type(destination, Type::Field, input.span()),
|
||||
)
|
||||
}
|
||||
(Some(t1), t2) => {
|
||||
// Allow integer t2 magnitude (u8, u16, u32)
|
||||
self.visitor.assert_magnitude_type(&t2, input.right.span());
|
||||
Some(self.visitor.assert_expected_type(destination, t1, input.span()))
|
||||
}
|
||||
(None, t2) => {
|
||||
// Allow integer t2 magnitude (u8, u16, u32)
|
||||
self.visitor.assert_magnitude_type(&t2, input.right.span());
|
||||
*destination
|
||||
}
|
||||
}
|
||||
}
|
||||
BinaryOperation::Eq | BinaryOperation::Neq => {
|
||||
// Assert first and second address, boolean, field, group, scalar, or integer types.
|
||||
let t1 = self.visit_expression(&input.left, &None);
|
||||
let t2 = self.visit_expression(&input.right, &None);
|
||||
|
||||
match (t1, t2) {
|
||||
(Some(Type::IntegerType(_)), t2) => {
|
||||
// Assert rhs is integer.
|
||||
self.visitor.assert_int_type(&t2, input.left.span());
|
||||
}
|
||||
(t1, Some(Type::IntegerType(_))) => {
|
||||
// Assert lhs is integer.
|
||||
self.visitor.assert_int_type(&t1, input.right.span());
|
||||
}
|
||||
(t1, t2) => {
|
||||
self.visitor.assert_eq_types(t1, t2, input.span());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
t1
|
||||
}
|
||||
BinaryOperation::Eq | BinaryOperation::Ne => {
|
||||
let t1 = self.visit_expression(&input.left, &None);
|
||||
let t2 = self.visit_expression(&input.right, &None);
|
||||
|
||||
self.visitor.assert_eq_types(t1, t2, input.span());
|
||||
|
||||
Some(Type::Boolean)
|
||||
// Assert destination is boolean.
|
||||
Some(
|
||||
self.visitor
|
||||
.assert_expected_type(destination, Type::Boolean, input.span()),
|
||||
)
|
||||
}
|
||||
BinaryOperation::Lt | BinaryOperation::Gt | BinaryOperation::Le | BinaryOperation::Ge => {
|
||||
// Assert left and right are equal field, scalar, or integer types.
|
||||
let t1 = self.visit_expression(&input.left, &None);
|
||||
self.visitor.assert_field_scalar_int_type(&t1, input.left.span());
|
||||
|
||||
let t2 = self.visit_expression(&input.right, &None);
|
||||
self.visitor.assert_field_scalar_int_type(&t2, input.right.span());
|
||||
|
||||
self.visitor.assert_eq_types(t1, t2, input.span());
|
||||
match (t1, t2) {
|
||||
(Some(Type::Field), t2) => {
|
||||
// Assert rhs is field.
|
||||
self.visitor.assert_expected_type(&t2, Type::Field, input.left.span());
|
||||
}
|
||||
(t1, Some(Type::Field)) => {
|
||||
// Assert lhs is field.
|
||||
self.visitor.assert_expected_type(&t1, Type::Field, input.right.span());
|
||||
}
|
||||
(Some(Type::Scalar), t2) => {
|
||||
// Assert rhs is scalar.
|
||||
self.visitor.assert_expected_type(&t2, Type::Scalar, input.left.span());
|
||||
}
|
||||
(t1, Some(Type::Scalar)) => {
|
||||
// Assert lhs is scalar.
|
||||
self.visitor.assert_expected_type(&t1, Type::Scalar, input.right.span());
|
||||
}
|
||||
(Some(Type::IntegerType(_)), t2) => {
|
||||
// Assert rhs is integer.
|
||||
self.visitor.assert_int_type(&t2, input.left.span());
|
||||
}
|
||||
(t1, Some(Type::IntegerType(_))) => {
|
||||
// Assert lhs is integer.
|
||||
self.visitor.assert_int_type(&t1, input.right.span());
|
||||
}
|
||||
(_, _) => {
|
||||
// Not enough info to assert type.
|
||||
}
|
||||
}
|
||||
|
||||
Some(Type::Boolean)
|
||||
// Assert destination is boolean.
|
||||
Some(
|
||||
self.visitor
|
||||
.assert_expected_type(destination, Type::Boolean, input.span()),
|
||||
)
|
||||
}
|
||||
BinaryOperation::AddWrapped
|
||||
| BinaryOperation::SubWrapped
|
||||
| BinaryOperation::DivWrapped
|
||||
| BinaryOperation::MulWrapped => {
|
||||
// Assert equal integer types.
|
||||
self.visitor.assert_int_type(destination, input.span);
|
||||
let t1 = self.visit_expression(&input.left, destination);
|
||||
let t2 = self.visit_expression(&input.right, destination);
|
||||
|
||||
return_incorrect_type(t1, t2, destination)
|
||||
}
|
||||
BinaryOperation::Shl
|
||||
| BinaryOperation::ShlWrapped
|
||||
| BinaryOperation::Shr
|
||||
| BinaryOperation::ShrWrapped
|
||||
| BinaryOperation::PowWrapped => {
|
||||
// Assert left and destination are equal integer types.
|
||||
self.visitor.assert_int_type(destination, input.span);
|
||||
let t1 = self.visit_expression(&input.left, destination);
|
||||
|
||||
// Assert right type is a magnitude (u8, u16, u32).
|
||||
let t2 = self.visit_expression(&input.right, &None);
|
||||
self.visitor.assert_magnitude_type(&t2, input.right.span());
|
||||
|
||||
return_incorrect_type(t1, t2, destination)
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -316,17 +415,34 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
None
|
||||
}
|
||||
|
||||
fn visit_unary(&mut self, input: &'a UnaryExpression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
fn visit_unary(&mut self, input: &'a UnaryExpression, destination: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||
match input.op {
|
||||
UnaryOperation::Not => {
|
||||
self.visitor.assert_type(Type::Boolean, expected, input.span());
|
||||
self.visit_expression(&input.inner, expected)
|
||||
UnaryOperation::Abs => {
|
||||
// Assert integer type only.
|
||||
self.visitor.assert_int_type(destination, input.span());
|
||||
self.visit_expression(&input.receiver, destination)
|
||||
}
|
||||
UnaryOperation::AbsWrapped => {
|
||||
// Assert integer type only.
|
||||
self.visitor.assert_int_type(destination, input.span());
|
||||
self.visit_expression(&input.receiver, destination)
|
||||
}
|
||||
UnaryOperation::Double => {
|
||||
// Assert field and group type only.
|
||||
self.visitor.assert_field_group_type(destination, input.span());
|
||||
self.visit_expression(&input.receiver, destination)
|
||||
}
|
||||
UnaryOperation::Inverse => {
|
||||
// Assert field type only.
|
||||
self.visitor
|
||||
.assert_expected_type(destination, Type::Field, input.span());
|
||||
self.visit_expression(&input.receiver, destination)
|
||||
}
|
||||
UnaryOperation::Negate => {
|
||||
let prior_negate_state = self.visitor.negate;
|
||||
self.visitor.negate = true;
|
||||
|
||||
let type_ = self.visit_expression(&input.inner, expected);
|
||||
let type_ = self.visit_expression(&input.receiver, destination);
|
||||
self.visitor.negate = prior_negate_state;
|
||||
match type_.as_ref() {
|
||||
Some(
|
||||
@ -343,11 +459,27 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
Some(t) => self
|
||||
.visitor
|
||||
.handler
|
||||
.emit_err(TypeCheckerError::type_is_not_negatable(t, input.inner.span()).into()),
|
||||
.emit_err(TypeCheckerError::type_is_not_negatable(t, input.receiver.span()).into()),
|
||||
_ => {}
|
||||
};
|
||||
type_
|
||||
}
|
||||
UnaryOperation::Not => {
|
||||
// Assert boolean, integer types only.
|
||||
self.visitor.assert_bool_int_type(destination, input.span());
|
||||
self.visit_expression(&input.receiver, destination)
|
||||
}
|
||||
UnaryOperation::Square => {
|
||||
// Assert field type only.
|
||||
self.visitor
|
||||
.assert_expected_type(destination, Type::Field, input.span());
|
||||
self.visit_expression(&input.receiver, destination)
|
||||
}
|
||||
UnaryOperation::SquareRoot => {
|
||||
// Assert field and scalar types only.
|
||||
self.visitor.assert_field_scalar_type(destination, input.span());
|
||||
self.visit_expression(&input.receiver, destination)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,7 +504,7 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
match &*input.function {
|
||||
Expression::Identifier(ident) => {
|
||||
if let Some(func) = self.visitor.symbol_table.clone().lookup_fn(&ident.name) {
|
||||
let ret = self.visitor.assert_type(func.output, expected, func.span());
|
||||
let ret = self.visitor.assert_expected_option(func.output, expected, func.span());
|
||||
|
||||
if func.input.len() != input.arguments.len() {
|
||||
self.visitor.handler.emit_err(
|
||||
|
@ -45,6 +45,12 @@ const INT_TYPES: [Type; 10] = [
|
||||
Type::IntegerType(IntegerType::U128),
|
||||
];
|
||||
|
||||
const MAGNITUDE_TYPES: [Type; 3] = [
|
||||
Type::IntegerType(IntegerType::U8),
|
||||
Type::IntegerType(IntegerType::U16),
|
||||
Type::IntegerType(IntegerType::U32),
|
||||
];
|
||||
|
||||
const fn create_type_superset<const S: usize, const A: usize, const O: usize>(
|
||||
subset: [Type; S],
|
||||
additional: [Type; A],
|
||||
@ -63,14 +69,18 @@ const fn create_type_superset<const S: usize, const A: usize, const O: usize>(
|
||||
superset
|
||||
}
|
||||
|
||||
const FIELD_INT_TYPES: [Type; 11] = create_type_superset(INT_TYPES, [Type::Field]);
|
||||
const BOOL_INT_TYPES: [Type; 11] = create_type_superset(INT_TYPES, [Type::Boolean]);
|
||||
|
||||
const FIELD_SCALAR_INT_TYPES: [Type; 12] = create_type_superset(FIELD_INT_TYPES, [Type::Scalar]);
|
||||
const FIELD_INT_TYPES: [Type; 11] = create_type_superset(INT_TYPES, [Type::Field]);
|
||||
|
||||
const FIELD_GROUP_INT_TYPES: [Type; 12] = create_type_superset(FIELD_INT_TYPES, [Type::Group]);
|
||||
|
||||
const FIELD_GROUP_SCALAR_INT_TYPES: [Type; 13] = create_type_superset(FIELD_GROUP_INT_TYPES, [Type::Scalar]);
|
||||
|
||||
const FIELD_GROUP_TYPES: [Type; 2] = [Type::Field, Type::Group];
|
||||
|
||||
const FIELD_SCALAR_TYPES: [Type; 2] = [Type::Field, Type::Scalar];
|
||||
|
||||
impl<'a> TypeChecker<'a> {
|
||||
/// Returns a new type checker given a symbol table and error handler.
|
||||
pub fn new(symbol_table: &'a mut SymbolTable<'a>, handler: &'a Handler) -> Self {
|
||||
@ -108,16 +118,29 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the given type if it equals the expected type or the expected type is none.
|
||||
pub(crate) fn assert_type(&mut self, type_: Type, expected: &Option<Type>, span: Span) -> Type {
|
||||
/// Returns the given `actual` type and emits an error if the `expected` type does not match.
|
||||
pub(crate) fn assert_expected_option(&mut self, actual: Type, expected: &Option<Type>, span: Span) -> Type {
|
||||
if let Some(expected) = expected {
|
||||
if &type_ != expected {
|
||||
if &actual != expected {
|
||||
self.handler
|
||||
.emit_err(TypeCheckerError::type_should_be(type_, expected, span).into());
|
||||
.emit_err(TypeCheckerError::type_should_be(actual, expected, span).into());
|
||||
}
|
||||
}
|
||||
|
||||
type_
|
||||
actual
|
||||
}
|
||||
|
||||
/// Returns the given `expected` type and emits an error if the `actual` type does not match.
|
||||
/// `span` should be the location of the expected type.
|
||||
pub(crate) fn assert_expected_type(&mut self, actual: &Option<Type>, expected: Type, span: Span) -> Type {
|
||||
if let Some(actual) = actual {
|
||||
if actual != &expected {
|
||||
self.handler
|
||||
.emit_err(TypeCheckerError::type_should_be(actual, expected, span).into());
|
||||
}
|
||||
}
|
||||
|
||||
expected
|
||||
}
|
||||
|
||||
/// Emits an error to the error handler if the given type is not equal to any of the expected types.
|
||||
@ -136,14 +159,19 @@ impl<'a> TypeChecker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits an error to the handler if the given type is not a boolean or an integer.
|
||||
pub(crate) fn assert_bool_int_type(&self, type_: &Option<Type>, span: Span) {
|
||||
self.assert_one_of_types(type_, &BOOL_INT_TYPES, span)
|
||||
}
|
||||
|
||||
/// Emits an error to the handler if the given type is not a field or integer.
|
||||
pub(crate) fn assert_field_int_type(&self, type_: &Option<Type>, span: Span) {
|
||||
self.assert_one_of_types(type_, &FIELD_INT_TYPES, span)
|
||||
}
|
||||
|
||||
/// Emits an error to the handler if the given type is not a field, scalar, or integer.
|
||||
pub(crate) fn assert_field_scalar_int_type(&self, type_: &Option<Type>, span: Span) {
|
||||
self.assert_one_of_types(type_, &FIELD_SCALAR_INT_TYPES, span)
|
||||
/// Emits an error to the handler if the given type is not a field or group.
|
||||
pub(crate) fn assert_field_group_type(&self, type_: &Option<Type>, span: Span) {
|
||||
self.assert_one_of_types(type_, &FIELD_GROUP_TYPES, span)
|
||||
}
|
||||
|
||||
/// Emits an error to the handler if the given type is not a field, group, or integer.
|
||||
@ -155,4 +183,18 @@ impl<'a> TypeChecker<'a> {
|
||||
pub(crate) fn assert_field_group_scalar_int_type(&self, type_: &Option<Type>, span: Span) {
|
||||
self.assert_one_of_types(type_, &FIELD_GROUP_SCALAR_INT_TYPES, span)
|
||||
}
|
||||
/// Emits an error to the handler if the given type is not a field or scalar.
|
||||
pub(crate) fn assert_field_scalar_type(&self, type_: &Option<Type>, span: Span) {
|
||||
self.assert_one_of_types(type_, &FIELD_SCALAR_TYPES, span)
|
||||
}
|
||||
|
||||
/// Emits an error to the handler if the given type is not an integer.
|
||||
pub(crate) fn assert_int_type(&self, type_: &Option<Type>, span: Span) {
|
||||
self.assert_one_of_types(type_, &INT_TYPES, span)
|
||||
}
|
||||
|
||||
/// Emits an error to the handler if the given type is not a magnitude (u8, u16, u32).
|
||||
pub(crate) fn assert_magnitude_type(&self, type_: &Option<Type>, span: Span) {
|
||||
self.assert_one_of_types(type_, &MAGNITUDE_TYPES, span)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
function main() -> bool {
|
||||
console.log("hello world");
|
||||
return true;
|
||||
function main(a: u8) -> u8 {
|
||||
return a >> 1u32;
|
||||
}
|
@ -366,4 +366,12 @@ create_messages!(
|
||||
msg: "Expression statements are no longer supported.",
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// Previously, arbitrary methods were allowed, but not anymore.
|
||||
@formatted
|
||||
expr_arbitrary_method_call {
|
||||
args: (),
|
||||
msg: "Arbitrary methods calls are not supported. Only special ones are.",
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
@ -53,6 +53,16 @@ create_messages!(
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// The method name is known but not supported for the given type.
|
||||
@formatted
|
||||
type_method_not_supported {
|
||||
args: (type_: impl Display, method: impl Display),
|
||||
msg: format!(
|
||||
"Type `{type_}` does not support associated method `{method}`",
|
||||
),
|
||||
help: None,
|
||||
}
|
||||
|
||||
/// For when the user tries to return a unknown variable.
|
||||
@formatted
|
||||
unknown_sym {
|
||||
|
@ -16,9 +16,8 @@
|
||||
|
||||
use leo_errors::Result;
|
||||
|
||||
use std::{fmt, sync::Once};
|
||||
|
||||
use colored::Colorize;
|
||||
use std::{fmt, sync::Once};
|
||||
use tracing::{event::Event, subscriber::Subscriber};
|
||||
use tracing_subscriber::{
|
||||
fmt::{format::*, time::*, FmtContext, FormattedFields},
|
||||
|
@ -100,30 +100,94 @@ macro_rules! symbols {
|
||||
}
|
||||
|
||||
symbols! {
|
||||
// unary operators index 0-7
|
||||
abs,
|
||||
abs_wrapped,
|
||||
double,
|
||||
inv,
|
||||
neg,
|
||||
not,
|
||||
square,
|
||||
sqrt,
|
||||
|
||||
// binary operators index 8-32
|
||||
add,
|
||||
add_wrapped,
|
||||
and,
|
||||
div,
|
||||
div_wrapped,
|
||||
eq,
|
||||
ge,
|
||||
gt,
|
||||
le,
|
||||
lt,
|
||||
mul,
|
||||
mul_wrapped,
|
||||
nand,
|
||||
neq,
|
||||
nor,
|
||||
or,
|
||||
pow,
|
||||
pow_wrapped,
|
||||
shl,
|
||||
shl_wrapped,
|
||||
shr,
|
||||
shr_wrapped,
|
||||
sub,
|
||||
sub_wrapped,
|
||||
xor,
|
||||
|
||||
// algorithm operator names 33-44
|
||||
bhp256,
|
||||
bhp512,
|
||||
bhp768,
|
||||
bhp1024,
|
||||
commit,
|
||||
hash,
|
||||
ped64,
|
||||
ped128,
|
||||
prf,
|
||||
psd2,
|
||||
psd4,
|
||||
psd8,
|
||||
|
||||
// types
|
||||
address,
|
||||
AlwaysConst,
|
||||
array,
|
||||
assert,
|
||||
bool,
|
||||
Class: "class",
|
||||
context,
|
||||
constants,
|
||||
CoreFunction,
|
||||
console,
|
||||
Const: "const",
|
||||
Constant,
|
||||
Else: "else",
|
||||
error,
|
||||
False: "false",
|
||||
constants,
|
||||
field,
|
||||
For: "for",
|
||||
function,
|
||||
group,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
scalar,
|
||||
string,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
|
||||
// values
|
||||
False: "false",
|
||||
True: "true",
|
||||
|
||||
// general keywords
|
||||
AlwaysConst,
|
||||
assert,
|
||||
Class: "class",
|
||||
context,
|
||||
CoreFunction,
|
||||
console,
|
||||
Else: "else",
|
||||
error,
|
||||
For: "for",
|
||||
function,
|
||||
If: "if",
|
||||
In: "in",
|
||||
input,
|
||||
@ -134,19 +198,11 @@ symbols! {
|
||||
prelude,
|
||||
Public,
|
||||
Return: "return",
|
||||
scalar,
|
||||
Star: "*",
|
||||
std,
|
||||
string,
|
||||
Struct: "struct",
|
||||
test,
|
||||
True: "true",
|
||||
Type: "type",
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
|
||||
CONTAINER_PSEUDO_CIRCUIT: "$InputContainer",
|
||||
REGISTERS_PSEUDO_CIRCUIT: "$InputRegister",
|
||||
@ -154,11 +210,11 @@ symbols! {
|
||||
STATE_PSEUDO_CIRCUIT: "$InputState",
|
||||
STATE_LEAF_PSEUDO_CIRCUIT: "$InputStateLeaf",
|
||||
|
||||
// input file
|
||||
registers,
|
||||
record,
|
||||
state,
|
||||
state_leaf,
|
||||
|
||||
public,
|
||||
private,
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
use crate::config::Config;
|
||||
use leo_errors::{CliError, Result};
|
||||
|
||||
use std::fmt::Write as _;
|
||||
|
||||
use colored::Colorize;
|
||||
use self_update::{backends::github, version::bump_is_greater, Status};
|
||||
|
||||
@ -40,7 +42,7 @@ impl Updater {
|
||||
|
||||
let mut output = "\nList of available versions\n".to_string();
|
||||
for release in releases {
|
||||
output += &format!(" * {}\n", release.version);
|
||||
let _ = writeln!(output, " * {}", release.version);
|
||||
}
|
||||
|
||||
// Forgo using tracing to list the available versions without a log status.
|
||||
|
13
tests/compiler/address/binary.leo
Normal file
13
tests/compiler/address/binary.leo
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/address1.in
|
||||
*/
|
||||
|
||||
|
||||
function main (x: address) -> bool {
|
||||
let a: address = aleo1fj982yqchhy973kz7e9jk6er7t6qd6jm9anplnlprem507w6lv9spwvfxx;
|
||||
let b: bool = x.eq(a);
|
||||
let c: bool = x.neq(a);
|
||||
return c;
|
||||
}
|
25
tests/compiler/boolean/operator_methods.leo
Normal file
25
tests/compiler/boolean/operator_methods.leo
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file:
|
||||
- inputs/false_false.in
|
||||
- inputs/false_true.in
|
||||
- inputs/true_false.in
|
||||
- inputs/true_true.in
|
||||
*/
|
||||
|
||||
function main(a: bool, b: bool) -> bool {
|
||||
// unary
|
||||
let h: bool = a.not();
|
||||
|
||||
// binary
|
||||
let l: bool = a.and(b);
|
||||
let o: bool = a.eq(b);
|
||||
let v: bool = a.nand(b);
|
||||
let w: bool = a.neq(b);
|
||||
let x: bool = a.nor(b);
|
||||
let y: bool = a.or(b);
|
||||
let ar: bool = a.xor(b);
|
||||
|
||||
return h;
|
||||
}
|
28
tests/compiler/field/operator_methods.leo
Normal file
28
tests/compiler/field/operator_methods.leo
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file:
|
||||
- inputs/fields.in
|
||||
*/
|
||||
|
||||
function main(a: field, b: field) -> bool {
|
||||
// unary
|
||||
let f: field = a.inv();
|
||||
let g: field = a.neg();
|
||||
let i: field = a.square();
|
||||
let j: field = a.sqrt();
|
||||
|
||||
// binary
|
||||
let k: field = a.add(b);
|
||||
let m: field = a.div(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: field = a.mul(b);
|
||||
let w: bool = a.neq(b);
|
||||
let z: field = a.pow(b);
|
||||
|
||||
return w;
|
||||
}
|
@ -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;
|
||||
}
|
20
tests/compiler/group/operator_methods.leo
Normal file
20
tests/compiler/group/operator_methods.leo
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/three.in
|
||||
*/
|
||||
|
||||
function main(a: group, b: group) -> bool {
|
||||
// unary
|
||||
let e: group = a.double();
|
||||
let g: group = a.neg();
|
||||
|
||||
// binary
|
||||
let j: group = a.add(b);
|
||||
let o: bool = a.eq(b);
|
||||
let t: group = a.mul(2scalar);
|
||||
let q: group = 2scalar.mul(a);
|
||||
let w: bool = a.neq(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/i128/and.leo
Normal file
9
tests/compiler/integers/i128/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i128, b: i128, c: i128) -> bool {
|
||||
return a & b == c;
|
||||
}
|
50
tests/compiler/integers/i128/operator_methods.leo
Normal file
50
tests/compiler/integers/i128/operator_methods.leo
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i128, b: i128) -> bool {
|
||||
// unary
|
||||
let c: i128 = a.abs();
|
||||
let d: i128 = a.abs_wrapped();
|
||||
let g: i128 = a.neg();
|
||||
let h: i128 = a.not();
|
||||
|
||||
// binary
|
||||
let j: i128 = a.add(b);
|
||||
let k: i128 = a.add_wrapped(b);
|
||||
let l: i128 = a.and(b);
|
||||
let m: i128 = a.div(b);
|
||||
let n: i128 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: i128 = a.mul(b);
|
||||
let u: i128 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: i128 = a.or(b);
|
||||
let z: i128 = a.pow(2u8);
|
||||
let aa: i128 = a.pow(2u16);
|
||||
let ab: i128 = a.pow(2u32);
|
||||
let ac: i128 = a.pow_wrapped(2u8);
|
||||
let ad: i128 = a.pow_wrapped(2u16);
|
||||
let ae: i128 = a.pow_wrapped(2u32);
|
||||
let af: i128 = a.shl(2u8);
|
||||
let ag: i128 = a.shl(2u16);
|
||||
let ah: i128 = a.shl(2u32);
|
||||
let ai: i128 = a.shl_wrapped(2u8);
|
||||
let aj: i128 = a.shl_wrapped(2u16);
|
||||
let ak: i128 = a.shl_wrapped(2u32);
|
||||
let al: i128 = a.shr(2u8);
|
||||
let am: i128 = a.shr(2u16);
|
||||
let an: i128 = a.shr(2u32);
|
||||
let ao: i128 = a.shr_wrapped(2u8);
|
||||
let ap: i128 = a.shr_wrapped(2u16);
|
||||
let aq: i128 = a.shr_wrapped(2u32);
|
||||
let ar: i128 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/i128/or.leo
Normal file
9
tests/compiler/integers/i128/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i128, b: i128, c: i128) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
expectation: Pass
|
||||
input_file: inputs/pow.in
|
||||
*/
|
||||
|
||||
function main(a: i128, b: i128, c: i128) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** 2u16 && a ** 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i128/shl.leo
Normal file
9
tests/compiler/integers/i128/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i128, b: i128, c: i128) -> bool {
|
||||
return a << 2u8 == a << 2u16 && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i128/shr.leo
Normal file
9
tests/compiler/integers/i128/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i128, b: i128, c: i128) -> bool {
|
||||
return a >> 2u8 == a >> 2u16 && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i128/xor.leo
Normal file
9
tests/compiler/integers/i128/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i128, b: i128, c: i128) -> bool {
|
||||
return a ^ 2u8 == a ^ 2u16 && a ^ 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i16/and.leo
Normal file
9
tests/compiler/integers/i16/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i16, b: i16, c: i16) -> bool {
|
||||
return a & b == c;
|
||||
}
|
50
tests/compiler/integers/i16/operator_methods.leo
Normal file
50
tests/compiler/integers/i16/operator_methods.leo
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i16, b: i16) -> bool {
|
||||
// unary
|
||||
let c: i16 = a.abs();
|
||||
let d: i16 = a.abs_wrapped();
|
||||
let g: i16 = a.neg();
|
||||
let h: i16 = a.not();
|
||||
|
||||
// binary
|
||||
let j: i16 = a.add(b);
|
||||
let k: i16 = a.add_wrapped(b);
|
||||
let l: i16 = a.and(b);
|
||||
let m: i16 = a.div(b);
|
||||
let n: i16 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: i16 = a.mul(b);
|
||||
let u: i16 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: i16 = a.or(b);
|
||||
let z: i16 = a.pow(2u8);
|
||||
let aa: i16 = a.pow(2u16);
|
||||
let ab: i16 = a.pow(2u32);
|
||||
let ac: i16 = a.pow_wrapped(2u8);
|
||||
let ad: i16 = a.pow_wrapped(2u16);
|
||||
let ae: i16 = a.pow_wrapped(2u32);
|
||||
let af: i16 = a.shl(2u8);
|
||||
let ag: i16 = a.shl(2u16);
|
||||
let ah: i16 = a.shl(2u32);
|
||||
let ai: i16 = a.shl_wrapped(2u8);
|
||||
let aj: i16 = a.shl_wrapped(2u16);
|
||||
let ak: i16 = a.shl_wrapped(2u32);
|
||||
let al: i16 = a.shr(2u8);
|
||||
let am: i16 = a.shr(2u16);
|
||||
let an: i16 = a.shr(2u32);
|
||||
let ao: i16 = a.shr_wrapped(2u8);
|
||||
let ap: i16 = a.shr_wrapped(2u16);
|
||||
let aq: i16 = a.shr_wrapped(2u32);
|
||||
let ar: i16 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/i16/or.leo
Normal file
9
tests/compiler/integers/i16/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i16, b: i16, c: i16) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
expectation: Pass
|
||||
input_file: inputs/pow.in
|
||||
*/
|
||||
|
||||
function main(a: i16, b: i16, c: i16) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** 2u16 && a ** 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i16/shl.leo
Normal file
9
tests/compiler/integers/i16/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i16, b: i16, c: i16) -> bool {
|
||||
return a << 2u8 == a << 2u16 && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i16/shr.leo
Normal file
9
tests/compiler/integers/i16/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i16, b: i16, c: i16) -> bool {
|
||||
return a >> 2u8 == a >> 2u16 && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i16/xor.leo
Normal file
9
tests/compiler/integers/i16/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i16, b: i16, c: i16) -> bool {
|
||||
return a ^ 2u8 == a ^ 2u16 && a ^ 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i32/and.leo
Normal file
9
tests/compiler/integers/i32/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i32, b: i32, c: i32) -> bool {
|
||||
return a & b == c;
|
||||
}
|
50
tests/compiler/integers/i32/operator_methods.leo
Normal file
50
tests/compiler/integers/i32/operator_methods.leo
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i32, b: i32) -> bool {
|
||||
// unary
|
||||
let c: i32 = a.abs();
|
||||
let d: i32 = a.abs_wrapped();
|
||||
let g: i32 = a.neg();
|
||||
let h: i32 = a.not();
|
||||
|
||||
// binary
|
||||
let j: i32 = a.add(b);
|
||||
let k: i32 = a.add_wrapped(b);
|
||||
let l: i32 = a.and(b);
|
||||
let m: i32 = a.div(b);
|
||||
let n: i32 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: i32 = a.mul(b);
|
||||
let u: i32 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: i32 = a.or(b);
|
||||
let z: i32 = a.pow(2u8);
|
||||
let aa: i32 = a.pow(2u16);
|
||||
let ab: i32 = a.pow(2u32);
|
||||
let ac: i32 = a.pow_wrapped(2u8);
|
||||
let ad: i32 = a.pow_wrapped(2u16);
|
||||
let ae: i32 = a.pow_wrapped(2u32);
|
||||
let af: i32 = a.shl(2u8);
|
||||
let ag: i32 = a.shl(2u16);
|
||||
let ah: i32 = a.shl(2u32);
|
||||
let ai: i32 = a.shl_wrapped(2u8);
|
||||
let aj: i32 = a.shl_wrapped(2u16);
|
||||
let ak: i32 = a.shl_wrapped(2u32);
|
||||
let al: i32 = a.shr(2u8);
|
||||
let am: i32 = a.shr(2u16);
|
||||
let an: i32 = a.shr(2u32);
|
||||
let ao: i32 = a.shr_wrapped(2u8);
|
||||
let ap: i32 = a.shr_wrapped(2u16);
|
||||
let aq: i32 = a.shr_wrapped(2u32);
|
||||
let ar: i32 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/i32/or.leo
Normal file
9
tests/compiler/integers/i32/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i32, b: i32, c: i32) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
expectation: Pass
|
||||
input_file: inputs/pow.in
|
||||
*/
|
||||
|
||||
function main(a: i32, b: i32, c: i32) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** 2u16 && a ** 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i32/shl.leo
Normal file
9
tests/compiler/integers/i32/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i32, b: i32, c: i32) -> bool {
|
||||
return a << 2u8 == a << 2u16 && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i32/shr.leo
Normal file
9
tests/compiler/integers/i32/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i32, b: i32, c: i32) -> bool {
|
||||
return a >> 2u8 == a >> 2u16 && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i32/xor.leo
Normal file
9
tests/compiler/integers/i32/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i32, b: i32, c: i32) -> bool {
|
||||
return a ^ 2u8 == a ^ 2u16 && a ^ 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i64/and.leo
Normal file
9
tests/compiler/integers/i64/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i64, b: i64, c: i64) -> bool {
|
||||
return a & b == c;
|
||||
}
|
50
tests/compiler/integers/i64/operator_methods.leo
Normal file
50
tests/compiler/integers/i64/operator_methods.leo
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i64, b: i64) -> bool {
|
||||
// unary
|
||||
let c: i64 = a.abs();
|
||||
let d: i64 = a.abs_wrapped();
|
||||
let g: i64 = a.neg();
|
||||
let h: i64 = a.not();
|
||||
|
||||
// binary
|
||||
let j: i64 = a.add(b);
|
||||
let k: i64 = a.add_wrapped(b);
|
||||
let l: i64 = a.and(b);
|
||||
let m: i64 = a.div(b);
|
||||
let n: i64 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: i64 = a.mul(b);
|
||||
let u: i64 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: i64 = a.or(b);
|
||||
let z: i64 = a.pow(2u8);
|
||||
let aa: i64 = a.pow(2u16);
|
||||
let ab: i64 = a.pow(2u32);
|
||||
let ac: i64 = a.pow_wrapped(2u8);
|
||||
let ad: i64 = a.pow_wrapped(2u16);
|
||||
let ae: i64 = a.pow_wrapped(2u32);
|
||||
let af: i64 = a.shl(2u8);
|
||||
let ag: i64 = a.shl(2u16);
|
||||
let ah: i64 = a.shl(2u32);
|
||||
let ai: i64 = a.shl_wrapped(2u8);
|
||||
let aj: i64 = a.shl_wrapped(2u16);
|
||||
let ak: i64 = a.shl_wrapped(2u32);
|
||||
let al: i64 = a.shr(2u8);
|
||||
let am: i64 = a.shr(2u16);
|
||||
let an: i64 = a.shr(2u32);
|
||||
let ao: i64 = a.shr_wrapped(2u8);
|
||||
let ap: i64 = a.shr_wrapped(2u16);
|
||||
let aq: i64 = a.shr_wrapped(2u32);
|
||||
let ar: i64 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/i64/or.leo
Normal file
9
tests/compiler/integers/i64/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i64, b: i64, c: i64) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
expectation: Pass
|
||||
input_file: inputs/pow.in
|
||||
*/
|
||||
|
||||
function main(a: i64, b: i64, c: i64) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** 2u16 && a ** 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i64/shl.leo
Normal file
9
tests/compiler/integers/i64/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i64, b: i64, c: i64) -> bool {
|
||||
return a << 2u8 == a << 2u16 && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i64/shr.leo
Normal file
9
tests/compiler/integers/i64/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i64, b: i64, c: i64) -> bool {
|
||||
return a >> 2u8 == a >> 2u16 && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i64/xor.leo
Normal file
9
tests/compiler/integers/i64/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i64, b: i64, c: i64) -> bool {
|
||||
return a ^ 2u8 == a ^ 2u16 && a ^ 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i8/and.leo
Normal file
9
tests/compiler/integers/i8/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i8, b: i8, c: i8) -> bool {
|
||||
return a & b == c;
|
||||
}
|
50
tests/compiler/integers/i8/operator_methods.leo
Normal file
50
tests/compiler/integers/i8/operator_methods.leo
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i8, b: i8) -> bool {
|
||||
// unary
|
||||
let c: i8 = a.abs();
|
||||
let d: i8 = a.abs_wrapped();
|
||||
let g: i8 = a.neg();
|
||||
let h: i8 = a.not();
|
||||
|
||||
// binary
|
||||
let j: i8 = a.add(b);
|
||||
let k: i8 = a.add_wrapped(b);
|
||||
let l: i8 = a.and(b);
|
||||
let m: i8 = a.div(b);
|
||||
let n: i8 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: i8 = a.mul(b);
|
||||
let u: i8 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: i8 = a.or(b);
|
||||
let z: i8 = a.pow(2u8);
|
||||
let aa: i8 = a.pow(2u16);
|
||||
let ab: i8 = a.pow(2u32);
|
||||
let ac: i8 = a.pow_wrapped(2u8);
|
||||
let ad: i8 = a.pow_wrapped(2u16);
|
||||
let ae: i8 = a.pow_wrapped(2u32);
|
||||
let af: i8 = a.shl(2u8);
|
||||
let ag: i8 = a.shl(2u16);
|
||||
let ah: i8 = a.shl(2u32);
|
||||
let ai: i8 = a.shl_wrapped(2u8);
|
||||
let aj: i8 = a.shl_wrapped(2u16);
|
||||
let ak: i8 = a.shl_wrapped(2u32);
|
||||
let al: i8 = a.shr(2u8);
|
||||
let am: i8 = a.shr(2u16);
|
||||
let an: i8 = a.shr(2u32);
|
||||
let ao: i8 = a.shr_wrapped(2u8);
|
||||
let ap: i8 = a.shr_wrapped(2u16);
|
||||
let aq: i8 = a.shr_wrapped(2u32);
|
||||
let ar: i8 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/i8/or.leo
Normal file
9
tests/compiler/integers/i8/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i8, b: i8, c: i8) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
expectation: Pass
|
||||
input_file: inputs/pow.in
|
||||
*/
|
||||
|
||||
function main(a: i8, b: i8, c: i8) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** 2u16 && a ** 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i8/shl.leo
Normal file
9
tests/compiler/integers/i8/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i8, b: i8, c: i8) -> bool {
|
||||
return a << 2u8 == a << 2u16 && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i8/shr.leo
Normal file
9
tests/compiler/integers/i8/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i8, b: i8, c: i8) -> bool {
|
||||
return a >> 2u8 == a >> 2u16 && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/i8/xor.leo
Normal file
9
tests/compiler/integers/i8/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: i8, b: i8, c: i8) -> bool {
|
||||
return a ^ 2u8 == a ^ 2u16 && a ^ 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u128/and.leo
Normal file
9
tests/compiler/integers/u128/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u128, b: u128, c: u128) -> bool {
|
||||
return a & b == c;
|
||||
}
|
49
tests/compiler/integers/u128/operator_methods.leo
Normal file
49
tests/compiler/integers/u128/operator_methods.leo
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u128, b: u128) -> bool {
|
||||
// unary
|
||||
let c: u128 = a.abs();
|
||||
let d: u128 = a.abs_wrapped();
|
||||
let h: u128 = a.not();
|
||||
|
||||
// binary
|
||||
let j: u128 = a.add(b);
|
||||
let k: u128 = a.add_wrapped(b);
|
||||
let l: u128 = a.and(b);
|
||||
let m: u128 = a.div(b);
|
||||
let n: u128 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: u128 = a.mul(b);
|
||||
let u: u128 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: u128 = a.or(b);
|
||||
let z: u128 = a.pow(2u8);
|
||||
let aa: u128 = a.pow(2u16);
|
||||
let ab: u128 = a.pow(2u32);
|
||||
let ac: u128 = a.pow_wrapped(2u8);
|
||||
let ad: u128 = a.pow_wrapped(2u16);
|
||||
let ae: u128 = a.pow_wrapped(2u32);
|
||||
let af: u128 = a.shl(2u8);
|
||||
let ag: u128 = a.shl(2u16);
|
||||
let ah: u128 = a.shl(2u32);
|
||||
let ai: u128 = a.shl_wrapped(2u8);
|
||||
let aj: u128 = a.shl_wrapped(2u16);
|
||||
let ak: u128 = a.shl_wrapped(2u32);
|
||||
let al: u128 = a.shr(2u8);
|
||||
let am: u128 = a.shr(2u16);
|
||||
let an: u128 = a.shr(2u32);
|
||||
let ao: u128 = a.shr_wrapped(2u8);
|
||||
let ap: u128 = a.shr_wrapped(2u16);
|
||||
let aq: u128 = a.shr_wrapped(2u32);
|
||||
let ar: u128 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/u128/or.leo
Normal file
9
tests/compiler/integers/u128/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u128, b: u128, c: u128) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
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: u128, b: u128, c: u128) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** 2u16 && a ** 2u32 == c;
|
||||
}
|
||||
|
9
tests/compiler/integers/u128/shl.leo
Normal file
9
tests/compiler/integers/u128/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u128, b: u128, c: u128) -> bool {
|
||||
return a << 2u8 == a << 2u16 && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u128/shr.leo
Normal file
9
tests/compiler/integers/u128/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u128, b: u128, c: u128) -> bool {
|
||||
return a >> 2u8 == a >> 2u16 && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u128/xor.leo
Normal file
9
tests/compiler/integers/u128/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u128, b: u128, c: u128) -> bool {
|
||||
return a ^ 2u8 == a ^ 2u16 && a ^ 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u16/and.leo
Normal file
9
tests/compiler/integers/u16/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u16, b: u16, c: u16) -> bool {
|
||||
return a & b == c;
|
||||
}
|
55
tests/compiler/integers/u16/operator_methods.leo
Normal file
55
tests/compiler/integers/u16/operator_methods.leo
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u16, b: u16) -> bool {
|
||||
// unary
|
||||
let c: u16 = a.abs();
|
||||
let d: u16 = a.abs_wrapped();
|
||||
let h: u16 = a.not();
|
||||
|
||||
// binary
|
||||
let j: u16 = a.add(b);
|
||||
let k: u16 = a.add_wrapped(b);
|
||||
let l: u16 = a.and(b);
|
||||
let m: u16 = a.div(b);
|
||||
let n: u16 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: u16 = a.mul(b);
|
||||
let u: u16 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: u16 = a.or(b);
|
||||
let z: u16 = a.pow(2u8);
|
||||
let aa: u16 = a.pow(b);
|
||||
let ab: u16 = a.pow(2u32);
|
||||
let ac: u16 = a.pow_wrapped(2u8);
|
||||
let ad: u16 = a.pow_wrapped(b);
|
||||
let ae: u16 = a.pow_wrapped(2u32);
|
||||
let af: u16 = a.shl(2u8);
|
||||
let ag: u16 = a.shl(b);
|
||||
let ah: u16 = a.shl(2u32);
|
||||
let ai: u16 = a.shl_wrapped(2u8);
|
||||
let aj: u16 = a.shl_wrapped(b);
|
||||
let ak: u16 = a.shl_wrapped(2u32);
|
||||
let al: u16 = a.shr(2u8);
|
||||
let am: u16 = a.shr(b);
|
||||
let an: u16 = a.shr(2u32);
|
||||
let ao: u16 = a.shr_wrapped(2u8);
|
||||
let ap: u16 = a.shr_wrapped(b);
|
||||
let aq: u16 = a.shr_wrapped(2u32);
|
||||
let ar: u16 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/u16/or.leo
Normal file
9
tests/compiler/integers/u16/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u16, b: u16, c: u16) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -5,5 +5,5 @@ input_file: inputs/pow.in
|
||||
*/
|
||||
|
||||
function main(a: u16, b: u16, c: u16) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** b && a ** 2u32 == c;
|
||||
}
|
||||
|
9
tests/compiler/integers/u16/shl.leo
Normal file
9
tests/compiler/integers/u16/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u16, b: u16, c: u16) -> bool {
|
||||
return a << 2u8 == a << b && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u16/shr.leo
Normal file
9
tests/compiler/integers/u16/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u16, b: u16, c: u16) -> bool {
|
||||
return a >> 2u8 == a >> b && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u16/xor.leo
Normal file
9
tests/compiler/integers/u16/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u16, b: u16, c: u16) -> bool {
|
||||
return a ^ 2u8 == a ^ b && a ^ 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u32/and.leo
Normal file
9
tests/compiler/integers/u32/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u32, b: u32, c: u32) -> bool {
|
||||
return a & b == c;
|
||||
}
|
55
tests/compiler/integers/u32/operator_methods.leo
Normal file
55
tests/compiler/integers/u32/operator_methods.leo
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u32, b: u32) -> bool {
|
||||
// unary
|
||||
let c: u32 = a.abs();
|
||||
let d: u32 = a.abs_wrapped();
|
||||
let h: u32 = a.not();
|
||||
|
||||
// binary
|
||||
let j: u32 = a.add(b);
|
||||
let k: u32 = a.add_wrapped(b);
|
||||
let l: u32 = a.and(b);
|
||||
let m: u32 = a.div(b);
|
||||
let n: u32 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: u32 = a.mul(b);
|
||||
let u: u32 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: u32 = a.or(b);
|
||||
let z: u32 = a.pow(2u8);
|
||||
let aa: u32 = a.pow(2u16);
|
||||
let ab: u32 = a.pow(b);
|
||||
let ac: u32 = a.pow_wrapped(2u8);
|
||||
let ad: u32 = a.pow_wrapped(2u16);
|
||||
let ae: u32 = a.pow_wrapped(b);
|
||||
let af: u32 = a.shl(2u8);
|
||||
let ag: u32 = a.shl(2u16);
|
||||
let ah: u32 = a.shl(b);
|
||||
let ai: u32 = a.shl_wrapped(2u8);
|
||||
let aj: u32 = a.shl_wrapped(2u16);
|
||||
let ak: u32 = a.shl_wrapped(b);
|
||||
let al: u32 = a.shr(2u8);
|
||||
let am: u32 = a.shr(2u16);
|
||||
let an: u32 = a.shr(b);
|
||||
let ao: u32 = a.shr_wrapped(2u8);
|
||||
let ap: u32 = a.shr_wrapped(2u16);
|
||||
let aq: u32 = a.shr_wrapped(b);
|
||||
let ar: u32 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/u32/or.leo
Normal file
9
tests/compiler/integers/u32/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u32, b: u32, c: u32) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -8,5 +8,5 @@ input_file: inputs/pow.in
|
||||
*/
|
||||
|
||||
function main(a: u32, b: u32, c: u32) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** 2u16 && a ** b == c;
|
||||
}
|
||||
|
9
tests/compiler/integers/u32/shl.leo
Normal file
9
tests/compiler/integers/u32/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u32, b: u32, c: u32) -> bool {
|
||||
return a << 2u8 == a << 2u16 && a << b == c;
|
||||
}
|
9
tests/compiler/integers/u32/shr.leo
Normal file
9
tests/compiler/integers/u32/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u32, b: u32, c: u32) -> bool {
|
||||
return a >> 2u8 == a >> 2u16 && a >> b == c;
|
||||
}
|
9
tests/compiler/integers/u32/xor.leo
Normal file
9
tests/compiler/integers/u32/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u32, b: u32, c: u32) -> bool {
|
||||
return a ^ 2u8 == a ^ 2u16 && a ^ b == c;
|
||||
}
|
9
tests/compiler/integers/u64/and.leo
Normal file
9
tests/compiler/integers/u64/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u64, b: u64, c: u64) -> bool {
|
||||
return a & b == c;
|
||||
}
|
49
tests/compiler/integers/u64/operator_methods.leo
Normal file
49
tests/compiler/integers/u64/operator_methods.leo
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u64, b: u64) -> bool {
|
||||
// unary
|
||||
let c: u64 = a.abs();
|
||||
let d: u64 = a.abs_wrapped();
|
||||
let h: u64 = a.not();
|
||||
|
||||
// binary
|
||||
let j: u64 = a.add(b);
|
||||
let k: u64 = a.add_wrapped(b);
|
||||
let l: u64 = a.and(b);
|
||||
let m: u64 = a.div(b);
|
||||
let n: u64 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: u64 = a.mul(b);
|
||||
let u: u64 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: u64 = a.or(b);
|
||||
let z: u64 = a.pow(2u8);
|
||||
let aa: u64 = a.pow(2u16);
|
||||
let ab: u64 = a.pow(2u32);
|
||||
let ac: u64 = a.pow_wrapped(2u8);
|
||||
let ad: u64 = a.pow_wrapped(2u16);
|
||||
let ae: u64 = a.pow_wrapped(2u32);
|
||||
let af: u64 = a.shl(2u8);
|
||||
let ag: u64 = a.shl(2u16);
|
||||
let ah: u64 = a.shl(2u32);
|
||||
let ai: u64 = a.shl_wrapped(2u8);
|
||||
let aj: u64 = a.shl_wrapped(2u16);
|
||||
let ak: u64 = a.shl_wrapped(2u32);
|
||||
let al: u64 = a.shr(2u8);
|
||||
let am: u64 = a.shr(2u16);
|
||||
let an: u64 = a.shr(2u32);
|
||||
let ao: u64 = a.shr_wrapped(2u8);
|
||||
let ap: u64 = a.shr_wrapped(2u16);
|
||||
let aq: u64 = a.shr_wrapped(2u32);
|
||||
let ar: u64 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/u64/or.leo
Normal file
9
tests/compiler/integers/u64/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u64, b: u64, c: u64) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -3,10 +3,9 @@ namespace: Compile
|
||||
expectation: Pass
|
||||
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 {
|
||||
return a ** b == c;
|
||||
return a ** 2u8 == a ** 2u16 && a ** 2u32 == c;
|
||||
}
|
||||
|
9
tests/compiler/integers/u64/shl.leo
Normal file
9
tests/compiler/integers/u64/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u64, b: u64, c: u64) -> bool {
|
||||
return a << 2u8 == a << 2u16 && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u64/shr.leo
Normal file
9
tests/compiler/integers/u64/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u64, b: u64, c: u64) -> bool {
|
||||
return a >> 2u8 == a >> 2u16 && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u64/xor.leo
Normal file
9
tests/compiler/integers/u64/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u64, b: u64, c: u64) -> bool {
|
||||
return a ^ 2u8 == a ^ 2u16 && a ^ 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u8/and.leo
Normal file
9
tests/compiler/integers/u8/and.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u8, b: u8, c: u8) -> bool {
|
||||
return a & b == c;
|
||||
}
|
49
tests/compiler/integers/u8/operator_methods.leo
Normal file
49
tests/compiler/integers/u8/operator_methods.leo
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u8, b: u8) -> bool {
|
||||
// unary
|
||||
let c: u8 = a.abs();
|
||||
let d: u8 = a.abs_wrapped();
|
||||
let h: u8 = a.not();
|
||||
|
||||
// binary
|
||||
let j: u8 = a.add(b);
|
||||
let k: u8 = a.add_wrapped(b);
|
||||
let l: u8 = a.and(b);
|
||||
let m: u8 = a.div(b);
|
||||
let n: u8 = a.div_wrapped(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: u8 = a.mul(b);
|
||||
let u: u8 = a.mul_wrapped(b);
|
||||
let w: bool = a.neq(b);
|
||||
let y: u8 = a.or(b);
|
||||
let z: u8 = a.pow(b);
|
||||
let aa: u8 = a.pow(2u16);
|
||||
let ab: u8 = a.pow(2u32);
|
||||
let ac: u8 = a.pow_wrapped(b);
|
||||
let ad: u8 = a.pow_wrapped(2u16);
|
||||
let ae: u8 = a.pow_wrapped(2u32);
|
||||
let af: u8 = a.shl(b);
|
||||
let ag: u8 = a.shl(2u16);
|
||||
let ah: u8 = a.shl(2u32);
|
||||
let ai: u8 = a.shl_wrapped(b);
|
||||
let aj: u8 = a.shl_wrapped(2u16);
|
||||
let ak: u8 = a.shl_wrapped(2u32);
|
||||
let al: u8 = a.shr(b);
|
||||
let am: u8 = a.shr(2u16);
|
||||
let an: u8 = a.shr(2u32);
|
||||
let ao: u8 = a.shr_wrapped(b);
|
||||
let ap: u8 = a.shr_wrapped(2u16);
|
||||
let aq: u8 = a.shr_wrapped(2u32);
|
||||
let ar: u8 = a.xor(b);
|
||||
|
||||
return a == b;
|
||||
}
|
9
tests/compiler/integers/u8/or.leo
Normal file
9
tests/compiler/integers/u8/or.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u8, b: u8, c: u8) -> bool {
|
||||
return a | b == c;
|
||||
}
|
@ -5,5 +5,5 @@ input_file: inputs/pow.in
|
||||
*/
|
||||
|
||||
function main(a: u8, b: u8, c: u8) -> bool {
|
||||
return a ** b == c;
|
||||
return a ** b == a ** 2u16 && a ** 2u32 == c;
|
||||
}
|
||||
|
9
tests/compiler/integers/u8/shl.leo
Normal file
9
tests/compiler/integers/u8/shl.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u8, b: u8, c: u8) -> bool {
|
||||
return a << b == a << 2u16 && a << 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u8/shr.leo
Normal file
9
tests/compiler/integers/u8/shr.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u8, b: u8, c: u8) -> bool {
|
||||
return a >> b == a >> 2u16 && a >> 2u32 == c;
|
||||
}
|
9
tests/compiler/integers/u8/xor.leo
Normal file
9
tests/compiler/integers/u8/xor.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/add.in
|
||||
*/
|
||||
|
||||
function main(a: u8, b: u8, c: u8) -> bool {
|
||||
return a ^ b == a ^ 2u16 && a ^ 2u32 == c;
|
||||
}
|
24
tests/compiler/scalar/operator_methods.leo
Normal file
24
tests/compiler/scalar/operator_methods.leo
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file:
|
||||
- inputs/scalars.in
|
||||
*/
|
||||
|
||||
function main(a: scalar, b: scalar) -> bool {
|
||||
// unary
|
||||
let i: scalar = a.sqrt();
|
||||
|
||||
// binary
|
||||
let j: scalar = a.add(b);
|
||||
let o: bool = a.eq(b);
|
||||
let p: bool = a.ge(b);
|
||||
let q: bool = a.gt(b);
|
||||
let r: bool = a.le(b);
|
||||
let s: bool = a.lt(b);
|
||||
let t: group = 2group.mul(b);
|
||||
let u: group = a.mul(2group);
|
||||
let w: bool = a.neq(b);
|
||||
|
||||
return a == b;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
expectation: Pass
|
||||
input_file: inputs/i8.in
|
||||
*/
|
||||
|
||||
|
8
tests/expectations/compiler/compiler/address/binary.out
Normal file
8
tests/expectations/compiler/compiler/address/binary.out
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
outputs:
|
||||
- output:
|
||||
- initial_input_ast: ed65ff9337fc5a00cd28d780a985bcb05de7d0e5fe02b555774984552f0c14e8
|
||||
initial_ast: 64b4179c6d21058f1e4a91826cd91364f7011e35e5e30a1d9dbc899ec3b500df
|
||||
symbol_table: b736692dc7bdc91c5a808a20a3965f4c8ed2c46c212696d33fc6dd4cfc9a5844
|
@ -5,4 +5,4 @@ outputs:
|
||||
- output:
|
||||
- initial_input_ast: c7315faf1ac3ceeb90260e64e4a411a27a8aa732892a64c15f49e81adf464beb
|
||||
initial_ast: 767d8228dd9818cb115e7369cec91352dd406008981487380e863deb06dc11a0
|
||||
symbol_table: e8029086f943767e4f98014b3991bff8336cb6472c2d2dc3d51b4b13e5c72ea5
|
||||
symbol_table: a712053d471b6165809fc2b4f717282ea5590a2cfaeae8a630c8a3250478d179
|
||||
|
@ -6,4 +6,4 @@ outputs:
|
||||
- initial_input_ast: dc6b4b00185dd6c1f2b83a1bfae619c1d6e3f68ac0f1d3d87ae3bd0ed5caf083
|
||||
- initial_input_ast: 73a38568160c3d2be402043d04ccdc2290abe27647bc81c4bd50367834c206cf
|
||||
initial_ast: 31f3fdca173acafc69b0975e91e891bbb27bf6d63bdc986c86b4d22c70d928cc
|
||||
symbol_table: 25f09247dfa86534ff321b8e1b2ca1666c92751d37a611d62e56b8cfac96261d
|
||||
symbol_table: 18395a136ea969d319cc4c12c59bb7a590a1b11339375240700d7c87f26b1d5d
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user