Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for structs #203

Merged
merged 3 commits into from
Feb 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
toolchain: nightly-2021-01-30
override: true
- name: coverage with tarpaulin
run: |
Expand Down Expand Up @@ -66,7 +66,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
toolchain: nightly-2021-01-30
override: true
components: rustfmt, clippy
- name: Validate release notes entry
Expand Down Expand Up @@ -116,7 +116,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
toolchain: nightly-2021-01-30
override: true
- name: Build
run: cargo build --all-features --verbose
Expand All @@ -132,7 +132,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
toolchain: nightly-2021-01-30
override: true
- name: Run WASM tests
run: wasm-pack test --node -- --workspace
Expand Down Expand Up @@ -167,7 +167,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
toolchain: nightly-2021-01-30
override: true
- name: Build
run: cargo build --all-features --release && strip target/release/fe && mv target/release/fe target/release/${{ matrix.BIN_FILE }}
Expand Down
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