Skip to content

Commit

Permalink
Add basic support for structs
Browse files Browse the repository at this point in the history
  • Loading branch information
cburgdorf committed Feb 8, 2021
1 parent 013787a commit 68a4024
Show file tree
Hide file tree
Showing 21 changed files with 494 additions and 28 deletions.
21 changes: 15 additions & 6 deletions analyzer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::namespace::scopes::{
use crate::namespace::types::{
Contract,
FixedSize,
Struct,
Type,
};
use fe_parser::ast as fe;
Expand Down Expand Up @@ -55,6 +56,7 @@ impl Location {
Type::Array(_) => Ok(Location::Memory),
Type::Tuple(_) => Ok(Location::Memory),
Type::String(_) => Ok(Location::Memory),
Type::Struct(_) => Ok(Location::Memory),
Type::Map(_) => Err(SemanticError::cannot_move()),
}
}
Expand All @@ -71,6 +73,8 @@ pub struct ContractAttributes {
pub events: Vec<Event>,
/// Static strings that the contract defines
pub string_literals: HashSet<String>,
/// Structs that have been defined by the user
pub structs: Vec<Struct>,
/// External contracts that may be called from within this contract.
pub external_contracts: Vec<Contract>,
}
Expand Down Expand Up @@ -108,6 +112,14 @@ impl From<Shared<ContractScope>> for ContractAttributes {
}
});

let structs = scope.borrow().get_module_type_defs(|typ| {
if let Type::Struct(val) = typ {
Some(val.to_owned())
} else {
None
}
});

ContractAttributes {
public_functions,
init_function,
Expand All @@ -118,6 +130,7 @@ impl From<Shared<ContractScope>> for ContractAttributes {
.map(|event| event.to_owned())
.collect::<Vec<Event>>(),
string_literals: scope.borrow().string_defs.clone(),
structs,
external_contracts,
}
}
Expand Down Expand Up @@ -248,12 +261,8 @@ impl Context {
}

/// Attribute contextual information to an expression node.
pub fn add_expression(
&mut self,
spanned: &Spanned<fe::Expr>,
attributes: ExpressionAttributes,
) {
self.expressions.insert(spanned.span, attributes);
pub fn add_expression<T: Into<Span>>(&mut self, span: T, attributes: ExpressionAttributes) {
self.expressions.insert(span.into(), attributes);
}

/// Get information that has been attributed to an expression node.
Expand Down
1 change: 1 addition & 0 deletions analyzer/src/namespace/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub fn index(value: Type, index: Type) -> Result<Type, SemanticError> {
Type::Tuple(_) => Err(SemanticError::not_subscriptable()),
Type::String(_) => Err(SemanticError::not_subscriptable()),
Type::Contract(_) => Err(SemanticError::not_subscriptable()),
Type::Struct(_) => Err(SemanticError::not_subscriptable()),
}
}

