]>
Witch of Git - ivy/blob - src/ast.rs
5 sync
::atomic
::{AtomicU32
, Ordering
},
8 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
11 #[derive(PartialEq, Clone, Debug)]
13 Let(Vec
<(Name
, Ast
)>, Box
<Ast
>),
26 vars
: HashMap
<String
, Name
>,
27 upvars
: RefCell
<HashMap
<String
, Name
>>,
28 up
: Option
<&'e Env
<'e
>>,
32 fn new() -> Env
<'
static> {
34 fresh
: AtomicU32
::new(0),
36 upvars
: RefCell
::new(HashMap
::new()),
41 fn wrapping
<'e
, 'r
: 'e
>(env
: &'r Env
<'e
>) -> Env
<'r
> {
43 fresh
: AtomicU32
::new(env
.fresh
.load(Ordering
::Relaxed
)),
45 upvars
: RefCell
::new(HashMap
::new()),
50 fn fresh(&mut self, text
: &str) -> Name
{
51 let name
= Name(*self.fresh
.get_mut());
52 self.vars
.insert
(text
.into
(), name
);
53 *self.fresh
.get_mut() += 1;
57 fn _get(&self, name
: &str) -> Option
<Name
> {
58 if let Some(&resolved
) = self.vars
.get(name
) {
59 return Some(resolved
);
61 self.up
.and_then(|up
| up
._get
(name
)).map(|resolved
| {
62 self.upvars
.borrow_mut().insert
(name
.into
(), resolved
);
67 fn lookup(&mut self, name
: &str) -> Option
<Name
> {
68 if let Some(&resolved
) = self.vars
.get(name
) {
69 return Some(resolved
);
71 self.up
.and_then(|up
| up
._get
(name
)).map(|resolved
| {
72 self.vars
.insert
(name
.into
(), resolved
);
73 self.upvars
.get_mut().insert
(name
.into
(), resolved
);
78 fn upvars(&self) -> Vec
<Name
> {
79 self.upvars
.borrow().values().map(|&x
| x
).collect()
83 impl Drop
for Env
<'_
> {
85 if let Some(up
) = &self.up
{
86 up
.fresh
.store(*self.fresh
.get_mut(), Ordering
::Relaxed
);
92 pub fn parse(sexp
: &Sexp
) -> Result
<Ast
, &'
static str> {
93 Ast
::from_sexp(&mut Env
::new(), sexp
)
96 fn from_sexp
<'r
, 'e
: 'r
>(env
: &'r
mut Env
<'e
>, sexp
: &Sexp
) -> Result
<Ast
, &'
static str> {
98 Sexp
::List(xs
, _
) => match xs
.first
() {
99 Some(Sexp
::Sym(s
, _
)) if s
== "let" => {
101 return Err("too many body expressions in 'let'");
103 let binds
= match xs
.get(1) {
104 Some(Sexp
::List(binds
, _
)) => binds
106 .map(|bind
| match bind
{
107 Sexp
::List(bind
, _
) => {
109 return Err("binding lists must have two elements");
111 // We do the body before the name to avoid being "letrec"
112 let body
= Ast
::from_sexp(env
, &bind
[1])?
;
113 let name
= match &bind
[0] {
114 Sexp
::Sym(name
, _
) => env
.fresh
(&name
),
116 return Err("binding lists must start with a variable")
121 _
=> Err("bindings must be lists"),
123 .collect
::<Result
<_
, _
>>()?
,
124 Some(_
) => return Err("the binding in 'let' is not a list"),
125 None
=> return Err("no binding form in 'let'"),
127 let body
= match xs
.get(2) {
128 Some(x
) => Box
::new(Ast
::from_sexp(env
, x
)?
),
129 None
=> return Err("no body expression in 'let'"),
131 Ok(Ast
::Let(binds
, body
))
133 Some(Sexp
::Sym(s
, _
)) if s
== "lam" => {
135 return Err("too many body expressions in 'lam'");
137 let mut env
= Env
::wrapping(env
);
138 let binds
= match xs
.get(1) {
139 Some(Sexp
::List(names
, _
)) => names
141 .map(|name
| match name
{
142 Sexp
::Sym(s
, _
) => Ok(env
.fresh
(&s
)),
143 _
=> Err("non-symbol in 'lam' arguments"),
145 .collect
::<Result
<_
, _
>>()?
,
146 Some(_
) => return Err("'lam' arguments weren't a list"),
147 None
=> return Err("no arguments in 'lam'"),
149 let body
= match xs
.get(2) {
150 Some(x
) => Box
::new(Ast
::from_sexp(&mut env
, x
)?
),
151 None
=> return Err("no body expression in 'lam'"),
153 let upvars
= env
.upvars
();
160 Some(_
) => Ok(Ast
::App(
162 .map(|x
| Ast
::from_sexp(env
, x
))
163 .collect
::<Result
<_
, _
>>()?
,
165 None
=> Err("expected a non-empty list for an application"),
167 Sexp
::Sym(s
, _
) if s
== "let" => Err("unexpected id 'let'"),
168 Sexp
::Sym(s
, _
) if s
== "lam" => Err("unexpected id 'lam'"),
169 Sexp
::Sym(s
, _
) => Ok(Ast
::Var(
170 env
.lookup(s
).ok_or("variable used but not defined")?
,
172 Sexp
::Int(i
, _
) => Ok(Ast
::Num(*i
)),
173 _
=> Err("unexpected s-expression type"),