impl expression operations

This commit is contained in:
collin 2020-10-17 16:47:33 -07:00
parent 42a892480a
commit 154fa45b4d
17 changed files with 110 additions and 106 deletions

View File

@ -14,24 +14,26 @@
// 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 crate::{Expression, ExpressionError, ExpressionValue};
use leo_static_check::{SymbolTable, Type};
use crate::{Expression, ExpressionError, ExpressionValue, Frame};
use leo_static_check::Type;
use leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolve the type of adding `lhs + rhs`
///
/// Returns a new `Expression` adding `lhs + rhs`.
///
pub(crate) fn add(
table: &mut SymbolTable,
expected_type: Option<Type>,
frame: &Frame,
type_: &Type,
lhs: UnresolvedExpression,
rhs: UnresolvedExpression,
span: Span,
) -> Result<Self, ExpressionError> {
// Resolve lhs and rhs expressions
let (lhs_resolved, rhs_resolved) = Self::binary(table, expected_type, lhs, rhs, span.clone())?;
let (lhs_resolved, rhs_resolved) = Self::binary(frame, type_, lhs, rhs, &span)?;
Ok(Expression {
type_: lhs_resolved.type_.clone(),
type_: type_.clone(),
value: ExpressionValue::Add(Box::new(lhs_resolved), Box::new(rhs_resolved), span),
})
}

View File

@ -14,24 +14,26 @@
// 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 crate::{Expression, ExpressionError, ExpressionValue};
use leo_static_check::{SymbolTable, Type};
use crate::{Expression, ExpressionError, ExpressionValue, Frame};
use leo_static_check::Type;
use leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolve the type of dividing `lhs / rhs`
///
/// Returns a new `Expression` dividing `lhs / rhs`.
///
pub(crate) fn div(
table: &mut SymbolTable,
expected_type: Option<Type>,
frame: &Frame,
type_: &Type,
lhs: UnresolvedExpression,
rhs: UnresolvedExpression,
span: Span,
) -> Result<Self, ExpressionError> {
// Resolve lhs and rhs expressions
let (lhs_resolved, rhs_resolved) = Self::binary(table, expected_type, lhs, rhs, span.clone())?;
let (lhs_resolved, rhs_resolved) = Self::binary(frame, type_, lhs, rhs, &span)?;
Ok(Expression {
type_: lhs_resolved.type_.clone(),
type_: type_.clone(),
value: ExpressionValue::Div(Box::new(lhs_resolved), Box::new(rhs_resolved), span),
})
}

View File

@ -14,24 +14,26 @@
// 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 crate::{Expression, ExpressionError, ExpressionValue};
use leo_static_check::{SymbolTable, Type};
use crate::{Expression, ExpressionError, ExpressionValue, Frame};
use leo_static_check::Type;
use leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolve the type of multiplying `lhs * rhs`
///
/// Returns a new `Expression` multiplying `lhs * rhs`.
///
pub(crate) fn mul(
table: &mut SymbolTable,
expected_type: Option<Type>,
frame: &Frame,
type_: &Type,
lhs: UnresolvedExpression,
rhs: UnresolvedExpression,
span: Span,
) -> Result<Self, ExpressionError> {
// Resolve lhs and rhs expressions
let (lhs_resolved, rhs_resolved) = Self::binary(table, expected_type, lhs, rhs, span.clone())?;
let (lhs_resolved, rhs_resolved) = Self::binary(frame, type_, lhs, rhs, &span)?;
Ok(Expression {
type_: lhs_resolved.type_.clone(),
type_: type_.clone(),
value: ExpressionValue::Mul(Box::new(lhs_resolved), Box::new(rhs_resolved), span),
})
}

View File

@ -14,22 +14,22 @@
// 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 crate::{Expression, ExpressionError, ExpressionValue, ResolvedNode};
use leo_static_check::{SymbolTable, Type};
use crate::{Expression, ExpressionError, ExpressionValue, Frame};
use leo_static_check::Type;
use leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolve the type of negating `-expression`
pub(crate) fn negate(
table: &mut SymbolTable,
expected_type: Option<Type>,
expression: UnresolvedExpression,
frame: &Frame,
type_: &Type,
unresolved_expression: UnresolvedExpression,
span: Span,
) -> Result<Self, ExpressionError> {
let expression_resolved = Self::resolve(table, (expected_type, expression))?;
let expression_resolved = Self::new(frame, type_, unresolved_expression)?;
Ok(Expression {
type_: expression_resolved.type_.clone(),
type_: type_.clone(),
value: ExpressionValue::Negate(Box::new(expression_resolved), span),
})
}

