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
use crate::common::{
span::Spanned,
data::Data,
};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct UniqueSymbol(pub usize);
#[derive(Debug, Clone, PartialEq)]
pub enum SSTPattern {
Symbol(UniqueSymbol),
Data(Data),
Label(String, Box<Spanned<SSTPattern>>),
Tuple(Vec<Spanned<SSTPattern>>),
}
#[derive(Debug, Clone, PartialEq)]
pub struct Scope {
pub locals: Vec<UniqueSymbol>,
pub nonlocals: Vec<UniqueSymbol>,
}
impl Scope {
pub fn new() -> Scope {
Scope {
locals: vec![],
nonlocals: vec![],
}
}
pub fn is_local(&self, unique_symbol: UniqueSymbol) -> bool {
self.locals.contains(&unique_symbol)
}
pub fn is_nonlocal(&self, unique_symbol: UniqueSymbol) -> bool {
self.nonlocals.contains(&unique_symbol)
}
pub fn local_index(&self, unique_symbol: UniqueSymbol) -> Option<usize> {
self.locals.iter().position(|l| l == &unique_symbol)
}
pub fn nonlocal_index(&self, unique_symbol: UniqueSymbol) -> Option<usize> {
self.nonlocals.iter().position(|l| l == &unique_symbol)
}
}
impl Default for Scope {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum SST {
Symbol(UniqueSymbol),
Data(Data),
Block(Vec<Spanned<SST>>),
Assign {
pattern: Box<Spanned<SSTPattern>>,
expression: Box<Spanned<SST>>,
},
Lambda {
pattern: Box<Spanned<SSTPattern>>,
expression: Box<Spanned<SST>>,
scope: Scope,
},
Call {
fun: Box<Spanned<SST>>,
arg: Box<Spanned<SST>>,
},
Label(String, Box<Spanned<SST>>),
Tuple(Vec<Spanned<SST>>),
FFI {
name: String,
expression: Box<Spanned<SST>>,
},
}
impl SST {
pub fn assign(
pattern: Spanned<SSTPattern>,
expression: Spanned<SST>
) -> SST {
SST::Assign {
pattern: Box::new(pattern),
expression: Box::new(expression)
}
}
pub fn lambda(
pattern: Spanned<SSTPattern>,
expression: Spanned<SST>,
scope: Scope,
) -> SST {
SST::Lambda {
pattern: Box::new(pattern),
expression: Box::new(expression),
scope,
}
}
pub fn label(name: &str, expression: Spanned<SST>) -> SST {
SST::Label(name.to_string(), Box::new(expression))
}
pub fn call(fun: Spanned<SST>, arg: Spanned<SST>) -> SST {
SST::Call {
fun: Box::new(fun),
arg: Box::new(arg),
}
}
pub fn ffi(name: &str, expression: Spanned<SST>) -> SST {
SST::FFI {
name: name.to_string(),
expression: Box::new(expression),
}
}
}