Expand Down
79 changes: 78 additions & 1 deletion analyzer/src/namespace/types.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::errors::SemanticError;
use fe_parser::ast as fe;
use std::collections::HashMap;
use std::collections::{
BTreeMap,
HashMap,
};
use std::convert::TryFrom;
use std::num::{
IntErrorKind,
Expand Down Expand Up @@ -103,6 +106,7 @@ pub enum Type {
Tuple(Tuple),
String(FeString),
Contract(Contract),
Struct(Struct),
}

#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
Expand All @@ -112,6 +116,7 @@ pub enum FixedSize {
Tuple(Tuple),
String(FeString),
Contract(Contract),
Struct(Struct),
}

#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
Expand Down Expand Up @@ -157,6 +162,12 @@ pub struct Tuple {
pub items: Vec<Base>,
}

#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
pub struct Struct {
pub name: String,
fields: BTreeMap<String, Base>,
}

#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
pub struct FeString {
pub max_size: usize,
Expand All @@ -168,6 +179,40 @@ pub struct Contract {
pub functions: Vec<FunctionAttributes>,
}

impl Struct {
pub fn new(name: &str) -> Struct {
Struct {
name: name.to_string(),
fields: BTreeMap::new(),
}
}

// Return `true` if the struct has any fields, otherwise return `false`
pub fn is_empty(&self) -> bool {
self.fields.is_empty()
}

/// Add a field to the struct
pub fn add_field(&mut self, name: &str, value: &Base) -> Option<Base> {
self.fields.insert(name.to_string(), value.clone())
}

// Return the type of the given field name
pub fn get_field_type(&self, name: &str) -> Option<&Base> {
self.fields.get(name)
}

// Return a vector of field types
pub fn get_field_types(&self) -> Vec<Type> {
self.fields.values().map(|val| val.clone().into()).collect()
}

//Return a vector of field names
pub fn get_field_names(&self) -> Vec<String> {
self.fields.keys().cloned().collect()
}
}

impl TryFrom<&str> for FeString {
type Error = String;

Expand Down Expand Up @@ -258,10 +303,17 @@ impl From<FixedSize> for Type {
FixedSize::Tuple(tuple) => Type::Tuple(tuple),
FixedSize::String(string) => Type::String(string),
FixedSize::Contract(contract) => Type::Contract(contract),
FixedSize::Struct(val) => Type::Struct(val),
}
}
}

impl From<Base> for Type {
fn from(value: Base) -> Self {
Type::Base(value)
}
}

impl FeSized for FixedSize {
fn size(&self) -> usize {
match self {
Expand All @@ -270,6 +322,7 @@ impl FeSized for FixedSize {
FixedSize::Tuple(tuple) => tuple.size(),
FixedSize::String(string) => string.size(),
FixedSize::Contract(contract) => contract.size(),
FixedSize::Struct(val) => val.size(),
}
}
}
Expand Down Expand Up @@ -301,6 +354,7 @@ impl AbiEncoding for FixedSize {
FixedSize::Tuple(tuple) => tuple.abi_name(),
FixedSize::String(string) => string.abi_name(),
FixedSize::Contract(contract) => contract.abi_name(),
FixedSize::Struct(val) => val.abi_name(),
}
}

Expand All @@ -311,6 +365,7 @@ impl AbiEncoding for FixedSize {
FixedSize::Tuple(tuple) => tuple.abi_safe_name(),
FixedSize::String(string) => string.abi_safe_name(),
FixedSize::Contract(contract) => contract.abi_safe_name(),
FixedSize::Struct(val) => val.abi_safe_name(),
}
}

Expand All @@ -321,6 +376,7 @@ impl AbiEncoding for FixedSize {
FixedSize::Tuple(tuple) => tuple.abi_type(),
FixedSize::String(string) => string.abi_type(),
FixedSize::Contract(contract) => contract.abi_type(),
FixedSize::Struct(val) => val.abi_type(),
}
}
}
Expand Down Expand Up @@ -348,6 +404,7 @@ impl TryFrom<Type> for FixedSize {
Type::Base(base) => Ok(FixedSize::Base(base)),
Type::Tuple(tuple) => Ok(FixedSize::Tuple(tuple)),
Type::String(string) => Ok(FixedSize::String(string)),
Type::Struct(val) => Ok(FixedSize::Struct(val)),
Type::Map(_) => Err(SemanticError::type_error()),
Type::Contract(contract) => Ok(FixedSize::Contract(contract)),
}
Expand Down Expand Up @@ -543,6 +600,26 @@ impl FeSized for Tuple {
}
}

impl FeSized for Struct {
fn size(&self) -> usize {
self.fields.len() * 32
}
}

impl AbiEncoding for Struct {
fn abi_name(&self) -> String {
unimplemented!();
}

fn abi_safe_name(&self) -> String {
unimplemented!();
}

fn abi_type(&self) -> AbiType {
unimplemented!();
}
}

impl AbiEncoding for Tuple {
fn abi_name(&self) -> String {
unimplemented!();
Expand Down
Loading

0 comments on commit 68a4024

Please sign in to comment.