Skip to content

Commit 16ada2a

Browse files
committed
Contract type and external calls.
1 parent c665b27 commit 16ada2a

22 files changed

Lines changed: 542 additions & 93 deletions

File tree

analyzer/src/lib.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::namespace::scopes::{
1717
Shared,
1818
};
1919
use crate::namespace::types::{
20+
Contract,
2021
FixedSize,
2122
Type,
2223
};
@@ -25,10 +26,7 @@ use fe_parser::span::{
2526
Span,
2627
Spanned,
2728
};
28-
use std::cell::{
29-
Ref,
30-
RefCell,
31-
};
29+
use std::cell::RefCell;
3230
use std::collections::{
3331
HashMap,
3432
HashSet,
@@ -53,6 +51,7 @@ impl Location {
5351
pub fn assign_location(typ: Type) -> Result<Self, SemanticError> {
5452
match typ {
5553
Type::Base(_) => Ok(Location::Value),
54+
Type::Contract(_) => Ok(Location::Value),
5655
Type::Array(_) => Ok(Location::Memory),
5756
Type::Tuple(_) => Ok(Location::Memory),
5857
Type::String(_) => Ok(Location::Memory),
@@ -72,14 +71,16 @@ pub struct ContractAttributes {
7271
pub events: Vec<Event>,
7372
/// Static strings that the contract defines
7473
pub string_literals: HashSet<String>,
74+
/// External contracts that may be called from within this contract.
75+
pub external_contracts: Vec<Contract>,
7576
}
7677

77-
impl From<Ref<'_, ContractScope>> for ContractAttributes {
78-
fn from(scope: Ref<'_, ContractScope>) -> Self {
78+
impl From<Shared<ContractScope>> for ContractAttributes {
79+
fn from(scope: Shared<ContractScope>) -> Self {
7980
let mut public_functions = vec![];
8081
let mut init_function = None;
8182

82-
for (name, def) in scope.function_defs.iter() {
83+
for (name, def) in scope.borrow().function_defs.iter() {
8384
if !def.is_public {
8485
continue;
8586
}
@@ -99,15 +100,32 @@ impl From<Ref<'_, ContractScope>> for ContractAttributes {
99100
}
100101
}
101102

103+
let external_contracts = scope
104+
.borrow()
105+
.module_scope()
106+
.borrow()
107+
.type_defs
108+
.values()
109+
.filter_map(|typ| {
110+
if let Type::Contract(contract) = typ {
111+
Some(contract.to_owned())
112+
} else {
113+
None
114+
}
115+
})
116+
.collect();
117+
102118
ContractAttributes {
103119
public_functions,
104120
init_function,
105121
events: scope
122+
.borrow()
106123
.event_defs
107124
.values()
108125
.map(|event| event.to_owned())
109126
.collect::<Vec<Event>>(),
110-
string_literals: scope.string_defs.clone(),
127+
string_literals: scope.borrow().string_defs.clone(),
128+
external_contracts,
111129
}
112130
}
113131
}
@@ -153,6 +171,7 @@ impl ExpressionAttributes {
153171
pub fn into_loaded(mut self) -> Result<Self, SemanticError> {
154172
match self.typ {
155173
Type::Base(_) => {}
174+
Type::Contract(_) => {}
156175
_ => return Err(SemanticError::cannot_move()),
157176
}
158177

@@ -200,7 +219,7 @@ pub enum CallType {
200219
}
201220

202221
/// Contains contextual information relating to a function definition AST node.
203-
#[derive(Clone, Debug, PartialEq)]
222+
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
204223
pub struct FunctionAttributes {
205224
pub name: String,
206225
pub param_types: Vec<FixedSize>,

analyzer/src/namespace/operations.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub fn index(value: Type, index: Type) -> Result<Type, SemanticError> {
1616
Type::Base(_) => Err(SemanticError::not_subscriptable()),
1717
Type::Tuple(_) => Err(SemanticError::not_subscriptable()),
1818
Type::String(_) => Err(SemanticError::not_subscriptable()),
19+
Type::Contract(_) => Err(SemanticError::not_subscriptable()),
1920
}
2021
}
2122

analyzer/src/namespace/scopes.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ impl ContractScope {
106106
}))
107107
}
108108

109+
/// Return the module scope that the contract scope inherits from
110+
pub fn module_scope(&self) -> Shared<ModuleScope> {
111+
Rc::clone(&self.parent)
112+
}
113+
109114
/// Lookup contract event definition by its name.
110115
pub fn event_def(&self, name: String) -> Option<Event> {
111116
self.event_defs.get(&name).map(|def| (*def).clone())

analyzer/src/namespace/types.rs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ use std::num::{
77
ParseIntError,
88
};
99

10+
use crate::FunctionAttributes;
1011
use num_bigint::BigInt;
1112

13+
const ADDRESS_BYTE_LENGTH: usize = 20;
14+
1215
pub fn u256_max() -> BigInt {
1316
BigInt::from(2).pow(256) - 1
1417
}
@@ -99,6 +102,7 @@ pub enum Type {
99102
Map(Map),
100103
Tuple(Tuple),
101104
String(FeString),
105+
Contract(Contract),
102106
}
103107

104108
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
@@ -107,6 +111,7 @@ pub enum FixedSize {
107111
Array(Array),
108112
Tuple(Tuple),
109113
String(FeString),
114+
Contract(Contract),
110115
}
111116

112117
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
@@ -157,6 +162,12 @@ pub struct FeString {
157162
pub max_size: usize,
158163
}
159164

165+
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
166+
pub struct Contract {
167+
pub name: String,
168+
pub functions: Vec<FunctionAttributes>,
169+
}
170+
160171
impl TryFrom<&str> for FeString {
161172
type Error = String;
162173

@@ -246,6 +257,7 @@ impl From<FixedSize> for Type {
246257
FixedSize::Base(base) => Type::Base(base),
247258
FixedSize::Tuple(tuple) => Type::Tuple(tuple),
248259
FixedSize::String(string) => Type::String(string),
260+
FixedSize::Contract(contract) => Type::Contract(contract),
249261
}
250262
}
251263
}
@@ -257,6 +269,7 @@ impl FeSized for FixedSize {
257269
FixedSize::Array(array) => array.size(),
258270
FixedSize::Tuple(tuple) => tuple.size(),
259271
FixedSize::String(string) => string.size(),
272+
FixedSize::Contract(contract) => contract.size(),
260273
}
261274
}
262275
}
@@ -287,6 +300,7 @@ impl AbiEncoding for FixedSize {
287300
FixedSize::Base(base) => base.abi_name(),
288301
FixedSize::Tuple(tuple) => tuple.abi_name(),
289302
FixedSize::String(string) => string.abi_name(),
303+
FixedSize::Contract(contract) => contract.abi_name(),
290304
}
291305
}
292306

@@ -296,6 +310,7 @@ impl AbiEncoding for FixedSize {
296310
FixedSize::Base(base) => base.abi_safe_name(),
297311
FixedSize::Tuple(tuple) => tuple.abi_safe_name(),
298312
FixedSize::String(string) => string.abi_safe_name(),
313+
FixedSize::Contract(contract) => contract.abi_safe_name(),
299314
}
300315
}
301316

