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

parser support for paths in expressions and type descriptions #1

Open
wants to merge 4 commits into
base: module-system2
Choose a base branch
from
Open
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
28 changes: 28 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 21 additions & 4 deletions crates/abi/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,11 @@ fn components(db: &dyn AnalyzerDb, typ: &types::FixedSize) -> Vec<Component> {
#[cfg(test)]
mod tests {
use crate::builder;
use fe_analyzer::Db;
use fe_analyzer::namespace::items::{Global, Module, ModuleContext, ModuleFileContent};
use fe_analyzer::{AnalyzerDb, TestDb};
use fe_common::files::SourceFileId;
use fe_parser::{grammar::module::parse_module, parse_code_chunk};
use std::rc::Rc;

#[test]
fn build_contract_abi() {
Expand All @@ -146,11 +149,25 @@ contract Foo:
pub fn bar(x: u256) -> Array<u256, 10>:
revert"#;

let module = parse_code_chunk(parse_module, contract)
let ast = parse_code_chunk(parse_module, contract)
.expect("unable to build module AST")
.kind;
let db = Db::default();
let module_id = fe_analyzer::analyze(&db, module).expect("failed to analyze source");
let db = TestDb::default();

let global = Global::default();
let global_id = db.intern_global(Rc::new(global));

let module = Module {
name: "".to_string(),
context: ModuleContext::Global(global_id),
file_content: ModuleFileContent::File {
file: SourceFileId(0),
},
ast,
};
let module_id = db.intern_module(Rc::new(module));

fe_analyzer::analyze_module(&db, module_id).expect("failed to analyze source");
let abis = builder::module(&db, module_id).expect("unable to build ABI");

if let Some(abi) = abis.get("Foo") {
Expand Down
36 changes: 28 additions & 8 deletions crates/analyzer/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::context::{Analysis, FunctionBody};
use crate::errors::TypeError;
use crate::namespace::items::{
self, ContractFieldId, ContractId, EventId, FunctionId, Item, ModuleConstantId, ModuleId,
StructFieldId, StructId, TypeAliasId,
self, ContractFieldId, ContractId, EventId, FunctionId, GlobalId, IngotId, Item,
ModuleConstantId, ModuleId, StructFieldId, StructId, TypeAliasId,
};
use crate::namespace::types;
use indexmap::IndexMap;
use indexmap::map::IndexMap;
use std::rc::Rc;
use fe_parser::ast;

mod queries;

Expand All @@ -28,6 +29,10 @@ macro_rules! impl_intern_key {

#[salsa::query_group(AnalyzerDbStorage)]
pub trait AnalyzerDb {
#[salsa::interned]
fn intern_global(&self, data: Rc<items::Global>) -> GlobalId;
#[salsa::interned]
fn intern_ingot(&self, data: Rc<items::Ingot>) -> IngotId;
#[salsa::interned]
fn intern_module(&self, data: Rc<items::Module>) -> ModuleId;
#[salsa::interned]
Expand All @@ -47,17 +52,32 @@ pub trait AnalyzerDb {
#[salsa::interned]
fn intern_event(&self, data: Rc<items::Event>) -> EventId;

// Ingot
#[salsa::invoke(queries::ingots::ingot_all_modules)]
fn ingot_all_modules(&self, ingot: IngotId) -> Rc<Vec<ModuleId>>;

// Module
#[salsa::invoke(queries::module::module_all_items)]
fn module_all_items(&self, module: ModuleId) -> Rc<Vec<Item>>;
#[salsa::invoke(queries::module::module_item_map)]
fn module_item_map(&self, module: ModuleId) -> Analysis<Rc<IndexMap<String, Item>>>;
#[salsa::invoke(queries::module::module_imported_item_map)]
fn module_imported_item_map(&self, module: ModuleId) -> Rc<IndexMap<String, Item>>;
#[salsa::invoke(queries::module::module_contracts)]
fn module_contracts(&self, module: ModuleId) -> Rc<Vec<ContractId>>;
#[salsa::invoke(queries::module::module_structs)]
fn module_structs(&self, module: ModuleId) -> Rc<Vec<StructId>>;
#[salsa::invoke(queries::module::module_used_item_map)]
fn module_used_item_map(&self, module: ModuleId) -> Analysis<Rc<IndexMap<String, Item>>>;
// TODO: these ast nodes should be interned
#[salsa::invoke(queries::module::module_resolve_use_tree)]
fn module_resolve_use_tree(&self, module: ModuleId, tree: ast::UseTree) -> Analysis<Rc<IndexMap<String, Item>>>;
#[salsa::invoke(queries::module::module_resolve_path)]
fn module_resolve_path(&self, module: ModuleId, path: ast::Path) -> Analysis<Option<Item>>;
#[salsa::invoke(queries::module::module_parent_module)]
fn module_parent_module(&self, module: ModuleId) -> Option<ModuleId>;
#[salsa::invoke(queries::module::module_adjacent_modules)]
fn module_adjacent_modules(&self, module: ModuleId) -> Rc<IndexMap<String, ModuleId>>;
#[salsa::invoke(queries::module::module_sub_modules)]
fn module_sub_modules(&self, module: ModuleId) -> Rc<IndexMap<String, ModuleId>>;

// Module Constant
#[salsa::invoke(queries::module::module_constant_type)]
Expand Down Expand Up @@ -127,7 +147,7 @@ pub trait AnalyzerDb {

#[salsa::database(AnalyzerDbStorage)]
#[derive(Default)]
pub struct Db {
storage: salsa::Storage<Db>,
pub struct TestDb {
storage: salsa::Storage<TestDb>,
}
impl salsa::Database for Db {}
impl salsa::Database for TestDb {}
1 change: 1 addition & 0 deletions crates/analyzer/src/db/queries.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod contracts;
pub mod events;
pub mod functions;
pub mod ingots;
pub mod module;
pub mod structs;
pub mod types;
67 changes: 67 additions & 0 deletions crates/analyzer/src/db/queries/ingots.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use crate::namespace::items::{IngotId, Module, ModuleContext, ModuleFileContent, ModuleId};
use crate::AnalyzerDb;
use fe_parser::ast;
use indexmap::set::IndexSet;
use std::path::Path;
use std::rc::Rc;

pub fn ingot_all_modules(db: &dyn AnalyzerDb, ingot_id: IngotId) -> Rc<Vec<ModuleId>> {
let ingot = &ingot_id.data(db);

let file_modules = ingot
.fe_files
.values()
.into_iter()
.map(|(file, ast)| {
let module = Module {
name: Path::new(&file.name)
.file_stem()
.unwrap()
.to_str()
.unwrap()
.to_string(),
ast: ast.clone(),
file_content: ModuleFileContent::File { file: file.id },
context: ModuleContext::Ingot(ingot_id),
};

db.intern_module(Rc::new(module))
})
.collect::<Vec<_>>();

let dir_modules = ingot
.fe_files
.values()
.into_iter()
.map(|(file, ast)| {
Path::new(&file.name)
.parent()
.unwrap()
.to_str()
.unwrap()
.to_string()
})
.collect::<IndexSet<_>>()
.into_iter()
.map(|dir| {
let module = Module {
name: dir
.clone()
.split("/")
.collect::<Vec<_>>()
.last()
.unwrap()
.to_string(),
ast: ast::Module { body: vec![] },
context: ModuleContext::Ingot(ingot_id),
file_content: ModuleFileContent::Dir { dir_path: dir },
};

db.intern_module(Rc::new(module))
})
.collect::<Vec<ModuleId>>();

let modules = [file_modules, dir_modules].concat();
// panic!("{:?}", modules.iter().map(|module| module.name(db)).collect::<Vec<_>>());
Rc::new(modules)
}
Loading