on codex/command-discovery help sign in
j/src/ast.rs
162 lines 4.9 kB history raw
1//! AST for the j language (§3.4).
3use num_bigint::BigInt;
4use std::rc::Rc;
6#[derive(Debug, Clone, PartialEq)]
7pub enum TypeExpr {
8 Con(String), // type name or variable
9 List(Rc<TypeExpr>),
10 Record(Vec<(String, Rc<TypeExpr>)>),
11 Fun(Rc<TypeExpr>, Rc<TypeExpr>),
14#[derive(Debug, Clone)]
15pub enum Pattern {
16 Var(String),
17 Wildcard,
20#[derive(Debug, Clone)]
21pub enum Expr {
22 Var(String),
23 TypeName(String),
24 Int(BigInt),
25 Text(String),
26 IdLit(String), // unresolved prefix text; resolved to Expr::Id before eval
27 Id(String), // resolved full id
28 NewId,
29 LabelLit(String),
30 PathLit(Vec<String>),
31 Bool(bool),
32 Lambda(Vec<Pattern>, Rc<Expr>, Source), // params, body, source text
33 If(Rc<Expr>, Rc<Expr>, Rc<Expr>),
34 Let(Vec<(String, Rc<Expr>)>, Rc<Expr>),
35 App(Rc<Expr>, Rc<Expr>),
36 BinOp(&'static str, Rc<Expr>, Rc<Expr>),
37 Or(Rc<Expr>, Rc<Expr>),
38 Select(Rc<Expr>, String),
39 Update(Rc<Expr>, Vec<(String, Rc<Expr>)>),
40 Record(Vec<(String, Rc<Expr>)>),
41 List(Vec<Rc<Expr>>),
42 SelectorFun(String),
43 /// an explicitly parenthesised expression (for non-assoc chain checks)
44 Paren(Rc<Expr>),
45 Crash, // internal marker if needed
48/// The source text of a lambda or section, exactly as written, which is how
49/// its closure renders (§5.2): a span of the program text it was parsed
50/// from. The lambdas of one program share that text instead of each holding
51/// a copy, so nested lambdas cost a span each, not their text again.
52#[derive(Clone)]
53pub struct Source {
54 text: Rc<str>,
55 start: usize,
56 end: usize,
59impl Source {
60 /// The bytes `start..end` of `text`, which must fall on char boundaries.
61 pub fn new(text: Rc<str>, start: usize, end: usize) -> Self {
62 Source { text, start, end }
63 }
65 pub fn as_str(&self) -> &str {
66 &self.text[self.start..self.end]
67 }
70impl std::fmt::Debug for Source {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 write!(f, "{:?}", self.as_str())
73 }
76#[derive(Debug, Clone)]
77pub enum Item {
78 TypeDecl(String, TypeExpr),
79 Signature(String, TypeExpr, usize), // name, type, line
80 Definition(String, Rc<Expr>, usize),
83impl Expr {
84 /// Collect free variables of an expression (names not bound within it).
85 pub fn free_vars(&self, bound: &mut Vec<String>, out: &mut std::collections::BTreeSet<String>) {
86 match self {
87 Expr::Var(n) => {
88 if !bound.iter().any(|b| b == n) {
89 out.insert(n.clone());
90 }
91 }
92 // `%main` is `labelled "main"` (§4.11)
93 Expr::LabelLit(_) => {
94 if !bound.iter().any(|b| b == "labelled") {
95 out.insert("labelled".to_string());
96 }
97 }
98 Expr::TypeName(_)
99 | Expr::Int(_)
100 | Expr::Text(_)
101 | Expr::IdLit(_)
102 | Expr::Id(_)
103 | Expr::NewId
104 | Expr::PathLit(_)
105 | Expr::Bool(_)
106 | Expr::SelectorFun(_)
107 | Expr::Crash => {}
108 Expr::Paren(e) => e.free_vars(bound, out),
109 Expr::Lambda(ps, body, _) => {
110 let start = bound.len();
111 for p in ps {
112 if let Pattern::Var(n) = p {
113 bound.push(n.clone());
114 }
115 }
116 body.free_vars(bound, out);
117 bound.truncate(start);
118 }
119 Expr::If(a, b, c) => {
120 a.free_vars(bound, out);
121 b.free_vars(bound, out);
122 c.free_vars(bound, out);
123 }
124 Expr::Let(bs, body) => {
125 let start = bound.len();
126 for (n, _) in bs {
127 bound.push(n.clone());
128 }
129 for (_, e) in bs {
130 e.free_vars(bound, out);
131 }
132 body.free_vars(bound, out);
133 bound.truncate(start);
134 }
135 Expr::App(f, x) => {
136 f.free_vars(bound, out);
137 x.free_vars(bound, out);
138 }
139 Expr::BinOp(_, a, b) | Expr::Or(a, b) => {
140 a.free_vars(bound, out);
141 b.free_vars(bound, out);
142 }
143 Expr::Select(e, _) => e.free_vars(bound, out),
144 Expr::Update(e, fs) => {
145 e.free_vars(bound, out);
146 for (_, v) in fs {
147 v.free_vars(bound, out);
148 }
149 }
150 Expr::Record(fs) => {
151 for (_, v) in fs {
152 v.free_vars(bound, out);
153 }
154 }
155 Expr::List(es) => {
156 for e in es {
157 e.free_vars(bound, out);
158 }
159 }
160 }
161 }