1use std::fmt::Write;
2use std::{fmt, sync::Arc};
3
4use serde::{Deserialize, Serialize};
5
6use crate::{formatting::source_lines, lexer::loc_to_pos};
7
8#[derive(Clone)]
10pub struct Context {
11 pub source: Arc<Source>,
12 pub left: usize,
14 pub right: usize,
16}
17
18impl fmt::Display for Context {
19 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20 write!(f, "{}", self.source_position())?;
21 let lines = source_lines(&self.source, self.left, 0).replace('\n', "\n\t");
22 writeln!(f, ":\n\t{}", lines)?;
23 Ok(())
24 }
25}
26
27impl Context {
28 pub(crate) fn new(source: Arc<Source>, left: usize, right: usize) -> Self {
29 Self {
30 source,
31 left,
32 right,
33 }
34 }
35
36 pub(crate) fn source_position(&self) -> String {
37 let mut f = String::new();
38 let (row, column) = loc_to_pos(&self.source.src, self.left);
39 write!(f, " at line {}, column {}", row + 1, column + 1).unwrap();
40 if let Some(ref filename) = self.source.filename {
41 write!(f, " of file {}", filename).unwrap();
42 }
43 f
44 }
45}
46
47#[derive(Clone)]
48pub enum SourceInfo {
49 Parser(Context),
51
52 TemporaryVariable,
54
55 Ffi,
57
58 Test,
60}
61
62impl fmt::Debug for SourceInfo {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 match self {
65 Self::Parser(_) => f.write_str("SourceInfo::Parser"),
67 Self::TemporaryVariable => f.write_str("SourceInfo::TemporaryVariable"),
68 Self::Ffi => f.write_str("SourceInfo::Ffi"),
69 Self::Test => f.write_str("SourceInfo::Test"),
70 }
71 }
72}
73
74impl SourceInfo {
75 pub fn ffi() -> Self {
76 Self::Ffi
77 }
78
79 pub(crate) fn parser(source: Arc<Source>, left: usize, right: usize) -> Self {
80 Self::Parser(Context::new(source, left, right))
81 }
82}
83
84#[derive(PartialEq, Eq, Serialize, Deserialize)]
87pub struct Source {
88 pub filename: Option<String>,
89 pub src: String,
90}
91
92impl Source {
93 pub fn new<T: AsRef<str>>(src: T) -> Self {
94 Self {
95 filename: None,
96 src: src.as_ref().into(),
97 }
98 }
99
100 pub fn new_with_name<T: AsRef<str>, U: AsRef<str>>(filename: T, src: U) -> Self {
101 Self {
102 filename: Some(filename.as_ref().into()),
103 src: src.as_ref().into(),
104 }
105 }
106}