Skip to main content

knave_expand/core/
kernel.rs

1use super::ClosureKind;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
4pub enum KernelForm {
5    Expression(ExpressionForm),
6    Definition(DefinitionForm),
7    Local,
8    Macro,
9}
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
12pub enum ExpressionForm {
13    Fn,
14    Recur,
15    Try,
16    Infer,
17    Leaf(LeafForm),
18    Borrow(ReferenceKind),
19    Deref,
20    Control(ControlForm),
21    Struct(StructForm),
22    Match,
23    Assoc,
24    MapAt,
25    SetAt,
26}
27
28#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
29pub enum LeafForm {
30    Quote,
31    Rust,
32}
33
34#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
35pub enum ControlForm {
36    Do,
37    If,
38}
39
40#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
41pub enum StructForm {
42    New,
43    Field,
44}
45
46#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
47pub enum DefinitionForm {
48    Def,
49    Type,
50    Struct,
51    Enum,
52    Derive,
53    RustTrait,
54    RustType,
55    Trait,
56    Impl,
57    Use,
58    Export,
59}
60
61struct KernelFormRow {
62    form: KernelForm,
63    name: &'static str,
64    shape: &'static str,
65}
66
67impl KernelForm {
68    const ROWS: [KernelFormRow; 30] = [
69        KernelFormRow {
70            form: KernelForm::Expression(ExpressionForm::Fn),
71            name: "fn",
72            shape: "(fn (parameter ...) body ...)",
73        },
74        KernelFormRow {
75            form: KernelForm::Definition(DefinitionForm::Def),
76            name: "def",
77            shape: "(def name value)",
78        },
79        KernelFormRow {
80            form: KernelForm::Local,
81            name: "local",
82            shape: "(local name value)",
83        },
84        KernelFormRow {
85            form: KernelForm::Expression(ExpressionForm::Control(ControlForm::Do)),
86            name: "do",
87            shape: "(do form ...)",
88        },
89        KernelFormRow {
90            form: KernelForm::Expression(ExpressionForm::Control(ControlForm::If)),
91            name: "if",
92            shape: "(if test then else)",
93        },
94        KernelFormRow {
95            form: KernelForm::Definition(DefinitionForm::Type),
96            name: "type",
97            shape: "(type name type)",
98        },
99        KernelFormRow {
100            form: KernelForm::Definition(DefinitionForm::Struct),
101            name: "struct",
102            shape: "(struct (name parameter ...) (field type) ...)",
103        },
104        KernelFormRow {
105            form: KernelForm::Definition(DefinitionForm::Enum),
106            name: "enum",
107            shape: "(enum (name parameter ...) (rust \"Path\")? variant ...)",
108        },
109        KernelFormRow {
110            form: KernelForm::Definition(DefinitionForm::Derive),
111            name: "derive",
112            shape: "(derive type trait ...)",
113        },
114        KernelFormRow {
115            form: KernelForm::Expression(ExpressionForm::Match),
116            name: "match",
117            shape: "(match value (pattern body ...) ...)",
118        },
119        KernelFormRow {
120            form: KernelForm::Expression(ExpressionForm::Assoc),
121            name: "assoc-at",
122            shape: "(assoc-at value (key ...) item)",
123        },
124        KernelFormRow {
125            form: KernelForm::Expression(ExpressionForm::MapAt),
126            name: "map-at",
127            shape: "(map-at operation value argument ...)",
128        },
129        KernelFormRow {
130            form: KernelForm::Expression(ExpressionForm::SetAt),
131            name: "set-at",
132            shape: "(set-at value (key ...) item)",
133        },
134        KernelFormRow {
135            form: KernelForm::Expression(ExpressionForm::Struct(StructForm::New)),
136            name: "new",
137            shape: "(new name (field value) ...) or (new _ base (field value) ...)",
138        },
139        KernelFormRow {
140            form: KernelForm::Expression(ExpressionForm::Struct(StructForm::Field)),
141            name: "field",
142            shape: "(field value name)",
143        },
144        KernelFormRow {
145            form: KernelForm::Expression(ExpressionForm::Borrow(ReferenceKind::Shared)),
146            name: "ref",
147            shape: "(ref value)",
148        },
149        KernelFormRow {
150            form: KernelForm::Expression(ExpressionForm::Borrow(ReferenceKind::Mutable)),
151            name: "mut",
152            shape: "(mut place)",
153        },
154        KernelFormRow {
155            form: KernelForm::Expression(ExpressionForm::Deref),
156            name: "deref",
157            shape: "(deref value)",
158        },
159        KernelFormRow {
160            form: KernelForm::Expression(ExpressionForm::Leaf(LeafForm::Quote)),
161            name: "quote",
162            shape: "(quote form)",
163        },
164        KernelFormRow {
165            form: KernelForm::Macro,
166            name: "macro",
167            shape: "(macro (form) body ...)",
168        },
169        KernelFormRow {
170            form: KernelForm::Expression(ExpressionForm::Leaf(LeafForm::Rust)),
171            name: "rust",
172            shape: "(rust \"template\" type (target \"template\") ...)",
173        },
174        KernelFormRow {
175            form: KernelForm::Definition(DefinitionForm::RustTrait),
176            name: "rust-trait",
177            shape: "(rust-trait name \"Path\" (requires trait ...)? (method name type)? (help \"text\")? type ...)",
178        },
179        KernelFormRow {
180            form: KernelForm::Definition(DefinitionForm::RustType),
181            name: "rust-type",
182            shape: "(rust-type (name parameter ...) \"template\" (type \"template\") ...)",
183        },
184        KernelFormRow {
185            form: KernelForm::Expression(ExpressionForm::Recur),
186            name: "recur",
187            shape: "(recur argument ...)",
188        },
189        KernelFormRow {
190            form: KernelForm::Expression(ExpressionForm::Try),
191            name: "try",
192            shape: "(try expression)",
193        },
194        KernelFormRow {
195            form: KernelForm::Expression(ExpressionForm::Infer),
196            name: "infer",
197            shape: "(infer expression)",
198        },
199        KernelFormRow {
200            form: KernelForm::Definition(DefinitionForm::Trait),
201            name: "trait",
202            shape: "(trait name (method type) ...)",
203        },
204        KernelFormRow {
205            form: KernelForm::Definition(DefinitionForm::Impl),
206            name: "impl",
207            shape: "(impl trait type (method (parameter ...) body ...) ...)",
208        },
209        KernelFormRow {
210            form: KernelForm::Definition(DefinitionForm::Use),
211            name: "use",
212            shape: "(use module name ...)",
213        },
214        KernelFormRow {
215            form: KernelForm::Definition(DefinitionForm::Export),
216            name: "export",
217            shape: "(export name ...)",
218        },
219    ];
220
221    pub fn all() -> impl Iterator<Item = KernelForm> {
222        Self::ROWS.iter().map(|row| row.form)
223    }
224
225    pub fn name(self) -> &'static str {
226        self.row().name
227    }
228
229    pub fn shape(self) -> &'static str {
230        self.row().shape
231    }
232
233    fn row(self) -> &'static KernelFormRow {
234        Self::ROWS
235            .iter()
236            .find(|row| row.form == self)
237            .expect("every kernel form has a row in the kernel form table")
238    }
239}
240
241#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
242pub enum PrimitiveType {
243    Bool,
244    Char,
245    Str,
246    String,
247    Unit,
248    I8,
249    I16,
250    I32,
251    I64,
252    I128,
253    Isize,
254    U8,
255    U16,
256    U32,
257    U64,
258    U128,
259    Usize,
260    F32,
261    F64,
262}
263
264struct PrimitiveRow {
265    primitive: PrimitiveType,
266    name: &'static str,
267    integer_range: Option<(i128, i128)>,
268}
269
270impl PrimitiveType {
271    const ROWS: [PrimitiveRow; 19] = [
272        PrimitiveRow {
273            primitive: PrimitiveType::Bool,
274            name: "bool",
275            integer_range: None,
276        },
277        PrimitiveRow {
278            primitive: PrimitiveType::Char,
279            name: "char",
280            integer_range: None,
281        },
282        PrimitiveRow {
283            primitive: PrimitiveType::Str,
284            name: "str",
285            integer_range: None,
286        },
287        PrimitiveRow {
288            primitive: PrimitiveType::String,
289            name: "string",
290            integer_range: None,
291        },
292        PrimitiveRow {
293            primitive: PrimitiveType::Unit,
294            name: "unit",
295            integer_range: None,
296        },
297        PrimitiveRow {
298            primitive: PrimitiveType::I8,
299            name: "i8",
300            integer_range: Some((i8::MIN as i128, i8::MAX as i128)),
301        },
302        PrimitiveRow {
303            primitive: PrimitiveType::I16,
304            name: "i16",
305            integer_range: Some((i16::MIN as i128, i16::MAX as i128)),
306        },
307        PrimitiveRow {
308            primitive: PrimitiveType::I32,
309            name: "i32",
310            integer_range: Some((i32::MIN as i128, i32::MAX as i128)),
311        },
312        PrimitiveRow {
313            primitive: PrimitiveType::I64,
314            name: "i64",
315            integer_range: Some((i64::MIN as i128, i64::MAX as i128)),
316        },
317        PrimitiveRow {
318            primitive: PrimitiveType::I128,
319            name: "i128",
320            integer_range: Some((i128::MIN, i128::MAX)),
321        },
322        PrimitiveRow {
323            primitive: PrimitiveType::Isize,
324            name: "isize",
325            integer_range: Some((i64::MIN as i128, i64::MAX as i128)),
326        },
327        PrimitiveRow {
328            primitive: PrimitiveType::U8,
329            name: "u8",
330            integer_range: Some((0, u8::MAX as i128)),
331        },
332        PrimitiveRow {
333            primitive: PrimitiveType::U16,
334            name: "u16",
335            integer_range: Some((0, u16::MAX as i128)),
336        },
337        PrimitiveRow {
338            primitive: PrimitiveType::U32,
339            name: "u32",
340            integer_range: Some((0, u32::MAX as i128)),
341        },
342        PrimitiveRow {
343            primitive: PrimitiveType::U64,
344            name: "u64",
345            integer_range: Some((0, u64::MAX as i128)),
346        },
347        PrimitiveRow {
348            primitive: PrimitiveType::U128,
349            name: "u128",
350            integer_range: Some((0, i128::MAX)),
351        },
352        PrimitiveRow {
353            primitive: PrimitiveType::Usize,
354            name: "usize",
355            integer_range: Some((0, u64::MAX as i128)),
356        },
357        PrimitiveRow {
358            primitive: PrimitiveType::F32,
359            name: "f32",
360            integer_range: None,
361        },
362        PrimitiveRow {
363            primitive: PrimitiveType::F64,
364            name: "f64",
365            integer_range: None,
366        },
367    ];
368
369    pub fn all() -> impl Iterator<Item = PrimitiveType> {
370        Self::ROWS.iter().map(|row| row.primitive)
371    }
372
373    pub fn name(self) -> &'static str {
374        self.row().name
375    }
376
377    pub fn integer_range(self) -> Option<(i128, i128)> {
378        self.row().integer_range
379    }
380
381    pub fn is_integer(self) -> bool {
382        self.integer_range().is_some()
383    }
384
385    pub fn is_float(self) -> bool {
386        matches!(self, PrimitiveType::F32 | PrimitiveType::F64)
387    }
388
389    fn row(self) -> &'static PrimitiveRow {
390        Self::ROWS
391            .iter()
392            .find(|row| row.primitive == self)
393            .expect("every primitive type has a row in the primitive table")
394    }
395}
396
397#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
398pub enum KernelType {
399    Function(ClosureKind),
400    Reference(ReferenceKind),
401    Where,
402    With,
403    Hole,
404    Primitive(PrimitiveType),
405}
406
407#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
408pub enum ReferenceKind {
409    Shared,
410    Mutable,
411}
412
413impl ReferenceKind {
414    pub fn keyword(self) -> &'static str {
415        match self {
416            ReferenceKind::Shared => "ref",
417            ReferenceKind::Mutable => "mut",
418        }
419    }
420}
421
422impl KernelType {
423    pub fn all() -> impl Iterator<Item = KernelType> {
424        [
425            KernelType::Function(ClosureKind::Fn),
426            KernelType::Function(ClosureKind::FnMut),
427            KernelType::Function(ClosureKind::FnOnce),
428            KernelType::Reference(ReferenceKind::Shared),
429            KernelType::Reference(ReferenceKind::Mutable),
430            KernelType::Where,
431            KernelType::With,
432            KernelType::Hole,
433        ]
434        .into_iter()
435        .chain(PrimitiveType::all().map(KernelType::Primitive))
436    }
437
438    pub fn shape(self) -> &'static str {
439        match self {
440            KernelType::Function(kind) => kind.shape(),
441            KernelType::Reference(ReferenceKind::Shared) => "(ref type)",
442            KernelType::Reference(ReferenceKind::Mutable) => "(mut type)",
443            KernelType::Where => "(where (variable (variable trait ...) ...) type)",
444            KernelType::With => "(with type type)",
445            KernelType::Hole | KernelType::Primitive(_) => self.name(),
446        }
447    }
448
449    pub fn name(self) -> &'static str {
450        match self {
451            KernelType::Function(kind) => kind.name(),
452            KernelType::Reference(kind) => kind.keyword(),
453            KernelType::Where => "where",
454            KernelType::With => "with",
455            KernelType::Hole => "_",
456            KernelType::Primitive(primitive) => primitive.name(),
457        }
458    }
459}
460
461pub struct KernelConstants;
462
463impl KernelConstants {
464    pub const BOOLEANS: [(&'static str, bool); 2] = [("true", true), ("false", false)];
465}
466
467pub struct CopyTrait;
468
469impl CopyTrait {
470    pub const PATH: &'static str = "Copy";
471}
472
473pub struct OrderTrait;
474
475impl OrderTrait {
476    pub const PATH: &'static str = "Ord";
477}
478
479pub struct FunctionFieldTraits;
480
481impl FunctionFieldTraits {
482    pub const ALLOWED: [&'static str; 3] = ["Clone", "Copy", "Debug"];
483}
484
485pub struct StructDerives;
486
487impl StructDerives {
488    pub const COPY: &'static str = "Copy";
489    pub const INFERRED: [&'static str; 5] = ["Clone", "Copy", "PartialEq", "Eq", "Hash"];
490    pub const DERIVABLE: [&'static str; 8] = [
491        "Clone",
492        "Copy",
493        "Debug",
494        "PartialEq",
495        "Eq",
496        "PartialOrd",
497        "Ord",
498        "Hash",
499    ];
500    const REQUIRED: [(&'static str, &'static str); 5] = [
501        ("Copy", "Clone"),
502        ("Eq", "PartialEq"),
503        ("PartialOrd", "PartialEq"),
504        ("Ord", "Eq"),
505        ("Ord", "PartialOrd"),
506    ];
507
508    pub fn derive_name(path: &str) -> &str {
509        path.rsplit("::").next().unwrap_or(path)
510    }
511
512    pub fn brings(listed: &str, derived: &str) -> bool {
513        listed == derived
514            || Self::REQUIRED
515                .iter()
516                .any(|(requirer, required)| *requirer == listed && Self::brings(required, derived))
517    }
518}