1
+use bumpalo::collections::{String, Vec};
2
+
3
+use crate::{IdentifierId, InstructionId, ScopeId, Type};
4
+
5
+pub struct Instruction<'a> {
6
+ pub id: InstructionId,
7
+ pub lvalue: Place<'a>,
8
+ pub value: InstructionValue<'a>,
9
+}
10
+
11
+pub enum InstructionValue<'a> {
12
+ Array(Array<'a>),
13
+ // Await(Await<'a>),
14
+ // Binary(Binary<'a>),
15
+ // Call(Call<'a>),
16
+ // ComputedDelete(ComputedDelete<'a>),
17
+ // ComputedLoad(ComputedLoad<'a>),
18
+ // ComputedStore(ComputedStore<'a>),
19
+ // Debugger(Debugger<'a>),
20
+ DeclareContext(DeclareContext<'a>),
21
+ DeclareLocal(DeclareLocal<'a>),
22
+ // Destructure(Destructure<'a>),
23
+ // Expression(Expression<'a>),
24
+ // Function(Function<'a>),
25
+ // JsxFragment(JsxFragment<'a>),
26
+ // JsxText(JsxText<'a>),
27
+ LoadContext(LoadContext<'a>),
28
+ // LoadGlobal(LoadGlobal<'a>),
29
+ LoadLocal(LoadLocal<'a>),
30
+ // MethodCall(MethodCall<'a>),
31
+ // New(New<'a>),
32
+ // NextIterable(NextIterable<'a>),
33
+ // Object(Object<'a>),
34
+ // Primitive(Primitive<'a>),
35
+ // PropertyDelete(PropertyDelete<'a>),
36
+ // PropertyLoad(PropertyLoad<'a>),
37
+ // PropertyStore(PropertyStore<'a>),
38
+ // RegExp(RegExp<'a>),
39
+ // StoreContext(StoreContext<'a>),
40
+ StoreLocal(StoreLocal<'a>),
41
+ // TaggedTemplate(TaggedTemplate<'a>),
42
+ // Template(Template<'a>),
43
+ // TypeCast(TypeCast<'a>),
44
+ // Unary(Unary<'a>),
45
+ // Unsupported(Unsupported<'a>),
46
+}
47
+
48
+pub struct Array<'a> {
49
+ pub elements: Vec<'a, ArrayElement<'a>>,
50
+}
51
+
52
+pub enum ArrayElement<'a> {
53
+ Place(Place<'a>),
54
+ Spread(Place<'a>),
55
+}
56
+
57
+pub struct LoadLocal<'a> {
58
+ pub place: Place<'a>,
59
+}
60
+
61
+pub struct LoadContext<'a> {
62
+ pub place: Place<'a>,
63
+}
64
+
65
+pub struct DeclareLocal<'a> {
66
+ pub lvalue: LValue<'a>,
67
+}
68
+
69
+pub struct DeclareContext<'a> {
70
+ pub lvalue: LValue<'a>, // note: kind must be InstructionKind::Let
71
+}
72
+
73
+pub struct StoreLocal<'a> {
74
+ pub lvalue: LValue<'a>,
75
+ pub value: Place<'a>,
76
+}
77
+
78
+pub struct Place<'a> {
79
+ pub identifier: Identifier<'a>,
80
+ pub effect: Option<Effect>,
81
+}
82
+
83
+pub struct LValue<'a> {
84
+ pub place: Place<'a>,
85
+ pub kind: InstructionKind,
86
+}
87
+
88
+pub enum InstructionKind {
89
+ /// `const` declaration
90
+ Const,
91
+
92
+ /// `let` declaration
93
+ Let,
94
+
95
+ /// Reassignment from `=` or assignment-update (`+=` etc)
96
+ Reassign,
97
+}
98
+
99
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
100
+pub enum Effect {
101
+ /// This reference freezes the value (corresponds to a place where codegen should emit a freeze instruction)
102
+ Freeze,
103
+
104
+ /// This reference reads the value
105
+ Read,
106
+
107
+ /// This reference reads and stores the value
108
+ Capture,
109
+
110
+ /// This reference *may* write to (mutate) the value. This covers two similar cases:
111
+ /// - The compiler is being conservative and assuming that a value *may* be mutated
112
+ /// - The effect is polymorphic: mutable values may be mutated, non-mutable values
113
+ /// will not be mutated.
114
+ /// In both cases, we conservatively assume that mutable values will be mutated.
115
+ /// But we do not error if the value is known to be immutable.
116
+ ConditionallyMutate,
117
+
118
+ /// This reference *does* write to (mutate) the value. It is an error (invalid input)
119
+ /// if an immutable value flows into a location with this effect.
120
+ Mutate,
121
+
122
+ /// This reference may alias to (mutate) the value
123
+ Store,
124
+}
125
+
126
+impl Effect {
127
+ pub fn is_mutable(self) -> bool {
128
+ match self {
129
+ Self::Capture | Self::Store | Self::ConditionallyMutate | Self::Mutate => true,
130
+ Self::Read | Self::Freeze => false,
131
+ }
132
+ }
133
+}
134
+
135
+pub struct Identifier<'a> {
136
+ /// Uniquely identifiers this identifier
137
+ pub id: IdentifierId,
138
+
139
+ pub name: Option<String<'a>>,
140
+
141
+ pub mutable_range: MutableRange,
142
+
143
+ pub scope: Option<ReactiveScope>,
144
+
145
+ pub type_: Type,
146
+}
147
+
148
+/// Describes a span of code, generally used to describe the range in which
149
+/// a particular value or set of values is mutable (hence the name).
150
+///
151
+/// Start is inclusive, end is exclusive (ie end is the "first" instruction
152
+/// for which the value is not mutable).
153
+pub struct MutableRange {
154
+ /// start of the range, inclusive.
155
+ pub start: InstructionId,
156
+
157
+ /// end of the range, exclusive
158
+ pub end: InstructionId,
159
+}
160
+
161
+pub struct ReactiveScope {
162
+ pub id: ScopeId,
163
+ pub range: MutableRange,
164
+}