Skip to content

Commit

Permalink
Make Ariadne use linker provided file text
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Feb 20, 2024
1 parent f4c41cb commit ede5587
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 88 deletions.
71 changes: 62 additions & 9 deletions src/dev_aid/syntax_highlighting.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

use std::{ops::Range, path::PathBuf};

use crate::{arena_alloc::ArenaVector, ast::*, file_position::{FileText, Span}, flattening::{Instruction, WireSource}, linker::{FileData, FileUUID, FileUUIDMarker, Linker, NameElem}, parser::*, tokenizer::*};
use crate::{arena_alloc::ArenaVector, ast::*, errors::{CompileError, ErrorLevel}, file_position::{FileText, Span}, flattening::{Instruction, WireSource}, linker::{FileData, FileUUID, FileUUIDMarker, Linker, NameElem}, parser::*, tokenizer::*};

use ariadne::FileCache;
use ariadne::*;
use console::Style;


Expand Down Expand Up @@ -219,9 +219,9 @@ fn generate_character_offsets(file_text : &FileText) -> Vec<Range<usize>> {
character_offsets
}

pub fn compile_all(file_paths : Vec<PathBuf>) -> (Linker, ArenaVector<PathBuf, FileUUIDMarker>) {
pub fn compile_all(file_paths : Vec<PathBuf>) -> (Linker, ArenaVector<(PathBuf, Source), FileUUIDMarker>) {
let mut linker = Linker::new();
let mut paths_arena = ArenaVector::new();
let mut paths_arena : ArenaVector<(PathBuf, Source), FileUUIDMarker> = ArenaVector::new();
for file_path in file_paths {
let uuid = linker.reserve_file();
let file_text = match std::fs::read_to_string(&file_path) {
Expand All @@ -236,25 +236,78 @@ pub fn compile_all(file_paths : Vec<PathBuf>) -> (Linker, ArenaVector<PathBuf, F

println!("{:?}", full_parse.ast);

paths_arena.insert(uuid, (file_path, Source::from(&full_parse.file_text.file_text)));
linker.add_reserved_file(uuid, full_parse);
paths_arena.insert(uuid, file_path);
}

linker.recompile_all();

(linker, paths_arena)
}

pub fn print_all_errors(linker : &Linker, paths_arena : &ArenaVector<PathBuf, FileUUIDMarker>) {
let mut file_cache : FileCache = Default::default();


struct CustomSpan {
file : FileUUID,
span : Range<usize>
}
impl ariadne::Span for CustomSpan {
type SourceId = FileUUID;

fn source(&self) -> &FileUUID { &self.file }
fn start(&self) -> usize { self.span.start }
fn end(&self) -> usize { self.span.end }
}

// Requires that character_ranges.len() == tokens.len() + 1 to include EOF token
pub fn pretty_print_error<AriadneCache : Cache<FileUUID>>(error : &CompileError, file : FileUUID, character_ranges : &[Range<usize>], file_cache : &mut AriadneCache) {
// Generate & choose some colours for each of our elements
let (err_color, report_kind) = match error.level {
ErrorLevel::Error => (Color::Red, ReportKind::Error),
ErrorLevel::Warning => (Color::Yellow, ReportKind::Warning),
};
let info_color = Color::Blue;

let error_span = error.position.to_range(character_ranges);

let mut report: ReportBuilder<'_, CustomSpan> = Report::build(report_kind, file, error_span.start);
report = report
.with_message(&error.reason)
.with_label(
Label::new(CustomSpan{file : file, span : error_span})
.with_message(&error.reason)
.with_color(err_color)
);

for info in &error.infos {
let info_span = info.position.to_range(character_ranges);
report = report.with_label(
Label::new(CustomSpan{file : info.file, span : info_span})
.with_message(&info.info)
.with_color(info_color)
)
}

report.finish().eprint(file_cache).unwrap();
}

impl Cache<FileUUID> for ArenaVector<(PathBuf, Source), FileUUIDMarker> {
fn fetch(&mut self, id: &FileUUID) -> Result<&Source, Box<dyn std::fmt::Debug + '_>> {
Ok(&self[*id].1)
}
fn display<'a>(&self, id: &'a FileUUID) -> Option<Box<dyn std::fmt::Display + 'a>> {
let text : String = self[*id].0.to_string_lossy().into_owned();
Some(Box::new(text))
}
}

pub fn print_all_errors(linker : &Linker, paths_arena : &mut ArenaVector<(PathBuf, Source), FileUUIDMarker>) {
for (file_uuid, f) in &linker.files {
let token_offsets = generate_character_offsets(&f.file_text);

let errors = linker.get_all_errors_in_file(file_uuid);

for err in errors.get().0 {
err.pretty_print_error(f.parsing_errors.file, &token_offsets, &paths_arena, &mut file_cache);
pretty_print_error(&err, f.parsing_errors.file, &token_offsets, paths_arena);
}
}
}
Expand Down
70 changes: 8 additions & 62 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@


use std::{ops::Range, path::{Path, PathBuf}, cell::{RefCell, Cell}};
use std::cell::{RefCell, Cell};

use crate::{linker::{FileUUID, FileUUIDMarker}, arena_alloc::ArenaVector, file_position::Span};
use ariadne::*;
use crate::{linker::FileUUID, file_position::Span};

use crate::tokenizer::{TokenTypeIdx, get_token_type_name};

Expand All @@ -28,77 +27,24 @@ pub struct CompileError {
pub level : ErrorLevel
}

struct CustomSpan<'a> {
file : &'a Path,
span : Range<usize>
}
impl<'a> ariadne::Span for CustomSpan<'a> {
type SourceId = Path;

fn source(&self) -> &Self::SourceId { &self.file }
fn start(&self) -> usize { self.span.start }
fn end(&self) -> usize { self.span.end }
}

