Skip to content

Commit

Permalink
Switch to Paths everywhere for FileName storage
Browse files Browse the repository at this point in the history
  • Loading branch information
VonTum committed Sep 10, 2023
1 parent 764b31f commit 33cbe75
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 54 deletions.
4 changes: 4 additions & 0 deletions multiply_add.sus
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,7 @@ module test_exists : -> int result {
int x = exists(5);
int b = doesnt_exist(3);
}

module exists : duplicate a {
// Should be a duplicate of previous exists
}
10 changes: 5 additions & 5 deletions src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

use num_bigint::BigUint;

use crate::{tokenizer::TokenTypeIdx, linker::GlobalValueUUID, linker::GlobalTypeUUID};
use crate::{tokenizer::TokenTypeIdx, linker::ValueUUID, linker::TypeUUID};
use core::ops::Range;
use std::rc::Rc;
use std::{rc::Rc, path::Path};

// Token span. Indices are INCLUSIVE
#[derive(Clone,Copy,Debug,PartialEq,Eq)]
Expand Down Expand Up @@ -105,7 +105,7 @@ pub enum Statement {
TimelineStage(usize)
}

pub type FileName = Rc<String>;
pub type FileName = Rc<Path>;

#[derive(Debug)]
pub struct Location {
Expand All @@ -118,8 +118,8 @@ pub struct Dependencies {
pub global_references : Vec<GlobalReference>,
pub type_references : Vec<GlobalReference>,

pub resolved_globals : Vec<GlobalValueUUID>,
pub resolved_types : Vec<GlobalTypeUUID>
pub resolved_globals : Vec<ValueUUID>,
pub resolved_types : Vec<TypeUUID>
}

#[derive(Debug)]
Expand Down
5 changes: 2 additions & 3 deletions src/dev_aid/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ fn convert_diagnostic(err : ParsingError, severity : DiagnosticSeverity, token_p
let mut related_info = Vec::new();
for info in err.infos {
let info_pos = cvt_span_to_lsp_range(info.position, token_positions);
let location = Location{uri : Url::parse(&info.file_name).unwrap(), range : info_pos};
let location = Location{uri : Url::from_file_path(info.file_name).unwrap(), range : info_pos};
related_info.push(DiagnosticRelatedInformation { location, message: info.info });
}
Diagnostic::new(error_pos, Some(severity), None, None, err.reason, Some(related_info), None)
Expand Down Expand Up @@ -339,8 +339,7 @@ fn main_loop(
let path : PathBuf = params.text_document.uri.to_file_path().unwrap();
let file_data : Rc<LoadedFile> = file_cache.get(&path);

let file_uri_text = params.text_document.uri.to_string();
let (full_parse, errors) = perform_full_semantic_parse(&file_data.file_text, Rc::from(file_uri_text));
let (full_parse, errors) = perform_full_semantic_parse(&file_data.file_text, Rc::from(path));

let (syntax_highlight, token_positions) = do_syntax_highlight(&file_data, &full_parse);

Expand Down
21 changes: 14 additions & 7 deletions src/dev_aid/syntax_highlighting.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

use std::{ops::Range, rc::Rc};
use std::{ops::Range, rc::Rc, collections::HashMap};

use crate::{ast::*, tokenizer::*, parser::*, linker::Linker};

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


Expand Down Expand Up @@ -178,13 +179,16 @@ fn generate_character_offsets(file_text : &str, tokens : &[Token]) -> Vec<Range<
character_offsets
}

pub fn syntax_highlight_file(file_paths : &[String]) {
pub fn syntax_highlight_file(file_paths : &[FileName]) {
let mut linker : Linker = Linker::new();
let mut file_list = Vec::new();
let mut file_list = HashMap::new();
for file_path in file_paths {
let file_text = match std::fs::read_to_string(file_path) {
Ok(file_text) => file_text,
Err(reason) => panic!("Could not open file '{file_path}' for syntax highlighting because {reason}")
Err(reason) => {
let file_path_disp = file_path.display();
panic!("Could not open file '{file_path_disp}' for syntax highlighting because {reason}")
}
};

let (full_parse, errors) = perform_full_semantic_parse(&file_text, Rc::from(file_path.to_owned()));
Expand All @@ -198,16 +202,19 @@ pub fn syntax_highlight_file(file_paths : &[String]) {

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

file_list.push(linker.add_file(file_text, full_parse.ast, errors, (full_parse.tokens, ide_tokens)));
let file_data = linker.add_file(file_text, full_parse.ast, errors, (full_parse.tokens, ide_tokens));
file_list.insert(file_path.clone(), file_data);
}

let linked = linker.link_all(file_list);

for f in &linked.files {
let mut file_cache : FileCache = Default::default();

for (_file_name, f) in &linked.files {
let token_offsets = generate_character_offsets(&f.file_text, &f.extra_data.0);

for err in &f.errors.errors {
err.pretty_print_error(&f.errors.main_file, &f.file_text, &token_offsets);
err.pretty_print_error(&f.errors.main_file, &token_offsets, &mut file_cache);
}
}
}
27 changes: 20 additions & 7 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@


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

use crate::ast::{Span, FileName};
use ariadne::*;
Expand All @@ -19,27 +19,40 @@ pub struct ParsingError {
pub infos : Vec<ErrorInfo>
}

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 ParsingError {
// Requires that character_ranges.len() == tokens.len() + 1 to include EOF token
pub fn pretty_print_error(&self, main_file_name : &str, file_text : &str, character_ranges : &[Range<usize>]) {
pub fn pretty_print_error(&self, main_file : &Path, character_ranges : &[Range<usize>], file_cache : &mut FileCache) {
// Generate & choose some colours for each of our elements
let err_color = Color::Red;
let info_color = Color::Blue;

let error_span = self.position.to_range(character_ranges);
let mut report = Report::build(ReportKind::Error, main_file_name, error_span.start)

let mut report: ReportBuilder<'_, CustomSpan> = Report::build(ReportKind::Error, main_file, error_span.start);
report = report
.with_message(&self.reason)
.with_label(
Label::new((main_file_name, error_span))
Label::new(CustomSpan{file : main_file, 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);
let info_file : &str = &info.file_name;
report = report.with_label(
Label::new((info_file, info_span))
Label::new(CustomSpan{file : &info.file_name, span : info_span})
.with_message(&info.info)
.with_color(info_color)
)
Expand All @@ -49,7 +62,7 @@ impl ParsingError {
"match".fg(out)
))*/
report.finish()
.print((main_file_name, Source::from(file_text)))
.eprint(file_cache)
.unwrap();
}
}
Expand Down
56 changes: 28 additions & 28 deletions src/linker.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::collections::HashMap;

use crate::{ast::{Module, ASTRoot, Span, Location, Dependencies}, errors::{ErrorCollector, error_info}};
use crate::{ast::{Module, ASTRoot, Span, Location, Dependencies, FileName}, errors::{ErrorCollector, error_info}};


#[derive(Debug, Clone, Copy)]
pub struct GlobalValueUUID(usize);
#[derive(Debug, Clone, Copy)]
pub struct GlobalTypeUUID(usize);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ValueUUID(usize);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TypeUUID(usize);

const INVALID_UUID : usize = usize::MAX;

Expand Down Expand Up @@ -91,16 +91,16 @@ impl Linkable for NamedType {

#[derive(Debug, Clone, Copy)]
pub enum GlobalNamespaceNode {
Value(GlobalValueUUID),
Type(GlobalTypeUUID),
Value(ValueUUID),
Type(TypeUUID),
}

pub struct FileData<T> {
pub file_text : String,
pub extra_data : T,
pub errors : ErrorCollector,
associated_values : Vec<GlobalValueUUID>,
associated_types : Vec<GlobalTypeUUID>
associated_values : Vec<ValueUUID>,
associated_types : Vec<TypeUUID>
}

// All modules in the workspace
Expand All @@ -113,17 +113,17 @@ pub struct Linker {
// All modules in the workspace
pub struct FullyLinked<T> {
pub data : Linker,
pub files : Vec<FileData<T>>
pub files : HashMap<FileName, FileData<T>>
}

impl Linker {
// Returns None for builtins
fn get_location(&self, node : GlobalNamespaceNode) -> Option<&Location> {
match node {
GlobalNamespaceNode::Value(GlobalValueUUID(pos)) => {
GlobalNamespaceNode::Value(ValueUUID(pos)) => {
self.values[pos].get_location()
},
GlobalNamespaceNode::Type(GlobalTypeUUID(pos)) => {
GlobalNamespaceNode::Type(TypeUUID(pos)) => {
self.types[pos].get_location()
},
}
Expand All @@ -136,7 +136,7 @@ impl Linker {
let mut global_namespace = HashMap::new();

for name in BUILTIN_TYPES {
let success = global_namespace.insert(name.to_owned(), GlobalNamespaceNode::Type(GlobalTypeUUID(named_types.len()))).is_none();
let success = global_namespace.insert(name.to_owned(), GlobalNamespaceNode::Type(TypeUUID(named_types.len()))).is_none();
assert!(success);
named_types.push(NamedType::Builtin(name));
}
Expand All @@ -159,24 +159,24 @@ impl Linker {
}
}
std::collections::hash_map::Entry::Vacant(vac) => {
vac.insert(GlobalNamespaceNode::Value(GlobalValueUUID(self.values.len())));
associated_values.push(GlobalValueUUID(self.values.len()));
vac.insert(GlobalNamespaceNode::Value(ValueUUID(self.values.len())));
associated_values.push(ValueUUID(self.values.len()));
self.values.push(NamedValue::Module(md));
}
}
}
FileData{file_text, errors, associated_values, associated_types: Vec::new(), extra_data}
}

fn link_dependencies(&self, file_text : &str, deps : &Dependencies, errors : &mut ErrorCollector) -> (Vec<GlobalValueUUID>, Vec<GlobalTypeUUID>) {
let value_references : Vec<GlobalValueUUID> = deps.global_references.iter().map(|reference| {
fn link_dependencies(&self, file_text : &str, deps : &Dependencies, errors : &mut ErrorCollector) -> (Vec<ValueUUID>, Vec<TypeUUID>) {
let value_references : Vec<ValueUUID> = deps.global_references.iter().map(|reference| {
let reference_span = Span(reference.last().unwrap().position, reference[0].position);
let reference_name_str = &file_text[reference[0].text.clone()];
match self.global_namespace.get(reference_name_str) {
Some(GlobalNamespaceNode::Value(v)) => {
*v
}
Some(GlobalNamespaceNode::Type(GlobalTypeUUID(t))) => {
Some(GlobalNamespaceNode::Type(TypeUUID(t))) => {
let found_instead = &self.types[*t];
let found_full_name = found_instead.get_full_name();
let infos = if let Some(loc) = found_instead.get_location() {
Expand All @@ -185,23 +185,23 @@ impl Linker {
vec![]
};
errors.error_with_info(reference_span, format!("No Module or Constant of the name '{reference_name_str}' was found. Found type '{found_full_name}'"), infos);
GlobalValueUUID(INVALID_UUID)
ValueUUID(INVALID_UUID)
}
None => {
errors.error_basic(reference_span, format!("No Module or Constant of the name '{reference_name_str}' was found. Did you forget to import it?"));
GlobalValueUUID(INVALID_UUID)
ValueUUID(INVALID_UUID)
}
}
}).collect();

let type_references : Vec<GlobalTypeUUID> = deps.type_references.iter().map(|reference| {
let type_references : Vec<TypeUUID> = deps.type_references.iter().map(|reference| {
let reference_span = Span(reference.last().unwrap().position, reference[0].position);
let reference_name_str = &file_text[reference[0].text.clone()];
match self.global_namespace.get(reference_name_str) {
Some(GlobalNamespaceNode::Type(v)) => {
*v
}
Some(GlobalNamespaceNode::Value(GlobalValueUUID(idx))) => {
Some(GlobalNamespaceNode::Value(ValueUUID(idx))) => {
let found_instead = &self.values[*idx];
let found_full_name = found_instead.get_full_name();
let infos = if let Some(loc) = found_instead.get_location() {
Expand All @@ -210,11 +210,11 @@ impl Linker {
vec![]
};
errors.error_with_info(reference_span, format!("No Type of the name '{reference_name_str}' was found. Found type '{found_full_name}'"), infos);
GlobalTypeUUID(INVALID_UUID)
TypeUUID(INVALID_UUID)
}
None => {
errors.error_basic(reference_span, format!("No Type of the name '{reference_name_str}' was found. Did you forget to import it?"));
GlobalTypeUUID(INVALID_UUID)
TypeUUID(INVALID_UUID)
}
}
}).collect();
Expand All @@ -223,16 +223,16 @@ impl Linker {
}

// This should be called once all modules have been added. Adds errors for globals it couldn't match
pub fn link_all<T>(mut self, mut files : Vec<FileData<T>>) -> FullyLinked<T> {
for file in &mut files {
for GlobalValueUUID(idx) in &file.associated_values {
pub fn link_all<T>(mut self, mut files : HashMap<FileName, FileData<T>>) -> FullyLinked<T> {
for (_file_name, file) in &mut files {
for ValueUUID(idx) in &file.associated_values {
let deps = self.values[*idx].get_dependencies();
let (vals_this_refers_to, types_this_refers_to) = self.link_dependencies(&file.file_text, deps, &mut file.errors);
let deps_mut = self.values[*idx].get_dependencies_mut();
deps_mut.resolved_globals = vals_this_refers_to;
deps_mut.resolved_types = types_this_refers_to;
}
for GlobalTypeUUID(idx) in &file.associated_types {
for TypeUUID(idx) in &file.associated_types {
let deps = self.types[*idx].get_dependencies();
let (vals_this_refers_to, types_this_refers_to) = self.link_dependencies(&file.file_text, deps, &mut file.errors);
let deps_mut = self.types[*idx].get_dependencies_mut();
Expand Down
9 changes: 6 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ mod linker;

use std::env;
use std::error::Error;
use std::path::PathBuf;
use std::rc::Rc;
use ast::FileName;
use dev_aid::syntax_highlighting::*;


Expand All @@ -18,13 +21,13 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {

let _executable_path = args.next();

let mut file_paths : Vec<String> = Vec::new();
let mut file_paths : Vec<FileName> = Vec::new();
let mut is_lsp : bool = false;
for arg in args {
if arg == "--lsp" {
is_lsp = true;
} else {
file_paths.push(arg);
file_paths.push(Rc::from(PathBuf::from(arg)));
}
}
#[cfg(feature = "lsp")]
Expand All @@ -33,7 +36,7 @@ fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
}
if file_paths.len() == 0 {
// Quick debug file
file_paths.push("multiply_add.sus".to_owned());
file_paths.push(Rc::from(PathBuf::from("multiply_add.sus")));
}
syntax_highlight_file(&file_paths);

Expand Down
2 changes: 1 addition & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ impl<'g, 'file> ASTParserContext<'g, 'file> {
type_references : replace(&mut self.type_references, Vec::new()),
..Default::default()
};
let full_name : String = [self.errors.main_file.as_ref(), &self.file_text[name.text.clone()]].join("::");
let full_name : String = [&self.errors.main_file.as_ref().to_string_lossy(), &self.file_text[name.text.clone()]].join("::");
Some(Module{name, declarations, code, full_name, location : Location{span, file_name : self.errors.main_file.clone()}, dependencies})
}

Expand Down

0 comments on commit 33cbe75

Please sign in to comment.