salsa/examples/calc/ir.rs

126 lines
2.7 KiB
Rust
Raw Normal View History

2022-08-24 16:43:29 +00:00
#![allow(clippy::needless_borrow)]
use derive_new::new;
2022-08-01 05:32:47 +00:00
use ordered_float::OrderedFloat;
// ANCHOR: input
#[salsa::input]
pub struct SourceProgram {
#[return_ref]
pub text: String,
}
// ANCHOR_END: input
2022-08-01 05:32:47 +00:00
// ANCHOR: interned_ids
#[salsa::interned]
2024-05-24 01:16:30 +00:00
pub struct VariableId<'db> {
2022-08-01 05:32:47 +00:00
#[return_ref]
pub text: String,
}
#[salsa::interned]
2024-05-24 01:16:30 +00:00
pub struct FunctionId<'db> {
2022-08-01 05:32:47 +00:00
#[return_ref]
pub text: String,
}
// ANCHOR_END: interned_ids
// ANCHOR: program
2022-08-19 09:53:33 +00:00
#[salsa::tracked]
2024-05-24 01:16:30 +00:00
pub struct Program<'db> {
#[return_ref]
2024-05-24 01:16:30 +00:00
pub statements: Vec<Statement<'db>>,
2022-08-19 09:53:33 +00:00
}
// ANCHOR_END: program
2022-08-19 09:53:33 +00:00
// ANCHOR: statements_and_expressions
2024-07-17 13:25:04 +00:00
#[derive(Eq, PartialEq, Debug, Hash, new, salsa::Update)]
2024-05-24 01:16:30 +00:00
pub struct Statement<'db> {
pub span: Span<'db>,
2024-05-24 01:16:30 +00:00
pub data: StatementData<'db>,
}
2024-07-17 13:25:04 +00:00
#[derive(Eq, PartialEq, Debug, Hash, salsa::Update)]
2024-05-24 01:16:30 +00:00
pub enum StatementData<'db> {
2022-08-01 05:32:47 +00:00
/// Defines `fn <name>(<args>) = <body>`
2024-05-24 01:16:30 +00:00
Function(Function<'db>),
2022-08-01 05:32:47 +00:00
/// Defines `print <expr>`
2024-05-24 01:16:30 +00:00
Print(Expression<'db>),
2022-08-01 05:32:47 +00:00
}
2024-07-15 11:46:23 +00:00
#[derive(Eq, PartialEq, Debug, Hash, new, salsa::Update)]
2024-05-24 01:16:30 +00:00
pub struct Expression<'db> {
pub span: Span<'db>,
2024-05-24 01:16:30 +00:00
pub data: ExpressionData<'db>,
}
2024-07-17 13:25:04 +00:00
#[derive(Eq, PartialEq, Debug, Hash, salsa::Update)]
2024-05-24 01:16:30 +00:00
pub enum ExpressionData<'db> {
Op(Box<Expression<'db>>, Op, Box<Expression<'db>>),
2022-08-01 05:32:47 +00:00
Number(OrderedFloat<f64>),
2024-05-24 01:16:30 +00:00
Variable(VariableId<'db>),
Call(FunctionId<'db>, Vec<Expression<'db>>),
2022-08-01 05:32:47 +00:00
}
2024-07-17 13:25:04 +00:00
#[derive(Eq, PartialEq, Copy, Clone, Hash, Debug, salsa::Update)]
2022-08-01 05:32:47 +00:00
pub enum Op {
Add,
Subtract,
Multiply,
Divide,
}
// ANCHOR_END: statements_and_expressions
// ANCHOR: functions
#[salsa::tracked]
2024-05-24 01:16:30 +00:00
pub struct Function<'db> {
2022-08-01 05:32:47 +00:00
#[id]
2024-05-24 01:16:30 +00:00
pub name: FunctionId<'db>,
2024-05-24 01:16:30 +00:00
name_span: Span<'db>,
#[return_ref]
2024-05-24 01:16:30 +00:00
pub args: Vec<VariableId<'db>>,
#[return_ref]
2024-05-24 01:16:30 +00:00
pub body: Expression<'db>,
2022-08-01 05:32:47 +00:00
}
// ANCHOR_END: functions
#[salsa::tracked]
2024-05-24 01:16:30 +00:00
pub struct Span<'db> {
pub start: usize,
pub end: usize,
}
2022-08-01 05:32:47 +00:00
// ANCHOR: diagnostic
#[salsa::accumulator]
2024-07-19 13:50:00 +00:00
#[allow(dead_code)] // Debug impl uses them
2024-07-19 11:08:11 +00:00
#[derive(new)]
2022-08-01 05:32:47 +00:00
pub struct Diagnostic {
pub start: usize,
pub end: usize,
2022-08-01 05:32:47 +00:00
pub message: String,
}
// ANCHOR_END: diagnostic
2024-07-19 12:46:14 +00:00
impl Diagnostic {
2024-07-19 13:50:00 +00:00
#[cfg(test)]
2024-07-19 12:46:14 +00:00
pub fn render(&self, db: &dyn crate::Db, src: SourceProgram) -> String {
use annotate_snippets::*;
let line_start = src.text(db)[..self.start].lines().count() + 1;
Renderer::plain()
.render(
Level::Error.title(&self.message).snippet(
Snippet::source(src.text(db))
.line_start(line_start)
.origin("input")
.annotation(Level::Error.span(self.start..self.end).label("here")),
),
)
.to_string()
}
}