-
Notifications
You must be signed in to change notification settings - Fork 39
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
feat(hir): expose hir from parsing context #210
base: main
Are you sure you want to change the base?
Changes from 4 commits
964b054
09446fa
0c17b7b
ec3430d
a586705
9c654cc
82c9218
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ mod ast_lowering; | |
mod ast_passes; | ||
|
||
mod parse; | ||
use crate::hir::{Arena, Hir}; | ||
pub use parse::{ParsedSource, ParsedSources, ParsingContext}; | ||
|
||
pub mod builtins; | ||
|
@@ -100,6 +101,32 @@ pub fn parse_and_resolve(pcx: ParsingContext<'_>) -> Result<()> { | |
Ok(()) | ||
} | ||
|
||
/// Parses and lowers to HIR, recursing into imports. | ||
pub fn parse_and_lower_to_hir<'hir>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want to avoid any code dup here and also avoid using Hir directly, but instead through gcx; I think what we can do here is something like this fn parse_and_resolve() {
let gcx = *parse_and_lower()?;
analysis(gcx)?;
Ok(())
}
fn parse_and_lower<'hir>(pcx: '_, hir_arena: 'hir) -> impl Deref<Target=Gcx<'hir>> {
// all the code currently in parse_and_resolve ...
GcxWrapper(...)
}
struct GcxWrapper(GlobalContext);
impl Deref for GcxWrapper {
// move the unsafe here
}
impl Drop for GcxWrapper {
// move from OnDrop closure
} This way we can keep the drop impl and avoid a closure for using Gcx There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @DaniPopes would the approach in 9c654cc which doesn't introduce a new wrapper work? |
||
pcx: ParsingContext<'_>, | ||
hir_arena: &'hir Arena, | ||
) -> Result<Hir<'hir>> { | ||
let sess = pcx.sess; | ||
|
||
if pcx.sources.is_empty() { | ||
let msg = "no files found"; | ||
let note = "if you wish to use the standard input, please specify `-` explicitly"; | ||
return Err(sess.dcx.err(msg).note(note).emit()); | ||
} | ||
|
||
let ast_arenas = OnDrop::new(ThreadLocal::<ast::Arena>::new(), |mut arenas| { | ||
debug!(asts_allocated = arenas.iter_mut().map(|a| a.allocated_bytes()).sum::<usize>()); | ||
debug_span!("dropping_ast_arenas").in_scope(|| drop(arenas)); | ||
}); | ||
let mut sources = pcx.parse(&ast_arenas); | ||
|
||
sources.topo_sort(); | ||
|
||
let (hir, _) = lower(sess, &sources, hir_arena)?; | ||
|
||
Ok(hir) | ||
} | ||
|
||
/// Lowers the parsed ASTs into the HIR. | ||
fn lower<'sess, 'hir>( | ||
sess: &'sess Session, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.13; | ||
|
||
import "./Counter.sol"; | ||
|
||
contract AnotherCounter { | ||
Counter counter = new Counter(); | ||
|
||
constructor(Counter _counter) { | ||
counter = _counter; | ||
} | ||
|
||
function setNumber(uint256 newNumber) public { | ||
counter.setNumber(newNumber); | ||
} | ||
|
||
function increment() public { | ||
counter.increment(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
use solar::{ | ||
interface::{diagnostics::EmittedDiagnostics, Session}, | ||
sema::{ | ||
hir::{Arena, ContractId}, | ||
ParsingContext, | ||
}, | ||
}; | ||
use std::path::Path; | ||
|
||
#[test] | ||
fn main() -> Result<(), EmittedDiagnostics> { | ||
let paths = vec![Path::new("src/AnotherCounter.sol")]; | ||
|
||
// Create a new session with a buffer emitter. | ||
// This is required to capture the emitted diagnostics and to return them at the end. | ||
let sess = Session::builder().with_buffer_emitter(solar::interface::ColorChoice::Auto).build(); | ||
|
||
// Enter the context and parse the file. | ||
// Counter will be parsed, even if not explicitly provided, since it is a dependency. | ||
let _ = sess.enter_parallel(|| -> solar::interface::Result<()> { | ||
// Set up the parser. | ||
let hir_arena = Arena::new(); | ||
let mut parsing_context = ParsingContext::new(&sess); | ||
parsing_context.load_files(paths)?; | ||
let hir = parsing_context.parse_and_lower_to_hir(&hir_arena)?; | ||
let counter_contract = hir.contract(ContractId::new(0)); | ||
assert_eq!(counter_contract.name.to_string(), "Counter"); | ||
let another_counter_contract = hir.contract(ContractId::new(1)); | ||
assert_eq!(another_counter_contract.name.to_string(), "AnotherCounter"); | ||
Ok(()) | ||
}); | ||
|
||
// Return the emitted diagnostics as a `Result<(), _>`. | ||
// If any errors were emitted, this returns `Err(_)`, otherwise `Ok(())`. | ||
sess.emitted_errors().unwrap() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ | |
#![allow(unreachable_pub)] | ||
#![cfg(test)] | ||
|
||
mod hir; | ||
mod parser; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should maintain style of the other fns, using hir:: as a module instead of importing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed in 9c654cc