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

Remove event/emit and introduce ctx.emit that works with the Emittable trait #772

Merged
merged 6 commits into from
Sep 19, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,16 @@ Run `fe --help` to explore further options.
The following is a simple contract implemented in Fe.

```rust
struct Signed {
book_msg: String<100>
}

contract GuestBook {
messages: Map<address, String<100>>

event Signed {
book_msg: String<100>
}

pub fn sign(self, ctx: Context, book_msg: String<100>) {
self.messages[ctx.msg_sender()] = book_msg
emit Signed(ctx, book_msg: book_msg)
ctx.emit(Signed(book_msg: book_msg))
}

pub fn get_msg(self, addr: address) -> String<100> {
Expand Down
3 changes: 3 additions & 0 deletions crates/analyzer/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
pub const EMITTABLE_TRAIT_NAME: &str = "Emittable";
pub const EMIT_FN_NAME: &str = "emit";
pub const INDEXED: &str = "indexed";
Comment on lines +1 to +3
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are #event/#indexed specific and can be used from any code in the fe compiler because it's public.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could move these to a place closer to their usage. My reasoning for putting them here is that they are simple strings and I dislike using magic strings inline because it is easy to mistype a string without the compiler noticing (e.g. "inexed" but you can not mistype INDEXED without the compiler noticing it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should INDEXED or EMITTABLE be used from several modules? I think exposing constants in an arbitrary way is not good especially if you know these constants are used as a stopgap. How long do you think these constants will remain?

pub const MAX_INDEXED_EVENT_FIELDS: usize = 3;
3 changes: 1 addition & 2 deletions crates/analyzer/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};

use crate::namespace::items::{
ContractId, DiagnosticSink, EventId, FunctionId, FunctionSigId, Item, TraitId,
ContractId, DiagnosticSink, FunctionId, FunctionSigId, Item, TraitId,
};
use crate::namespace::types::{Generic, SelfDecl, Type, TypeId};
use crate::AnalyzerDb;
Expand Down Expand Up @@ -408,7 +408,6 @@ impl Location {
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct FunctionBody {
pub expressions: IndexMap<NodeId, ExpressionAttributes>,
pub emits: IndexMap<NodeId, EventId>,
// Map match statements to the corresponding [`PatternMatrix`]
pub matches: IndexMap<NodeId, PatternMatrix>,
// Map lhs of variable declaration to type.
Expand Down
17 changes: 3 additions & 14 deletions crates/analyzer/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::namespace::items::{
self, ContractFieldId, ContractId, DepGraphWrapper, EnumVariantKind, EventId, FunctionId,
FunctionSigId, ImplId, IngotId, Item, ModuleConstantId, ModuleId, StructFieldId, StructId,
TraitId, TypeAliasId,
self, ContractFieldId, ContractId, DepGraphWrapper, EnumVariantKind, FunctionId, FunctionSigId,
ImplId, IngotId, Item, ModuleConstantId, ModuleId, StructFieldId, StructId, TraitId,
TypeAliasId,
};
use crate::namespace::types::{self, Type, TypeId};
use crate::{
Expand Down Expand Up @@ -51,8 +51,6 @@ pub trait AnalyzerDb: SourceDb + Upcast<dyn SourceDb> + UpcastMut<dyn SourceDb>
#[salsa::interned]
fn intern_function(&self, data: Rc<items::Function>) -> FunctionId;
#[salsa::interned]
fn intern_event(&self, data: Rc<items::Event>) -> EventId;
#[salsa::interned]
fn intern_type(&self, data: Type) -> TypeId;

// Ingot
Expand Down Expand Up @@ -132,11 +130,6 @@ pub trait AnalyzerDb: SourceDb + Upcast<dyn SourceDb> + UpcastMut<dyn SourceDb>
#[salsa::invoke(queries::contracts::contract_call_function)]
fn contract_call_function(&self, id: ContractId) -> Analysis<Option<FunctionId>>;

#[salsa::invoke(queries::contracts::contract_all_events)]
fn contract_all_events(&self, id: ContractId) -> Rc<[EventId]>;
#[salsa::invoke(queries::contracts::contract_event_map)]
fn contract_event_map(&self, id: ContractId) -> Analysis<Rc<IndexMap<SmolStr, EventId>>>;

#[salsa::invoke(queries::contracts::contract_all_fields)]
fn contract_all_fields(&self, id: ContractId) -> Rc<[ContractFieldId]>;
#[salsa::invoke(queries::contracts::contract_field_map)]
Expand Down Expand Up @@ -206,10 +199,6 @@ pub trait AnalyzerDb: SourceDb + Upcast<dyn SourceDb> + UpcastMut<dyn SourceDb>
#[salsa::invoke(queries::impls::impl_function_map)]
fn impl_function_map(&self, id: ImplId) -> Analysis<Rc<IndexMap<SmolStr, FunctionId>>>;

// Event
#[salsa::invoke(queries::events::event_type)]
fn event_type(&self, event: EventId) -> Analysis<Rc<types::Event>>;

// Type
#[salsa::invoke(queries::types::all_impls)]
fn all_impls(&self, ty: TypeId) -> Rc<[ImplId]>;
Expand Down
1 change: 0 additions & 1 deletion crates/analyzer/src/db/queries.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub mod contracts;
pub mod enums;
pub mod events;
pub mod functions;
pub mod impls;
pub mod ingots;
Expand Down
85 changes: 10 additions & 75 deletions crates/analyzer/src/db/queries/contracts.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use crate::db::{Analysis, AnalyzerDb};
use crate::errors;
use crate::namespace::items::{
self, ContractFieldId, ContractId, DepGraph, DepGraphWrapper, DepLocality, EventId, FunctionId,
Item, TypeDef,
self, ContractFieldId, ContractId, DepGraph, DepGraphWrapper, DepLocality, FunctionId, Item,
TypeDef,
};
use crate::namespace::scopes::ItemScope;
use crate::namespace::types::{self, Type};
use crate::traversal::types::type_desc;
use crate::{
context::{AnalyzerContext, NamedThing},
namespace::types::TypeId,
};
use crate::{context::AnalyzerContext, namespace::types::TypeId};
use fe_common::diagnostics::Label;
use fe_parser::ast;
use indexmap::map::{Entry, IndexMap};
Expand All @@ -23,16 +20,13 @@ pub fn contract_all_functions(db: &dyn AnalyzerDb, contract: ContractId) -> Rc<[
let module = contract.module(db);
let body = &contract.data(db).ast.kind.body;
body.iter()
.filter_map(|stmt| match stmt {
ast::ContractStmt::Event(_) => None,
ast::ContractStmt::Function(node) => {
Some(db.intern_function(Rc::new(items::Function::new(
db,
node,
Some(Item::Type(TypeDef::Contract(contract))),
module,
))))
}
.map(|stmt| match stmt {
ast::ContractStmt::Function(node) => db.intern_function(Rc::new(items::Function::new(
db,
node,
Some(Item::Type(TypeDef::Contract(contract))),
module,
))),
})
.collect()
}
Expand All @@ -51,17 +45,6 @@ pub fn contract_function_map(
continue;
}

if let Some(event) = contract.event(db, def_name) {
scope.name_conflict_error(
"function",
def_name,
&NamedThing::Item(Item::Event(event)),
Some(event.name_span(db)),
def.kind.sig.kind.name.span,
);
continue;
}

if let Ok(Some(named_item)) = scope.resolve_name(def_name, func.name_span(db)) {
scope.name_conflict_error(
"function",
Expand Down Expand Up @@ -269,54 +252,6 @@ pub fn contract_call_function(
}
}

/// A `Vec` of all events defined within the contract, including those with
/// duplicate names.
pub fn contract_all_events(db: &dyn AnalyzerDb, contract: ContractId) -> Rc<[EventId]> {
let body = &contract.data(db).ast.kind.body;
body.iter()
.filter_map(|stmt| match stmt {
ast::ContractStmt::Function(_) => None,
ast::ContractStmt::Event(node) => Some(db.intern_event(Rc::new(items::Event {
ast: node.clone(),
module: contract.module(db),
contract: Some(contract),
}))),
})
.collect()
}

pub fn contract_event_map(
db: &dyn AnalyzerDb,
contract: ContractId,
) -> Analysis<Rc<IndexMap<SmolStr, EventId>>> {
let scope = ItemScope::new(db, contract.module(db));
let mut map = IndexMap::<SmolStr, EventId>::new();

let contract_name = contract.name(db);
for event in db.contract_all_events(contract).iter() {
let node = &event.data(db).ast;

match map.entry(node.name().into()) {
Entry::Occupied(entry) => {
scope.duplicate_name_error(
&format!("duplicate event names in `contract {}`", contract_name,),
entry.key(),
entry.get().data(db).ast.span,
node.span,
);
}
Entry::Vacant(entry) => {
entry.insert(*event);
}
}
}

Analysis {
value: Rc::new(map),
diagnostics: scope.diagnostics.take().into(),
}
}

/// All field ids, including those with duplicate names
pub fn contract_all_fields(db: &dyn AnalyzerDb, contract: ContractId) -> Rc<[ContractFieldId]> {
contract
Expand Down
115 changes: 0 additions & 115 deletions crates/analyzer/src/db/queries/events.rs

This file was deleted.

5 changes: 0 additions & 5 deletions crates/analyzer/src/db/queries/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,6 @@ pub fn function_dependency_graph(db: &dyn AnalyzerDb, function: FunctionId) -> D
}
}

directs.extend(
body.emits
.values()
.map(|event| (root, Item::Event(*event), DepLocality::Local)),
);
directs.extend(
body.var_types
.values()
Expand Down
9 changes: 2 additions & 7 deletions crates/analyzer/src/db/queries/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::context::{Analysis, AnalyzerContext, Constant, NamedThing};
use crate::display::Displayable;
use crate::errors::{self, ConstEvalError, TypeError};
use crate::namespace::items::{
Contract, ContractId, Enum, Event, Function, Impl, ImplId, Item, ModuleConstant,
ModuleConstantId, ModuleId, ModuleSource, Struct, StructId, Trait, TraitId, TypeAlias, TypeDef,
Contract, ContractId, Enum, Function, Impl, ImplId, Item, ModuleConstant, ModuleConstantId,
ModuleId, ModuleSource, Struct, StructId, Trait, TraitId, TypeAlias, TypeDef,
};
use crate::namespace::scopes::ItemScope;
use crate::namespace::types::{self, TypeId};
Expand Down Expand Up @@ -101,11 +101,6 @@ pub fn module_all_items(db: &dyn AnalyzerDb, module: ModuleId) -> Rc<[Item]> {
module,
})))),
ast::ModuleStmt::Pragma(_) | ast::ModuleStmt::Use(_) | ast::ModuleStmt::Impl(_) => None,
ast::ModuleStmt::Event(node) => Some(Item::Event(db.intern_event(Rc::new(Event {
ast: node.clone(),
module,
contract: None,
})))),
ast::ModuleStmt::ParseError(_) => None,
})
.collect()
Expand Down