@@ -305,6 +320,7 @@ impl AbiEncoding for FixedSize {
305320
FixedSize::Array(array) => array.abi_type(),
306321
FixedSize::Tuple(tuple) => tuple.abi_type(),
307322
FixedSize::String(string) => string.abi_type(),
323+
FixedSize::Contract(contract) => contract.abi_type(),
308324
}
309325
}
310326
}
@@ -333,6 +349,7 @@ impl TryFrom<Type> for FixedSize {
333349
Type::Tuple(tuple) => Ok(FixedSize::Tuple(tuple)),
334350
Type::String(string) => Ok(FixedSize::String(string)),
335351
Type::Map(_) => Err(SemanticError::type_error()),
352+
Type::Contract(contract) => Ok(FixedSize::Contract(contract)),
336353
}
337354
}
338355
}
@@ -343,7 +360,7 @@ impl FeSized for Base {
343360
Base::Numeric(integer) => integer.size(),
344361
Base::Bool => 1,
345362
Base::Byte => 1,
346-
Base::Address => 20,
363+
Base::Address => ADDRESS_BYTE_LENGTH,
347364
}
348365
}
349366
}
@@ -457,7 +474,7 @@ impl AbiEncoding for Base {
457474
},
458475
Base::Address => AbiType::Uint {
459476
size: AbiUintSize {
460-
data_size: 20,
477+
data_size: ADDRESS_BYTE_LENGTH,
461478
padded_size: 32,
462479
},
463480
},
@@ -568,17 +585,31 @@ impl AbiEncoding for FeString {
568585
}
569586
}
570587

