Skip to main content

oak_wat/ast/
mod.rs

1#![doc = include_str!("readme.md")]
2use oak_core::source::{SourceBuffer, ToSource};
3
4/// Root node of the WAT AST.
5#[derive(Clone, Debug)]
6pub struct WatRoot {
7    /// Items in the WAT file.
8    pub items: Vec<WatItem>,
9}
10
11impl ToSource for WatRoot {
12    fn to_source(&self, buffer: &mut SourceBuffer) {
13        for item in &self.items {
14            item.to_source(buffer);
15            buffer.push("\n")
16        }
17    }
18}
19
20/// An item in a WAT file.
21#[derive(Clone, Debug)]
22pub enum WatItem {
23    /// A module definition.
24    Module(WatModule),
25}
26
27impl ToSource for WatItem {
28    fn to_source(&self, buffer: &mut SourceBuffer) {
29        match self {
30            WatItem::Module(m) => m.to_source(buffer),
31        }
32    }
33}
34
35/// A WebAssembly module.
36#[derive(Clone, Debug)]
37pub struct WatModule {
38    /// Optional name of the module.
39    pub name: Option<String>,
40    /// Fields within the module.
41    pub items: Vec<WatModuleField>,
42}
43
44impl ToSource for WatModule {
45    fn to_source(&self, buffer: &mut SourceBuffer) {
46        buffer.push("(module");
47        if let Some(name) = &self.name {
48            buffer.push(" ");
49            buffer.push(name)
50        }
51        for item in &self.items {
52            buffer.push("\n  ");
53            item.to_source(buffer)
54        }
55        buffer.push(")")
56    }
57}
58
59/// A field within a WebAssembly module.
60#[derive(Clone, Debug)]
61pub enum WatModuleField {
62    /// A function definition.
63    Func(WatFunc),
64    /// An import definition.
65    Import(WatImport),
66    /// An export definition.
67    Export(WatExport),
68    /// A type definition.
69    Type(WatType),
70    /// A table definition.
71    Table(WatTable),
72    /// A memory definition.
73    Memory(WatMemory),
74    /// A global variable definition.
75    Global(WatGlobal),
76}
77
78impl ToSource for WatModuleField {
79    fn to_source(&self, buffer: &mut SourceBuffer) {
80        match self {
81            WatModuleField::Func(f) => f.to_source(buffer),
82            WatModuleField::Import(i) => i.to_source(buffer),
83            WatModuleField::Export(e) => e.to_source(buffer),
84            WatModuleField::Type(t) => t.to_source(buffer),
85            WatModuleField::Table(t) => t.to_source(buffer),
86            WatModuleField::Memory(m) => m.to_source(buffer),
87            WatModuleField::Global(g) => g.to_source(buffer),
88        }
89    }
90}
91
92/// A WebAssembly function.
93#[derive(Clone, Debug)]
94pub struct WatFunc {
95    /// Optional name of the function.
96    pub name: Option<String>,
97    /// Parameters of the function.
98    pub params: Vec<WatParam>,
99    /// Result types of the function.
100    pub results: Vec<WatResult>,
101    /// Local variables of the function.
102    pub locals: Vec<WatLocal>,
103    /// Instructions in the function body.
104    pub body: Vec<WatInstruction>,
105}
106
107impl ToSource for WatFunc {
108    fn to_source(&self, buffer: &mut SourceBuffer) {
109        buffer.push("(func");
110        if let Some(name) = &self.name {
111            buffer.push(" ");
112            buffer.push(name)
113        }
114        for param in &self.params {
115            buffer.push(" ");
116            param.to_source(buffer)
117        }
118        for result in &self.results {
119            buffer.push(" ");
120            result.to_source(buffer)
121        }
122        for local in &self.locals {
123            buffer.push(" ");
124            local.to_source(buffer)
125        }
126        for instr in &self.body {
127            buffer.push("\n    ");
128            instr.to_source(buffer)
129        }
130        buffer.push(")")
131    }
132}
133
134/// A parameter in a WAT function.
135#[derive(Clone, Debug)]
136pub struct WatParam {
137    /// Optional name of the parameter.
138    pub name: Option<String>,
139    /// Type of the parameter.
140    pub ty: WatTypeKind,
141}
142
143impl ToSource for WatParam {
144    fn to_source(&self, buffer: &mut SourceBuffer) {
145        buffer.push("(param");
146        if let Some(name) = &self.name {
147            buffer.push(" ");
148            buffer.push(name)
149        }
150        buffer.push(" ");
151        self.ty.to_source(buffer);
152        buffer.push(")")
153    }
154}
155
156/// A result type in a WAT function.
157#[derive(Clone, Debug)]
158pub struct WatResult {
159    /// Type of the result.
160    pub ty: WatTypeKind,
161}
162
163impl ToSource for WatResult {
164    fn to_source(&self, buffer: &mut SourceBuffer) {
165        buffer.push("(result ");
166        self.ty.to_source(buffer);
167        buffer.push(")")
168    }
169}
170
171/// A local variable in a WAT function.
172#[derive(Clone, Debug)]
173pub struct WatLocal {
174    /// Optional name of the local variable.
175    pub name: Option<String>,
176    /// Type of the local variable.
177    pub ty: WatTypeKind,
178}
179
180impl ToSource for WatLocal {
181    fn to_source(&self, buffer: &mut SourceBuffer) {
182        buffer.push("(local");
183        if let Some(name) = &self.name {
184            buffer.push(" ");
185            buffer.push(name)
186        }
187        buffer.push(" ");
188        self.ty.to_source(buffer);
189        buffer.push(")")
190    }
191}
192
193/// Supported types in WAT.
194#[derive(Clone, Debug)]
195pub enum WatTypeKind {
196    /// 32-bit integer.
197    I32,
198    /// 64-bit integer.
199    I64,
200    /// 32-bit float.
201    F32,
202    /// 64-bit float.
203    F64,
204}
205
206impl ToSource for WatTypeKind {
207    fn to_source(&self, buffer: &mut SourceBuffer) {
208        match self {
209            WatTypeKind::I32 => buffer.push("i32"),
210            WatTypeKind::I64 => buffer.push("i64"),
211            WatTypeKind::F32 => buffer.push("f32"),
212            WatTypeKind::F64 => buffer.push("f64"),
213        }
214    }
215}
216
217/// A WebAssembly instruction.
218#[derive(Clone, Debug)]
219pub enum WatInstruction {
220    /// unreachable
221    Unreachable,
222    /// nop
223    Nop,
224    /// drop
225    Drop,
226    /// select
227    Select,
228    /// return
229    Return,
230    /// local.get
231    LocalGet(String),
232    /// local.set
233    LocalSet(String),
234    /// local.tee
235    LocalTee(String),
236    /// global.get
237    GlobalGet(String),
238    /// global.set
239    GlobalSet(String),
240    /// i32.const
241    I32Const(i32),
242    /// i64.const
243    I64Const(i64),
244    /// f32.const
245    F32Const(f32),
246    /// f64.const
247    F64Const(f64),
248    /// i32.add
249    I32Add,
250    /// i32.sub
251    I32Sub,
252    /// i32.mul
253    I32Mul,
254    /// i64.add
255    I64Add,
256    /// i64.sub
257    I64Sub,
258    /// i64.mul
259    I64Mul,
260    /// Other instruction
261    Other(String, Vec<String>),
262}
263
264impl ToSource for WatInstruction {
265    fn to_source(&self, buffer: &mut SourceBuffer) {
266        match self {
267            WatInstruction::Unreachable => buffer.push("unreachable"),
268            WatInstruction::Nop => buffer.push("nop"),
269            WatInstruction::Drop => buffer.push("drop"),
270            WatInstruction::Select => buffer.push("select"),
271            WatInstruction::Return => buffer.push("return"),
272            WatInstruction::LocalGet(id) => {
273                buffer.push("local.get ");
274                buffer.push(id);
275            }
276            WatInstruction::LocalSet(id) => {
277                buffer.push("local.set ");
278                buffer.push(id);
279            }
280            WatInstruction::LocalTee(id) => {
281                buffer.push("local.tee ");
282                buffer.push(id);
283            }
284            WatInstruction::GlobalGet(id) => {
285                buffer.push("global.get ");
286                buffer.push(id);
287            }
288            WatInstruction::GlobalSet(id) => {
289                buffer.push("global.set ");
290                buffer.push(id);
291            }
292            WatInstruction::I32Const(val) => {
293                buffer.push("i32.const ");
294                buffer.push(&val.to_string());
295            }
296            WatInstruction::I64Const(val) => {
297                buffer.push("i64.const ");
298                buffer.push(&val.to_string());
299            }
300            WatInstruction::F32Const(val) => {
301                buffer.push("f32.const ");
302                buffer.push(&val.to_string());
303            }
304            WatInstruction::F64Const(val) => {
305                buffer.push("f64.const ");
306                buffer.push(&val.to_string());
307            }
308            WatInstruction::I32Add => buffer.push("i32.add"),
309            WatInstruction::I32Sub => buffer.push("i32.sub"),
310            WatInstruction::I32Mul => buffer.push("i32.mul"),
311            WatInstruction::I64Add => buffer.push("i64.add"),
312            WatInstruction::I64Sub => buffer.push("i64.sub"),
313            WatInstruction::I64Mul => buffer.push("i64.mul"),
314            WatInstruction::Other(name, args) => {
315                buffer.push(name);
316                for arg in args {
317                    buffer.push(" ");
318                    buffer.push(arg);
319                }
320            }
321        }
322    }
323}
324
325/// A WebAssembly import.
326#[derive(Clone, Debug)]
327pub struct WatImport {
328    /// Module name being imported from.
329    pub module: String,
330    /// Field name being imported.
331    pub name: String,
332    /// Kind of import (e.g., "func", "memory").
333    pub kind: String,
334}
335
336impl ToSource for WatImport {
337    fn to_source(&self, buffer: &mut SourceBuffer) {
338        buffer.push("(import \"");
339        buffer.push(&self.module);
340        buffer.push("\" \"");
341        buffer.push(&self.name);
342        buffer.push("\" (");
343        buffer.push(&self.kind);
344        buffer.push("))")
345    }
346}
347
348/// A WebAssembly export.
349#[derive(Clone, Debug)]
350pub struct WatExport {
351    /// Name being exported as.
352    pub name: String,
353    /// Kind of export (e.g., "func", "memory").
354    pub kind: String,
355    /// ID of the exported item (index or name).
356    pub id: String,
357}
358
359impl ToSource for WatExport {
360    fn to_source(&self, buffer: &mut SourceBuffer) {
361        buffer.push("(export \"");
362        buffer.push(&self.name);
363        buffer.push("\" (");
364        buffer.push(&self.kind);
365        buffer.push(" ");
366        buffer.push(&self.id);
367        buffer.push("))")
368    }
369}
370
371/// A WebAssembly type definition.
372#[derive(Clone, Debug)]
373pub struct WatType {
374    /// Optional name of the type.
375    pub id: Option<String>,
376}
377
378impl ToSource for WatType {
379    fn to_source(&self, buffer: &mut SourceBuffer) {
380        buffer.push("(type");
381        if let Some(id) = &self.id {
382            buffer.push(" ");
383            buffer.push(id)
384        }
385        buffer.push(")")
386    }
387}
388
389/// A WebAssembly table definition.
390#[derive(Clone, Debug)]
391pub struct WatTable {
392    /// Optional ID of the table.
393    pub id: Option<String>,
394    /// Span of the table.
395    pub span: oak_core::Range<usize>,
396}
397
398impl ToSource for WatTable {
399    fn to_source(&self, buffer: &mut SourceBuffer) {
400        buffer.push("(table");
401        if let Some(id) = &self.id {
402            buffer.push(" ");
403            buffer.push(id)
404        }
405        buffer.push(")")
406    }
407}
408
409/// A WebAssembly memory definition.
410#[derive(Clone, Debug)]
411pub struct WatMemory {
412    /// Optional ID of the memory.
413    pub id: Option<String>,
414    /// Span of the memory.
415    pub span: oak_core::Range<usize>,
416}
417
418impl ToSource for WatMemory {
419    fn to_source(&self, buffer: &mut SourceBuffer) {
420        buffer.push("(memory");
421        if let Some(id) = &self.id {
422            buffer.push(" ");
423            buffer.push(id)
424        }
425        buffer.push(")")
426    }
427}
428
429/// A WebAssembly global variable definition.
430#[derive(Clone, Debug)]
431pub struct WatGlobal {
432    /// Optional name of the global variable.
433    pub id: Option<String>,
434    /// Type of the global variable.
435    pub ty: WatTypeKind,
436    /// Whether the global variable is mutable.
437    pub mutable: bool,
438}
439
440impl ToSource for WatGlobal {
441    fn to_source(&self, buffer: &mut SourceBuffer) {
442        buffer.push("(global");
443        if let Some(id) = &self.id {
444            buffer.push(" ");
445            buffer.push(id)
446        }
447        buffer.push(" ");
448        if self.mutable {
449            buffer.push("(mut ");
450            self.ty.to_source(buffer);
451            buffer.push(")");
452        }
453        else {
454            self.ty.to_source(buffer);
455        }
456        buffer.push(")")
457    }
458}