diff --git a/codegen-luau/src/backend/expression.rs b/codegen-luau/src/backend/expression.rs new file mode 100644 index 0000000..358b833 --- /dev/null +++ b/codegen-luau/src/backend/expression.rs @@ -0,0 +1,147 @@ +use std::io::{Result, Write}; + +use wasm_ast::node::{ + BinOp, CmpOp, Expression, GetGlobal, GetLocal, LoadAt, MemoryGrow, MemorySize, Recall, Select, + UnOp, Value, +}; + +use super::manager::{write_f32, write_f64, write_separated, write_variable, Driver, Manager}; + +impl Driver for Recall { + fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { + write!(w, "reg_{} ", self.var) + } +} + +impl Driver for Select { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + write!(w, "(")?; + self.cond.write(mng, w)?; + write!(w, "~= 0 and ")?; + self.a.write(mng, w)?; + write!(w, "or ")?; + self.b.write(mng, w)?; + write!(w, ")") + } +} + +impl Driver for GetLocal { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + write_variable(self.var, mng, w) + } +} + +impl Driver for GetGlobal { + fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { + write!(w, "GLOBAL_LIST[{}].value ", self.var) + } +} + +impl Driver for LoadAt { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + write!(w, "load_{}(memory_at_0, ", self.what.as_name())?; + self.pointer.write(mng, w)?; + write!(w, "+ {})", self.offset) + } +} + +impl Driver for MemorySize { + fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { + write!(w, "memory_at_{}.min ", self.memory) + } +} + +impl Driver for MemoryGrow { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + write!(w, "rt.allocator.grow(memory_at_{}, ", self.memory)?; + self.value.write(mng, w)?; + write!(w, ")") + } +} + +impl Driver for Value { + fn write(&self, _: &mut Manager, w: &mut dyn Write) -> Result<()> { + match self { + Self::I32(i) => write!(w, "{i} "), + Self::I64(i) => write!(w, "{i} "), + Self::F32(f) => write_f32(*f, w), + Self::F64(f) => write_f64(*f, w), + } + } +} + +impl Driver for UnOp { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + let (a, b) = self.op.as_name(); + + write!(w, "{a}_{b}(")?; + self.rhs.write(mng, w)?; + write!(w, ")") + } +} + +fn write_bin_op(bin_op: &BinOp, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + let op = bin_op.op.as_operator().unwrap(); + + write!(w, "(")?; + bin_op.lhs.write(mng, w)?; + write!(w, "{op} ")?; + bin_op.rhs.write(mng, w)?; + write!(w, ")") +} + +fn write_bin_op_call(bin_op: &BinOp, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + let (a, b) = bin_op.op.as_name(); + + write!(w, "{a}_{b}(")?; + bin_op.lhs.write(mng, w)?; + write!(w, ", ")?; + bin_op.rhs.write(mng, w)?; + write!(w, ")") +} + +impl Driver for BinOp { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + if self.op.as_operator().is_some() { + write_bin_op(self, mng, w) + } else { + write_bin_op_call(self, mng, w) + } + } +} + +impl Driver for CmpOp { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + let (a, b) = self.op.as_name(); + + write!(w, "{a}_{b}(")?; + self.lhs.write(mng, w)?; + write!(w, ", ")?; + self.rhs.write(mng, w)?; + write!(w, ")") + } +} + +impl Driver for Expression { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + match self { + Self::Recall(e) => e.write(mng, w), + Self::Select(e) => e.write(mng, w), + Self::GetLocal(e) => e.write(mng, w), + Self::GetGlobal(e) => e.write(mng, w), + Self::LoadAt(e) => e.write(mng, w), + Self::MemorySize(e) => e.write(mng, w), + Self::MemoryGrow(e) => e.write(mng, w), + Self::Value(e) => e.write(mng, w), + Self::UnOp(e) => e.write(mng, w), + Self::BinOp(e) => e.write(mng, w), + Self::CmpOp(e) => e.write(mng, w), + } + } +} + +impl Driver for &[Expression] { + fn write(&self, mng: &mut Manager, w: &mut dyn Write) -> Result<()> { + write_separated(self.iter(), |e, w| e.write(mng, w), w) + } +} diff --git a/codegen-luau/src/backend/manager.rs b/codegen-luau/src/backend/manager.rs new file mode 100644 index 0000000..d917b54 --- /dev/null +++ b/codegen-luau/src/backend/manager.rs @@ -0,0 +1,89 @@ +use std::{ + io::{Result, Write}, + ops::Range, +}; + +#[derive(PartialEq, Eq)] +pub enum Label { + Forward, + Backward, + If, +} + +#[derive(Default)] +pub struct Manager { + label_list: Vec