1use crate::ast::*;
2use crate::opcodes::*;
3
4pub struct Compiler<'a> {
5 module: &'a ModuleSoA,
6 buf: Vec<u8>,
7}
8
9impl<'a> Compiler<'a> {
10 pub fn new(module: &'a ModuleSoA) -> Self {
11 Self {
12 module,
13 buf: Vec::new(),
14 }
15 }
16
17 pub fn compile(mut self, root_nodes: &[NodeId]) -> Vec<u8> {
18 self.buf.extend_from_slice(&MAGIC_HEADER);
19
20 self.compile_span(root_nodes);
21
22 self.buf
23 }
24
25 fn compile_span(&mut self, nodes: &[NodeId]) {
26 for node in nodes {
27 match node {
28 NodeId::Element(id) => self.compile_element(*id),
29 NodeId::Directive(id) => self.compile_directive(*id),
30 }
31 }
32 }
33
34 fn compile_block(&mut self, span: (u32, u32)) {
35 let start = span.0 as usize;
36 let len = span.1 as usize;
37 let nodes = &self.module.hierarchy[start..start + len];
38 self.compile_span(nodes);
39 self.buf.push(OP_END_BLOCK);
40 }
41
42 fn compile_element(&mut self, id: u32) {
43 let idx = id as usize;
44 let typ = &self.module.elem_types[idx];
45
46 self.buf.push(OP_ELEM_PUSH);
47 self.write_string(typ);
48
49 let (p_start, p_len) = self.module.elem_prop_spans[idx];
50 for i in p_start..(p_start + p_len) {
51 let key = &self.module.prop_keys[i as usize];
52 let val = &self.module.prop_values[i as usize];
53 self.compile_property(key, val);
54 }
55
56 if let Some(content) = &self.module.elem_content[idx] {
57 self.buf.push(OP_CONTENT);
58 self.compile_value(content);
59 }
60
61 let child_span = self.module.elem_child_spans[idx];
62 if child_span.1 > 0 {
63 self.compile_block(child_span);
64 }
65
66 self.buf.push(OP_ELEM_POP);
67 }
68
69 fn compile_directive(&mut self, id: u32) {
70 let dir = &self.module.directives[id as usize];
71 match dir {
72 Directive::Version(v) => {
73 self.buf.push(OP_VERSION);
74 self.write_i64(*v);
75 }
76 Directive::Style(s) => {
77 self.buf.push(OP_STYLE);
78 self.write_string(s);
79 }
80 Directive::Global { name, value } => {
81 self.buf.push(OP_GLOBAL);
82 self.write_string(name);
83 self.compile_value(value);
84 }
85 Directive::Singleton { name, prop_span } => {
86 self.buf.push(OP_SINGLETON);
87 self.write_string(name);
88 self.write_u32(prop_span.1);
89
90 let (start, len) = *prop_span;
91 for i in start..(start + len) {
92 let key = &self.module.prop_keys[i as usize];
93 let val = &self.module.prop_values[i as usize];
94 self.write_string(key);
95 self.compile_value(val);
96 }
97 }
98 Directive::Component {
99 name,
100 params,
101 child_span,
102 } => {
103 self.buf.push(OP_COMPONENT);
104 self.write_string(name);
105 self.write_u32(params.len() as u32);
106 for (pname, ptype) in params {
107 self.write_string(pname);
108 self.write_string(ptype);
109 }
110 self.compile_block(*child_span);
111 }
112 Directive::Let { name, value } => {
113 self.buf.push(OP_LET);
114 self.write_string(name);
115 self.compile_value(value);
116 }
117 Directive::If {
118 condition,
119 child_span,
120 else_span,
121 } => {
122 self.buf.push(OP_IF);
123 self.compile_value(condition);
124 self.compile_block(*child_span);
125 if let Some(es) = else_span {
126 self.buf.push(1); self.compile_block(*es);
128 } else {
129 self.buf.push(0); }
131 }
132 Directive::Each {
133 item,
134 collection,
135 child_span,
136 } => {
137 self.buf.push(OP_EACH);
138 self.write_string(item);
139 self.compile_value(collection);
140 self.compile_block(*child_span);
141 }
142 Directive::On {
143 event,
144 args,
145 child_span,
146 } => {
147 self.buf.push(OP_ON);
148 self.write_string(event);
149 self.write_u32(args.len() as u32);
150 for (k, v) in args {
151 self.write_string(k);
152 self.compile_value(v);
153 }
154 self.compile_block(*child_span);
155 }
156 Directive::RheiBlock(code) => {
157 self.buf.push(OP_RHEI_BLK);
158 self.write_string(code);
159 }
160 }
161 }
162
163 fn compile_property(&mut self, key: &str, val: &Value) {
164 match val {
165 Value::String(s) => {
166 self.buf.push(OP_PROP_STR);
167 self.write_string(key);
168 self.write_string(s);
169 }
170 Value::Int(i) => {
171 self.buf.push(OP_PROP_INT);
172 self.write_string(key);
173 self.write_i64(*i);
174 }
175 Value::Float(f) => {
176 self.buf.push(OP_PROP_FLOAT);
177 self.write_string(key);
178 self.write_f64(*f);
179 }
180 Value::Bool(b) => {
181 self.buf.push(OP_PROP_BOOL);
182 self.write_string(key);
183 self.buf.push(if *b { 1 } else { 0 });
184 }
185 Value::Color(c) => {
186 self.buf.push(OP_PROP_COLOR);
187 self.write_string(key);
188 self.write_string(c);
189 }
190 Value::FsPath(p) => {
191 self.buf.push(OP_PROP_FSPATH);
192 self.write_string(key);
193 self.write_string(p);
194 }
195 Value::Variable(v) => {
196 self.buf.push(OP_PROP_VAR);
197 self.write_string(key);
198 self.write_string(v);
199 }
200 Value::Rhei(r) => {
201 self.buf.push(OP_PROP_RHEI);
202 self.write_string(key);
203 self.write_string(r);
204 }
205 }
206 }
207
208 fn compile_value(&mut self, val: &Value) {
209 match val {
210 Value::String(s) => {
211 self.buf.push(OP_PROP_STR);
212 self.write_string(s);
213 }
214 Value::Int(i) => {
215 self.buf.push(OP_PROP_INT);
216 self.write_i64(*i);
217 }
218 Value::Float(f) => {
219 self.buf.push(OP_PROP_FLOAT);
220 self.write_f64(*f);
221 }
222 Value::Bool(b) => {
223 self.buf.push(OP_PROP_BOOL);
224 self.buf.push(if *b { 1 } else { 0 });
225 }
226 Value::Color(c) => {
227 self.buf.push(OP_PROP_COLOR);
228 self.write_string(c);
229 }
230 Value::FsPath(p) => {
231 self.buf.push(OP_PROP_FSPATH);
232 self.write_string(p);
233 }
234 Value::Variable(v) => {
235 self.buf.push(OP_PROP_VAR);
236 self.write_string(v);
237 }
238 Value::Rhei(r) => {
239 self.buf.push(OP_PROP_RHEI);
240 self.write_string(r);
241 }
242 }
243 }
244
245 fn write_string(&mut self, s: &str) {
246 let bytes = s.as_bytes();
247 self.write_u32(bytes.len() as u32);
248 self.buf.extend_from_slice(bytes);
249 }
250
251 fn write_u32(&mut self, v: u32) {
252 self.buf.extend_from_slice(&v.to_le_bytes());
253 }
254
255 fn write_i64(&mut self, v: i64) {
256 self.buf.extend_from_slice(&v.to_le_bytes());
257 }
258
259 fn write_f64(&mut self, v: f64) {
260 self.buf.extend_from_slice(&v.to_le_bytes());
261 }
262}