diff --git a/src/backend/edition/data.rs b/src/backend/edition/data.rs new file mode 100644 index 0000000..f22a982 --- /dev/null +++ b/src/backend/edition/data.rs @@ -0,0 +1,48 @@ +use super::{luajit::LuaJIT, luau::Luau}; +use crate::backend::helper::writer::Writer; +use std::{fmt::Display, io::Result}; + +pub struct Infix { + rhs: &'static str, + inner: T, +} + +impl Infix { + pub fn new(rhs: &'static str, inner: T) -> Self { + Infix { rhs, inner } + } +} + +impl Display for Infix +where + T: Display, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.inner.fmt(f)?; + self.rhs.fmt(f) + } +} + +pub trait Edition { + fn runtime(&self) -> &'static str; + + fn start_block(&self, w: Writer) -> Result<()>; + fn start_loop(&self, level: usize, w: Writer) -> Result<()>; + fn start_if(&self, cond: &str, w: Writer) -> Result<()>; + fn end_block(&self, level: usize, w: Writer) -> Result<()>; + fn end_loop(&self, w: Writer) -> Result<()>; + fn end_if(&self, level: usize, w: Writer) -> Result<()>; + + fn br_target(&self, level: usize, in_loop: bool, w: Writer) -> Result<()>; + fn br_to_level(&self, level: usize, up: usize, is_loop: bool, w: Writer) -> Result<()>; + + fn i64(&self, i: i64) -> Infix; +} + +pub fn from_string(name: &str) -> Option<&'static dyn Edition> { + match name.to_ascii_lowercase().as_str() { + "luau" => Some(&Luau), + "luajit" => Some(&LuaJIT), + _ => None, + } +} diff --git a/src/backend/edition/luajit.rs b/src/backend/edition/luajit.rs new file mode 100644 index 0000000..e2c3d35 --- /dev/null +++ b/src/backend/edition/luajit.rs @@ -0,0 +1,50 @@ +use super::data::{Edition, Infix}; +use crate::backend::helper::writer::Writer; +use std::io::Result; + +pub struct LuaJIT; + +impl Edition for LuaJIT { + fn runtime(&self) -> &'static str { + "'luajit'" + } + + fn start_block(&self, w: Writer) -> Result<()> { + write!(w, "do ") + } + + fn start_loop(&self, level: usize, w: Writer) -> Result<()> { + write!(w, "do ")?; + write!(w, "::continue_at_{}::", level) + } + + fn start_if(&self, cond: &str, w: Writer) -> Result<()> { + write!(w, "if {} ~= 0 then ", cond) + } + + fn end_block(&self, level: usize, w: Writer) -> Result<()> { + write!(w, "::continue_at_{}::", level)?; + write!(w, "end ") + } + + fn end_loop(&self, w: Writer) -> Result<()> { + write!(w, "end ") + } + + fn end_if(&self, level: usize, w: Writer) -> Result<()> { + write!(w, "::continue_at_{}::", level)?; + write!(w, "end ") + } + + fn br_target(&self, _level: usize, _in_loop: bool, _w: Writer) -> Result<()> { + Ok(()) + } + + fn br_to_level(&self, level: usize, up: usize, _is_loop: bool, w: Writer) -> Result<()> { + write!(w, "goto continue_at_{} ", level - up) + } + + fn i64(&self, i: i64) -> Infix { + Infix::new("LL", i) + } +} diff --git a/src/backend/edition/luau.rs b/src/backend/edition/luau.rs new file mode 100644 index 0000000..58419d2 --- /dev/null +++ b/src/backend/edition/luau.rs @@ -0,0 +1,75 @@ +use super::data::{Edition, Infix}; +use crate::backend::helper::writer::Writer; +use std::io::Result; + +pub struct Luau; + +impl Edition for Luau { + fn runtime(&self) -> &'static str { + "script.Runtime" + } + + fn start_block(&self, w: Writer) -> Result<()> { + write!(w, "while true do ") + } + + fn start_loop(&self, _level: usize, w: Writer) -> Result<()> { + write!(w, "while true do ") + } + + fn start_if(&self, cond: &str, w: Writer) -> Result<()> { + write!(w, "while true do ")?; + write!(w, "if {} ~= 0 then ", cond) + } + + fn end_block(&self, _level: usize, w: Writer) -> Result<()> { + write!(w, "break ")?; + write!(w, "end ") + } + + fn end_loop(&self, w: Writer) -> Result<()> { + write!(w, "break ")?; + write!(w, "end ") + } + + fn end_if(&self, _level: usize, w: Writer) -> Result<()> { + write!(w, "end ")?; + write!(w, "break ")?; + write!(w, "end ") + } + + fn br_target(&self, level: usize, in_loop: bool, w: Writer) -> Result<()> { + write!(w, "if desired then ")?; + write!(w, "if desired == {} then ", level)?; + write!(w, "desired = nil ")?; + + if in_loop { + write!(w, "continue ")?; + } + + write!(w, "end ")?; + write!(w, "break ")?; + write!(w, "end ") + } + + fn br_to_level(&self, level: usize, up: usize, is_loop: bool, w: Writer) -> Result<()> { + write!(w, "do ")?; + + if up == 0 { + if is_loop { + write!(w, "continue ")?; + } else { + write!(w, "break ")?; + } + } else { + write!(w, "desired = {} ", level - up)?; + write!(w, "break ")?; + } + + write!(w, "end ") + } + + fn i64(&self, i: i64) -> Infix { + Infix::new("", i) + } +} diff --git a/src/backend/edition/mod.rs b/src/backend/edition/mod.rs new file mode 100644 index 0000000..9d8c742 --- /dev/null +++ b/src/backend/edition/mod.rs @@ -0,0 +1,3 @@ +pub mod data; +pub mod luajit; +pub mod luau; diff --git a/src/backend/helper/edition.rs b/src/backend/helper/edition.rs deleted file mode 100755 index 577d166..0000000 --- a/src/backend/helper/edition.rs +++ /dev/null @@ -1,155 +0,0 @@ -use super::writer::Writer; -use std::{fmt::Display, io::Result}; - -pub struct Infix { - rhs: &'static str, - inner: T, -} - -impl Display for Infix -where - T: Display, -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.inner.fmt(f)?; - self.rhs.fmt(f) - } -} - -pub trait Edition { - fn runtime(&self) -> &'static str; - - fn start_block(&self, w: Writer) -> Result<()>; - fn start_loop(&self, level: usize, w: Writer) -> Result<()>; - fn start_if(&self, cond: &str, w: Writer) -> Result<()>; - fn end_block(&self, level: usize, w: Writer) -> Result<()>; - fn end_loop(&self, w: Writer) -> Result<()>; - fn end_if(&self, level: usize, w: Writer) -> Result<()>; - - fn br_target(&self, level: usize, in_loop: bool, w: Writer) -> Result<()>; - fn br_to_level(&self, level: usize, up: usize, is_loop: bool, w: Writer) -> Result<()>; - - fn i64(&self, i: i64) -> Infix; -} - -pub struct LuaJIT; - -impl Edition for LuaJIT { - fn runtime(&self) -> &'static str { - "'luajit'" - } - - fn start_block(&self, w: Writer) -> Result<()> { - write!(w, "do ") - } - - fn start_loop(&self, level: usize, w: Writer) -> Result<()> { - write!(w, "do ")?; - write!(w, "::continue_at_{}::", level) - } - - fn start_if(&self, cond: &str, w: Writer) -> Result<()> { - write!(w, "if {} ~= 0 then ", cond) - } - - fn end_block(&self, level: usize, w: Writer) -> Result<()> { - write!(w, "::continue_at_{}::", level)?; - write!(w, "end ") - } - - fn end_loop(&self, w: Writer) -> Result<()> { - write!(w, "end ") - } - - fn end_if(&self, level: usize, w: Writer) -> Result<()> { - write!(w, "::continue_at_{}::", level)?; - write!(w, "end ") - } - - fn br_target(&self, _level: usize, _in_loop: bool, _w: Writer) -> Result<()> { - Ok(()) - } - - fn br_to_level(&self, level: usize, up: usize, _is_loop: bool, w: Writer) -> Result<()> { - write!(w, "goto continue_at_{} ", level - up) - } - - fn i64(&self, i: i64) -> Infix { - Infix { - rhs: "LL", - inner: i, - } - } -} - -pub struct Luau; - -impl Edition for Luau { - fn runtime(&self) -> &'static str { - "script.Runtime" - } - - fn start_block(&self, w: Writer) -> Result<()> { - write!(w, "while true do ") - } - - fn start_loop(&self, _level: usize, w: Writer) -> Result<()> { - write!(w, "while true do ") - } - - fn start_if(&self, cond: &str, w: Writer) -> Result<()> { - write!(w, "while true do ")?; - write!(w, "if {} ~= 0 then ", cond) - } - - fn end_block(&self, _level: usize, w: Writer) -> Result<()> { - write!(w, "break ")?; - write!(w, "end ") - } - - fn end_loop(&self, w: Writer) -> Result<()> { - write!(w, "break ")?; - write!(w, "end ") - } - - fn end_if(&self, _level: usize, w: Writer) -> Result<()> { - write!(w, "end ")?; - write!(w, "break ")?; - write!(w, "end ") - } - - fn br_target(&self, level: usize, in_loop: bool, w: Writer) -> Result<()> { - write!(w, "if desired then ")?; - write!(w, "if desired == {} then ", level)?; - write!(w, "desired = nil ")?; - - if in_loop { - write!(w, "continue ")?; - } - - write!(w, "end ")?; - write!(w, "break ")?; - write!(w, "end ") - } - - fn br_to_level(&self, level: usize, up: usize, is_loop: bool, w: Writer) -> Result<()> { - write!(w, "do ")?; - - if up == 0 { - if is_loop { - write!(w, "continue ")?; - } else { - write!(w, "break ")?; - } - } else { - write!(w, "desired = {} ", level - up)?; - write!(w, "break ")?; - } - - write!(w, "end ") - } - - fn i64(&self, i: i64) -> Infix { - Infix { rhs: "", inner: i } - } -} diff --git a/src/backend/helper/mod.rs b/src/backend/helper/mod.rs index 2b70580..2f4b365 100644 --- a/src/backend/helper/mod.rs +++ b/src/backend/helper/mod.rs @@ -1,3 +1,2 @@ -pub mod edition; pub mod register; pub mod writer; diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 48c91a8..643b8c8 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,2 +1,3 @@ +pub mod edition; pub mod helper; pub mod translation; diff --git a/src/backend/translation/level_1.rs b/src/backend/translation/level_1.rs index 0d83cb9..421b8f3 100644 --- a/src/backend/translation/level_1.rs +++ b/src/backend/translation/level_1.rs @@ -1,6 +1,9 @@ use super::level_2::list_to_range; use crate::{ - backend::helper::{edition::Edition, register::Register, writer::Writer}, + backend::{ + edition::data::Edition, + helper::{register::Register, writer::Writer}, + }, data::{Arity, Code, Module}, }; use parity_wasm::elements::{BrTableData, Instruction}; diff --git a/src/backend/translation/level_2.rs b/src/backend/translation/level_2.rs index a5f87a8..fca4ebb 100644 --- a/src/backend/translation/level_2.rs +++ b/src/backend/translation/level_2.rs @@ -1,8 +1,8 @@ use super::level_1::Body; use crate::{ - backend::helper::{ - edition::Edition, - writer::{write_ordered, Writer}, + backend::{ + edition::data::Edition, + helper::writer::{write_ordered, Writer}, }, data::Module, }; diff --git a/src/backend/translation/level_3.rs b/src/backend/translation/level_3.rs index 2430523..d352cc0 100755 --- a/src/backend/translation/level_3.rs +++ b/src/backend/translation/level_3.rs @@ -1,6 +1,6 @@ use super::level_2::{gen_function, gen_init_expression}; use crate::{ - backend::helper::{edition::Edition, writer::Writer}, + backend::{edition::data::Edition, helper::writer::Writer}, data::Module, }; use parity_wasm::elements::{External, ImportCountType, Internal, ResizableLimits}; diff --git a/src/main.rs b/src/main.rs index a8d8731..883b9be 100755 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,4 @@ -use backend::{ - helper::edition::{Edition, LuaJIT, Luau}, - translation::level_3, -}; +use backend::{edition::data::from_string, translation::level_3}; use data::Module; use parity_wasm::elements::deserialize_file; @@ -10,14 +7,11 @@ mod data; fn main() { let mut args = std::env::args().skip(1); - let spec: &dyn Edition = match args.next().as_deref().map(str::to_lowercase).as_deref() { - Some("luau") => &Luau, - Some("luajit") => &LuaJIT, - _ => { - println!("expected either 'luau' or 'luajit' option"); - return; - } - }; + let spec = args + .next() + .as_deref() + .and_then(from_string) + .expect("No language argument provided"); let output = std::io::stdout();