View File

@ -14,24 +14,26 @@
// 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 crate::{Expression, ExpressionError, ExpressionValue};
use leo_static_check::{SymbolTable, Type};
use crate::{Expression, ExpressionError, ExpressionValue, Frame};
use leo_static_check::Type;
use leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolve the type of exponentiation `lhs ** rhs`
///
/// Returns a new `Expression` raising `lhs` to the power of `rhs`.
///
pub(crate) fn pow(
table: &mut SymbolTable,
expected_type: Option<Type>,
frame: &Frame,
type_: &Type,
lhs: UnresolvedExpression,
rhs: UnresolvedExpression,
span: Span,
) -> Result<Self, ExpressionError> {
// Resolve lhs and rhs expressions
let (lhs_resolved, rhs_resolved) = Self::binary(table, expected_type, lhs, rhs, span.clone())?;
let (lhs_resolved, rhs_resolved) = Self::binary(frame, type_, lhs, rhs, &span)?;
Ok(Expression {
type_: lhs_resolved.type_.clone(),
type_: type_.clone(),
value: ExpressionValue::Pow(Box::new(lhs_resolved), Box::new(rhs_resolved), span),
})
}

View File

@ -14,24 +14,26 @@
// 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 crate::{Expression, ExpressionError, ExpressionValue};
use leo_static_check::{SymbolTable, Type};
use crate::{Expression, ExpressionError, ExpressionValue, Frame};
use leo_static_check::Type;
use leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolve the type of subtracting `lhs - rhs`
///
/// Returns a new `Expression` subtracting `lhs - rhs`.
///
pub(crate) fn sub(
table: &mut SymbolTable,
expected_type: Option<Type>,
frame: &Frame,
type_: &Type,
lhs: UnresolvedExpression,
rhs: UnresolvedExpression,
span: Span,
) -> Result<Self, ExpressionError> {
// Resolve lhs and rhs expressions
let (lhs_resolved, rhs_resolved) = Self::binary(table, expected_type, lhs, rhs, span.clone())?;
let (lhs_resolved, rhs_resolved) = Self::binary(frame, type_, lhs, rhs, &span)?;
Ok(Expression {
type_: lhs_resolved.type_.clone(),
type_: type_.clone(),
value: ExpressionValue::Sub(Box::new(lhs_resolved), Box::new(rhs_resolved), span),
})
}

View File

@ -13,28 +13,25 @@
// 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 crate::{Expression, ExpressionError, ResolvedNode};
use leo_static_check::{SymbolTable, Type};
use crate::{Expression, ExpressionError, Frame};
use leo_static_check::Type;
use leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolve a binary expression from left to right.
/// If no expected type is given, then the expression resolves to the lhs type.
pub(crate) fn binary(
table: &mut SymbolTable,
mut expected_type: Option<Type>,
frame: &Frame,
type_: &Type,
lhs: UnresolvedExpression,
rhs: UnresolvedExpression,
_span: Span,
_span: &Span,
) -> Result<(Self, Self), ExpressionError> {
// Resolve lhs with expected type
let lhs_resolved = Expression::resolve(table, (expected_type, lhs))?;
// Set the expected type to the lhs type
expected_type = Some(lhs_resolved.type_.clone());
let lhs_resolved = Expression::new(frame, type_, lhs)?;
// Resolve the rhs with expected type
let rhs_resolved = Expression::resolve(table, (expected_type, rhs))?;
let rhs_resolved = Expression::new(frame, type_, rhs)?;
Ok((lhs_resolved, rhs_resolved))
}

View File