impl CompileError {
// Requires that character_ranges.len() == tokens.len() + 1 to include EOF token
pub fn pretty_print_error(&self, file : FileUUID, character_ranges : &[Range<usize>], paths : &ArenaVector<PathBuf, FileUUIDMarker>, file_cache : &mut FileCache) {
// Generate & choose some colours for each of our elements
let (err_color, report_kind) = match self.level {
ErrorLevel::Error => (Color::Red, ReportKind::Error),
ErrorLevel::Warning => (Color::Yellow, ReportKind::Warning),
};
let info_color = Color::Blue;

let error_span = self.position.to_range(character_ranges);

let file_path = &paths[file];

let mut report: ReportBuilder<'_, CustomSpan> = Report::build(report_kind, file_path, error_span.start);
report = report
.with_message(&self.reason)
.with_label(
Label::new(CustomSpan{file : file_path, span : error_span})
.with_message(&self.reason)
.with_color(err_color)
);

for info in &self.infos {
let info_span = info.position.to_range(character_ranges);
report = report.with_label(
Label::new(CustomSpan{file : &paths[info.file], span : info_span})
.with_message(&info.info)
.with_color(info_color)
)
}
/*.with_note(format!(
"Outputs of {} expressions must coerce to the same type",
"match".fg(out)
))*/
report.finish()
.eprint(file_cache)
.unwrap();
}
}

pub fn error_info<S : Into<String>>(position : Span, file : FileUUID, reason : S) -> ErrorInfo {
ErrorInfo{position, file, info : reason.into()}
}

pub fn join_expected_list(expected : &[TokenTypeIdx]) -> String {
use std::fmt::Write;

assert!(!expected.is_empty());
let mut result = String::new();
for exp in expected.get(..expected.len() - 1).unwrap() {
result += "'";
result += get_token_type_name(*exp);
result += "',";
let tok_typ_name = get_token_type_name(*exp);
writeln!(&mut result, "'{tok_typ_name}',").unwrap();
}
if expected.len() >= 2 {
result += " or ";
}
result += "'";
result += get_token_type_name(expected[expected.len() - 1]);
result += "'";
let tok_typ_name = get_token_type_name(expected[expected.len() - 1]);
writeln!(&mut result, "'{tok_typ_name}'").unwrap();
result
}

Expand Down
12 changes: 9 additions & 3 deletions src/file_position.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ops::Range;
use std::ops::{Index, Range};

// Token span. Indices are INCLUSIVE
#[derive(Clone,Copy,Debug,PartialEq,Eq,Hash)]
Expand Down Expand Up @@ -113,8 +113,6 @@ impl Ord for CharLine {
}




pub struct FileText {
pub file_text : String,
// List of all boundaries. Starts with 0, in whitespace mode, and then alternatingly switch to being a token, switch to being whitespace, back and forth
Expand Down Expand Up @@ -177,3 +175,11 @@ impl FileText {
span.1 < self.num_tokens()
}
}

impl Index<Span> for FileText {
type Output = str;

fn index(&self, index: Span) -> &str {
&self.file_text[self.get_span_range(index)]
}
}
2 changes: 1 addition & 1 deletion src/flattening/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ impl<'prev, 'inst, 'l, 'runtime> FlatteningContext<'prev, 'inst, 'l, 'runtime> {
// Possibly local
if let Some(single_tok_idx) = identifier.span.is_single_token() {
assert!(self.linker.file.tokens[single_tok_idx] == TOKEN_IDENTIFIER);
if let Some(decl_id) = self.local_variable_context.get_declaration_for(self.linker.file.get_token_text(single_tok_idx)) {
if let Some(decl_id) = self.local_variable_context.get_declaration_for(&self.linker.file.file_text[Span::new_single_token(single_tok_idx)]) {
return LocalOrGlobal::Local(decl_id);
}
}
Expand Down
11 changes: 1 addition & 10 deletions src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,6 @@ pub struct FileData {
pub associated_values : Vec<NameElem>
}

impl FileData {
pub fn get_token_text(&self, token_idx : usize) -> &str {
&self.file_text.file_text[self.file_text.get_token_range(token_idx)]
}
pub fn get_span_text(&self, span : Span) -> &str {
&self.file_text.file_text[self.file_text.get_span_range(span)]
}
}

#[derive(Debug,Clone,Copy,PartialEq,Eq,Hash)]
pub enum NameElem {
Module(ModuleUUID),
Expand Down Expand Up @@ -526,7 +517,7 @@ impl<'linker> GlobalResolver<'linker> {
}

pub fn resolve_global<'error_collector>(&self, name_span : Span, errors : &'error_collector ErrorCollector) -> ResolvedNameElem<'linker, 'error_collector> {
let name = self.file.get_span_text(name_span);
let name = &self.file.file_text[name_span];

let mut resolved_globals_borrow = self.resolved_globals.borrow_mut();
let resolved_globals = resolved_globals_borrow.as_mut().unwrap();
Expand Down
6 changes: 3 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
return Ok(())
}

let (linker, paths_arena) = compile_all(file_paths);
print_all_errors(&linker, &paths_arena);
for (id, path) in &paths_arena {
let (linker, mut paths_arena) = compile_all(file_paths);
print_all_errors(&linker, &mut paths_arena);
for (id, (path, _)) in &paths_arena {
println!("\n\n[{}]: ", path.to_string_lossy());
syntax_highlight_file(&linker, id, &settings);
}
Expand Down

0 comments on commit ede5587

Please sign in to comment.