pub mod types;
use std::fmt;
use std::sync::Arc;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SourceLoc {
pub line: usize,
pub column: usize,
pub file: Arc<str>,
}
impl SourceLoc {
pub fn new(line: usize, column: usize, file: impl Into<Arc<str>>) -> Self {
Self {
line,
column,
file: file.into(),
}
}
pub fn unknown() -> Self {
Self {
line: 0,
column: 0,
file: Arc::from("<unknown>"),
}
}
pub fn file_only(file: impl Into<Arc<str>>) -> Self {
Self {
line: 1,
column: 1,
file: file.into(),
}
}
}
impl fmt::Display for SourceLoc {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}:{}", self.file, self.line, self.column)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Program {
pub type_defs: Vec<TypeDef>,
pub word_defs: Vec<WordDef>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct TypeDef {
pub name: String,
pub type_params: Vec<String>,
pub variants: Vec<Variant>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Variant {
pub name: String,
pub fields: Vec<types::Type>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct WordDef {
pub name: String,
pub effect: types::Effect,
pub body: Vec<Expr>,
pub loc: SourceLoc, }
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
IntLit(i64, SourceLoc),
BoolLit(bool, SourceLoc),
StringLit(String, SourceLoc),
WordCall(String, SourceLoc),
Quotation(Vec<Expr>, SourceLoc),
Match {
branches: Vec<MatchBranch>,
loc: SourceLoc,
},
If {
then_branch: Box<Expr>,
else_branch: Box<Expr>,
loc: SourceLoc,
},
}
impl Expr {
pub fn loc(&self) -> &SourceLoc {
match self {
Expr::IntLit(_, loc) => loc,
Expr::BoolLit(_, loc) => loc,
Expr::StringLit(_, loc) => loc,
Expr::WordCall(_, loc) => loc,
Expr::Quotation(_, loc) => loc,
Expr::Match { loc, .. } => loc,
Expr::If { loc, .. } => loc,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchBranch {
pub pattern: Pattern,
pub body: Vec<Expr>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Pattern {
Variant {
name: String,
},
}
impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Expr::IntLit(n, _) => write!(f, "{}", n),
Expr::BoolLit(b, _) => write!(f, "{}", b),
Expr::StringLit(s, _) => write!(f, "\"{}\"", s),
Expr::WordCall(name, _) => write!(f, "{}", name),
Expr::Quotation(exprs, _) => {
write!(f, "[ ")?;
for expr in exprs {
write!(f, "{} ", expr)?;
}
write!(f, "]")
}
Expr::Match { branches, .. } => {
writeln!(f, "match")?;
for branch in branches {
writeln!(f, " {:?} => [ ... ]", branch.pattern)?;
}
write!(f, "end")
}
Expr::If { .. } => write!(f, "if"),
}
}
}