Add vector_lib/vector_ctor options to Luau Compiler (hidden)

This commit is contained in:
Alex Orlenko 2022-03-31 19:05:19 +01:00
parent d5315da8d1
commit ac28c8d8d2
No known key found for this signature in database
GPG Key ID: 4C150C250863B96D
1 changed files with 67 additions and 20 deletions

View File

@ -66,11 +66,13 @@ pub enum ChunkMode {
/// Luau compiler /// Luau compiler
#[cfg(any(feature = "luau", doc))] #[cfg(any(feature = "luau", doc))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))] #[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
#[derive(Clone, Copy, Debug)] #[derive(Clone, Debug)]
pub struct Compiler { pub struct Compiler {
optimization_level: u8, optimization_level: u8,
debug_level: u8, debug_level: u8,
coverage_level: u8, coverage_level: u8,
vector_lib: Option<String>,
vector_ctor: Option<String>,
} }
#[cfg(any(feature = "luau", doc))] #[cfg(any(feature = "luau", doc))]
@ -81,6 +83,8 @@ impl Default for Compiler {
optimization_level: 1, optimization_level: 1,
debug_level: 1, debug_level: 1,
coverage_level: 0, coverage_level: 0,
vector_lib: None,
vector_ctor: None,
} }
} }
} }
@ -95,10 +99,10 @@ impl Compiler {
/// Sets Luau compiler optimization level. /// Sets Luau compiler optimization level.
/// ///
/// Possible values: /// Possible values:
/// 0 - no optimization /// * 0 - no optimization
/// 1 - baseline optimization level that doesn't prevent debuggability (default) /// * 1 - baseline optimization level that doesn't prevent debuggability (default)
/// 2 - includes optimizations that harm debuggability such as inlining /// * 2 - includes optimizations that harm debuggability such as inlining
pub fn set_optimization_level(mut self, level: u8) -> Self { pub fn set_optimization_level(&mut self, level: u8) -> &mut Self {
self.optimization_level = level; self.optimization_level = level;
self self
} }
@ -106,10 +110,10 @@ impl Compiler {
/// Sets Luau compiler debug level. /// Sets Luau compiler debug level.
/// ///
/// Possible values: /// Possible values:
/// 0 - no debugging support /// * 0 - no debugging support
/// 1 - line info & function names only; sufficient for backtraces (default) /// * 1 - line info & function names only; sufficient for backtraces (default)
/// 2 - full debug info with local & upvalue names; necessary for debugger /// * 2 - full debug info with local & upvalue names; necessary for debugger
pub fn set_debug_level(mut self, level: u8) -> Self { pub fn set_debug_level(&mut self, level: u8) -> &mut Self {
self.debug_level = level; self.debug_level = level;
self self
} }
@ -117,26 +121,45 @@ impl Compiler {
/// Sets Luau compiler code coverage level. /// Sets Luau compiler code coverage level.
/// ///
/// Possible values: /// Possible values:
/// 0 - no code coverage support (default) /// * 0 - no code coverage support (default)
/// 1 - statement coverage /// * 1 - statement coverage
/// 2 - statement and expression coverage (verbose) /// * 2 - statement and expression coverage (verbose)
pub fn set_coverage_level(mut self, level: u8) -> Self { pub fn set_coverage_level(&mut self, level: u8) -> &mut Self {
self.coverage_level = level; self.coverage_level = level;
self self
} }
#[doc(hidden)]
pub fn set_vector_lib(&mut self, lib: Option<String>) -> &mut Self {
self.vector_lib = lib;
self
}
#[doc(hidden)]
pub fn set_vector_ctor(&mut self, ctor: Option<String>) -> &mut Self {
self.vector_ctor = ctor;
self
}
/// Compiles the `source` into bytecode. /// Compiles the `source` into bytecode.
pub fn compile(&self, source: impl AsRef<[u8]>) -> Vec<u8> { pub fn compile(&self, source: impl AsRef<[u8]>) -> Vec<u8> {
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr; use std::ptr;
let vector_lib = self.vector_lib.clone();
let vector_lib = vector_lib.and_then(|lib| CString::new(lib).ok());
let vector_lib = vector_lib.as_ref();
let vector_ctor = self.vector_ctor.clone();
let vector_ctor = vector_ctor.and_then(|ctor| CString::new(ctor).ok());
let vector_ctor = vector_ctor.as_ref();
unsafe { unsafe {
let options = ffi::lua_CompileOptions { let options = ffi::lua_CompileOptions {
optimizationLevel: self.optimization_level as c_int, optimizationLevel: self.optimization_level as c_int,
debugLevel: self.debug_level as c_int, debugLevel: self.debug_level as c_int,
coverageLevel: self.coverage_level as c_int, coverageLevel: self.coverage_level as c_int,
vectorLib: ptr::null(), vectorLib: vector_lib.map_or(ptr::null(), |s| s.as_ptr()),
vectorCtor: ptr::null(), vectorCtor: vector_ctor.map_or(ptr::null(), |s| s.as_ptr()),
mutableGlobals: ptr::null_mut(), mutableGlobals: ptr::null_mut(),
}; };
ffi::luau_compile(source.as_ref(), options) ffi::luau_compile(source.as_ref(), options)
@ -146,7 +169,7 @@ impl Compiler {
impl<'lua, 'a> Chunk<'lua, 'a> { impl<'lua, 'a> Chunk<'lua, 'a> {
/// Sets the name of this chunk, which results in more informative error traces. /// Sets the name of this chunk, which results in more informative error traces.
pub fn set_name<S: AsRef<[u8]> + ?Sized>(mut self, name: &S) -> Result<Chunk<'lua, 'a>> { pub fn set_name<S: AsRef<[u8]> + ?Sized>(mut self, name: &S) -> Result<Self> {
let name = let name =
CString::new(name.as_ref().to_vec()).map_err(|e| Error::ToLuaConversionError { CString::new(name.as_ref().to_vec()).map_err(|e| Error::ToLuaConversionError {
from: "&str", from: "&str",
@ -168,7 +191,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
/// All global variables (including the standard library!) are looked up in `_ENV`, so it may be /// All global variables (including the standard library!) are looked up in `_ENV`, so it may be
/// necessary to populate the environment in order for scripts using custom environments to be /// necessary to populate the environment in order for scripts using custom environments to be
/// useful. /// useful.
pub fn set_environment<V: ToLua<'lua>>(mut self, env: V) -> Result<Chunk<'lua, 'a>> { pub fn set_environment<V: ToLua<'lua>>(mut self, env: V) -> Result<Self> {
// Prefer to propagate errors here and wrap to `Ok` // Prefer to propagate errors here and wrap to `Ok`
self.env = Ok(Some(env.to_lua(self.lua)?)); self.env = Ok(Some(env.to_lua(self.lua)?));
Ok(self) Ok(self)
@ -178,7 +201,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
/// ///
/// Be aware, Lua does not check the consistency of the code inside binary chunks. /// Be aware, Lua does not check the consistency of the code inside binary chunks.
/// Running maliciously crafted bytecode can crash the interpreter. /// Running maliciously crafted bytecode can crash the interpreter.
pub fn set_mode(mut self, mode: ChunkMode) -> Chunk<'lua, 'a> { pub fn set_mode(mut self, mode: ChunkMode) -> Self {
self.mode = Some(mode); self.mode = Some(mode);
self self
} }
@ -225,6 +248,26 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
self self
} }
#[cfg(any(feature = "luau", doc))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
#[doc(hidden)]
pub fn set_vector_lib(mut self, lib: Option<String>) -> Self {
self.compiler
.get_or_insert_with(Default::default)
.set_vector_lib(lib);
self
}
#[cfg(any(feature = "luau", doc))]
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
#[doc(hidden)]
pub fn set_vector_ctor(mut self, ctor: Option<String>) -> Self {
self.compiler
.get_or_insert_with(Default::default)
.set_vector_ctor(ctor);
self
}
/// Compiles the chunk and changes mode to binary. /// Compiles the chunk and changes mode to binary.
/// ///
/// It does nothing if the chunk is already binary. /// It does nothing if the chunk is already binary.
@ -234,7 +277,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
if self.detect_mode() == ChunkMode::Text { if self.detect_mode() == ChunkMode::Text {
let data = self let data = self
.compiler .compiler
.unwrap_or_default() .get_or_insert_with(Default::default)
.compile(self.source.as_ref()); .compile(self.source.as_ref());
self.mode = Some(ChunkMode::Binary); self.mode = Some(ChunkMode::Binary);
self.source = Cow::Owned(data); self.source = Cow::Owned(data);
@ -373,7 +416,11 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
let source = self.expression_source(); let source = self.expression_source();
// We don't need to compile source if no compiler options set // We don't need to compile source if no compiler options set
#[cfg(feature = "luau")] #[cfg(feature = "luau")]
let source = self.compiler.map(|c| c.compile(&source)).unwrap_or(source); let source = self
.compiler
.as_ref()
.map(|c| c.compile(&source))
.unwrap_or(source);
self.lua self.lua
.load_chunk(&source, self.name.as_ref(), self.env()?, None) .load_chunk(&source, self.name.as_ref(), self.env()?, None)