mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-23 17:43:06 +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::*;
|
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;
|
||||||
@ -50,8 +48,6 @@ pub enum Expression {
|
|||||||
Ternary(TernaryExpression),
|
Ternary(TernaryExpression),
|
||||||
/// A call expression, e.g., `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),
|
||||||
@ -67,7 +63,6 @@ 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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,7 +76,6 @@ 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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +91,6 @@ 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,7 +46,6 @@ 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()),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,18 +106,6 @@ 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,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
|
// 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,10 +58,6 @@ 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,7 +41,6 @@ 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),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -100,20 +99,6 @@ 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
|
||||||
|
@ -25,9 +25,6 @@ pub use account::*;
|
|||||||
mod algorithms;
|
mod algorithms;
|
||||||
pub use algorithms::*;
|
pub use algorithms::*;
|
||||||
|
|
||||||
mod methods;
|
|
||||||
pub use methods::*;
|
|
||||||
|
|
||||||
pub trait Types {
|
pub trait Types {
|
||||||
fn types() -> IndexSet<Symbol>;
|
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::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),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -411,55 +410,4 @@ 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> {
|
|
||||||
// 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) negate: bool,
|
||||||
pub(crate) account_types: IndexSet<Symbol>,
|
pub(crate) account_types: IndexSet<Symbol>,
|
||||||
pub(crate) algorithms_types: IndexSet<Symbol>,
|
pub(crate) algorithms_types: IndexSet<Symbol>,
|
||||||
pub(crate) method_table: MethodTable,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const INT_TYPES: [Type; 10] = [
|
const INT_TYPES: [Type; 10] = [
|
||||||
@ -83,7 +82,6 @@ impl<'a> TypeChecker<'a> {
|
|||||||
negate: false,
|
negate: false,
|
||||||
account_types: Account::types(),
|
account_types: Account::types(),
|
||||||
algorithms_types: Algorithms::types(),
|
algorithms_types: Algorithms::types(),
|
||||||
method_table: MethodTable::load(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user