fix errors, focus on dynamic checks

This commit is contained in:
collin 2020-10-18 23:53:37 -07:00
parent 8de889ada5
commit e50029c466
23 changed files with 761 additions and 704 deletions

View File

@ -14,35 +14,42 @@
// 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::{ast::expressions::array::SpreadOrExpression, Expression, ExpressionError, ExpressionValue, ResolvedNode};
use leo_static_check::{SymbolTable, Type};
use crate::{
ast::expressions::array::SpreadOrExpression, Expression, ExpressionError, ExpressionValue, Frame, ResolvedNode,
};
use leo_static_check::Type;
use leo_typed::{Span, SpreadOrExpression as UnresolvedSpreadOrExpression};
impl Expression {
/// Resolves an array expression
///
/// Returns a new array `Expression` from a given vector of `UnresolvedSpreadOrExpression`s.
///
/// Performs a lookup in the given function body's variable table if the expression contains
/// user-defined variables.
///
pub(crate) fn array(
table: &mut SymbolTable,
expected_type: Option<Type>,
frame: &Frame,
type_: &Type,
expressions: Vec<Box<UnresolvedSpreadOrExpression>>,
span: Span,
) -> Result<Self, ExpressionError> {
// Expressions should evaluate to array type or array element type
let expected_element_type = if let Some(type_) = expected_type {
let (element_type, dimensions) = type_.get_type_array(span.clone())?;
if dimensions[0] != expressions.len() {
//throw array dimension mismatch error
return Err(ExpressionError::invalid_length_array(
dimensions[0],
expressions.len(),
span.clone(),
));
}
Some(element_type.clone())
} else {
None
};
// // Expressions should evaluate to array type or array element type
// let expected_element_type = if let Some(type_) = type_ {
// let (element_type, dimensions) = type_.get_type_array(span.clone())?;
//
// if dimensions[0] != expressions.len() {
// //throw array dimension mismatch error
// return Err(ExpressionError::invalid_length_array(
// dimensions[0],
// expressions.len(),
// span.clone(),
// ));
// }
//
// Some(element_type.clone())
// } else {
// None
// };
// Store actual array element type
let mut actual_element_type = None;
@ -50,7 +57,7 @@ impl Expression {
// Resolve all array elements
for expression in expressions {
let expression_resolved = SpreadOrExpression::resolve(table, (expected_element_type.clone(), *expression))?;
let expression_resolved = SpreadOrExpression::new(frame, type_, *expression)?;
let expression_type = expression_resolved.type_().clone();
array.push(Box::new(expression_resolved));

View File

@ -13,30 +13,36 @@
// 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::{ast::expressions::array::RangeOrExpression, Expression, ExpressionError, ExpressionValue, ResolvedNode};
use leo_static_check::{SymbolTable, Type};
use leo_typed::{Expression as UnresolvedExpression, RangeOrExpression as UnresolvedRangeOrExpression, Span};
impl Expression {
/// Resolves an array access expression
pub(crate) fn array_access(
table: &mut SymbolTable,
expected_type: Option<Type>,
array: Box<UnresolvedExpression>,
range: Box<UnresolvedRangeOrExpression>,
span: Span,
) -> Result<Self, ExpressionError> {
// Lookup the array in the symbol table.
// We do not know the length from this context so `expected_type = None`.
let array_resolved = Expression::resolve(table, (None, *array))?;
// Resolve the range or expression
let range_resolved = RangeOrExpression::resolve(table, (expected_type, *range))?;
Ok(Expression {
type_: range_resolved.type_().clone(),
value: ExpressionValue::ArrayAccess(Box::new(array_resolved), Box::new(range_resolved), span),
})
}
}
//
// use crate::{
// ast::expressions::array::RangeOrExpression, Expression, ExpressionError, ExpressionValue, Frame, ResolvedNode,
// };
// use leo_static_check::Type;
// use leo_typed::{Expression as UnresolvedExpression, RangeOrExpression as UnresolvedRangeOrExpression, Span};
//
// impl Expression {
// ///
// /// Returns a new array `Expression` from a given array access.
// ///
// /// Performs a lookup in the given function body's variable table if the expression contains
// /// user-defined variables.
// ///
// pub(crate) fn array_access(
// frame: &Frame,
// type_: &Type,
// array: Box<UnresolvedExpression>,
// range: Box<UnresolvedRangeOrExpression>,
// span: Span,
// ) -> Result<Self, ExpressionError> {
// // Lookup the array in the variable table.
// let array_resolved = Expression::new(frame, type_, *array)?;
//
// // Resolve the range or expression
// let range_resolved = RangeOrExpression::new(frame, type_, *range)?;
//
// Ok(Expression {
// type_: range_resolved.type_().clone(),
// value: ExpressionValue::ArrayAccess(Box::new(array_resolved), Box::new(range_resolved), span),
// })
// }
// }

View File

@ -14,8 +14,8 @@
// 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, ResolvedNode};
use leo_static_check::Type;
use leo_typed::RangeOrExpression as UnresolvedRangeOrExpression;
use serde::{Deserialize, Serialize};
@ -27,33 +27,35 @@ pub enum RangeOrExpression {
}
impl RangeOrExpression {
/// If this is a range, return an array type.
/// If this is an expression, return a data type.
pub(crate) fn type_(&self) -> &Type {
match self {
RangeOrExpression::Range(expresion, _expression) => expresion.type_(),
RangeOrExpression::Expression(expression) => expression.type_(),
}
}
}
// /// If this is a range, return an array type.
// /// If this is an expression, return a data type.
// pub(crate) fn type_(&self) -> &Type {
// match self {
// RangeOrExpression::Range(expresion, _expression) => expresion.type_(),
// RangeOrExpression::Expression(expression) => expression.type_(),
// }
// }
impl ResolvedNode for RangeOrExpression {
type Error = ExpressionError;
type UnresolvedNode = (Option<Type>, UnresolvedRangeOrExpression);
fn resolve(table: &mut SymbolTable, unresolved: Self::UnresolvedNode) -> Result<Self, Self::Error> {
let expected_type = unresolved.0;
let r_or_e = unresolved.1;
Ok(match r_or_e {
///
/// Returns a new `RangeOrExpression` from a given `UnresolvedRangeOrExpression`.
///
/// Performs a lookup in the given function body's variable table if the expression contains
/// user-defined variables.
///
pub fn new(
frame: &Frame,
type_: &Type,
unresolved_expression: UnresolvedRangeOrExpression,
) -> Result<Self, ExpressionError> {
Ok(match unresolved_expression {
UnresolvedRangeOrExpression::Range(from, to) => {
let resolved_from = Expression::resolve(table, (expected_type.clone(), from.unwrap())).unwrap();
let resolved_to = Expression::resolve(table, (expected_type, to.unwrap())).unwrap();
let resolved_from = Expression::new(frame, type_, from.unwrap())?;
let resolved_to = Expression::new(frame, type_, to.unwrap())?;
// TODO: add check for range type and array type
RangeOrExpression::Range(resolved_from, resolved_to)
}
UnresolvedRangeOrExpression::Expression(expression) => {
let expression_resolved = Expression::resolve(table, (expected_type, expression)).unwrap();
let expression_resolved = Expression::new(frame, type_, expression)?;
// TODO: add check for array type
RangeOrExpression::Expression(expression_resolved)
}

View File

@ -14,8 +14,8 @@
// 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::SpreadOrExpression as UnresolvedSpreadOrExpression;
use serde::{Deserialize, Serialize};
@ -33,24 +33,26 @@ impl SpreadOrExpression {
SpreadOrExpression::Expression(expression) => expression.type_(),
}
}
}
impl ResolvedNode for SpreadOrExpression {
type Error = ExpressionError;
type UnresolvedNode = (Option<Type>, UnresolvedSpreadOrExpression);
fn resolve(table: &mut SymbolTable, unresolved: Self::UnresolvedNode) -> Result<Self, Self::Error> {
let expected_type = unresolved.0;
let s_or_e = unresolved.1;
Ok(match s_or_e {
///
/// Returns a new `SpreadOrExpression` from a given `UnresolvedSpreadOrExpression`.
///
/// Performs a lookup in the given function body's variable table if the expression contains
/// user-defined variables.
///
pub fn new(
frame: &Frame,
type_: &Type,
unresolved_expression: UnresolvedSpreadOrExpression,
) -> Result<Self, ExpressionError> {
Ok(match unresolved_expression {
UnresolvedSpreadOrExpression::Spread(spread) => {
let spread_resolved = Expression::resolve(table, (expected_type, spread)).unwrap();
let spread_resolved = Expression::new(frame, type_, spread)?;
// TODO: add check for array type or array element type
SpreadOrExpression::Spread(spread_resolved)
}
UnresolvedSpreadOrExpression::Expression(expression) => {
let expression_resolved = Expression::resolve(table, (expected_type, expression)).unwrap();
let expression_resolved = Expression::new(frame, type_, expression)?;
// TODO: add check for array type or array element type
SpreadOrExpression::Expression(expression_resolved)
}

View File

@ -13,66 +13,67 @@
// 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::{CircuitVariableDefinition, Expression, ExpressionError, ExpressionValue, ResolvedNode};
use leo_static_check::{SymbolTable, Type};
use leo_typed::{CircuitVariableDefinition as UnresolvedCircuitVariableDefinition, Identifier, Span};
impl Expression {
///
/// Resolves an inline circuit expression.
///
pub(crate) fn circuit(
table: &mut SymbolTable,
expected_type: Option<Type>,
identifier: Identifier,
variables: Vec<UnresolvedCircuitVariableDefinition>,
span: Span,
) -> Result<Self, ExpressionError> {
// Check expected type
let type_ = Type::Circuit(identifier.clone());
Type::check_type(&expected_type, &type_, span.clone())?;
// Lookup circuit in symbol table
let circuit = table
.get_circuit(&identifier.name)
.ok_or(ExpressionError::undefined_circuit(identifier.clone()))?;
// Check the number of variables given
let expected_variables = circuit.variables.clone();
if variables.len() != expected_variables.len() {
return Err(ExpressionError::invalid_length_circuit_members(
expected_variables.len(),
variables.len(),
span,
));
}
// Check the name and type for each circuit variable
let mut variables_resolved = vec![];
for variable in variables {
// Find variable by name
let matched_variable = expected_variables
.iter()
.find(|expected| expected.identifier.eq(&variable.identifier));
let variable_type = match matched_variable {
Some(variable_type) => variable_type,
None => return Err(ExpressionError::undefined_circuit_variable(variable.identifier)),
};
// Resolve the variable expression using the expected variable type
let expected_variable_type = Some(variable_type.type_.clone());
let variable_resolved = CircuitVariableDefinition::resolve(table, (expected_variable_type, variable))?;
variables_resolved.push(variable_resolved);
}
Ok(Expression {
type_,
value: ExpressionValue::Circuit(identifier, variables_resolved, span),
})
}
}
//
// use crate::{CircuitVariableDefinition, Expression, ExpressionError, ExpressionValue, ResolvedNode};
// use leo_static_check::{SymbolTable, Type};
// use leo_typed::{CircuitVariableDefinition as UnresolvedCircuitVariableDefinition, Identifier, Span};
//
// impl Expression {
// ///
// /// Resolves an inline circuit expression.
// ///
// pub(crate) fn circuit(
// table: &mut SymbolTable,
// expected_type: Option<Type>,
// identifier: Identifier,
// variables: Vec<UnresolvedCircuitVariableDefinition>,
// span: Span,
// ) -> Result<Self, ExpressionError> {
// // Check expected type
// let type_ = Type::Circuit(identifier.clone());
// Type::check_type(&expected_type, &type_, span.clone())?;
//
// // Lookup circuit in symbol table
// let circuit = table
// .get_circuit(&identifier.name)
// .ok_or(ExpressionError::undefined_circuit(identifier.clone()))?;
//
// // Check the number of variables given
// let expected_variables = circuit.variables.clone();
//
// if variables.len() != expected_variables.len() {
// return Err(ExpressionError::invalid_length_circuit_members(
// expected_variables.len(),
// variables.len(),
// span,
// ));
// }
//
// // Check the name and type for each circuit variable
// let mut variables_resolved = vec![];
//
// for variable in variables {
// // Find variable by name
// let matched_variable = expected_variables
// .iter()
// .find(|expected| expected.identifier.eq(&variable.identifier));
//
// let variable_type = match matched_variable {
// Some(variable_type) => variable_type,
// None => return Err(ExpressionError::undefined_circuit_variable(variable.identifier)),
// };
//
// // Resolve the variable expression using the expected variable type
// let expected_variable_type = Some(variable_type.type_.clone());
//
// let variable_resolved = CircuitVariableDefinition::resolve(table, (expected_variable_type, variable))?;
//
// variables_resolved.push(variable_resolved);
// }
//
// Ok(Expression {
// type_,
// value: ExpressionValue::Circuit(identifier, variables_resolved, span),
// })
// }
// }

View File

@ -13,67 +13,67 @@
// 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::{Attribute, SymbolTable, Type};
use leo_typed::{Expression as UnresolvedExpression, Identifier, Span};
impl Expression {
/// Resolve the type of a circuit member
pub(crate) fn circuit_access(
table: &mut SymbolTable,
expected_type: Option<Type>,
circuit: Box<UnresolvedExpression>,
member: Identifier,
span: Span,
) -> Result<Self, ExpressionError> {
// Lookup the circuit in the symbol table.
// We do not know the exact circuit type from this context so `expected_type = None`.
let circuit_resolved = Expression::resolve(table, (None, *circuit))?;
let circuit_name = circuit_resolved.type_().get_type_circuit(span.clone())?;
// Lookup the circuit type in the symbol table
let circuit_type = table
.get_circuit(&circuit_name.name)
.ok_or(ExpressionError::undefined_circuit(circuit_name.clone()))?;
// Resolve the circuit member as a circuit variable
let matched_variable = circuit_type
.variables
.iter()
.find(|variable| variable.identifier.eq(&member));
let type_ = match matched_variable {
// Return variable type
Some(variable) => variable.type_.clone(),
None => {
// Resolve the circuit member as a circuit function
let matched_function = circuit_type
.functions
.iter()
.find(|function| function.function.identifier.eq(&member));
match matched_function {
// Return function output type
Some(function) => {
// Check non-static method
if function.attributes.contains(&Attribute::Static) {
return Err(ExpressionError::invalid_static_member_access(member.name.clone(), span));
}
function.function.output.type_.clone()
}
None => return Err(ExpressionError::undefined_circuit_function(member, span)),
}
}
};
// Check type of circuit member
Type::check_type(&expected_type, &type_, span.clone())?;
Ok(Expression {
type_,
value: ExpressionValue::CircuitMemberAccess(Box::new(circuit_resolved), member, span),
})
}
}
//
// use crate::{Expression, ExpressionError, ExpressionValue, ResolvedNode};
// use leo_static_check::{Attribute, SymbolTable, Type};
// use leo_typed::{Expression as UnresolvedExpression, Identifier, Span};
//
// impl Expression {
// /// Resolve the type of a circuit member
// pub(crate) fn circuit_access(
// table: &mut SymbolTable,
// expected_type: Option<Type>,
// circuit: Box<UnresolvedExpression>,
// member: Identifier,
// span: Span,
// ) -> Result<Self, ExpressionError> {
// // Lookup the circuit in the symbol table.
// // We do not know the exact circuit type from this context so `expected_type = None`.
// let circuit_resolved = Expression::resolve(table, (None, *circuit))?;
// let circuit_name = circuit_resolved.type_().get_type_circuit(span.clone())?;
//
// // Lookup the circuit type in the symbol table
// let circuit_type = table
// .get_circuit(&circuit_name.name)
// .ok_or(ExpressionError::undefined_circuit(circuit_name.clone()))?;
//
// // Resolve the circuit member as a circuit variable
// let matched_variable = circuit_type
// .variables
// .iter()
// .find(|variable| variable.identifier.eq(&member));
//
// let type_ = match matched_variable {
// // Return variable type
// Some(variable) => variable.type_.clone(),
// None => {
// // Resolve the circuit member as a circuit function
// let matched_function = circuit_type
// .functions
// .iter()
// .find(|function| function.function.identifier.eq(&member));
//
// match matched_function {
// // Return function output type
// Some(function) => {
// // Check non-static method
// if function.attributes.contains(&Attribute::Static) {
// return Err(ExpressionError::invalid_static_member_access(member.name.clone(), span));
// }
//
// function.function.output.type_.clone()
// }
// None => return Err(ExpressionError::undefined_circuit_function(member, span)),
// }
// }
// };
//
// // Check type of circuit member
// Type::check_type(&expected_type, &type_, span.clone())?;
//
// Ok(Expression {
// type_,
// value: ExpressionValue::CircuitMemberAccess(Box::new(circuit_resolved), member, span),
// })
// }
// }

View File

@ -13,54 +13,54 @@
// 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::{Attribute, SymbolTable, Type};
use leo_typed::{Expression as UnresolvedExpression, Identifier, Span};
impl Expression {
/// Resolve the type of a static circuit member
pub(crate) fn circuit_static_access(
table: &mut SymbolTable,
expected_type: Option<Type>,
circuit: Box<UnresolvedExpression>,
member: Identifier,
span: Span,
) -> Result<Self, ExpressionError> {
// Lookup the circuit in the symbol table.
// We do not know the exact circuit type from this context so `expected_type = None`.
let circuit_resolved = Expression::resolve(table, (None, *circuit))?;
let circuit_name = circuit_resolved.type_().get_type_circuit(span.clone())?;
// Lookup the circuit type in the symbol table
let circuit_type = table
.get_circuit(&circuit_name.name)
.ok_or(ExpressionError::undefined_circuit(circuit_name.clone()))?;
// Resolve the circuit member as a circuit function
let matched_function = circuit_type
.functions
.iter()
.find(|function| function.function.identifier.eq(&member));
let type_ = match matched_function {
Some(function) => {
// Check static method
if function.attributes.contains(&Attribute::Static) {
function.function.output.type_.clone()
} else {
return Err(ExpressionError::invalid_member_access(member.name, span));
}
}
None => return Err(ExpressionError::undefined_circuit_function_static(member, span)),
};
// Check type of static circuit function output
Type::check_type(&expected_type, &type_, span.clone())?;
Ok(Expression {
type_,
value: ExpressionValue::CircuitStaticFunctionAccess(Box::new(circuit_resolved), member, span),
})
}
}
//
// use crate::{Expression, ExpressionError, ExpressionValue, ResolvedNode};
// use leo_static_check::{Attribute, SymbolTable, Type};
// use leo_typed::{Expression as UnresolvedExpression, Identifier, Span};
//
// impl Expression {
// /// Resolve the type of a static circuit member
// pub(crate) fn circuit_static_access(
// table: &mut SymbolTable,
// expected_type: Option<Type>,
// circuit: Box<UnresolvedExpression>,
// member: Identifier,
// span: Span,
// ) -> Result<Self, ExpressionError> {
// // Lookup the circuit in the symbol table.
// // We do not know the exact circuit type from this context so `expected_type = None`.
// let circuit_resolved = Expression::resolve(table, (None, *circuit))?;
// let circuit_name = circuit_resolved.type_().get_type_circuit(span.clone())?;
//
// // Lookup the circuit type in the symbol table
// let circuit_type = table
// .get_circuit(&circuit_name.name)
// .ok_or(ExpressionError::undefined_circuit(circuit_name.clone()))?;
//
// // Resolve the circuit member as a circuit function
// let matched_function = circuit_type
// .functions
// .iter()
// .find(|function| function.function.identifier.eq(&member));
//
// let type_ = match matched_function {
// Some(function) => {
// // Check static method
// if function.attributes.contains(&Attribute::Static) {
// function.function.output.type_.clone()
// } else {
// return Err(ExpressionError::invalid_member_access(member.name, span));
// }
// }
// None => return Err(ExpressionError::undefined_circuit_function_static(member, span)),
// };
//
// // Check type of static circuit function output
// Type::check_type(&expected_type, &type_, span.clone())?;
//
// Ok(Expression {
// type_,
// value: ExpressionValue::CircuitStaticFunctionAccess(Box::new(circuit_resolved), member, span),
// })
// }
// }

View File

@ -13,38 +13,38 @@
// 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 leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolves an `if {cond} ? {first} : {second}` expression
/// `{cond}` should resolve to a boolean type
/// `{first}` and `{second}` should have equal types
pub(crate) fn conditional(
table: &mut SymbolTable,
expected_type: Option<Type>,
cond: UnresolvedExpression,
first: UnresolvedExpression,
second: UnresolvedExpression,
span: Span,
) -> Result<Self, ExpressionError> {
// Resolve the condition to a boolean type
let cond_type = Some(Type::Boolean);
let cond_resolved = Expression::resolve(table, (cond_type, cond))?;
// Resolve the first and second expressions to the expected type
let (first_resolved, second_resolved) = Expression::binary(table, expected_type, first, second, span.clone())?;
Ok(Expression {
type_: first_resolved.type_.clone(),
value: ExpressionValue::IfElse(
Box::new(cond_resolved),
Box::new(first_resolved),
Box::new(second_resolved),
span,
),
})
}
}
//
// use crate::{Expression, ExpressionError, ExpressionValue, Frame, ResolvedNode};
// use leo_static_check::{SymbolTable, Type};
// use leo_typed::{Expression as UnresolvedExpression, Span};
//
// impl Expression {
// /// Resolves an `if {cond} ? {first} : {second}` expression
// /// `{cond}` should resolve to a boolean type
// /// `{first}` and `{second}` should have equal types
// pub(crate) fn conditional(
// frame: &Frame,
// type_: &Type,
// cond: UnresolvedExpression,
// first: UnresolvedExpression,
// second: UnresolvedExpression,
// span: Span,
// ) -> Result<Self, ExpressionError> {
// // Resolve the condition to a boolean type
// let boolean_type = Type::Boolean;
// let cond_resolved = Expression::new(frame, &boolean_type, cond)?;
//
// // Resolve the first and second expressions to the expected type
// let (first_resolved, second_resolved) = Expression::binary(frame, type_, first, second, &span)?;
//
// Ok(Expression {
// type_: type_.clone(),
// value: ExpressionValue::IfElse(
// Box::new(cond_resolved),
// Box::new(first_resolved),
// Box::new(second_resolved),
// span,
// ),
// })
// }
// }

View File

@ -92,17 +92,17 @@ impl Expression {
UnresolvedExpression::Le(lhs, rhs, span) => Self::le(frame, *lhs, *rhs, span),
UnresolvedExpression::Lt(lhs, rhs, span) => Self::lt(frame, *lhs, *rhs, span),
// // Conditionals
// Conditionals
// UnresolvedExpression::IfElse(cond, first, second, span) => {
// Self::conditional(variable_table, *cond, *first, *second, span)
// Self::conditional(variable_table, type_, *cond, *first, *second, span)
// }
//
// // Arrays
// UnresolvedExpression::Array(elements, span) => Self::array(variable_table, elements, span),
// Arrays
UnresolvedExpression::Array(elements, span) => Self::array(frame, type_, elements, span),
// UnresolvedExpression::ArrayAccess(array, access, span) => {
// Self::array_access(variable_table, array, access, span)
// Self::array_access(frame, type_, array, access, span)
// }
//
// // Tuples
// UnresolvedExpression::Tuple(elements, span) => Self::tuple(variable_table, elements, span),
// UnresolvedExpression::TupleAccess(tuple, index, span) => {

View File

@ -13,59 +13,59 @@
// 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 leo_typed::{Expression as UnresolvedExpression, Span};
impl Expression {
/// Resolves an inline function call
/// Checks for errors in function name, inputs, and output.
pub(crate) fn function_call(
table: &mut SymbolTable,
expected_type: Option<Type>,
function: Box<UnresolvedExpression>,
inputs: Vec<UnresolvedExpression>,
span: Span,
) -> Result<Self, ExpressionError> {
// Lookup function in symbol table.
// We do not know the exact function type from this context so `expected_type = None`.
let function_resolved = Expression::resolve(table, (None, *function))?;
let function_name = function_resolved.type_().get_type_function(span.clone())?;
// Lookup the function type in the symbol table
let function_type = table
.get_function(&function_name.name)
.ok_or(ExpressionError::undefined_function(function_name.clone()))?;
let type_ = function_type.output.type_.clone();
let expected_inputs = function_type.inputs.clone();
// Check the number of inputs given
if inputs.len() != expected_inputs.len() {
return Err(ExpressionError::invalid_length_function_inputs(
expected_inputs.len(),
inputs.len(),
span,
));
}
// Check the type for each function input
let mut inputs_resolved = vec![];
for (input, function_input_type) in inputs.into_iter().zip(expected_inputs) {
let input_type = function_input_type.type_().clone();
let input_resolved = Expression::resolve(table, (Some(input_type), input))?;
inputs_resolved.push(input_resolved)
}
// Check the function output type
Type::check_type(&expected_type, &type_, span.clone())?;
Ok(Expression {
type_,
value: ExpressionValue::FunctionCall(Box::new(function_resolved), inputs_resolved, span),
})
}
}
//
// use crate::{Expression, ExpressionError, ExpressionValue, ResolvedNode};
// use leo_static_check::{SymbolTable, Type};
// use leo_typed::{Expression as UnresolvedExpression, Span};
//
// impl Expression {
// /// Resolves an inline function call
// /// Checks for errors in function name, inputs, and output.
// pub(crate) fn function_call(
// table: &mut SymbolTable,
// expected_type: Option<Type>,
// function: Box<UnresolvedExpression>,
// inputs: Vec<UnresolvedExpression>,
// span: Span,
// ) -> Result<Self, ExpressionError> {
// // Lookup function in symbol table.
// // We do not know the exact function type from this context so `expected_type = None`.
// let function_resolved = Expression::resolve(table, (None, *function))?;
// let function_name = function_resolved.type_().get_type_function(span.clone())?;
//
// // Lookup the function type in the symbol table
// let function_type = table
// .get_function(&function_name.name)
// .ok_or(ExpressionError::undefined_function(function_name.clone()))?;
//
// let type_ = function_type.output.type_.clone();
// let expected_inputs = function_type.inputs.clone();
//
// // Check the number of inputs given
// if inputs.len() != expected_inputs.len() {
// return Err(ExpressionError::invalid_length_function_inputs(
// expected_inputs.len(),
// inputs.len(),
// span,
// ));
// }
//
// // Check the type for each function input
// let mut inputs_resolved = vec![];
//
// for (input, function_input_type) in inputs.into_iter().zip(expected_inputs) {
// let input_type = function_input_type.type_().clone();
// let input_resolved = Expression::resolve(table, (Some(input_type), input))?;
//
// inputs_resolved.push(input_resolved)
// }
//
// // Check the function output type
// Type::check_type(&expected_type, &type_, span.clone())?;
//
// Ok(Expression {
// type_,
// value: ExpressionValue::FunctionCall(Box::new(function_resolved), inputs_resolved, span),
// })
// }
// }

View File

@ -41,6 +41,7 @@ impl Function {
// Create a new `Statement` from every given `UnresolvedStatement`.
let statements = function_body
.statements
.clone()
.into_iter()
.map(|unresolved_statement| Statement::new(&function_body, unresolved_statement))
.collect::<Result<Vec<Statement>, StatementError>>()?;

View File

@ -29,74 +29,69 @@ pub struct Assign {
pub span: Span,
}
impl Statement {
///
/// Resolves an assign statement
///
pub(crate) fn assign(
function_body: &Frame,
assignee: Assignee,
expression: UnresolvedExpression,
span: Span,
) -> Result<Self, StatementError> {
// Lookup variable in symbol table
let key = &assignee.identifier.name;
let variable = function_body.variable_table.get(key, &span)?;
// Throw an error if this variable is not mutable
if !variable.is_mutable() {
return Err(StatementError::immutable_assign(variable.identifier.name.clone(), span));
}
// Get inner assignee type
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::new(variable_table, (Some(type_), expression))?;
Ok(Statement::Assign(Assign {
assignee,
expression: expression_resolved,
span,
}))
}
}
///
/// Accesses the inner type of an assignee such as an array, tuple, or circuit member.
/// Returns an error for invalid accesses.
///
fn get_inner_assignee_type(
table: &SymbolTable,
type_: Type,
accesses: Vec<AssigneeAccess>,
span: Span,
) -> Result<Type, StatementError> {
match accesses.first() {
None => Ok(type_),
Some(access) => {
// Check that we are correctly accessing the type
let next_type = match (&type_, access) {
(Type::Array(next_type, _), AssigneeAccess::Array(_)) => *next_type.clone(),
(Type::Tuple(types), AssigneeAccess::Tuple(index)) => types[*index].clone(),
(Type::Circuit(identifier), AssigneeAccess::Member(member)) => {
let circuit_type_option = table.get_circuit(&identifier.name);
let circuit_type = match circuit_type_option {
Some(circuit_type) => circuit_type,
None => return Err(StatementError::undefined_circuit(identifier.clone())),
};
circuit_type.member_type(member)?.clone()
}
(type_, _) => return Err(StatementError::invalid_assign(type_, span)),
};
return get_inner_assignee_type(table, next_type, accesses[1..].to_vec(), span);
}
}
}
// impl Statement {
// ///
// /// Resolves an assign statement
// ///
// pub(crate) fn assign(
// frame: &Frame,
// assignee: Assignee,
// expression: UnresolvedExpression,
// span: Span,
// ) -> Result<Self, StatementError> {
// // Lookup variable in symbol table
// let key = &assignee.identifier.name;
// let variable = frame.variable_table.get(key, &span)?;
//
// // Throw an error if this variable is not mutable
// if !variable.is_mutable() {
// return Err(StatementError::immutable_assign(variable.identifier.name.clone(), span));
// }
//
// // Get inner assignee type
// let type_ = get_inner_assignee_type(frame, variable.type_.clone(), assignee.accesses.clone(), span.clone())?;
//
// // Resolve the expression based on the assignee type
// let expression_resolved = Expression::new(variable_table, (Some(type_), expression))?;
//
// Ok(Statement::Assign(Assign {
// assignee,
// expression: expression_resolved,
// span,
// }))
// }
// }
//
// ///
// /// Accesses the inner type of an assignee such as an array, tuple, or circuit member.
// /// Returns an error for invalid accesses.
// ///
// fn get_inner_assignee_type(
// frame: &Frame,
// type_: Type,
// accesses: Vec<AssigneeAccess>,
// span: Span,
// ) -> Result<Type, StatementError> {
// match accesses.first() {
// None => Ok(type_),
// Some(access) => {
// // Check that we are correctly accessing the type
// let next_type = match (&type_, access) {
// (Type::Array(next_type, _), AssigneeAccess::Array(_)) => *next_type.clone(),
// (Type::Tuple(types), AssigneeAccess::Tuple(index)) => types[*index].clone(),
// (Type::Circuit(identifier), AssigneeAccess::Member(member)) => {
// let circuit_type_option = frame.get_circuit(&identifier.name);
//
// let circuit_type = match circuit_type_option {
// Some(circuit_type) => circuit_type,
// None => return Err(StatementError::undefined_circuit(identifier.clone())),
// };
// circuit_type.member_type(member)?.clone()
// }
// (type_, _) => return Err(StatementError::invalid_assign(type_, span)),
// };
//
// return get_inner_assignee_type(frame, next_type, accesses[1..].to_vec(), span);
// }
// }
// }

View File

@ -14,12 +14,10 @@
// 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};
use leo_static_check::{FunctionOutputType, SymbolTable, Type};
use leo_typed::{
ConditionalNestedOrEndStatement as UnresolvedNestedOrEnd,
ConditionalStatement as UnresolvedConditional,
Span,
ConditionalNestedOrEndStatement as UnresolvedNestedOrEnd, ConditionalStatement as UnresolvedConditional, Span,
Statement as UnresolvedStatement,
};
@ -41,90 +39,90 @@ pub struct Conditional {
pub span: Span,
}
impl Conditional {
///
/// Resolves a conditional statement.
///
pub(crate) fn from_unresolved(
table: &mut SymbolTable,
return_type: FunctionOutputType,
conditional: UnresolvedConditional,
span: Span,
) -> Result<Self, StatementError> {
// Create child symbol table.
let mut child_table = SymbolTable::new(Some(Box::new(table.clone())));
// impl Conditional {
// ///
// /// Resolves a conditional statement.
// ///
// pub(crate) fn from_unresolved(
// table: &mut SymbolTable,
// return_type: FunctionOutputType,
// conditional: UnresolvedConditional,
// span: Span,
// ) -> Result<Self, StatementError> {
// // Create child symbol table.
// let mut child_table = SymbolTable::new(Some(Box::new(table.clone())));
//
// // Resolve the condition to a boolean.
// let type_boolean = Some(Type::Boolean);
// let condition_resolved = Expression::resolve(&mut child_table, (type_boolean, conditional.condition))?;
//
// // Resolve all statements.
// let statements_resolved = resolve_statements(&mut child_table, return_type.clone(), conditional.statements)?;
//
// // Check for an `else if` or `else` clause.
// let nested_or_end = match conditional.next {
// Some(nested_or_end) => nested_or_end,
// None => {
// return Ok(Conditional {
// condition: condition_resolved,
// statements: statements_resolved,
// next: None,
// span,
// });
// }
// };
//
// // Evaluate the `else if` or `else` clause.
// let next_resolved = match nested_or_end {
// UnresolvedNestedOrEnd::Nested(conditional) => {
// // Type check the `else if` clause.
// let conditional_resolved =
// Self::from_unresolved(table, return_type.clone(), *conditional, span.clone())?;
//
// ConditionalNestedOrEndStatement::Nested(Box::new(conditional_resolved))
// }
// UnresolvedNestedOrEnd::End(statements) => {
// // Create child symbol table.
// let mut child_table = SymbolTable::new(Some(Box::new(table.clone())));
//
// // Type check the `else` clause.
// let statements_resolved = resolve_statements(&mut child_table, return_type, statements)?;
//
// ConditionalNestedOrEndStatement::End(statements_resolved)
// }
// };
//
// Ok(Conditional {
// condition: condition_resolved,
// statements: statements_resolved,
// next: Some(next_resolved),
// span,
// })
// }
// }
// Resolve the condition to a boolean.
let type_boolean = Some(Type::Boolean);
let condition_resolved = Expression::resolve(&mut child_table, (type_boolean, conditional.condition))?;
// /// Resolve an array of statements.
// fn resolve_statements(
// table: &mut SymbolTable,
// return_type: FunctionOutputType,
// statements: Vec<UnresolvedStatement>,
// ) -> Result<Vec<Statement>, StatementError> {
// Ok(statements
// .into_iter()
// .map(|statement| Statement::resolve(table, (return_type.clone(), statement)))
// .collect::<Result<Vec<_>, _>>()?)
// }
// Resolve all statements.
let statements_resolved = resolve_statements(&mut child_table, return_type.clone(), conditional.statements)?;
// Check for an `else if` or `else` clause.
let nested_or_end = match conditional.next {
Some(nested_or_end) => nested_or_end,
None => {
return Ok(Conditional {
condition: condition_resolved,
statements: statements_resolved,
next: None,
span,
});
}
};
// Evaluate the `else if` or `else` clause.
let next_resolved = match nested_or_end {
UnresolvedNestedOrEnd::Nested(conditional) => {
// Type check the `else if` clause.
let conditional_resolved =
Self::from_unresolved(table, return_type.clone(), *conditional, span.clone())?;
ConditionalNestedOrEndStatement::Nested(Box::new(conditional_resolved))
}
UnresolvedNestedOrEnd::End(statements) => {
// Create child symbol table.
let mut child_table = SymbolTable::new(Some(Box::new(table.clone())));
// Type check the `else` clause.
let statements_resolved = resolve_statements(&mut child_table, return_type, statements)?;
ConditionalNestedOrEndStatement::End(statements_resolved)
}
};
Ok(Conditional {
condition: condition_resolved,
statements: statements_resolved,
next: Some(next_resolved),
span,
})
}
}
/// Resolve an array of statements.
fn resolve_statements(
table: &mut SymbolTable,
return_type: FunctionOutputType,
statements: Vec<UnresolvedStatement>,
) -> Result<Vec<Statement>, StatementError> {
Ok(statements
.into_iter()
.map(|statement| Statement::resolve(table, (return_type.clone(), statement)))
.collect::<Result<Vec<_>, _>>()?)
}
impl Statement {
/// Resolves a conditional statement.
pub(crate) fn conditional(
function_body: &function_body,
return_type: FunctionOutputType,
conditional: UnresolvedConditional,
span: Span,
) -> Result<Self, StatementError> {
let conditional = Conditional::from_unresolved(function_body, return_type, conditional, span)?;
Ok(Statement::Conditional(conditional))
}
}
// impl Statement {
// /// Resolves a conditional statement.
// pub(crate) fn conditional(
// function_body: &Frame,
// return_type: FunctionOutputType,
// conditional: UnresolvedConditional,
// span: Span,
// ) -> Result<Self, StatementError> {
// let conditional = Conditional::from_unresolved(function_body, return_type, conditional, span)?;
//
// Ok(Statement::Conditional(conditional))
// }
// }

View File

@ -15,14 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{
check_tuple_type,
Expression,
ExpressionValue,
Frame,
ResolvedNode,
Statement,
StatementError,
VariableTable,
check_tuple_type, Expression, ExpressionValue, Frame, ResolvedNode, Statement, StatementError, VariableTable,
VariableTableError,
};
use leo_static_check::{Attribute, ParameterType, SymbolTable, Type};
@ -106,11 +99,14 @@ impl DefinitionVariables {
}
// Get the type of each variable.
let variable_types = variables
let variable_types: Vec<Type> = variables
.names
.iter()
.map(|variable_name| function_body.variable_table.get(variable_name.name_string(), span))
.collect::<Result<Vec<Type>, VariableTableError>>()?;
.collect::<Result<Vec<&Type>, VariableTableError>>()?
.into_iter()
.map(|type_ref| type_ref.clone())
.collect();
// Create a new vector of `Expression`s from the given vector of `UnresolvedExpression`s.
let mut expressions_resolved = vec![];
@ -135,11 +131,14 @@ impl DefinitionVariables {
span: &Span,
) -> Result<Self, StatementError> {
// Get the type of each variable.
let variable_types = variables
let variable_types: Vec<Type> = variables
.names
.iter()
.map(|variable_name| function_body.variable_table.get(variable_name.name_string(), span))
.collect::<Result<Vec<Type>, VariableTableError>>()?;
.collect::<Result<Vec<&Type>, VariableTableError>>()?
.into_iter()
.map(|type_ref| type_ref.clone())
.collect();
// Create a new tuple type from the vector of variable types.
let tuple_type = Type::Tuple(variable_types);
@ -152,39 +151,39 @@ impl DefinitionVariables {
}
}
/// Inserts a variable definition into the given symbol table
fn insert_defined_variable(
table: &mut SymbolTable,
variable: &VariableName,
type_: &Type,
span: Span,
) -> Result<(), StatementError> {
let attributes = if variable.mutable {
vec![Attribute::Mutable]
} else {
vec![]
};
// Insert variable into symbol table
let key = variable.identifier.name.clone();
let value = ParameterType {
identifier: variable.identifier.clone(),
type_: type_.clone(),
attributes,
};
// Check that variable name was not defined twice
let duplicate = table.insert_name(key, value);
if duplicate.is_some() {
return Err(StatementError::duplicate_variable(
variable.identifier.name.clone(),
span,
));
}
Ok(())
}
// /// Inserts a variable definition into the given symbol table
// fn insert_defined_variable(
// table: &mut SymbolTable,
// variable: &VariableName,
// type_: &Type,
// span: Span,
// ) -> Result<(), StatementError> {
// let attributes = if variable.mutable {
// vec![Attribute::Mutable]
// } else {
// vec![]
// };
//
// // Insert variable into symbol table
// let key = variable.identifier.name.clone();
// let value = ParameterType {
// identifier: variable.identifier.clone(),
// type_: type_.clone(),
// attributes,
// };
//
// // Check that variable name was not defined twice
// let duplicate = table.insert_name(key, value);
//
// if duplicate.is_some() {
// return Err(StatementError::duplicate_variable(
// variable.identifier.name.clone(),
// span,
// ));
// }
//
// Ok(())
// }
impl Statement {
///

View File

@ -29,47 +29,47 @@ pub struct Iteration {
pub span: Span,
}
impl Statement {
/// Resolve an iteration statement
pub(crate) fn iteration(
table: &mut SymbolTable,
return_type: FunctionOutputType,
index: Identifier,
start: UnresolvedExpression,
stop: UnresolvedExpression,
statements: Vec<UnresolvedStatement>,
span: Span,
) -> Result<Self, StatementError> {
// TODO: Create child symbol table and add variables from parent
// Resolve index numbers to a u32 type
let type_number = Type::IntegerType(IntegerType::U32);
let start_resolved = Expression::resolve(table, (Some(type_number.clone()), start))?;
let stop_resolved = Expression::resolve(table, (Some(type_number.clone()), stop))?;
// Add index to symbol table
let key = index.name.clone();
let value = ParameterType {
identifier: index.clone(),
type_: type_number,
attributes: vec![],
};
table.insert_name(key, value);
// Resolve statements
let statements_resolved = statements
.into_iter()
.map(|statement| Statement::resolve(table, (return_type.clone(), statement)))
.collect::<Result<Vec<Statement>, _>>()?;
Ok(Statement::Iteration(Iteration {
index,
start: start_resolved,
stop: stop_resolved,
statements: statements_resolved,
span,
}))
}
}
// impl Statement {
// /// Resolve an iteration statement
// pub(crate) fn iteration(
// table: &mut SymbolTable,
// return_type: FunctionOutputType,
// index: Identifier,
// start: UnresolvedExpression,
// stop: UnresolvedExpression,
// statements: Vec<UnresolvedStatement>,
// span: Span,
// ) -> Result<Self, StatementError> {
// // TODO: Create child symbol table and add variables from parent
//
// // Resolve index numbers to a u32 type
// let type_number = Type::IntegerType(IntegerType::U32);
//
// let start_resolved = Expression::resolve(table, (Some(type_number.clone()), start))?;
// let stop_resolved = Expression::resolve(table, (Some(type_number.clone()), stop))?;
//
// // Add index to symbol table
// let key = index.name.clone();
// let value = ParameterType {
// identifier: index.clone(),
// type_: type_number,
// attributes: vec![],
// };
//
// table.insert_name(key, value);
//
// // Resolve statements
// let statements_resolved = statements
// .into_iter()
// .map(|statement| Statement::resolve(table, (return_type.clone(), statement)))
// .collect::<Result<Vec<Statement>, _>>()?;
//
// Ok(Statement::Iteration(Iteration {
// index,
// start: start_resolved,
// stop: stop_resolved,
// statements: statements_resolved,
// span,
// }))
// }
// }

View File

@ -29,8 +29,11 @@ impl Statement {
unresolved_expression: UnresolvedExpression,
span: Span,
) -> Result<Self, StatementError> {
// Get function return type from frame.
let return_type = &function_body.function_type.output.type_;
// Create a new `Expression` from the unresolved return expression
let expression = Expression::new(function_body, unresolved_expression)?;
let expression = Expression::new(function_body, return_type, unresolved_expression)?;
Ok(Statement::Return(expression, span))
}

View File

@ -14,15 +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::{
Assign,
Conditional,
Definition,
Expression,
Frame,
Iteration,
ResolvedNode,
StatementError,
VariableTable,
Assign, Conditional, Definition, Expression, Frame, Iteration, ResolvedNode, StatementError, VariableTable,
};
use leo_static_check::{FunctionOutputType, FunctionType, SymbolTable};
use leo_typed::{ConsoleFunctionCall, Span, Statement as UnresolvedStatement};
@ -54,17 +46,18 @@ impl Statement {
UnresolvedStatement::Definition(declare, variables, expressions, 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(frame, return_type, conditional, span)
}
UnresolvedStatement::Iteration(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::new(frame, expression)?, span))
}
// UnresolvedStatement::Assign(assignee, expression, span) => Self::assign(frame, assignee, expression, span),
// UnresolvedStatement::Conditional(conditional, span) => {
// Self::conditional(frame, return_type, conditional, span)
// }
// UnresolvedStatement::Iteration(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::new(frame, expression)?, span))
// }
_ => unimplemented!("statement not implemented"),
}
}
}
@ -74,29 +67,30 @@ impl ResolvedNode for Statement {
type UnresolvedNode = (FunctionOutputType, UnresolvedStatement);
/// Type check a statement inside a program AST
fn resolve(table: &mut SymbolTable, unresolved: Self::UnresolvedNode) -> Result<Self, Self::Error> {
let return_type = unresolved.0;
let statement = unresolved.1;
match statement {
UnresolvedStatement::Return(expression, span) => {
Self::resolve_return(table, return_type.type_, expression, span)
}
UnresolvedStatement::Definition(declare, variables, expressions, span) => {
Self::definition(table, declare, variables, expressions, span)
}
UnresolvedStatement::Assign(assignee, expression, span) => Self::assign(table, assignee, expression, span),
UnresolvedStatement::Conditional(conditional, span) => {
Self::conditional(table, return_type, conditional, span)
}
UnresolvedStatement::Iteration(index, start, stop, statements, span) => {
Self::iteration(table, 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(table, (None, expression))?,
span,
)),
}
fn resolve(_table: &mut SymbolTable, _unresolved: Self::UnresolvedNode) -> Result<Self, Self::Error> {
// let return_type = unresolved.0;
// let statement = unresolved.1;
//
// match statement {
// // UnresolvedStatement::Return(expression, span) => {
// // Self::resolve_return(table, return_type.type_, expression, span)
// // }
// // UnresolvedStatement::Definition(declare, variables, expressions, span) => {
// // Self::definition(table, declare, variables, expressions, span)
// // }
// // UnresolvedStatement::Assign(assignee, expression, span) => Self::assign(table, assignee, expression, span),
// // UnresolvedStatement::Conditional(conditional, span) => {
// // Self::conditional(table, return_type, conditional, span)
// // }
// // UnresolvedStatement::Iteration(index, start, stop, statements, span) => {
// // Self::iteration(table, 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(table, (None, expression))?,
// // span,
// // )),
// }
unimplemented!("statement resolve deprecated");
}
}

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::{DynamicCheckError, Function, FunctionError, LeoResolvedAst, VariableTableError};
use crate::{DynamicCheckError, FrameError, VariableTableError};
use leo_static_check::{FunctionInputType, FunctionType, SymbolTable, Type, TypeVariable};
use leo_typed::{
Expression,
@ -26,7 +26,7 @@ use leo_typed::{
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::{collections::HashMap, path::PathBuf};
/// Performs a dynamic type inference check over a program.
pub struct DynamicCheck {
@ -87,12 +87,12 @@ impl DynamicCheck {
/// Returns a `LeoResolvedAst` if all `TypeAssertion` predicates are true.
/// Returns ERROR if a `TypeAssertion` predicate is false or a solution does not exist.
///
pub fn solve(self) -> Result<LeoResolvedAst, DynamicCheckError> {
pub fn solve(self) -> Result<(), DynamicCheckError> {
for function_body in self.functions {
function_body.solve();
function_body.solve()?;
}
Ok(LeoResolvedAst::new())
Ok(())
}
}
@ -142,8 +142,8 @@ impl Frame {
/// Collects a vector of `TypeAssertion` predicates from a vector of statements.
///
fn parse_statements(&mut self) {
for statement in &self.statements {
self.parse_statement(statement);
for statement in self.statements.clone() {
self.parse_statement(&statement);
}
}
@ -309,7 +309,7 @@ impl Frame {
///
/// Returns a new `Function` if all `TypeAssertions` can be solved successfully.
///
fn solve(self) -> Result<Function, FunctionError> {
fn solve(self) -> Result<(), FrameError> {
let mut unsolved = self.type_assertions.clone();
while !unsolved.is_empty() {
@ -337,7 +337,9 @@ impl Frame {
// }
// Return a new resolved function struct.
Function::new(self)
// Function::new(self)
Ok(())
}
}

View File

@ -14,7 +14,8 @@
// 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, FunctionError, ProgramError, StatementError};
// use crate::{ExpressionError, FunctionError, ProgramError, StatementError};
use crate::FrameError;
use leo_typed::Error as FormattedError;
use std::path::PathBuf;
@ -26,16 +27,19 @@ pub enum DynamicCheckError {
Error(#[from] FormattedError),
#[error("{}", _0)]
ExpressionError(#[from] ExpressionError),
#[error("{}", _0)]
FunctionError(#[from] FunctionError),
#[error("{}", _0)]
StatementError(#[from] StatementError),
#[error("{}", _0)]
ProgramError(#[from] ProgramError),
FrameError(#[from] FrameError),
//
// #[error("{}", _0)]
// ExpressionError(#[from] ExpressionError),
//
// #[error("{}", _0)]
// FunctionError(#[from] FunctionError),
//
// #[error("{}", _0)]
// StatementError(#[from] StatementError),
//
// #[error("{}", _0)]
// ProgramError(#[from] ProgramError),
}
impl DynamicCheckError {
@ -43,10 +47,11 @@ impl DynamicCheckError {
pub fn set_path(&mut self, path: PathBuf) {
match self {
DynamicCheckError::Error(error) => error.set_path(path),
DynamicCheckError::ExpressionError(error) => error.set_path(path),
DynamicCheckError::FunctionError(error) => error.set_path(path),
DynamicCheckError::StatementError(error) => error.set_path(path),
DynamicCheckError::ProgramError(error) => error.set_path(path),
DynamicCheckError::FrameError(error) => error.set_path(path),
// DynamicCheckError::ExpressionError(error) => error.set_path(path),
// DynamicCheckError::FunctionError(error) => error.set_path(path),
// DynamicCheckError::StatementError(error) => error.set_path(path),
// DynamicCheckError::ProgramError(error) => error.set_path(path),
}
}
}

View File

@ -41,6 +41,7 @@ impl ExpressionError {
match self {
ExpressionError::Error(error) => error.set_path(path),
ExpressionError::TypeError(error) => error.set_path(path),
ExpressionError::VariableTableError(error) => error.set_path(path),
}
}

View File

@ -0,0 +1,44 @@
// Copyright (C) 2019-2020 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 leo_typed::{Error as FormattedError, Span};
use std::path::PathBuf;
/// Errors encountered when tracking variable names in a program.
#[derive(Debug, Error)]
pub enum FrameError {
#[error("{}", _0)]
Error(#[from] FormattedError),
}
impl FrameError {
///
/// Set the filepath for the error stacktrace
///
pub fn set_path(&mut self, path: PathBuf) {
match self {
FrameError::Error(error) => error.set_path(path),
}
}
///
/// Return a new formatted error with a given message and span information
///
fn new_from_span(message: String, span: Span) -> Self {
FrameError::Error(FormattedError::new_from_span(message, span))
}
}

View File

@ -14,32 +14,29 @@
// 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/>.
pub mod circuit;
pub use self::circuit::*;
// pub mod circuit;
// pub use self::circuit::*;
pub mod dynamic_check;
pub use self::dynamic_check::*;
pub mod expression;
pub use self::expression::*;
pub mod frame;
pub use self::frame::*;
pub mod function;
pub use self::function::*;
pub mod program;
pub use self::program::*;
pub mod resolver;
pub use self::resolver::*;
pub mod statement;
pub use self::statement::*;
// pub mod expression;
// pub use self::expression::*;
//
// pub mod function;
// pub use self::function::*;
//
// pub mod program;
// pub use self::program::*;
//
// pub mod resolver;
// pub use self::resolver::*;
//
// pub mod statement;
// pub use self::statement::*;
pub mod variable_table;
pub use self::variable_table::*;
// pub mod symbol_table;
// pub use self::symbol_table::*;
// pub mod type_;
// pub use self::type_::*;

View File

@ -17,8 +17,8 @@
#[macro_use]
extern crate thiserror;
pub mod ast;
pub use self::ast::*;
// pub mod ast;
// pub use self::ast::*;
pub mod dynamic_check;
pub use self::dynamic_check::*;