type checking !?!?

This commit is contained in:
2025-03-22 14:40:32 -04:00
parent 606cb30c6b
commit 7f809d797c
44 changed files with 664 additions and 314 deletions

80
src/common/file.rs Normal file
View File

@@ -0,0 +1,80 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FilePos {
pub line: usize,
pub col: usize,
}
#[derive(Debug, Clone, Copy)]
pub struct FileSpan {
pub start: FilePos,
pub end: FilePos,
}
impl FilePos {
pub fn start() -> Self {
Self { line: 0, col: 0 }
}
}
impl FilePos {
pub fn to(self, end: FilePos) -> FileSpan {
FileSpan { start: self, end }
}
pub fn char_span(self) -> FileSpan {
FileSpan::at(self)
}
}
const BEFORE: usize = 1;
const AFTER: usize = 0;
impl FileSpan {
pub fn at(pos: FilePos) -> Self {
Self {
start: pos,
end: pos,
}
}
pub fn write_for(&self, writer: &mut impl std::io::Write, file: &str) -> std::io::Result<()> {
let start = self.start.line.saturating_sub(BEFORE);
let num_before = self.start.line - start;
let mut lines = file.lines().skip(start);
let width = format!("{}", self.end.line + AFTER).len();
let same_line = self.start.line == self.end.line;
for i in 0..num_before {
writeln!(writer, "{:>width$} | {}", start + i, lines.next().unwrap())?;
}
let line = lines.next().unwrap();
writeln!(writer, "{:>width$} | {}", self.start.line, line)?;
let len = if same_line {
self.end.col - self.start.col + 1
} else {
line.len() - self.start.col
};
writeln!(
writer,
"{} | {}",
" ".repeat(width),
" ".repeat(self.start.col) + &"^".repeat(len)
)?;
if !same_line {
for _ in 0..self.end.line - self.start.line - 1 {
lines.next();
}
let line = lines.next().unwrap();
writeln!(writer, "{:>width$} | {}", self.end.line, line)?;
writeln!(
writer,
"{} | {}",
" ".repeat(width),
"^".repeat(self.end.col + 1)
)?;
}
// for i in 0..AFTER {
// if let Some(next) = lines.next() {
// writeln!(writer, "{:>width$} | {}", self.end.line + i + 1, next)?;
// }
// }
Ok(())
}
}

5
src/common/mod.rs Normal file
View File

@@ -0,0 +1,5 @@
mod output;
mod file;
pub use output::*;
pub use file::*;

64
src/common/output.rs Normal file
View File

@@ -0,0 +1,64 @@
use super::{FilePos, FileSpan};
#[derive(Debug, Clone)]
pub struct CompilerMsg {
pub msg: String,
pub spans: Vec<FileSpan>,
}
pub struct CompilerOutput {
pub errs: Vec<CompilerMsg>,
pub hints: Vec<CompilerMsg>,
}
impl CompilerMsg {
pub fn from_msg(msg: String) -> Self {
Self {
msg,
spans: Vec::new(),
}
}
pub fn from_span(span: FileSpan, msg: String) -> Self {
Self {
msg,
spans: vec![span],
}
}
pub fn at(pos: FilePos, msg: String) -> Self {
Self {
msg,
spans: vec![FileSpan::at(pos)],
}
}
pub fn write_for(&self, ty: &str, writer: &mut impl std::io::Write, file: &str) -> std::io::Result<()> {
let after = if self.spans.is_empty() { "" } else { ":" };
writeln!(writer, "{}: {}{}", ty, self.msg, after)?;
for span in &self.spans {
span.write_for(writer, file)?;
}
Ok(())
}
}
impl CompilerOutput {
pub fn new() -> Self {
Self {
errs: Vec::new(),
hints: Vec::new(),
}
}
pub fn err(&mut self, msg: CompilerMsg) {
self.errs.push(msg);
}
pub fn hint(&mut self, msg: CompilerMsg) {
self.hints.push(msg);
}
pub fn write_for(&self, out: &mut impl std::io::Write, file: &str) {
for err in &self.errs {
err.write_for("error", out, file).unwrap();
}
for hint in &self.hints {
hint.write_for("hint", out, file).unwrap();
}
}
}