Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
cburgdorf committed Jan 3, 2022
1 parent a07d9a9 commit ee5969a
Show file tree
Hide file tree
Showing 20 changed files with 116 additions and 49 deletions.
5 changes: 1 addition & 4 deletions crates/analyzer/src/db/queries/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,13 @@ pub fn struct_field_type(
let mut scope = ItemScope::new(db, field_data.parent.module(db));

let ast::Field {
is_pub,
is_pub: _,
is_const,
name: _,
typ,
value,
} = &field_data.ast.kind;

if *is_pub {
scope.not_yet_implemented("struct `pub` fields", field_data.ast.span);
}
if *is_const {
scope.not_yet_implemented("struct `const` fields", field_data.ast.span);
}
Expand Down
4 changes: 4 additions & 0 deletions crates/analyzer/src/namespace/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,10 @@ impl StructFieldId {
pub fn typ(&self, db: &dyn AnalyzerDb) -> Result<types::FixedSize, TypeError> {
db.struct_field_type(*self).value
}
pub fn is_public (&self, db: &dyn AnalyzerDb) -> bool {
self.data(db).ast.kind.is_pub
}

pub fn sink_diagnostics(&self, db: &dyn AnalyzerDb, sink: &mut impl DiagnosticSink) {
db.struct_field_type(*self).sink_diagnostics(sink)
}
Expand Down
5 changes: 5 additions & 0 deletions crates/analyzer/src/namespace/scopes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,11 @@ impl<'a, 'b> BlockScope<'a, 'b> {
pub fn inherits_type(&self, typ: BlockScopeType) -> bool {
self.typ == typ || self.parent.map_or(false, |scope| scope.inherits_type(typ))
}

/// Return the item that that the block scope belongs to
pub fn root_item(&self) -> Item {
self.root.function.parent(self.db())
}
}

/// temporary helper until `BTreeMap::try_insert` is stabilized
Expand Down
25 changes: 19 additions & 6 deletions crates/analyzer/src/traversal/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::builtins::{
};
use crate::context::{AnalyzerContext, CallType, ExpressionAttributes, Location, NamedThing};
use crate::errors::{FatalError, IndexingError, NotFixedSize};
use crate::namespace::items::{Class, FunctionId, Item};
use crate::namespace::items::{Class, FunctionId, Item, TypeDef};
use crate::namespace::scopes::{BlockScope, BlockScopeType};
use crate::namespace::types::{
Array, Base, Contract, FeString, Integer, Struct, Tuple, Type, TypeDowncast, U256,
Expand Down Expand Up @@ -515,6 +515,7 @@ fn expr_attribute(
fe::Expr::Attribute { value, attr } => (value, attr),
_ => unreachable!(),
};

let base_type = |typ| Ok(ExpressionAttributes::new(Type::Base(typ), Location::Value));

// We have to check if its a global object first, because the global
Expand Down Expand Up @@ -620,11 +621,23 @@ fn expr_attribute(
// If the value is a struct, we return the type of the struct field. The location stays the
// same and can be memory or storage.
Type::Struct(struct_) => {
if let Some(field) = struct_.id.field(scope.db(), &field.kind) {
Ok(ExpressionAttributes::new(
field.typ(scope.db())?.into(),
attrs.location,
))
let function_item = scope.root_item();
if let Some(struct_field) = struct_.id.field(scope.db(), &field.kind) {
if !matches!(function_item, Item::Type(TypeDef::Struct(_))) && !struct_field.is_public(scope.db()) {
Err(FatalError::new(scope.fancy_error(
&format!(
"Can not access private field `{}` on struct `{}`",
&field.kind, struct_.name
),
vec![Label::primary(field.span, "private field")],
vec![],
)))
} else {
Ok(ExpressionAttributes::new(
struct_field.typ(scope.db())?.into(),
attrs.location,
))
}
} else {
Err(FatalError::new(scope.fancy_error(
&format!(
Expand Down
2 changes: 2 additions & 0 deletions crates/analyzer/tests/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ test_file! { needs_mem_copy }
test_file! { not_callable }
test_file! { not_in_scope }
test_file! { not_in_scope_2 }
test_file! { private_struct_field }
test_file! { return_addition_with_mixed_types }
test_file! { return_call_to_fn_with_param_type_mismatch }
test_file! { return_call_to_fn_without_return }
Expand All @@ -323,6 +324,7 @@ test_file! { return_type_not_fixedsize }
test_file! { undefined_type_param }

test_file! { strict_boolean_if_else }
test_file! { struct_private_constructor }
test_file! { struct_call_bad_args }
test_file! { struct_call_without_kw_args }
test_file! { non_pub_init }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ expression: "build_snapshot(&files, module_id, &db)"
note:
┌─ stress/abi_encoding_stress.fe:2:5
2my_num: u256
^^^^^^^^^^^^ u256
3my_num2: u8
^^^^^^^^^^^ u8
4my_bool: bool
^^^^^^^^^^^^^ bool
5my_addr: address
^^^^^^^^^^^^^^^^ address
2pub my_num: u256
^^^^^^^^^^^^^^^^ u256
3pub my_num2: u8
^^^^^^^^^^^^^^^ u8
4pub my_bool: bool
^^^^^^^^^^^^^^^^^ bool
5pub my_addr: address
^^^^^^^^^^^^^^^^^^^^ address

note:
┌─ stress/abi_encoding_stress.fe:8:5
Expand Down
6 changes: 3 additions & 3 deletions crates/analyzer/tests/snapshots/analysis__associated_fns.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source: crates/analyzer/tests/analysis.rs
expression: "build_snapshot(\"features/associated_fns.fe\", &src, module, &db)"
expression: "build_snapshot(&files, module_id, &db)"

---
note:
Expand Down Expand Up @@ -50,8 +50,8 @@ note:
note:
┌─ features/associated_fns.fe:7:3
7x: u256
^^^^^^^ u256
7pub x: u256
^^^^^^^^^^^ u256

note:
┌─ features/associated_fns.fe:8:3
Expand Down
10 changes: 5 additions & 5 deletions crates/analyzer/tests/snapshots/analysis__struct_fns.snap
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
source: crates/analyzer/tests/analysis.rs
expression: "build_snapshot(&files, module, &db)"
expression: "build_snapshot(&files, module_id, &db)"

---
note:
┌─ features/struct_fns.fe:2:3
2x: u64
^^^^^^ u64
3y: u64
^^^^^^ u64
2pub x: u64
^^^^^^^^^^ u64
3pub y: u64
^^^^^^^^^^ u64

note:
┌─ features/struct_fns.fe:5:3
Expand Down
16 changes: 8 additions & 8 deletions crates/analyzer/tests/snapshots/analysis__structs.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ expression: "build_snapshot(&files, module_id, &db)"
note:
┌─ features/structs.fe:2:5
2price: u256
^^^^^^^^^^^ u256
3size: u256
^^^^^^^^^^ u256
4rooms: u8
^^^^^^^^^ u8
5vacant: bool
^^^^^^^^^^^^ bool
2pub price: u256
^^^^^^^^^^^^^^^ u256
3pub size: u256
^^^^^^^^^^^^^^ u256
4pub rooms: u8
^^^^^^^^^^^^^ u8
5pub vacant: bool
^^^^^^^^^^^^^^^^ bool

note:
┌─ features/structs.fe:7:5
Expand Down
12 changes: 12 additions & 0 deletions crates/analyzer/tests/snapshots/errors__private_struct_field.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
source: crates/analyzer/tests/errors.rs
expression: "error_string(&path, &src)"

---
error: Can not access private field `id` on struct `Bar`
┌─ compile_errors/private_struct_field.fe:8:14
8self.val.id
^^ private field


6 changes: 6 additions & 0 deletions crates/analyzer/tests/snapshots/errors__self_misuse.snap
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ error: `self` can only be used in contract or struct functions
3self = 5
^^^^ not allowed in functions defined outside of a contract or struct

error: Can not access private field `x` on struct `S`
┌─ compile_errors/self_misuse.fe:6:5
6s.x = 100
^ private field

error: `self` is not callable
┌─ compile_errors/self_misuse.fe:15:5
Expand Down
12 changes: 12 additions & 0 deletions crates/analyzer/tests/snapshots/errors__struct_private_fields.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
source: crates/analyzer/tests/errors.rs
expression: "error_string(&path, &src)"

---
error: feature not yet implemented: struct `pub` fields
┌─ compile_errors/struct_private_fields.fe:3:5
3pub price: u256
^^^^^^^^^^^^^^^ not yet implemented


Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ expression: "error_string(&path, &src)"

---
error: undefined type
┌─ compile_errors/undefined_type_param.fe:4:8
┌─ compile_errors/undefined_type_param.fe:4:12
4x: MysteryType
^^^^^^^^^^^ `MysteryType` has not been defined
4pub x: MysteryType
^^^^^^^^^^^ `MysteryType` has not been defined

error: undefined type
┌─ compile_errors/undefined_type_param.fe:8:19
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
struct Bar:
id: u256

contract Foo:
val: Bar

pub fn foo(self):
self.val.id
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
struct House:
vacant: bool
pub price: u256

contract Foo:

pub fn bar():
let my_house: House = House(vacant=true, price=1000000)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# https://github.com/ethereum/fe/issues/530

struct BadField:
x: MysteryType
pub x: MysteryType

contract Foo:
# case 1: using arg with undefined type within the fn body
Expand Down
2 changes: 1 addition & 1 deletion crates/test-files/fixtures/features/associated_fns.fe
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ struct Lib: # This can't be a contract, yet
return x * x

struct MyStruct:
x: u256
pub x: u256
pub fn new(x: u256) -> MyStruct:
return MyStruct(x)

Expand Down
4 changes: 2 additions & 2 deletions crates/test-files/fixtures/features/struct_fns.fe
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
struct Point:
x: u64
y: u64
pub x: u64
pub y: u64

pub fn new(x: u64, y: u64) -> Point:
return Point(x, y)
Expand Down
8 changes: 4 additions & 4 deletions crates/test-files/fixtures/features/structs.fe
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
struct House:
price: u256
size: u256
rooms: u8
vacant: bool
pub price: u256
pub size: u256
pub rooms: u8
pub vacant: bool

pub fn encode(self) -> Array<u8, 128>:
return self.abi_encode()
Expand Down
8 changes: 4 additions & 4 deletions crates/test-files/fixtures/stress/abi_encoding_stress.fe
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
struct MyStruct:
my_num: u256
my_num2: u8
my_bool: bool
my_addr: address
pub my_num: u256
pub my_num2: u8
pub my_bool: bool
pub my_addr: address

contract Foo:
my_addrs: Array<address, 5>
Expand Down

0 comments on commit ee5969a

Please sign in to comment.