mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-19 15:41:36 +03:00
parse method calls directly
This commit is contained in:
parent
df08cd1e26
commit
a32418133c
@ -21,8 +21,10 @@ use super::*;
|
|||||||
/// Precedence is defined in the parser.
|
/// Precedence is defined in the parser.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum BinaryOperation {
|
pub enum BinaryOperation {
|
||||||
/// Addition, i.e. `+`.
|
/// Addition, i.e. `+`, `.add()`.
|
||||||
Add,
|
Add,
|
||||||
|
/// Wrapped addition, i.e. `.add_wrapped()`.
|
||||||
|
AddWrapped,
|
||||||
/// Subtraction, i.e. `-`.
|
/// Subtraction, i.e. `-`.
|
||||||
Sub,
|
Sub,
|
||||||
/// Multiplication, i.e. `*`.
|
/// Multiplication, i.e. `*`.
|
||||||
@ -61,41 +63,20 @@ pub enum BinaryOperationClass {
|
|||||||
impl AsRef<str> for BinaryOperation {
|
impl AsRef<str> for BinaryOperation {
|
||||||
fn as_ref(&self) -> &'static str {
|
fn as_ref(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
BinaryOperation::Add => "+",
|
BinaryOperation::Add => "add",
|
||||||
BinaryOperation::Sub => "-",
|
BinaryOperation::AddWrapped => "add_wrapped",
|
||||||
BinaryOperation::Mul => "*",
|
BinaryOperation::Sub => "sub",
|
||||||
BinaryOperation::Div => "/",
|
BinaryOperation::Mul => "mul",
|
||||||
BinaryOperation::Pow => "**",
|
BinaryOperation::Div => "div",
|
||||||
BinaryOperation::Or => "||",
|
BinaryOperation::Pow => "pow",
|
||||||
BinaryOperation::And => "&&",
|
BinaryOperation::Or => "or",
|
||||||
BinaryOperation::Eq => "==",
|
BinaryOperation::And => "and",
|
||||||
BinaryOperation::Ne => "!=",
|
BinaryOperation::Eq => "eq",
|
||||||
BinaryOperation::Ge => ">=",
|
BinaryOperation::Ne => "ne",
|
||||||
BinaryOperation::Gt => ">",
|
BinaryOperation::Ge => "ge",
|
||||||
BinaryOperation::Le => "<=",
|
BinaryOperation::Gt => "gt",
|
||||||
BinaryOperation::Lt => "<",
|
BinaryOperation::Le => "le",
|
||||||
}
|
BinaryOperation::Lt => "lt",
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,7 +97,7 @@ pub struct BinaryExpression {
|
|||||||
|
|
||||||
impl fmt::Display for BinaryExpression {
|
impl fmt::Display for BinaryExpression {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
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_ref(), self.right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +218,48 @@ impl ParserContext<'_> {
|
|||||||
Ok(inner)
|
Ok(inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_method_call_expression(&mut self, receiver: Expression) -> Result<Expression> {
|
||||||
|
// Get the name of the method.
|
||||||
|
if let Token::Ident(method) = self.token.token {
|
||||||
|
self.bump();
|
||||||
|
|
||||||
|
// Check if the method exists.
|
||||||
|
let index = method.as_u32();
|
||||||
|
|
||||||
|
if index <= 2 {
|
||||||
|
// Binary operators.
|
||||||
|
let operator = match index {
|
||||||
|
1 => BinaryOperation::Add,
|
||||||
|
2 => BinaryOperation::AddWrapped,
|
||||||
|
_ => unimplemented!("throw error for invalid method call")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse left parenthesis `(`.
|
||||||
|
self.expect(&Token::LeftParen)?;
|
||||||
|
|
||||||
|
// Parse operand.
|
||||||
|
let operand = self.parse_expression()?;
|
||||||
|
|
||||||
|
// Parse close parenthesis `)`.
|
||||||
|
let right_span = self.expect(&Token::RightParen)?;
|
||||||
|
|
||||||
|
return Ok(Expression::Binary(BinaryExpression {
|
||||||
|
span: receiver.span() + right_span,
|
||||||
|
op: operator,
|
||||||
|
left: Box::new(receiver),
|
||||||
|
right: Box::new(operand),
|
||||||
|
}))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// handle core module operators `commit`, `hash` etc.
|
||||||
|
unimplemented!("throw error for invalid method call")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let curr = &self.token;
|
||||||
|
Err(ParserError::unexpected_str(&curr.token, "int or ident", curr.span).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an [`Expression`] AST node if the next tokens represent an
|
/// Returns an [`Expression`] AST node if the next tokens represent an
|
||||||
/// array access, circuit member access, function call, or static function call expression.
|
/// array access, circuit member access, function call, or static function call expression.
|
||||||
///
|
///
|
||||||
@ -229,21 +271,7 @@ impl ParserContext<'_> {
|
|||||||
let mut expr = self.parse_primary_expression()?;
|
let mut expr = self.parse_primary_expression()?;
|
||||||
loop {
|
loop {
|
||||||
if self.eat(&Token::Dot) {
|
if self.eat(&Token::Dot) {
|
||||||
// Handle method call expression.
|
expr = self.parse_method_call_expression(expr)?
|
||||||
if let Some(method) = self.eat_identifier() {
|
|
||||||
if self.check(&Token::LeftParen) {
|
|
||||||
let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
|
|
||||||
expr = Expression::Method(MethodCallExpression {
|
|
||||||
span: expr.span() + span,
|
|
||||||
receiver: Box::new(expr),
|
|
||||||
method,
|
|
||||||
arguments,
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let curr = &self.token;
|
|
||||||
return Err(ParserError::unexpected_str(&curr.token, "int or ident", curr.span).into());
|
|
||||||
}
|
}
|
||||||
if !self.check(&Token::LeftParen) {
|
if !self.check(&Token::LeftParen) {
|
||||||
break;
|
break;
|
||||||
|
@ -311,6 +311,13 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
|||||||
|
|
||||||
Some(Type::Boolean)
|
Some(Type::Boolean)
|
||||||
}
|
}
|
||||||
|
BinaryOperation::AddWrapped => {
|
||||||
|
self.visitor.assert_int_type(expected, input.span);
|
||||||
|
let t1 = self.visit_expression(&input.left, expected);
|
||||||
|
let t2 = self.visit_expression(&input.right, expected);
|
||||||
|
|
||||||
|
return_incorrect_type(t1, t2, expected)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +138,11 @@ impl<'a> TypeChecker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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 field or integer.
|
/// 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) {
|
pub(crate) fn assert_field_int_type(&self, type_: &Option<Type>, span: Span) {
|
||||||
self.assert_one_of_types(type_, &FIELD_INT_TYPES, span)
|
self.assert_one_of_types(type_, &FIELD_INT_TYPES, span)
|
||||||
|
@ -100,30 +100,51 @@ macro_rules! symbols {
|
|||||||
}
|
}
|
||||||
|
|
||||||
symbols! {
|
symbols! {
|
||||||
|
// unary operators
|
||||||
|
|
||||||
|
// binary operators
|
||||||
|
add,
|
||||||
|
add_w,
|
||||||
|
|
||||||
|
// arity three operators
|
||||||
|
|
||||||
|
// types
|
||||||
address,
|
address,
|
||||||
AlwaysConst,
|
|
||||||
array,
|
array,
|
||||||
assert,
|
|
||||||
bool,
|
bool,
|
||||||
Class: "class",
|
|
||||||
context,
|
|
||||||
constants,
|
|
||||||
CoreFunction,
|
|
||||||
console,
|
|
||||||
Const: "const",
|
Const: "const",
|
||||||
Constant,
|
Constant,
|
||||||
Else: "else",
|
constants,
|
||||||
error,
|
|
||||||
False: "false",
|
|
||||||
field,
|
field,
|
||||||
For: "for",
|
|
||||||
function,
|
|
||||||
group,
|
group,
|
||||||
i8,
|
i8,
|
||||||
i16,
|
i16,
|
||||||
i32,
|
i32,
|
||||||
i64,
|
i64,
|
||||||
i128,
|
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",
|
If: "if",
|
||||||
In: "in",
|
In: "in",
|
||||||
input,
|
input,
|
||||||
@ -134,19 +155,11 @@ symbols! {
|
|||||||
prelude,
|
prelude,
|
||||||
Public,
|
Public,
|
||||||
Return: "return",
|
Return: "return",
|
||||||
scalar,
|
|
||||||
Star: "*",
|
Star: "*",
|
||||||
std,
|
std,
|
||||||
string,
|
|
||||||
Struct: "struct",
|
Struct: "struct",
|
||||||
test,
|
test,
|
||||||
True: "true",
|
|
||||||
Type: "type",
|
Type: "type",
|
||||||
u8,
|
|
||||||
u16,
|
|
||||||
u32,
|
|
||||||
u64,
|
|
||||||
u128,
|
|
||||||
|
|
||||||
CONTAINER_PSEUDO_CIRCUIT: "$InputContainer",
|
CONTAINER_PSEUDO_CIRCUIT: "$InputContainer",
|
||||||
REGISTERS_PSEUDO_CIRCUIT: "$InputRegister",
|
REGISTERS_PSEUDO_CIRCUIT: "$InputRegister",
|
||||||
@ -154,11 +167,11 @@ symbols! {
|
|||||||
STATE_PSEUDO_CIRCUIT: "$InputState",
|
STATE_PSEUDO_CIRCUIT: "$InputState",
|
||||||
STATE_LEAF_PSEUDO_CIRCUIT: "$InputStateLeaf",
|
STATE_LEAF_PSEUDO_CIRCUIT: "$InputStateLeaf",
|
||||||
|
|
||||||
|
// input file
|
||||||
registers,
|
registers,
|
||||||
record,
|
record,
|
||||||
state,
|
state,
|
||||||
state_leaf,
|
state_leaf,
|
||||||
|
|
||||||
public,
|
public,
|
||||||
private,
|
private,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user