Skip to content

Commit

Permalink
Ensure contract pure fns can be called via ContractName::fn_name()
Browse files Browse the repository at this point in the history
  • Loading branch information
cburgdorf committed Jul 11, 2022
1 parent 5a15ef4 commit 31869ef
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 17 deletions.
52 changes: 37 additions & 15 deletions crates/analyzer/src/namespace/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,26 +814,17 @@ pub enum TypeDef {
Contract(ContractId),
Primitive(types::Base),
}

impl TypeDef {
pub fn items(&self, db: &dyn AnalyzerDb) -> Rc<IndexMap<SmolStr, Item>> {
match self {
TypeDef::Struct(val) => {
Rc::new(
val.functions(db)
.iter()
.filter_map(|(name, field)| {
if field.takes_self(db) {
// In the future we probably want to resolve instance methods as well. But this would require
// the caller to pass an instance as the first argument e.g. `Rectangle::can_hold(self_instance, other)`.
// This isn't yet supported so for now path access to functions is limited to static functions only.
None
} else {
Some((name.to_owned(), Item::Function(*field)))
}
})
.collect(),
)
// In the future we probably want to resolve instance methods as well. But this would require
// the caller to pass an instance as the first argument e.g. `Rectangle::can_hold(self_instance, other)`.
// This isn't yet supported so for now path access to functions is limited to static functions only.
val.pure_functions_as_items(db)
}
TypeDef::Contract(val) => val.pure_functions_as_items(db),
_ => todo!("cannot access items in types yet"),
}
}
Expand Down Expand Up @@ -1323,6 +1314,37 @@ impl FunctionId {
}
}

trait FunctionsAsItems {
fn functions(&self, db: &dyn AnalyzerDb) -> Rc<IndexMap<SmolStr, FunctionId>>;

fn pure_functions_as_items(&self, db: &dyn AnalyzerDb) -> Rc<IndexMap<SmolStr, Item>> {
Rc::new(
self.functions(db)
.iter()
.filter_map(|(name, field)| {
if field.takes_self(db) {
None
} else {
Some((name.to_owned(), Item::Function(*field)))
}
})
.collect(),
)
}
}

impl FunctionsAsItems for StructId {
fn functions(&self, db: &dyn AnalyzerDb) -> Rc<IndexMap<SmolStr, FunctionId>> {
self.functions(db)
}
}

impl FunctionsAsItems for ContractId {
fn functions(&self, db: &dyn AnalyzerDb) -> Rc<IndexMap<SmolStr, FunctionId>> {
self.functions(db)
}
}

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct Struct {
pub ast: Node<ast::Struct>,
Expand Down
3 changes: 2 additions & 1 deletion crates/analyzer/src/traversal/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1459,7 +1459,8 @@ fn expr_call_method(
// and the global objects are replaced by `Context`, we can remove this.
// All other `NamedThing`s will be handled correctly by `expr()`.
if let fe::Expr::Name(name) = &target.kind {
if let Ok(Some(NamedThing::Item(Item::Type(def)))) = context.resolve_name(name, target.span) {
if let Ok(Some(NamedThing::Item(Item::Type(def)))) = context.resolve_name(name, target.span)
{
let typ = def.typ(context.db())?;
return expr_call_type_attribute(context, typ, target.span, field, generic_args, args);
}
Expand Down
19 changes: 19 additions & 0 deletions crates/test-files/fixtures/features/contract_pure_fns.fe
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
contract Example {

pub fn run_test(self) {
assert self.bar(42, 26) == 68
assert self.bar2(42, 26) == 68
}

pub fn bar(self, _ x: u256, _ y: u256) -> u256 {
return pure_bar(x, y)
}

pub fn bar2(self, _ x: u256, _ y: u256) -> u256 {
return Example::pure_bar(x, y)
}

fn pure_bar(x: u256, y: u256) -> u256 {
return x + y
}
}
3 changes: 2 additions & 1 deletion crates/tests/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2070,7 +2070,8 @@ fn ctx_init_in_call() {
fixture_file,
case::simple_traits("simple_traits.fe"),
case::generic_functions("generic_functions.fe"),
case::generic_functions_primitves("generic_functions_primitves.fe")
case::generic_functions_primitves("generic_functions_primitves.fe"),
case::contract_pure_fns("contract_pure_fns.fe")
)]
fn execution_tests(fixture_file: &str) {
with_executor(&|mut executor| {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/tests/src/features.rs
expression: "format!(\"{}\", harness.gas_reporter)"

---
bar([]) used 102 gas

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/tests/src/features.rs
expression: "format!(\"{}\", harness.gas_reporter)"

---
bar([Uint(1234)]) used 45055 gas

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/tests/src/features.rs
expression: "format!(\"{}\", harness.gas_reporter)"

---
bar([]) used 311 gas

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/tests/src/features.rs
expression: "format!(\"{}\", harness.gas_reporter)"

---
bar([Uint(12)]) used 22698 gas

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/tests/src/features.rs
expression: "format!(\"{}\", harness.gas_reporter)"

---
bar([Uint(10), Uint(20)]) used 2082 gas

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/tests/src/features.rs
expression: "format!(\"{}\", harness.gas_reporter)"

---
bar([Address(0x2012301230123012301230123012301230123002)]) used 192 gas

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/tests/src/features.rs
expression: "format!(\"{}\", harness.gas_reporter)"

---
bar([Uint(42), Uint(26)]) used 202 gas

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: crates/tests/src/features.rs
expression: "format!(\"{}\", harness.gas_reporter)"

---
run_test([]) used 35 gas

0 comments on commit 31869ef

Please sign in to comment.