@@ -130,6 +130,28 @@ pub enum ChunkMode {
130130 Binary ,
131131}
132132
133+ /// Represents a constant value that can be used by Luau compiler.
134+ #[ cfg( any( feature = "luau" , doc) ) ]
135+ #[ cfg_attr( docsrs, doc( cfg( feature = "luau" ) ) ) ]
136+ #[ derive( Clone , Debug ) ]
137+ pub enum CompileConstant {
138+ Nil ,
139+ Boolean ( bool ) ,
140+ Number ( crate :: Number ) ,
141+ Vector ( crate :: Vector ) ,
142+ String ( String ) ,
143+ }
144+
145+ #[ cfg( feature = "luau" ) ]
146+ impl From < & ' static str > for CompileConstant {
147+ fn from ( s : & ' static str ) -> Self {
148+ CompileConstant :: String ( s. to_string ( ) )
149+ }
150+ }
151+
152+ #[ cfg( any( feature = "luau" , doc) ) ]
153+ type LibraryMemberConstantMap = std:: sync:: Arc < HashMap < ( String , String ) , CompileConstant > > ;
154+
133155/// Luau compiler
134156#[ cfg( any( feature = "luau" , doc) ) ]
135157#[ cfg_attr( docsrs, doc( cfg( feature = "luau" ) ) ) ]
@@ -144,6 +166,9 @@ pub struct Compiler {
144166 vector_type : Option < String > ,
145167 mutable_globals : Vec < String > ,
146168 userdata_types : Vec < String > ,
169+ libraries_with_known_members : Vec < String > ,
170+ library_constants : Option < LibraryMemberConstantMap > ,
171+ disabled_builtins : Vec < String > ,
147172}
148173
149174#[ cfg( any( feature = "luau" , doc) ) ]
@@ -168,6 +193,9 @@ impl Compiler {
168193 vector_type : None ,
169194 mutable_globals : Vec :: new ( ) ,
170195 userdata_types : Vec :: new ( ) ,
196+ libraries_with_known_members : Vec :: new ( ) ,
197+ library_constants : None ,
198+ disabled_builtins : Vec :: new ( ) ,
171199 }
172200 }
173201
@@ -200,6 +228,7 @@ impl Compiler {
200228 /// Possible values:
201229 /// * 0 - generate for native modules (default)
202230 /// * 1 - generate for all modules
231+ #[ must_use]
203232 pub const fn set_type_info_level ( mut self , level : u8 ) -> Self {
204233 self . type_info_level = level;
205234 self
@@ -242,23 +271,56 @@ impl Compiler {
242271 ///
243272 /// It disables the import optimization for fields accessed through these.
244273 #[ must_use]
245- pub fn set_mutable_globals ( mut self , globals : Vec < String > ) -> Self {
246- self . mutable_globals = globals;
274+ pub fn set_mutable_globals < S : Into < String > > ( mut self , globals : Vec < S > ) -> Self {
275+ self . mutable_globals = globals. into_iter ( ) . map ( |s| s . into ( ) ) . collect ( ) ;
247276 self
248277 }
249278
250279 /// Sets a list of userdata types that will be included in the type information.
251280 #[ must_use]
252- pub fn set_userdata_types ( mut self , types : Vec < String > ) -> Self {
253- self . userdata_types = types;
281+ pub fn set_userdata_types < S : Into < String > > ( mut self , types : Vec < S > ) -> Self {
282+ self . userdata_types = types. into_iter ( ) . map ( |s| s. into ( ) ) . collect ( ) ;
283+ self
284+ }
285+
286+ /// Sets constants for known library members.
287+ ///
288+ /// The constants are used by the compiler to optimize the generated bytecode.
289+ /// Optimization level must be at least 2 for this to have any effect.
290+ ///
291+ /// The first element of the tuple is the library name,the second is the member name, and the
292+ /// third is the constant value.
293+ #[ must_use]
294+ pub fn set_library_constants < L , M > ( mut self , constants : Vec < ( L , M , CompileConstant ) > ) -> Self
295+ where
296+ L : Into < String > ,
297+ M : Into < String > ,
298+ {
299+ let map = constants
300+ . into_iter ( )
301+ . map ( |( lib, member, cons) | ( ( lib. into ( ) , member. into ( ) ) , cons) )
302+ . collect :: < HashMap < _ , _ > > ( ) ;
303+ self . library_constants = Some ( std:: sync:: Arc :: new ( map) ) ;
304+ self . libraries_with_known_members = ( self . library_constants . clone ( ) )
305+ . map ( |map| map. keys ( ) . map ( |( lib, _) | lib. clone ( ) ) . collect ( ) )
306+ . unwrap_or_default ( ) ;
307+ self
308+ }
309+
310+ /// Sets a list of builtins that should be disabled.
311+ #[ must_use]
312+ pub fn set_disabled_builtins < S : Into < String > > ( mut self , builtins : Vec < S > ) -> Self {
313+ self . disabled_builtins = builtins. into_iter ( ) . map ( |s| s. into ( ) ) . collect ( ) ;
254314 self
255315 }
256316
257317 /// Compiles the `source` into bytecode.
258318 ///
259319 /// Returns [`Error::SyntaxError`] if the source code is invalid.
260320 pub fn compile ( & self , source : impl AsRef < [ u8 ] > ) -> Result < Vec < u8 > > {
261- use std:: os:: raw:: c_int;
321+ use std:: cell:: RefCell ;
322+ use std:: ffi:: CStr ;
323+ use std:: os:: raw:: { c_char, c_int} ;
262324 use std:: ptr;
263325
264326 let vector_lib = self . vector_lib . clone ( ) ;
@@ -290,6 +352,44 @@ impl Compiler {
290352
291353 vec2cstring_ptr ! ( mutable_globals, mutable_globals_ptr) ;
292354 vec2cstring_ptr ! ( userdata_types, userdata_types_ptr) ;
355+ vec2cstring_ptr ! ( libraries_with_known_members, libraries_with_known_members_ptr) ;
356+ vec2cstring_ptr ! ( disabled_builtins, disabled_builtins_ptr) ;
357+
358+ thread_local ! {
359+ static LIBRARY_MEMBER_CONSTANT_MAP : RefCell <LibraryMemberConstantMap > = Default :: default ( ) ;
360+ }
361+
362+ #[ cfg( feature = "luau" ) ]
363+ unsafe extern "C-unwind" fn library_member_constant_callback (
364+ library : * const c_char ,
365+ member : * const c_char ,
366+ constant : * mut ffi:: lua_CompileConstant ,
367+ ) {
368+ let library = CStr :: from_ptr ( library) . to_string_lossy ( ) ;
369+ let member = CStr :: from_ptr ( member) . to_string_lossy ( ) ;
370+ LIBRARY_MEMBER_CONSTANT_MAP . with_borrow ( |map| {
371+ if let Some ( cons) = map. get ( & ( library. to_string ( ) , member. to_string ( ) ) ) {
372+ match cons {
373+ CompileConstant :: Nil => ffi:: luau_set_compile_constant_nil ( constant) ,
374+ CompileConstant :: Boolean ( b) => {
375+ ffi:: luau_set_compile_constant_boolean ( constant, * b as c_int )
376+ }
377+ CompileConstant :: Number ( n) => ffi:: luau_set_compile_constant_number ( constant, * n) ,
378+ CompileConstant :: Vector ( v) => {
379+ #[ cfg( not( feature = "luau-vector4" ) ) ]
380+ ffi:: luau_set_compile_constant_vector ( constant, v. x ( ) , v. y ( ) , v. z ( ) , 0.0 ) ;
381+ #[ cfg( feature = "luau-vector4" ) ]
382+ ffi:: luau_set_compile_constant_vector ( constant, v. x ( ) , v. y ( ) , v. z ( ) , v. w ( ) ) ;
383+ }
384+ CompileConstant :: String ( s) => ffi:: luau_set_compile_constant_string (
385+ constant,
386+ s. as_ptr ( ) as * const c_char ,
387+ s. len ( ) ,
388+ ) ,
389+ }
390+ }
391+ } )
392+ }
293393
294394 let bytecode = unsafe {
295395 let mut options = ffi:: lua_CompileOptions:: default ( ) ;
@@ -302,6 +402,14 @@ impl Compiler {
302402 options. vectorType = vector_type. map_or ( ptr:: null ( ) , |s| s. as_ptr ( ) ) ;
303403 options. mutableGlobals = mutable_globals_ptr;
304404 options. userdataTypes = userdata_types_ptr;
405+ options. librariesWithKnownMembers = libraries_with_known_members_ptr;
406+ if let Some ( map) = self . library_constants . as_ref ( ) {
407+ if !self . libraries_with_known_members . is_empty ( ) {
408+ LIBRARY_MEMBER_CONSTANT_MAP . with_borrow_mut ( |gmap| * gmap = map. clone ( ) ) ;
409+ options. libraryMemberConstantCallback = Some ( library_member_constant_callback) ;
410+ }
411+ }
412+ options. disabledBuiltins = disabled_builtins_ptr;
305413 ffi:: luau_compile ( source. as_ref ( ) , options)
306414 } ;
307415
0 commit comments