remove method call expr and type checking

This commit is contained in:
collin 2022-06-09 13:07:30 -07:00
parent a32418133c
commit 9797175f16
10 changed files with 0 additions and 239 deletions

View File

@ -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);

View File

@ -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),
} }
} }

View File

@ -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)?;

View File

@ -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)

View File

@ -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()
} }

View File

@ -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

View File

@ -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>;
} }

View File

@ -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,
}
}
}

View File

@ -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
}
}
} }

View File

@ -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(),
} }
} }