1pub mod types;
7
8use std::fmt;
9use std::sync::Arc;
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct SourceLoc {
18 pub line: usize,
19 pub column: usize,
20 pub file: Arc<str>,
21}
22
23impl SourceLoc {
24 pub fn new(line: usize, column: usize, file: impl Into<Arc<str>>) -> Self {
25 Self {
26 line,
27 column,
28 file: file.into(),
29 }
30 }
31
32 pub fn unknown() -> Self {
34 Self {
35 line: 0,
36 column: 0,
37 file: Arc::from("<unknown>"),
38 }
39 }
40
41 pub fn file_only(file: impl Into<Arc<str>>) -> Self {
43 Self {
44 line: 1,
45 column: 1,
46 file: file.into(),
47 }
48 }
49}
50
51impl fmt::Display for SourceLoc {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "{}:{}:{}", self.file, self.line, self.column)
54 }
55}
56
57#[derive(Debug, Clone, PartialEq)]
59pub struct Program {
60 pub type_defs: Vec<TypeDef>,
61 pub word_defs: Vec<WordDef>,
62}
63
64#[derive(Debug, Clone, PartialEq)]
66pub struct TypeDef {
67 pub name: String,
68 pub type_params: Vec<String>,
69 pub variants: Vec<Variant>,
70}
71
72#[derive(Debug, Clone, PartialEq)]
74pub struct Variant {
75 pub name: String,
76 pub fields: Vec<types::Type>,
77}
78
79#[derive(Debug, Clone, PartialEq)]
81pub struct WordDef {
82 pub name: String,
83 pub effect: types::Effect,
84 pub body: Vec<Expr>,
85 pub loc: SourceLoc, }
87
88#[derive(Debug, Clone, PartialEq)]
90pub enum Expr {
91 IntLit(i64, SourceLoc),
93
94 BoolLit(bool, SourceLoc),
96
97 StringLit(String, SourceLoc),
99
100 WordCall(String, SourceLoc),
102
103 Quotation(Vec<Expr>, SourceLoc),
105
106 Match {
108 branches: Vec<MatchBranch>,
109 loc: SourceLoc,
110 },
111
112 If {
114 then_branch: Box<Expr>,
115 else_branch: Box<Expr>,
116 loc: SourceLoc,
117 },
118}
119
120impl Expr {
121 pub fn loc(&self) -> &SourceLoc {
123 match self {
124 Expr::IntLit(_, loc) => loc,
125 Expr::BoolLit(_, loc) => loc,
126 Expr::StringLit(_, loc) => loc,
127 Expr::WordCall(_, loc) => loc,
128 Expr::Quotation(_, loc) => loc,
129 Expr::Match { loc, .. } => loc,
130 Expr::If { loc, .. } => loc,
131 }
132 }
133}
134
135#[derive(Debug, Clone, PartialEq)]
137pub struct MatchBranch {
138 pub pattern: Pattern,
139 pub body: Vec<Expr>,
140}
141
142#[derive(Debug, Clone, PartialEq)]
144pub enum Pattern {
145 Variant {
147 name: String,
148 },
150}
151
152impl fmt::Display for Expr {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 match self {
155 Expr::IntLit(n, _) => write!(f, "{}", n),
156 Expr::BoolLit(b, _) => write!(f, "{}", b),
157 Expr::StringLit(s, _) => write!(f, "\"{}\"", s),
158 Expr::WordCall(name, _) => write!(f, "{}", name),
159 Expr::Quotation(exprs, _) => {
160 write!(f, "[ ")?;
161 for expr in exprs {
162 write!(f, "{} ", expr)?;
163 }
164 write!(f, "]")
165 }
166 Expr::Match { branches, .. } => {
167 writeln!(f, "match")?;
168 for branch in branches {
169 writeln!(f, " {:?} => [ ... ]", branch.pattern)?;
170 }
171 write!(f, "end")
172 }
173 Expr::If { .. } => write!(f, "if"),
174 }
175 }
176}