@ -14,7 +14,7 @@
// 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 crate::{ExpressionError, ExpressionValue, FunctionBody, ResolvedNode, VariableTable};
use crate::{ExpressionError, ExpressionValue, Frame, ResolvedNode, VariableTable};
use leo_static_check::{SymbolTable, Type};
use leo_typed::{Expression as UnresolvedExpression, Span};
@ -54,13 +54,13 @@ impl Expression {
/// user-defined variables.
///
pub fn new(
function_body: &FunctionBody,
frame: &Frame,
type_: &Type,
unresolved_expression: UnresolvedExpression,
) -> Result<Self, ExpressionError> {
match unresolved_expression {
// Identifier
UnresolvedExpression::Identifier(identifier) => Self::variable(function_body, identifier),
UnresolvedExpression::Identifier(identifier) => Self::variable(frame, identifier),
// Values
UnresolvedExpression::Address(string, span) => Ok(Self::address(type_, string, span)),
@ -72,14 +72,14 @@ impl Expression {
}
UnresolvedExpression::Implicit(string, span) => Self::implicit(type_, string, span),
// // Arithmetic Operations
// UnresolvedExpression::Add(lhs, rhs, span) => Self::add(variable_table, *lhs, *rhs, span),
// UnresolvedExpression::Sub(lhs, rhs, span) => Self::sub(variable_table, *lhs, *rhs, span),
// UnresolvedExpression::Mul(lhs, rhs, span) => Self::mul(variable_table, *lhs, *rhs, span),
// UnresolvedExpression::Div(lhs, rhs, span) => Self::div(variable_table, *lhs, *rhs, span),
// UnresolvedExpression::Pow(lhs, rhs, span) => Self::pow(variable_table, *lhs, *rhs, span),
// UnresolvedExpression::Negate(expression, span) => Self::negate(variable_table, *expression, span),
//
// Arithmetic Operations
UnresolvedExpression::Add(lhs, rhs, span) => Self::add(variable_table, type_, *lhs, *rhs, span),
UnresolvedExpression::Sub(lhs, rhs, span) => Self::sub(variable_table, type_, *lhs, *rhs, span),
UnresolvedExpression::Mul(lhs, rhs, span) => Self::mul(variable_table, type_, *lhs, *rhs, span),
UnresolvedExpression::Div(lhs, rhs, span) => Self::div(variable_table, type_, *lhs, *rhs, span),
UnresolvedExpression::Pow(lhs, rhs, span) => Self::pow(variable_table, type_, *lhs, *rhs, span),
UnresolvedExpression::Negate(expression, span) => Self::negate(variable_table, type_, *expression, span),
// // Logical Operations
// UnresolvedExpression::And(lhs, rhs, span) => Self::and(variable_table, *lhs, *rhs, span),
// UnresolvedExpression::Or(lhs, rhs, span) => Self::or(variable_table, *lhs, *rhs, span),

View File

@ -14,7 +14,7 @@
// 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 crate::{Expression, ExpressionError, ExpressionValue, FunctionBody, VariableTable};
use crate::{Expression, ExpressionError, ExpressionValue, Frame, VariableTable};
use leo_static_check::{SymbolTable, Type};
use leo_typed::Identifier;
@ -24,7 +24,7 @@ impl Expression {
///
/// Performs a lookup in the given function body's variable table to find the variable's type.
///
pub(crate) fn variable(function_body: &FunctionBody, variable: Identifier) -> Result<Self, ExpressionError> {
pub(crate) fn variable(function_body: &Frame, variable: Identifier) -> Result<Self, ExpressionError> {
// Lookup the type of the given variable.
let type_ = function_body.variable_table.get(&variable.name, &variable.span)?;

View File

@ -14,7 +14,7 @@
// 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 crate::{Expression, ExpressionError, ExpressionValue, FunctionBody, ResolvedNode, VariableTable};
use crate::{Expression, ExpressionError, ExpressionValue, Frame, ResolvedNode, VariableTable};
use leo_static_check::{SymbolTable, Type};
use leo_typed::{Expression as UnresolvedExpression, Span};
@ -25,7 +25,7 @@ impl Expression {
/// Performs a lookup in the given variable table if an `UnresolvedExpression` contains user-defined types.
///
pub(crate) fn tuple(
function_body: &FunctionBody,
function_body: &Frame,
type_: &Type,
unresolved_expressions: Vec<UnresolvedExpression>,
span: Span,

View File

@ -14,7 +14,7 @@
// 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 crate::{FunctionBody, FunctionError, ResolvedNode, Statement, StatementError, VariableTable};
use crate::{Frame, FunctionError, ResolvedNode, Statement, StatementError, VariableTable};
use leo_static_check::{FunctionType, SymbolTable, TypeError};
use leo_typed::{Function as UnresolvedFunction, Statement as UnresolvedStatement};
@ -37,7 +37,7 @@ impl Function {
/// Performs a lookup in the given function body's variable table if the statement contains
/// user-defined types..
///
pub fn new(function_body: FunctionBody) -> Result<Self, FunctionError> {
pub fn new(function_body: Frame) -> Result<Self, FunctionError> {
// Create a new `Statement` from every given `UnresolvedStatement`.
let statements = function_body
.statements

View File

@ -14,7 +14,7 @@
// 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 crate::{Expression, ResolvedNode, Statement, StatementError};
use crate::{Expression, Frame, ResolvedNode, Statement, StatementError, VariableTable};
use leo_static_check::{SymbolTable, Type};
use leo_typed::{Assignee, AssigneeAccess, Expression as UnresolvedExpression, Span};
@ -34,16 +34,14 @@ impl Statement {
/// Resolves an assign statement
///
pub(crate) fn assign(
table: &mut SymbolTable,
function_body: &Frame,
assignee: Assignee,
expression: UnresolvedExpression,
span: Span,
) -> Result<Self, StatementError> {
// Lookup variable in symbol table
let key = &assignee.identifier.name;
let variable = table
.get_variable(key)
.ok_or(StatementError::undefined_variable(key.clone(), span.clone()))?;
let variable = function_body.variable_table.get(key, &span)?;
// Throw an error if this variable is not mutable
if !variable.is_mutable() {
@ -51,10 +49,15 @@ impl Statement {
}
// Get inner assignee type
let type_ = get_inner_assignee_type(table, variable.type_.clone(), assignee.accesses.clone(), span.clone())?;
let type_ = get_inner_assignee_type(
variable_table,
variable.type_.clone(),
assignee.accesses.clone(),
span.clone(),
)?;
// Resolve the expression based on the assignee type
let expression_resolved = Expression::resolve(table, (Some(type_), expression))?;
let expression_resolved = Expression::new(variable_table, (Some(type_), expression))?;
Ok(Statement::Assign(Assign {
assignee,

View File

@ -118,12 +118,12 @@ fn resolve_statements(
impl Statement {
/// Resolves a conditional statement.
pub(crate) fn conditional(
table: &mut SymbolTable,
function_body: &function_body,
return_type: FunctionOutputType,
conditional: UnresolvedConditional,
span: Span,
) -> Result<Self, StatementError> {
let conditional = Conditional::from_unresolved(table, return_type, conditional, span)?;
let conditional = Conditional::from_unresolved(function_body, return_type, conditional, span)?;
Ok(Statement::Conditional(conditional))
}

View File

@ -18,7 +18,7 @@ use crate::{
check_tuple_type,
Expression,
ExpressionValue,
FunctionBody,
Frame,
ResolvedNode,
Statement,
StatementError,
@ -55,7 +55,7 @@ impl DefinitionVariables {
/// Performs a lookup in the given variable table if the `UnresolvedExpression` contains user-defined variables.
///
fn single(
function_body: &FunctionBody,
function_body: &Frame,
variable_name: VariableName,
unresolved_expression: UnresolvedExpression,
span: &Span,
@ -75,7 +75,7 @@ impl DefinitionVariables {
/// Performs a lookup in the given variable table if an `UnresolvedExpression` contains user-defined variables.
///
fn tuple(
function_body: &FunctionBody,
function_body: &Frame,
variable: VariableName,
unresolved_expressions: Vec<UnresolvedExpression>,
span: &Span,
@ -91,7 +91,7 @@ impl DefinitionVariables {
/// Resolves multiple variables for multiple expressions
fn multiple_variable(
function_body: &FunctionBody,
function_body: &Frame,
variables: Variables,
unresolved_expressions: Vec<UnresolvedExpression>,
span: &Span,
@ -129,7 +129,7 @@ impl DefinitionVariables {
/// Resolves multiple variables for an expression that returns a tuple
fn multiple_variable_tuple(
function_body: &FunctionBody,
function_body: &Frame,
variables: Variables,
unresolved_expression: UnresolvedExpression,
span: &Span,
@ -193,7 +193,7 @@ impl Statement {
/// Performs a lookup in the given variable table if the statement contains user-defined variables.
///
pub(crate) fn definition(
function_body: &FunctionBody,
function_body: &Frame,
declare: Declare,
variables: Variables,
unresolved_expressions: Vec<UnresolvedExpression>,

View File

@ -14,7 +14,7 @@
// 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 crate::{Expression, FunctionBody, ResolvedNode, Statement, StatementError, VariableTable};
use crate::{Expression, Frame, ResolvedNode, Statement, StatementError, VariableTable};
use leo_static_check::{SymbolTable, Type};
use leo_typed::{Expression as UnresolvedExpression, Span};
@ -25,7 +25,7 @@ impl Statement {
/// Performs a lookup in the given variable table if the statement contains user-defined types.
///
pub(crate) fn resolve_return(
function_body: &FunctionBody,
function_body: &Frame,
unresolved_expression: UnresolvedExpression,
span: Span,
) -> Result<Self, StatementError> {

View File

@ -18,7 +18,7 @@ use crate::{
Conditional,
Definition,
Expression,
FunctionBody,
Frame,
Iteration,
ResolvedNode,
StatementError,
@ -48,29 +48,23 @@ impl Statement {
/// Performs a lookup in the given function body's variable table if the statement contains
/// user-defined types.
///
pub fn new(
function_body: &FunctionBody,
unresolved_statement: UnresolvedStatement,
) -> Result<Self, StatementError> {
pub fn new(frame: &Frame, unresolved_statement: UnresolvedStatement) -> Result<Self, StatementError> {
match unresolved_statement {
UnresolvedStatement::Return(expression, span) => Self::resolve_return(function_body, expression, span),
UnresolvedStatement::Return(expression, span) => Self::resolve_return(frame, expression, span),
UnresolvedStatement::Definition(declare, variables, expressions, span) => {
Self::definition(function_body, declare, variables, expressions, span)
}
UnresolvedStatement::Assign(assignee, expression, span) => {
Self::assign(variable_table, assignee, expression, span)
Self::definition(frame, declare, variables, expressions, span)
}
UnresolvedStatement::Assign(assignee, expression, span) => Self::assign(frame, assignee, expression, span),
UnresolvedStatement::Conditional(conditional, span) => {
Self::conditional(variable_table, return_type, conditional, span)
Self::conditional(frame, return_type, conditional, span)
}
UnresolvedStatement::Iteration(index, start, stop, statements, span) => {
Self::iteration(variable_table, return_type, index, start, stop, statements, span)
Self::iteration(frame, return_type, index, start, stop, statements, span)
}
UnresolvedStatement::Console(console_function_call) => Ok(Statement::Console(console_function_call)),
UnresolvedStatement::Expression(expression, span) => Ok(Statement::Expression(
Expression::resolve(variable_table, expression)?,
span,
)),
UnresolvedStatement::Expression(expression, span) => {
Ok(Statement::Expression(Expression::new(frame, expression)?, span))
}
}
}
}

View File

@ -31,7 +31,7 @@ use std::collections::HashMap;
/// Performs a dynamic type inference check over a program.
pub struct DynamicCheck {
table: SymbolTable,
functions: Vec<FunctionBody>,
functions: Vec<Frame>,
}
impl DynamicCheck {
@ -75,7 +75,7 @@ impl DynamicCheck {
/// Collects a vector of `TypeAssertion` predicates from a function.
///
fn parse_function(&mut self, function: &UnresolvedFunction) {
let function_body = FunctionBody::new(function.clone(), self.table.clone());
let function_body = Frame::new(function.clone(), self.table.clone());
self.functions.push(function_body);
}
@ -98,7 +98,7 @@ impl DynamicCheck {
/// A vector of `TypeAssertion` predicates created from a function body.
#[derive(Clone)]
pub struct FunctionBody {
pub struct Frame {
pub function_type: FunctionType,
pub statements: Vec<UnresolvedStatement>,
pub user_defined_types: SymbolTable,
@ -106,7 +106,7 @@ pub struct FunctionBody {
pub variable_table: VariableTable,
}
impl FunctionBody {
impl Frame {
///
/// Collects a vector of `TypeAssertion` predicates from a function.
///