aboutsummaryrefslogtreecommitdiff
path: root/src/sexp/mod.rs
blob: c1a5a8e459fb1a6aacdd5ed641eeb2e6e6f97e46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

pub mod step;
pub mod util;
pub mod subst;
pub mod display;
pub mod case;

use crate::r#type::Type;

/// A leaf node for S-Expressions.
///
/// May represent built-in operators,
/// variables, functions (to be added) or values.
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Clone)]
pub enum SLeaf {

    Add,
    Sub,
    Mul,
    Div,
    Eq,
    Neq,
    Gt,
    Lt,
    Ge,
    Le,
    And,
    Or,
    Not,
    Xor,
    Concat,

    Quote,
    Vector,
    Coprod,
    Inl,
    Inr,

    Let,

    Fun,

    Fix,

    Case,

    Ty(Type),

    Print,

    Int(i32),
    True,
    False,

    Var(String),
    RestPat(String),

    Nil,
}

/// An S-Expression; the defining structure of the language.
///
/// This structure is not intended to correspond with
/// IETF-standardized s-expressions; they are only inspiration.
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Clone)]
pub enum SExp {
    SCons(Box<SExp>, Box<SExp>),
    Atom(SLeaf),
}

use SExp::*;
use SLeaf::*;
use crate::sexp::util::*;


impl SExp {
    /// Quick test that lets are values
    /// ```rust
    /// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
    /// assert!(scons(Let, scons(var("a"), scons(5, Nil))).is_value())
    /// ```
    pub fn is_value(&self) -> bool {
        match self {
            SCons(a, b) =>
		scons(a.clone(), b.clone()).is_fun() ||
                SCons(a.clone(), b.clone()).check_let().is_some() ||
                (
                    (**a == Atom(Quote)
		     || **a == Atom(Vector)
		     || (**a).is_type_lit()
		     || **a == Atom(Coprod))
                    && b.consists_of_values()
                ),
            Atom(Var(_)) => false,
            Atom(RestPat(_)) => false,
            Atom(_) => true,
        }
    }

    pub fn consists_of_values(&self) -> bool {
        self.is_value() || match self {
            SCons(a, b) if (*a).is_value() => b.consists_of_values(),
            _ => false
        }
    }

    pub fn is_type_lit(&self) -> bool {
	match self {
	    Atom(Ty(_)) => true,
	    SCons(a, b) => scons(a.clone(), b.clone())
		.parts()
		.into_iter()
		.all(|x| x.is_type_lit()),
	    _ => false
	}
    }

    pub fn is_fun(&self) -> bool {
	match self {
	    SCons(a, _) if **a == Atom(Fun) => true,
	    _ => false
	}
    }

    pub fn is_type_atom(&self) -> bool {
	match self {
	    Atom(Ty(_)) => true,
	    _ => false,
	}
    }
}