Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fathom/src/core/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//! use codespan_reporting::term::termcolor::{BufferedStandardStream, ColorChoice};
//! use fathom::core::pretty::Context;
//! use fathom::core::Module;
//! use fathom::files::FileId;
//! use fathom::source::StringInterner;
//!
//! // These are created for demonstration
Expand Down
26 changes: 17 additions & 9 deletions fathom/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use codespan_reporting::term::termcolor::{BufferedStandardStream, ColorChoice, W
use crate::core::binary::{self, BufferError, ReadError};
use crate::files::{FileId, Files};
use crate::source::{ByteRange, Span, StringInterner};
use crate::surface::elaboration::ItemEnv;
use crate::surface::{self, elaboration};
use crate::{core, BUG_REPORT_URL};

Expand Down Expand Up @@ -192,7 +193,8 @@ impl<'surface, 'core> Driver<'surface, 'core> {
}

pub fn elaborate_and_emit_module(&mut self, file_id: FileId, pretty_core: bool) -> Status {
let mut context = elaboration::Context::new(&self.interner, &self.core_scope);
let mut context =
elaboration::Context::new(file_id, &self.interner, &self.core_scope, ItemEnv::new());

let surface_module = self.parse_module(file_id);
let module = context.elab_module(&self.core_scope, &surface_module, &mut |m| {
Expand All @@ -217,7 +219,8 @@ impl<'surface, 'core> Driver<'surface, 'core> {
}

pub fn elaborate_and_emit_term(&mut self, file_id: FileId) -> Status {
let mut context = elaboration::Context::new(&self.interner, &self.core_scope);
let mut context =
elaboration::Context::new(file_id, &self.interner, &self.core_scope, ItemEnv::new());

// Parse and elaborate the term
let surface_term = self.parse_term(file_id);
Expand All @@ -241,7 +244,8 @@ impl<'surface, 'core> Driver<'surface, 'core> {
}

pub fn normalise_and_emit_term(&mut self, file_id: FileId) -> Status {
let mut context = elaboration::Context::new(&self.interner, &self.core_scope);
let mut context =
elaboration::Context::new(file_id, &self.interner, &self.core_scope, ItemEnv::new());

// Parse and elaborate the term
let surface_term = self.parse_term(file_id);
Expand Down Expand Up @@ -277,22 +281,27 @@ impl<'surface, 'core> Driver<'surface, 'core> {

let initial_buffer = binary::Buffer::from(buffer_data);
let mut binary_context = binary::Context::new(initial_buffer);
let mut elab_context = elaboration::Context::new(&self.interner, &self.core_scope);
let mut item_env = ItemEnv::new();

// Parse and elaborate a module if one was provided
if let Some(file_id) = module_file_id {
let mut elab_context =
elaboration::Context::new(file_id, &self.interner, &self.core_scope, item_env);
let surface_module = self.parse_module(file_id);
let module = elab_context.elab_module(&self.core_scope, &surface_module, &mut |m| {
self.emit_diagnostic(m.to_diagnostic(&self.interner));
});
// Add it to the binary context
binary_context.add_module(&module);
item_env = elab_context.finish();
}

// Parse and elaborate the supplied format with the items from the
// supplied in the module in scope. This is still a bit of a hack, and
// will need to be revisited if we need to support multiple modules, but
// it works for now!
let mut elab_context =
elaboration::Context::new(format_file_id, &self.interner, &self.core_scope, item_env);
let surface_format = self.parse_term(format_file_id);
let format = elab_context.elab_format(&self.core_scope, &surface_format, &mut |m| {
self.emit_diagnostic(m.to_diagnostic(&self.interner));
Expand Down Expand Up @@ -333,17 +342,16 @@ impl<'surface, 'core> Driver<'surface, 'core> {
fn parse_module(&'surface self, file_id: FileId) -> surface::Module<'surface, ByteRange> {
let source = self.files.get(file_id).unwrap().source();
let (module, messages) =
surface::Module::parse(&self.interner, &self.surface_scope, file_id, source);
self.emit_diagnostics(messages.into_iter().map(|m| m.to_diagnostic()));
surface::Module::parse(&self.interner, &self.surface_scope, source);
self.emit_diagnostics(messages.into_iter().map(|m| m.to_diagnostic(file_id)));

module
}

fn parse_term(&'surface self, file_id: FileId) -> surface::Term<'surface, ByteRange> {
let source = self.files.get(file_id).unwrap().source();
let (term, messages) =
surface::Term::parse(&self.interner, &self.surface_scope, file_id, source);
self.emit_diagnostics(messages.into_iter().map(move |m| m.to_diagnostic()));
let (term, messages) = surface::Term::parse(&self.interner, &self.surface_scope, source);
self.emit_diagnostics(messages.into_iter().map(move |m| m.to_diagnostic(file_id)));

term
}
Expand Down
7 changes: 7 additions & 0 deletions fathom/src/files.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! A reimplementation of `codespan-reporting::files::SimpleFiles` that uses
//! `FileId` as the file id, instead of `usize`.

use std::fmt;
use std::num::NonZeroU32;
use std::ops::Range;

Expand All @@ -13,6 +14,12 @@ use codespan_reporting::files::{Error, SimpleFile};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct FileId(NonZeroU32);

impl fmt::Display for FileId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}

impl TryFrom<u32> for FileId {
type Error = <NonZeroU32 as TryFrom<u32>>::Error;

Expand Down
100 changes: 77 additions & 23 deletions fathom/src/source.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Types related to source files.

use std::fmt;
use std::ops::{Deref, DerefMut, Range};

use crate::files::FileId;
Expand Down Expand Up @@ -196,7 +197,7 @@ impl<T> DerefMut for Spanned<T> {

#[derive(Debug, Copy, Clone)]
pub enum Span {
Range(ByteRange),
Range(FileRange),
Empty,
}

Expand All @@ -209,20 +210,20 @@ impl Span {
}
}

impl From<ByteRange> for Span {
fn from(range: ByteRange) -> Self {
impl From<FileRange> for Span {
fn from(range: FileRange) -> Self {
Span::Range(range)
}
}

impl From<&ByteRange> for Span {
fn from(range: &ByteRange) -> Self {
impl From<&FileRange> for Span {
fn from(range: &FileRange) -> Self {
Span::Range(*range)
}
}

impl From<Option<ByteRange>> for Span {
fn from(range: Option<ByteRange>) -> Span {
impl From<Option<FileRange>> for Span {
fn from(range: Option<FileRange>) -> Span {
range.map_or(Span::Empty, Span::Range)
}
}
Expand All @@ -231,47 +232,94 @@ impl From<Option<ByteRange>> for Span {
pub type BytePos = u32;

/// Byte ranges in source files.
#[derive(Debug, Copy, Clone)]
pub struct ByteRange {
#[derive(Copy, Clone)]
pub struct FileRange {
file_id: FileId,
start: BytePos,
end: BytePos,
byte_range: ByteRange,
}

impl ByteRange {
pub const fn new(file_id: FileId, start: BytePos, end: BytePos) -> ByteRange {
ByteRange {
impl fmt::Debug for FileRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"FileRange({}, {}..{})",
self.file_id, self.byte_range.start, self.byte_range.end
)
}
}

impl FileRange {
pub const fn new(file_id: FileId, byte_range: ByteRange) -> FileRange {
FileRange {
file_id,
start,
end,
byte_range,
}
}

pub fn file_id(&self) -> FileId {
self.file_id
}

pub const fn byte_range(&self) -> ByteRange {
self.byte_range
}

pub const fn start(&self) -> BytePos {
self.start
self.byte_range.start
}

pub const fn end(&self) -> BytePos {
self.end
self.byte_range.end
}

pub fn merge(&self, other: &ByteRange) -> Option<ByteRange> {
pub fn merge(&self, other: &FileRange) -> Option<FileRange> {
if self.file_id == other.file_id {
Some(ByteRange::new(
Some(FileRange::new(
self.file_id,
self.start.min(other.start),
self.end.max(other.end),
ByteRange::merge(self.byte_range, other.byte_range),
))
} else {
None
}
}
}

impl From<FileRange> for Range<usize> {
fn from(file_range: FileRange) -> Self {
file_range.byte_range.into()
}
}

#[derive(Copy, Clone)]
pub struct ByteRange {
start: BytePos,
end: BytePos,
}

impl fmt::Debug for ByteRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ByteRange({}..{})", self.start, self.end)
}
}

impl ByteRange {
pub fn new(start: BytePos, end: BytePos) -> Self {
Self { start, end }
}

pub const fn start(&self) -> BytePos {
self.start
}

pub const fn end(&self) -> BytePos {
self.end
}

pub fn merge(self, other: Self) -> Self {
Self::new(self.start.min(other.start), self.end.max(other.end))
}
}

impl From<ByteRange> for Range<usize> {
fn from(range: ByteRange) -> Self {
(range.start as usize)..(range.end as usize)
Expand All @@ -285,7 +333,13 @@ mod tests {
#[test]
/// `ByteRange` is used a lot. Ensure it doesn't grow accidentally.
fn byte_range_size() {
assert_eq!(std::mem::size_of::<ByteRange>(), 12);
assert_eq!(std::mem::size_of::<ByteRange>(), 8);
}

#[test]
/// `FileRange` is used a lot. Ensure it doesn't grow accidentally.
fn file_range_size() {
assert_eq!(std::mem::size_of::<FileRange>(), 12);
}

#[test]
Expand Down
Loading