Skip to content

Commit

Permalink
resolve fields
Browse files Browse the repository at this point in the history
  • Loading branch information
SkymanOne committed Feb 24, 2024
1 parent de0d0c4 commit 348e1a4
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 21 deletions.
14 changes: 0 additions & 14 deletions crates/semantics/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,6 @@ impl Type {
set
}
TypeVariant::Struct(s) => HashSet::from([s.i]),
TypeVariant::Model(s) => {
contract.diagnostics.push(Report::semantic_error(
s.loc.clone(),
String::from("Cannot use model as a type here,"),
));
HashSet::new()
}
TypeVariant::State(s) => {
contract.diagnostics.push(Report::semantic_error(
s.loc.clone(),
String::from("Cannot use state as a type here,"),
));
HashSet::new()
}
_ => HashSet::new(),
}
}
Expand Down
10 changes: 7 additions & 3 deletions crates/semantics/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::ast::{
};
use crate::decls::DelayedDeclaration;
use crate::global_symbol::SymbolInfo;
use crate::types::map_type;
use crate::types::{find_user_type_recursion, map_type, validate_fields};
use crate::{decls::DelayedDeclarations, global_symbol::GlobalSymbol};

/// Arbitrary limit of a max number of topic.
Expand Down Expand Up @@ -73,6 +73,9 @@ impl ContractDefinition {
}

/// Resolves fields during the second pass.
/// - Discover fields for structs, models, and states.
/// - Detect any cycles and report them.
/// - Ensure that no fields have types of any state or model.
pub fn resolve_fields(&mut self, delay: &DelayedDeclarations) {
// Update fields of the models and structs together.
for (s, m) in delay.structs.iter().zip(delay.models.iter()) {
Expand Down Expand Up @@ -115,8 +118,9 @@ impl ContractDefinition {

self.states[state.i].body = body;
}
// todo: check for cycles.
// todo: check for valid types.

find_user_type_recursion(self);
validate_fields(self);
}

/// Resolve fields of declarations.
Expand Down
1 change: 1 addition & 0 deletions crates/semantics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod tests;
pub fn resolve_semantics(source: &Source) -> ContractDefinition {
let mut definition = ContractDefinition::default();
let delay = definition.resolve_declarations(source);
definition.resolve_fields(&delay);

definition
}
42 changes: 38 additions & 4 deletions crates/semantics/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashSet;

use crate::ast::{List, Mapping, Param, Set, Type, TypeVariant};
use crate::ast::{List, Mapping, Param, Set, StateBody, Type, TypeVariant};
use crate::contract::ContractDefinition;
use crate::global_symbol::{GlobalSymbol, SymbolInfo};
use folidity_diagnostics::Report;
Expand Down Expand Up @@ -81,7 +81,7 @@ pub fn map_type(contract: &mut ContractDefinition, ty: &parsed_ast::Type) -> Res
/// Licensed as Apache 2.0
//todo: rewrite.
//TODO: support finite size recursive types.
pub fn find_user_type_recursion(contract: &mut ContractDefinition) -> Result<(), Span> {
pub fn find_user_type_recursion(contract: &mut ContractDefinition) {
let mut edges = HashSet::new();
for n in 0..contract.structs.len() {
collect_edges(
Expand Down Expand Up @@ -111,8 +111,6 @@ pub fn find_user_type_recursion(contract: &mut ContractDefinition) -> Result<(),
));
}
}

Ok(())
}

/// Collect field dependencies into the graph edges.
Expand Down Expand Up @@ -145,3 +143,39 @@ fn check_for_recursive_types(node: usize, graph: &FieldGraph, contract: &mut Con
}
}
}

pub fn validate_fields(contract: &mut ContractDefinition) {
let mut validate = |fields: &[Param]| {
for field in fields.iter() {
match &field.ty.ty {
TypeVariant::Function(_) => contract.diagnostics.push(Report::semantic_error(
field.loc.clone(),
String::from("Function cannot be used as a field type."),
)),
TypeVariant::Model(_) => contract.diagnostics.push(Report::semantic_error(
field.loc.clone(),
String::from("Model cannot be used as a field type."),
)),
TypeVariant::State(_) => contract.diagnostics.push(Report::semantic_error(
field.loc.clone(),
String::from("State cannot be used as a field type."),
)),
_ => {}
}
}
};

for s in &contract.structs {
validate(&s.fields);
}

for s in &contract.states {
if let Some(StateBody::Raw(fields)) = &s.body {
validate(fields);
}
}

for m in &contract.models {
validate(&m.fields);
}
}

0 comments on commit 348e1a4

Please sign in to comment.