@@ -59,6 +59,33 @@ pub type Value
5959/// that will return references to the values instead of decoding them.
6060pub type ValueRef
6161
62+ /// A decoded lua function
63+ /// Accepts decoded values and returns decoded values
64+ pub type LuaFunc {
65+ LuaFunc ( func : fn ( Lua , List ( Value ) ) -> # ( Lua , List ( Value ) ) )
66+ }
67+
68+ @ external ( erlang , "glua_ffi" , "is_lua_func" )
69+ fn is_lua_func ( a : anything) -> Bool
70+
71+ @ external ( erlang , "glua_ffi" , "coerce" )
72+ fn coerce_lua_func ( a : anything) -> LuaFunc
73+
74+ pub fn decode_func ( ) {
75+ use then <- decode . then ( decode . dynamic )
76+ echo then
77+ case is_lua_func ( then ) {
78+ True -> decode . success ( coerce_lua_func ( then ) )
79+ False ->
80+ decode . failure (
81+ LuaFunc ( func : fn ( _ , _ ) { panic as "unreachable" } ) ,
82+ "LuaFunc" ,
83+ )
84+ }
85+ }
86+
87+ // {NewState, Ret} = Fun(State, Transformed),
88+
6289pub opaque type Output {
6390 Output ( lua : Lua , refs : List ( ValueRef ) )
6491}
@@ -169,17 +196,14 @@ pub fn function(
169196 f : fn ( Lua , List ( dynamic . Dynamic ) ) -> # ( Lua , List ( Value ) ) ,
170197) -> Value {
171198 // we need a little wrapper for functions to satisfy luerl's order of arguments and return value type
172- wrap_trans_function ( f )
199+ function_transform ( f , default_transformation )
173200}
174201
175202pub fn function_transform (
176203 f : fn ( Lua , List ( dynamic . Dynamic ) ) -> # ( Lua , List ( Value ) ) ,
177204 transformation : Transformation ,
178205) -> Value {
179- case transformation {
180- NoTransform -> wrap_function ( f )
181- ProplistTransform -> wrap_trans_function ( f )
182- }
206+ wrap_function ( f , transformation )
183207 // we need a little wrapper for functions to satisfy luerl's order of arguments and return value type
184208}
185209
@@ -236,11 +260,7 @@ pub fn userdata(v: anything) -> Value
236260@ external ( erlang , "glua_ffi" , "wrap_fun" )
237261fn wrap_function (
238262 fun : fn ( Lua , List ( dynamic . Dynamic ) ) -> # ( Lua , List ( Value ) ) ,
239- ) -> Value
240-
241- @ external ( erlang , "glua_ffi" , "wrap_trans_fun" )
242- fn wrap_trans_function (
243- fun : fn ( Lua , List ( dynamic . Dynamic ) ) -> # ( Lua , List ( Value ) ) ,
263+ transformation : Transformation ,
244264) -> Value
245265
246266@ external ( erlang , "luerl" , "decode_list" )
@@ -249,21 +269,32 @@ fn do_decode_list(ref: List(ValueRef), lua: Lua) -> List(dynamic.Dynamic)
249269@ external ( erlang , "luerl" , "decode" )
250270fn do_decode ( ref : ValueRef , lua : Lua ) -> dynamic . Dynamic
251271
252- @ external ( erlang , "glua_ffi" , "proplist_to_map" )
253- fn proplist_to_map ( a : anything) -> dynamic . Dynamic
272+ /// Precondition: ONLY luerl decoded terms can be added here or else it will SPECTACULARLY FAIL
273+ @ external ( erlang , "glua_ffi" , "transform" )
274+ fn transform ( a : luerl_value, transformation : Transformation ) -> dynamic . Dynamic
254275
276+ /// Internally in luerl, when a `Value` is decoded it has proplists and difficult to decode functions.
277+ /// This poses some problems; proplists make decoding difficult and erlang functions are hard to decode in gleam.
278+ ///
279+ /// Glua has decided to greatly improve type safety at a marginal performance cost.
280+ /// If you wish to remove these transformations for whatever reason, you may use the functions that accepts a `Transformation`.
255281pub type Transformation {
256- NoTransform
257- /// Default
258- ProplistTransform
282+ Transformation (
283+ /// If true, transforms proplists (ex. `[#("key", "value")]`) into dicts
284+ proplist : Bool ,
285+ /// If true, transforms functions to `LuaFunc`s making them callable with glua
286+ func : Bool ,
287+ )
259288}
260289
290+ pub const default_transformation = Transformation ( proplist : True , func : True )
291+
261292/// The decoder will always receive a list of values
262293pub fn dec (
263294 output : Result ( Output , LuaError ) ,
264295 using decoder : decode . Decoder ( a) ,
265296) -> Result ( # ( Lua , a) , LuaError ) {
266- dec_transform ( output , decoder , ProplistTransform )
297+ dec_transform ( output , decoder , default_transformation )
267298}
268299
269300pub fn dec_transform (
@@ -272,16 +303,9 @@ pub fn dec_transform(
272303 transformation tf : Transformation ,
273304) {
274305 use output <- result . try ( output )
275- let dyn =
276- do_decode_list ( output . refs , output . lua )
277- |> dynamic . list ( )
278-
279- let dyn = case tf {
280- NoTransform -> dyn
281- ProplistTransform -> proplist_to_map ( dyn )
282- }
283-
284- dyn
306+ do_decode_list ( output . refs , output . lua )
307+ |> list . map ( transform ( _, tf ) )
308+ |> dynamic . list ( )
285309 |> decode . run ( decoder )
286310 |> result . map ( pair . new ( output . lua , _) )
287311 |> result . map_error ( UnexpectedResultType )
@@ -292,7 +316,7 @@ pub fn dec_one(
292316 output : Result ( Output , LuaError ) ,
293317 using decoder : decode . Decoder ( a) ,
294318) -> Result ( # ( Lua , a) , LuaError ) {
295- dec_one_transform ( output , decoder , ProplistTransform )
319+ dec_one_transform ( output , decoder , default_transformation )
296320}
297321
298322/// Assume there will be only one item to decode
@@ -641,27 +665,43 @@ fn do_eval_file(
641665 path : String ,
642666) -> Result ( # ( Lua , List ( ValueRef ) ) , LuaError )
643667
644- pub fn call_function (
668+ pub fn call_function_ref (
645669 state lua : Lua ,
646670 ref fun : ValueRef ,
647671 args args : List ( Value ) ,
648672) -> Result ( Output , LuaError ) {
649- do_call_function ( lua , fun , args )
673+ do_call_function_ref ( lua , fun , args )
650674 |> result . map ( to_output )
651675}
652676
653677@ external ( erlang , "glua_ffi" , "call_function" )
654- fn do_call_function (
678+ fn do_call_function_ref (
655679 lua : Lua ,
656680 fun : ValueRef ,
657681 args : List ( Value ) ,
658682) -> Result ( # ( Lua , List ( ValueRef ) ) , LuaError )
659683
684+ @ external ( erlang , "glua_ffi" , "call_enc_function" )
685+ fn do_call_function (
686+ lua : Lua ,
687+ fun : LuaFunc ,
688+ args : List ( Value ) ,
689+ ) -> Result ( # ( Lua , List ( ValueRef ) ) , LuaError )
690+
691+ pub fn call_function (
692+ state lua : Lua ,
693+ func func : LuaFunc ,
694+ args args : List ( Value ) ,
695+ ) -> Result ( Output , LuaError ) {
696+ do_call_function ( lua , func , args )
697+ |> result . map ( to_output )
698+ }
699+
660700pub fn call_function_by_name (
661701 state lua : Lua ,
662702 keys keys : List ( String ) ,
663703 args args : List ( Value ) ,
664704) -> Result ( Output , LuaError ) {
665705 use fun <- result . try ( get ( lua , keys ) )
666- call_function ( lua , fun . ref , args )
706+ call_function_ref ( lua , fun . ref , args )
667707}
0 commit comments