#![doc = include_str!("readme.md")]
use oak_core::source::{SourceBuffer, ToSource};
#[derive(Clone, Debug)]
pub struct WatRoot {
pub items: Vec<WatItem>,
}
impl ToSource for WatRoot {
fn to_source(&self, buffer: &mut SourceBuffer) {
for item in &self.items {
item.to_source(buffer);
buffer.push("\n")
}
}
}
#[derive(Clone, Debug)]
pub enum WatItem {
Module(WatModule),
}
impl ToSource for WatItem {
fn to_source(&self, buffer: &mut SourceBuffer) {
match self {
WatItem::Module(m) => m.to_source(buffer),
}
}
}
#[derive(Clone, Debug)]
pub struct WatModule {
pub name: Option<String>,
pub items: Vec<WatModuleField>,
}
impl ToSource for WatModule {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(module");
if let Some(name) = &self.name {
buffer.push(" ");
buffer.push(name)
}
for item in &self.items {
buffer.push("\n ");
item.to_source(buffer)
}
buffer.push(")")
}
}
#[derive(Clone, Debug)]
pub enum WatModuleField {
Func(WatFunc),
Import(WatImport),
Export(WatExport),
Type(WatType),
Table(WatTable),
Memory(WatMemory),
Global(WatGlobal),
}
impl ToSource for WatModuleField {
fn to_source(&self, buffer: &mut SourceBuffer) {
match self {
WatModuleField::Func(f) => f.to_source(buffer),
WatModuleField::Import(i) => i.to_source(buffer),
WatModuleField::Export(e) => e.to_source(buffer),
WatModuleField::Type(t) => t.to_source(buffer),
WatModuleField::Table(t) => t.to_source(buffer),
WatModuleField::Memory(m) => m.to_source(buffer),
WatModuleField::Global(g) => g.to_source(buffer),
}
}
}
#[derive(Clone, Debug)]
pub struct WatFunc {
pub name: Option<String>,
pub params: Vec<WatParam>,
pub results: Vec<WatResult>,
pub locals: Vec<WatLocal>,
pub body: Vec<WatInstruction>,
}
impl ToSource for WatFunc {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(func");
if let Some(name) = &self.name {
buffer.push(" ");
buffer.push(name)
}
for param in &self.params {
buffer.push(" ");
param.to_source(buffer)
}
for result in &self.results {
buffer.push(" ");
result.to_source(buffer)
}
for local in &self.locals {
buffer.push(" ");
local.to_source(buffer)
}
for instr in &self.body {
buffer.push("\n ");
instr.to_source(buffer)
}
buffer.push(")")
}
}
#[derive(Clone, Debug)]
pub struct WatParam {
pub name: Option<String>,
pub ty: WatTypeKind,
}
impl ToSource for WatParam {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(param");
if let Some(name) = &self.name {
buffer.push(" ");
buffer.push(name)
}
buffer.push(" ");
self.ty.to_source(buffer);
buffer.push(")")
}
}
#[derive(Clone, Debug)]
pub struct WatResult {
pub ty: WatTypeKind,
}
impl ToSource for WatResult {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(result ");
self.ty.to_source(buffer);
buffer.push(")")
}
}
#[derive(Clone, Debug)]
pub struct WatLocal {
pub name: Option<String>,
pub ty: WatTypeKind,
}
impl ToSource for WatLocal {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(local");
if let Some(name) = &self.name {
buffer.push(" ");
buffer.push(name)
}
buffer.push(" ");
self.ty.to_source(buffer);
buffer.push(")")
}
}
#[derive(Clone, Debug)]
pub enum WatTypeKind {
I32,
I64,
F32,
F64,
}
impl ToSource for WatTypeKind {
fn to_source(&self, buffer: &mut SourceBuffer) {
match self {
WatTypeKind::I32 => buffer.push("i32"),
WatTypeKind::I64 => buffer.push("i64"),
WatTypeKind::F32 => buffer.push("f32"),
WatTypeKind::F64 => buffer.push("f64"),
}
}
}
#[derive(Clone, Debug)]
pub enum WatInstruction {
Unreachable,
Nop,
Drop,
Select,
Return,
LocalGet(String),
LocalSet(String),
LocalTee(String),
GlobalGet(String),
GlobalSet(String),
I32Const(i32),
I64Const(i64),
F32Const(f32),
F64Const(f64),
I32Add,
I32Sub,
I32Mul,
I64Add,
I64Sub,
I64Mul,
Other(String, Vec<String>),
}
impl ToSource for WatInstruction {
fn to_source(&self, buffer: &mut SourceBuffer) {
match self {
WatInstruction::Unreachable => buffer.push("unreachable"),
WatInstruction::Nop => buffer.push("nop"),
WatInstruction::Drop => buffer.push("drop"),
WatInstruction::Select => buffer.push("select"),
WatInstruction::Return => buffer.push("return"),
WatInstruction::LocalGet(id) => {
buffer.push("local.get ");
buffer.push(id);
}
WatInstruction::LocalSet(id) => {
buffer.push("local.set ");
buffer.push(id);
}
WatInstruction::LocalTee(id) => {
buffer.push("local.tee ");
buffer.push(id);
}
WatInstruction::GlobalGet(id) => {
buffer.push("global.get ");
buffer.push(id);
}
WatInstruction::GlobalSet(id) => {
buffer.push("global.set ");
buffer.push(id);
}
WatInstruction::I32Const(val) => {
buffer.push("i32.const ");
buffer.push(&val.to_string());
}
WatInstruction::I64Const(val) => {
buffer.push("i64.const ");
buffer.push(&val.to_string());
}
WatInstruction::F32Const(val) => {
buffer.push("f32.const ");
buffer.push(&val.to_string());
}
WatInstruction::F64Const(val) => {
buffer.push("f64.const ");
buffer.push(&val.to_string());
}
WatInstruction::I32Add => buffer.push("i32.add"),
WatInstruction::I32Sub => buffer.push("i32.sub"),
WatInstruction::I32Mul => buffer.push("i32.mul"),
WatInstruction::I64Add => buffer.push("i64.add"),
WatInstruction::I64Sub => buffer.push("i64.sub"),
WatInstruction::I64Mul => buffer.push("i64.mul"),
WatInstruction::Other(name, args) => {
buffer.push(name);
for arg in args {
buffer.push(" ");
buffer.push(arg);
}
}
}
}
}
#[derive(Clone, Debug)]
pub struct WatImport {
pub module: String,
pub name: String,
pub kind: String,
}
impl ToSource for WatImport {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(import \"");
buffer.push(&self.module);
buffer.push("\" \"");
buffer.push(&self.name);
buffer.push("\" (");
buffer.push(&self.kind);
buffer.push("))")
}
}
#[derive(Clone, Debug)]
pub struct WatExport {
pub name: String,
pub kind: String,
pub id: String,
}
impl ToSource for WatExport {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(export \"");
buffer.push(&self.name);
buffer.push("\" (");
buffer.push(&self.kind);
buffer.push(" ");
buffer.push(&self.id);
buffer.push("))")
}
}
#[derive(Clone, Debug)]
pub struct WatType {
pub id: Option<String>,
}
impl ToSource for WatType {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(type");
if let Some(id) = &self.id {
buffer.push(" ");
buffer.push(id)
}
buffer.push(")")
}
}
#[derive(Clone, Debug)]
pub struct WatTable {
pub id: Option<String>,
pub span: oak_core::Range<usize>,
}
impl ToSource for WatTable {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(table");
if let Some(id) = &self.id {
buffer.push(" ");
buffer.push(id)
}
buffer.push(")")
}
}
#[derive(Clone, Debug)]
pub struct WatMemory {
pub id: Option<String>,
pub span: oak_core::Range<usize>,
}
impl ToSource for WatMemory {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(memory");
if let Some(id) = &self.id {
buffer.push(" ");
buffer.push(id)
}
buffer.push(")")
}
}
#[derive(Clone, Debug)]
pub struct WatGlobal {
pub id: Option<String>,
pub ty: WatTypeKind,
pub mutable: bool,
}
impl ToSource for WatGlobal {
fn to_source(&self, buffer: &mut SourceBuffer) {
buffer.push("(global");
if let Some(id) = &self.id {
buffer.push(" ");
buffer.push(id)
}
buffer.push(" ");
if self.mutable {
buffer.push("(mut ");
self.ty.to_source(buffer);
buffer.push(")");
}
else {
self.ty.to_source(buffer);
}
buffer.push(")")
}
}