588+
impl FeSized for Contract {
589+
fn size(&self) -> usize {
590+
ADDRESS_BYTE_LENGTH
591+
}
592+
}
593+
594+
impl AbiEncoding for Contract {
595+
fn abi_name(&self) -> String {
596+
unimplemented!();
597+
}
598+
599+
fn abi_safe_name(&self) -> String {
600+
unimplemented!();
601+
}
602+
603+
fn abi_type(&self) -> AbiType {
604+
unimplemented!();
605+
}
606+
}
607+
571608
pub fn type_desc_fixed_size(
572609
defs: &HashMap<String, Type>,
573610
typ: &fe::TypeDesc,
574611
) -> Result<FixedSize, SemanticError> {
575-
match type_desc(defs, typ)? {
576-
Type::Base(base) => Ok(FixedSize::Base(base)),
577-
Type::Array(array) => Ok(FixedSize::Array(array)),
578-
Type::Tuple(tuple) => Ok(FixedSize::Tuple(tuple)),
579-
Type::String(string) => Ok(FixedSize::String(string)),
580-
Type::Map(_) => Err(SemanticError::type_error()),
581-
}
612+
FixedSize::try_from(type_desc(defs, typ)?)
582613
}
583614

584615
pub fn type_desc_base(

analyzer/src/traversal/contracts.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,19 @@ use crate::namespace::scopes::{
66
Scope,
77
Shared,
88
};
9-
use crate::namespace::types::FixedSize;
9+
use crate::namespace::types::{
10+
Contract,
11+
FixedSize,
12+
Type,
13+
};
1014
use crate::traversal::{
1115
functions,
1216
types,
1317
};
14-
use crate::Context;
18+
use crate::{
19+
Context,
20+
ContractAttributes,
21+
};
1522
use fe_parser::ast as fe;
1623
use fe_parser::span::Spanned;
1724
use std::rc::Rc;
@@ -23,8 +30,8 @@ pub fn contract_def(
2330
context: Shared<Context>,
2431
stmt: &Spanned<fe::ModuleStmt>,
2532
) -> Result<(), SemanticError> {
26-
if let fe::ModuleStmt::ContractDef { name: _, body } = &stmt.node {
27-
let contract_scope = ContractScope::new(module_scope);
33+
if let fe::ModuleStmt::ContractDef { name, body } = &stmt.node {
34+
let contract_scope = ContractScope::new(Rc::clone(&module_scope));
2835

2936
for stmt in body.iter() {
3037
match &stmt.node {
@@ -46,9 +53,21 @@ pub fn contract_def(
4653
};
4754
}
4855

49-
context
56+
let contract_attributes = ContractAttributes::from(Rc::clone(&contract_scope));
57+
58+
contract_scope
59+
.borrow()
60+
.module_scope()
5061
.borrow_mut()
51-
.add_contract(stmt, contract_scope.borrow().into());
62+
.add_type_def(
63+
name.node.to_string(),
64+
Type::Contract(Contract {
65+
name: name.node.to_string(),
66+
functions: contract_attributes.public_functions.clone(),
67+
}),
68+
);
69+
70+
context.borrow_mut().add_contract(stmt, contract_attributes);
5271

5372
return Ok(());
5473
}

analyzer/src/traversal/declarations.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ pub fn var_decl(
2525
let declared_type = types::type_desc_fixed_size(Scope::Block(Rc::clone(&scope)), typ)?;
2626
if let Some(value) = value {
2727
let value_attributes =
28-
expressions::expr(Rc::clone(&scope), Rc::clone(&context), value)?;
28+
expressions::assignable_expr(Rc::clone(&scope), Rc::clone(&context), value)?;
29+
2930
if Type::from(declared_type.clone()) != value_attributes.typ {
3031
return Err(SemanticError::type_error());
3132
}

0 commit comments

Comments
 (0)