mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-19 07:32:26 +03:00
remove method call expr and type checking
This commit is contained in:
parent
a32418133c
commit
9797175f16
@ -1,46 +0,0 @@
|
||||
// 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,8 +24,6 @@ mod binary;
|
||||
pub use binary::*;
|
||||
mod unary;
|
||||
pub use unary::*;
|
||||
mod method;
|
||||
pub use method::*;
|
||||
mod ternary;
|
||||
pub use ternary::*;
|
||||
mod value;
|
||||
@ -50,8 +48,6 @@ pub enum Expression {
|
||||
Ternary(TernaryExpression),
|
||||
/// A call expression, e.g., `my_fun(args)`.
|
||||
Call(CallExpression),
|
||||
/// A method call expression, e.g., `a.add(b)`.
|
||||
Method(MethodCallExpression),
|
||||
/// An expression of type "error".
|
||||
/// Will result in a compile error eventually.
|
||||
Err(ErrExpression),
|
||||
@ -67,7 +63,6 @@ impl Node for Expression {
|
||||
Unary(n) => n.span(),
|
||||
Ternary(n) => n.span(),
|
||||
Call(n) => n.span(),
|
||||
Method(n) => n.span(),
|
||||
Err(n) => n.span(),
|
||||
}
|
||||
}
|
||||
@ -81,7 +76,6 @@ impl Node for Expression {
|
||||
Unary(n) => n.set_span(span),
|
||||
Ternary(n) => n.set_span(span),
|
||||
Call(n) => n.set_span(span),
|
||||
Method(n) => n.set_span(span),
|
||||
Err(n) => n.set_span(span),
|
||||
}
|
||||
}
|
||||
@ -97,7 +91,6 @@ impl fmt::Display for Expression {
|
||||
Unary(n) => n.fmt(f),
|
||||
Ternary(n) => n.fmt(f),
|
||||
Call(n) => n.fmt(f),
|
||||
Method(n) => n.fmt(f),
|
||||
Err(n) => n.fmt(f),
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
Expression::Unary(unary) => Expression::Unary(self.reduce_unary(unary)?),
|
||||
Expression::Ternary(ternary) => Expression::Ternary(self.reduce_ternary(ternary)?),
|
||||
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()),
|
||||
};
|
||||
|
||||
@ -107,18 +106,6 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
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> {
|
||||
let function = self.reduce_expression(&call.function)?;
|
||||
|
||||
|
@ -123,21 +123,6 @@ 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
|
||||
fn reduce_statement(&mut self, _statement: &Statement, new: Statement) -> Result<Statement> {
|
||||
Ok(new)
|
||||
|
@ -58,10 +58,6 @@ pub trait ExpressionVisitor<'a> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_method(&mut self, _input: &'a MethodCallExpression) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_err(&mut self, _input: &'a ErrExpression) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ pub trait ExpressionVisitorDirector<'a>: VisitorDirector<'a> {
|
||||
Expression::Unary(expr) => self.visit_unary(expr, additional),
|
||||
Expression::Ternary(expr) => self.visit_ternary(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),
|
||||
};
|
||||
}
|
||||
@ -100,20 +99,6 @@ pub trait ExpressionVisitorDirector<'a>: VisitorDirector<'a> {
|
||||
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> {
|
||||
self.visitor_ref().visit_err(input);
|
||||
None
|
||||
|
@ -25,9 +25,6 @@ pub use account::*;
|
||||
mod algorithms;
|
||||
pub use algorithms::*;
|
||||
|
||||
mod methods;
|
||||
pub use methods::*;
|
||||
|
||||
pub trait Types {
|
||||
fn types() -> IndexSet<Symbol>;
|
||||
}
|
||||
|
@ -1,82 +0,0 @@
|
||||
// Copyright (C) 2019-2021 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/>.
|
||||
|
||||
//! This module defines AVM opcodes as associated method calls on Leo types.
|
||||
|
||||
use indexmap::{indexmap, indexset, IndexMap, IndexSet};
|
||||
use leo_ast::Type;
|
||||
use leo_span::Symbol;
|
||||
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Method {
|
||||
// todo @collinc97: this struct contains type checking info and does not consider opcodes.
|
||||
/// The name of the method as an interned string.
|
||||
pub name: Symbol,
|
||||
/// This count excludes the receiver e.g, `1u8.add(2u8)` contains 1 argument.
|
||||
pub num_arguments: usize,
|
||||
/// `true` if the receiver type == arguments type == return type
|
||||
pub types_are_equal: bool,
|
||||
}
|
||||
|
||||
impl Method {
|
||||
pub(crate) fn new(name: &str, num_arguments: usize, types_are_equal: bool) -> Self {
|
||||
Self {
|
||||
name: Symbol::intern(name),
|
||||
num_arguments,
|
||||
types_are_equal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct MethodTable {
|
||||
/// Maps method name => method definition.
|
||||
method_definitions: IndexMap<Symbol, Method>,
|
||||
/// Supported methods for the field type.
|
||||
field_methods: IndexSet<Symbol>,
|
||||
}
|
||||
|
||||
impl MethodTable {
|
||||
pub fn load() -> Self {
|
||||
// Initialize method definitions.
|
||||
let add = Method::new("add", 1, true);
|
||||
|
||||
// Initialize associated methods for each type.
|
||||
Self {
|
||||
field_methods: indexset! {
|
||||
add.name
|
||||
},
|
||||
method_definitions: indexmap! {
|
||||
add.name => add
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the method corresponding to the given symbol.
|
||||
/// Used during type checking.
|
||||
pub fn lookup_method(&self, symbol: &Symbol) -> Option<&Method> {
|
||||
self.method_definitions.get(symbol)
|
||||
}
|
||||
|
||||
/// Returns `true` if the associated method exists for the given type.
|
||||
/// Sometimes used during type checking if the receiver type is known.
|
||||
pub fn type_method_is_supported(&self, type_: &Type, method: &Symbol) -> bool {
|
||||
match type_ {
|
||||
Type::Field => self.field_methods.contains(method),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
@ -54,7 +54,6 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
Expression::Unary(expr) => self.visit_unary(expr, expected),
|
||||
Expression::Ternary(expr) => self.visit_ternary(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),
|
||||
};
|
||||
}
|
||||
@ -411,55 +410,4 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
|
||||
expr => self.visit_expression(expr, expected),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_method(
|
||||
&mut self,
|
||||
input: &'a MethodCallExpression,
|
||||
expected: &Self::AdditionalInput,
|
||||
) -> Option<Self::Output> {
|
||||
// Check if the method exists.
|
||||
if let Some(method) = self.visitor.method_table.clone().lookup_method(&input.method.name) {
|
||||
// Check number of arguments is correct.
|
||||
if method.num_arguments != input.arguments.len() {
|
||||
self.visitor.handler.emit_err(
|
||||
TypeCheckerError::incorrect_num_args_to_call(
|
||||
method.num_arguments,
|
||||
input.arguments.len(),
|
||||
input.span(),
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
// Handle case where receiver type == argument type == return type.
|
||||
if method.types_are_equal {
|
||||
// Check if the method is supported for the type.
|
||||
if let Some(type_) = expected {
|
||||
if !self.visitor.method_table.type_method_is_supported(type_, &method.name) {
|
||||
self.visitor.handler.emit_err(
|
||||
TypeCheckerError::type_method_not_supported(type_, &input.method.name, input.span()).into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if receiver is correct type for method.
|
||||
let ret = self.visit_expression(&input.receiver, expected);
|
||||
|
||||
// Check if arguments are correct types for method.
|
||||
input.arguments.iter().for_each(|arg| {
|
||||
self.visit_expression(arg, expected);
|
||||
});
|
||||
|
||||
ret
|
||||
} else {
|
||||
// Handle case where the method types are not known yet.
|
||||
*expected
|
||||
}
|
||||
} else {
|
||||
self.visitor
|
||||
.handler
|
||||
.emit_err(TypeCheckerError::unknown_sym("method", &input.method.name, input.span()).into());
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ pub struct TypeChecker<'a> {
|
||||
pub(crate) negate: bool,
|
||||
pub(crate) account_types: IndexSet<Symbol>,
|
||||
pub(crate) algorithms_types: IndexSet<Symbol>,
|
||||
pub(crate) method_table: MethodTable,
|
||||
}
|
||||
|
||||
const INT_TYPES: [Type; 10] = [
|
||||
@ -83,7 +82,6 @@ impl<'a> TypeChecker<'a> {
|
||||
negate: false,
|
||||
account_types: Account::types(),
|
||||
algorithms_types: Algorithms::types(),
|
||||
method_table: MethodTable::load(),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user