mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-19 15:41:36 +03:00
impl method call expression parsing
This commit is contained in:
parent
18b71d225b
commit
f0a1573058
46
compiler/ast/src/expression/method.rs
Normal file
46
compiler/ast/src/expression/method.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (C) 2019-2022 Aleo Systems Inc.
|
||||||
|
// This file is part of the Leo library.
|
||||||
|
|
||||||
|
// The Leo library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// The Leo library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// A method call expression, e.g., `1u8.add(2u8)`.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct MethodCallExpression {
|
||||||
|
/// The receiver of a method call, e.g. `1u8` in `1u8.add(2u8)`.
|
||||||
|
pub receiver: Box<Expression>,
|
||||||
|
/// The identifier of the called method.
|
||||||
|
pub method: Identifier,
|
||||||
|
/// Expressions for the arguments passed to the methods parameters.
|
||||||
|
pub arguments: Vec<Expression>,
|
||||||
|
/// Span of the entire call `receiver.method(arguments)`.
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MethodCallExpression {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}.", self.receiver)?;
|
||||||
|
write!(f, "{}(", self.method)?;
|
||||||
|
for (i, param) in self.arguments.iter().enumerate() {
|
||||||
|
write!(f, "{}", param)?;
|
||||||
|
if i < self.arguments.len() - 1 {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::simple_node_impl!(MethodCallExpression);
|
@ -24,6 +24,8 @@ mod binary;
|
|||||||
pub use binary::*;
|
pub use binary::*;
|
||||||
mod unary;
|
mod unary;
|
||||||
pub use unary::*;
|
pub use unary::*;
|
||||||
|
mod method;
|
||||||
|
pub use method::*;
|
||||||
mod ternary;
|
mod ternary;
|
||||||
pub use ternary::*;
|
pub use ternary::*;
|
||||||
mod value;
|
mod value;
|
||||||
@ -46,8 +48,10 @@ pub enum Expression {
|
|||||||
Unary(UnaryExpression),
|
Unary(UnaryExpression),
|
||||||
/// A ternary conditional expression `cond ? if_expr : else_expr`.
|
/// A ternary conditional expression `cond ? if_expr : else_expr`.
|
||||||
Ternary(TernaryExpression),
|
Ternary(TernaryExpression),
|
||||||
/// A call expression like `my_fun(args)`.
|
/// A call expression, e.g., `my_fun(args)`.
|
||||||
Call(CallExpression),
|
Call(CallExpression),
|
||||||
|
/// A method call expression, e.g., `a.add(b)`.
|
||||||
|
Method(MethodCallExpression),
|
||||||
/// An expression of type "error".
|
/// An expression of type "error".
|
||||||
/// Will result in a compile error eventually.
|
/// Will result in a compile error eventually.
|
||||||
Err(ErrExpression),
|
Err(ErrExpression),
|
||||||
@ -63,6 +67,7 @@ impl Node for Expression {
|
|||||||
Unary(n) => n.span(),
|
Unary(n) => n.span(),
|
||||||
Ternary(n) => n.span(),
|
Ternary(n) => n.span(),
|
||||||
Call(n) => n.span(),
|
Call(n) => n.span(),
|
||||||
|
Method(n) => n.span(),
|
||||||
Err(n) => n.span(),
|
Err(n) => n.span(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,6 +81,7 @@ impl Node for Expression {
|
|||||||
Unary(n) => n.set_span(span),
|
Unary(n) => n.set_span(span),
|
||||||
Ternary(n) => n.set_span(span),
|
Ternary(n) => n.set_span(span),
|
||||||
Call(n) => n.set_span(span),
|
Call(n) => n.set_span(span),
|
||||||
|
Method(n) => n.set_span(span),
|
||||||
Err(n) => n.set_span(span),
|
Err(n) => n.set_span(span),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,6 +97,7 @@ impl fmt::Display for Expression {
|
|||||||
Unary(n) => n.fmt(f),
|
Unary(n) => n.fmt(f),
|
||||||
Ternary(n) => n.fmt(f),
|
Ternary(n) => n.fmt(f),
|
||||||
Call(n) => n.fmt(f),
|
Call(n) => n.fmt(f),
|
||||||
|
Method(n) => n.fmt(f),
|
||||||
Err(n) => n.fmt(f),
|
Err(n) => n.fmt(f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
|||||||
Expression::Unary(unary) => Expression::Unary(self.reduce_unary(unary)?),
|
Expression::Unary(unary) => Expression::Unary(self.reduce_unary(unary)?),
|
||||||
Expression::Ternary(ternary) => Expression::Ternary(self.reduce_ternary(ternary)?),
|
Expression::Ternary(ternary) => Expression::Ternary(self.reduce_ternary(ternary)?),
|
||||||
Expression::Call(call) => Expression::Call(self.reduce_call(call)?),
|
Expression::Call(call) => Expression::Call(self.reduce_call(call)?),
|
||||||
|
Expression::Method(method) => Expression::Method(self.reduce_method(method)?),
|
||||||
Expression::Err(s) => Expression::Err(s.clone()),
|
Expression::Err(s) => Expression::Err(s.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,6 +107,18 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
|||||||
self.reducer.reduce_ternary(ternary, condition, if_true, if_false)
|
self.reducer.reduce_ternary(ternary, condition, if_true, if_false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reduce_method(&mut self, method: &MethodCallExpression) -> Result<MethodCallExpression> {
|
||||||
|
let receiver = self.reduce_expression(&method.receiver)?;
|
||||||
|
let method_id = self.reduce_identifier(&method.method)?;
|
||||||
|
|
||||||
|
let mut arguments = vec![];
|
||||||
|
for argument in method.arguments.iter() {
|
||||||
|
arguments.push(self.reduce_expression(argument)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.reducer.reduce_method(method, receiver, method_id, arguments)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reduce_call(&mut self, call: &CallExpression) -> Result<CallExpression> {
|
pub fn reduce_call(&mut self, call: &CallExpression) -> Result<CallExpression> {
|
||||||
let function = self.reduce_expression(&call.function)?;
|
let function = self.reduce_expression(&call.function)?;
|
||||||
|
|
||||||
|
@ -123,6 +123,21 @@ pub trait ReconstructingReducer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reduce_method(
|
||||||
|
&mut self,
|
||||||
|
method: &MethodCallExpression,
|
||||||
|
receiver: Expression,
|
||||||
|
method_id: Identifier,
|
||||||
|
arguments: Vec<Expression>,
|
||||||
|
) -> Result<MethodCallExpression> {
|
||||||
|
Ok(MethodCallExpression {
|
||||||
|
receiver: Box::new(receiver),
|
||||||
|
method: method_id,
|
||||||
|
arguments,
|
||||||
|
span: method.span,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Statements
|
// Statements
|
||||||
fn reduce_statement(&mut self, _statement: &Statement, new: Statement) -> Result<Statement> {
|
fn reduce_statement(&mut self, _statement: &Statement, new: Statement) -> Result<Statement> {
|
||||||
Ok(new)
|
Ok(new)
|
||||||
|
@ -58,6 +58,10 @@ pub trait ExpressionVisitor<'a> {
|
|||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_method(&mut self, _input: &'a MethodCallExpression) -> VisitResult {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_err(&mut self, _input: &'a ErrExpression) -> VisitResult {
|
fn visit_err(&mut self, _input: &'a ErrExpression) -> VisitResult {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ pub trait ExpressionVisitorDirector<'a>: VisitorDirector<'a> {
|
|||||||
Expression::Unary(expr) => self.visit_unary(expr, additional),
|
Expression::Unary(expr) => self.visit_unary(expr, additional),
|
||||||
Expression::Ternary(expr) => self.visit_ternary(expr, additional),
|
Expression::Ternary(expr) => self.visit_ternary(expr, additional),
|
||||||
Expression::Call(expr) => self.visit_call(expr, additional),
|
Expression::Call(expr) => self.visit_call(expr, additional),
|
||||||
|
Expression::Method(expr) => self.visit_method(expr, additional),
|
||||||
Expression::Err(expr) => self.visit_err(expr, additional),
|
Expression::Err(expr) => self.visit_err(expr, additional),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -99,6 +100,16 @@ pub trait ExpressionVisitorDirector<'a>: VisitorDirector<'a> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_method(&mut self, input: &'a MethodCallExpression, additional: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||||
|
self.visit_expression(&input.receiver, additional);
|
||||||
|
if let VisitResult::VisitChildren = self.visitor_ref().visit_method(input) {
|
||||||
|
input.arguments.iter().for_each(|expr| {
|
||||||
|
self.visit_expression(expr, additional);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_err(&mut self, input: &'a ErrExpression, _additional: &Self::AdditionalInput) -> Option<Self::Output> {
|
fn visit_err(&mut self, input: &'a ErrExpression, _additional: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||||
self.visitor_ref().visit_err(input);
|
self.visitor_ref().visit_err(input);
|
||||||
None
|
None
|
||||||
|
@ -229,10 +229,24 @@ 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.
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
println!("expr {}", expr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
let curr = &self.token;
|
let curr = &self.token;
|
||||||
return Err(ParserError::unexpected_str(&curr.token, "int or ident", curr.span).into());
|
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;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
|||||||
Expression::Unary(expr) => self.visit_unary(expr, expected),
|
Expression::Unary(expr) => self.visit_unary(expr, expected),
|
||||||
Expression::Ternary(expr) => self.visit_ternary(expr, expected),
|
Expression::Ternary(expr) => self.visit_ternary(expr, expected),
|
||||||
Expression::Call(expr) => self.visit_call(expr, expected),
|
Expression::Call(expr) => self.visit_call(expr, expected),
|
||||||
|
Expression::Method(expr) => self.visit_method(expr, expected),
|
||||||
Expression::Err(expr) => self.visit_err(expr, expected),
|
Expression::Err(expr) => self.visit_err(expr, expected),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -403,4 +404,38 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
|||||||
expr => self.visit_expression(expr, expected),
|
expr => self.visit_expression(expr, expected),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_method(&mut self, input: &'a MethodCallExpression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
|
||||||
|
None
|
||||||
|
// input.receiver.
|
||||||
|
//
|
||||||
|
// if let Some(func) = self.visitor.symbol_table.clone().lookup_fn(&input.method.name) {
|
||||||
|
// let ret = self.visitor.assert_type(func.output, expected, func.span());
|
||||||
|
//
|
||||||
|
// if func.input.len() != input.arguments.len() {
|
||||||
|
// self.visitor.handler.emit_err(
|
||||||
|
// TypeCheckerError::incorrect_num_args_to_call(
|
||||||
|
// func.input.len(),
|
||||||
|
// input.arguments.len(),
|
||||||
|
// input.span(),
|
||||||
|
// )
|
||||||
|
// .into(),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func.input
|
||||||
|
// .iter()
|
||||||
|
// .zip(input.arguments.iter())
|
||||||
|
// .for_each(|(expected, argument)| {
|
||||||
|
// self.visit_expression(argument, &Some(expected.get_variable().type_));
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// Some(ret)
|
||||||
|
// } else {
|
||||||
|
// self.visitor
|
||||||
|
// .handler
|
||||||
|
// .emit_err(TypeCheckerError::unknown_sym("method", &ident.name, ident.span()).into());
|
||||||
|
// None
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
function main() -> bool {
|
function main(a: u8, b: u8) -> u8 {
|
||||||
console.log("hello world");
|
return a.add(b);
|
||||||
return true;
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user