Skip to content

Commit

Permalink
resolve list inclusion expr
Browse files Browse the repository at this point in the history
  • Loading branch information
SkymanOne committed Mar 9, 2024
1 parent 7d4dc59 commit 9f819ba
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 1 deletion.
7 changes: 7 additions & 0 deletions crates/semantics/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ pub enum TypeVariant {
Model(SymbolInfo),
Enum(SymbolInfo),
State(SymbolInfo),

// A placeholder for generics.
// Mainly used in for built-in list function
// e.g. `map`, `filter`, etc.
// which can operate on lists of generic types.
Generic,
}

impl TypeVariant {
Expand Down Expand Up @@ -483,6 +489,7 @@ impl Display for TypeVariant {
TypeVariant::Model(_) => word("model"),
TypeVariant::Enum(_) => word("enum"),
TypeVariant::State(_) => word("state"),
TypeVariant::Generic => word("generic type"),
}
}
}
Expand Down
12 changes: 11 additions & 1 deletion crates/semantics/src/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use self::{
resolve_equality,
resolve_greater,
resolve_greater_eq,
resolve_in,
resolve_inequality,
resolve_less,
resolve_less_eq,
Expand Down Expand Up @@ -219,7 +220,16 @@ pub fn expression(
parsed_ast::Expression::Not(u) => {
resolve_not(&u.element, u.loc.clone(), scope, contract, expected_ty)
}
parsed_ast::Expression::In(_) => todo!(),
parsed_ast::Expression::In(b) => {
resolve_in(
&b.left,
&b.right,
b.loc.clone(),
scope,
contract,
expected_ty,
)
}
// complex expressions
parsed_ast::Expression::Variable(ident) => {
resolve_variable(ident, scope, contract, expected_ty)
Expand Down
133 changes: 133 additions & 0 deletions crates/semantics/src/expression/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ use super::{
};

/// Resolve multiplication.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_multiply(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -86,6 +90,10 @@ pub fn resolve_multiply(
}

/// Resolve division.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_division(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -146,6 +154,10 @@ pub fn resolve_division(
}

/// Resolve modulo.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_modulo(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -206,6 +218,10 @@ pub fn resolve_modulo(
}

/// Resolve addition.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_addition(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -271,6 +287,10 @@ pub fn resolve_addition(
}

/// Resolve subtraction.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_subtraction(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -331,6 +351,10 @@ pub fn resolve_subtraction(
}

/// Resolve equality.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_equality(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -410,6 +434,10 @@ pub fn resolve_equality(
}

/// Resolve inequality.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_inequality(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -489,6 +517,10 @@ pub fn resolve_inequality(
}

/// Resolve greater comparison.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_greater(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -564,6 +596,10 @@ pub fn resolve_greater(
}

/// Resolve less comparison.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_less(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -639,6 +675,10 @@ pub fn resolve_less(
}

/// Resolve greater or equal comparison.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_greater_eq(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -714,6 +754,10 @@ pub fn resolve_greater_eq(
}

/// Resolve less or equal comparison.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_less_eq(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -789,6 +833,10 @@ pub fn resolve_less_eq(
}

/// Resolve boolean conjunction.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_and(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -859,6 +907,10 @@ pub fn resolve_and(
}

/// Resolve boolean disjunction.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_or(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
Expand Down Expand Up @@ -929,6 +981,10 @@ pub fn resolve_or(
}

/// Resolve boolean negation.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_not(
expr: &parsed_ast::Expression,
loc: Span,
Expand Down Expand Up @@ -993,6 +1049,83 @@ pub fn resolve_not(
}
}

/// Resolve list inclusion.
///
/// # Errors
/// - Expected type is different.
/// - One of expression can not be resolved to any of the allowed types.
pub fn resolve_in(
left: &parsed_ast::Expression,
right: &parsed_ast::Expression,
loc: Span,
scope: &mut Scope,
contract: &mut ContractDefinition,
expected_ty: ExpectedType,
) -> Result<Expression, ()> {
let allowed_tys = &[TypeVariant::Bool];
match &expected_ty {
ExpectedType::Concrete(ty) => {
match ty {
TypeVariant::Bool => {
let resolved_right =
expression(right, ExpectedType::Dynamic(vec![]), scope, contract)?;

let right_list_ty = match resolved_right.ty() {
TypeVariant::List(ty) => ty.as_ref(),
TypeVariant::Set(ty) => ty.as_ref(),
_ => {
contract.diagnostics.push(Report::type_error(
loc,
String::from("Expected list-like type."),
));
return Err(());
}
};
let resolved_left = expression(
left,
ExpectedType::Concrete(right_list_ty.clone()),
scope,
contract,
)?;

Ok(Expression::In(BinaryExpression {
loc,
left: Box::new(resolved_left),
right: Box::new(resolved_right),
ty: TypeVariant::Bool,
}))
}
a_ty => {
let expected: Vec<ExpectedType> = allowed_tys
.iter()
.map(|ty| ExpectedType::Concrete(ty.clone()))
.collect();
report_type_mismatch(expected.as_slice(), a_ty, &loc, contract);
Err(())
}
}
}
// we can only resolve to boolean value.
ExpectedType::Dynamic(_) => {
resolve_in(
left,
right,
loc,
scope,
contract,
ExpectedType::Concrete(TypeVariant::Bool),
)
}
ExpectedType::Empty => {
contract.diagnostics.push(Report::semantic_error(
loc.clone(),
String::from("`Or` operation can only be used in expression."),
));
Err(())
}
}
}

/// Find a valid concrete type from the list of allowed types.
/// - If suggested types are empty, we resolve the type from the left hand expression.
/// - Otherwise, we check every possible allowed type and filter out the ones to which the
Expand Down

0 comments on commit 9f819ba

Please sign in to comment.