Skip to content

Commit 74fd380

Browse files
author
John Toman
committed
Updates polymorphic variants to variants
Polymorphic variants are a little bit more efficient than polymorphic variants and we don't really need any of the features offered by polymorphic variants. So this commit switches Ocamlua to use regular variants.
1 parent c4a5bd1 commit 74fd380

File tree

4 files changed

+99
-93
lines changed

4 files changed

+99
-93
lines changed

ocamlua.ml

+11-11
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
limitations under the License.
1515
*)
1616
type lua_state
17-
type lua_value = [ `Lua_Table of lua_table
18-
| `Lua_Nil
19-
| `Lua_String of string
20-
| `Lua_Number of float
21-
| `Lua_Boolean of bool
22-
| `Lua_Closure of lua_closure]
17+
type lua_value = Lua_Table of lua_table
18+
| Lua_Nil
19+
| Lua_String of string
20+
| Lua_Number of float
21+
| Lua_Boolean of bool
22+
| Lua_Closure of lua_closure
2323
and lua_table = (lua_value * lua_value) list
2424
and lua_closure = lua_value -> lua_value
2525
type func_map = (int, lua_closure) Hashtbl.t
@@ -30,21 +30,21 @@ let init_state () =
3030

3131
let table_of_list l =
3232
let rec loop (pair_accum,index) = function
33-
| [] -> `Lua_Table pair_accum
34-
| h::t -> loop ((`Lua_Number index,h)::pair_accum, index +. 1.0) t
33+
| [] -> Lua_Table pair_accum
34+
| h::t -> loop ((Lua_Number index,h)::pair_accum, index +. 1.0) t
3535
in
3636
loop ([],1.0) l;;
3737

3838
let list_of_table l =
3939
let cmp (a,_) (b,_) = match (a,b) with
40-
| (`Lua_Number a',`Lua_Number b') -> compare a' b'
40+
| (Lua_Number a',Lua_Number b') -> compare a' b'
4141
| _ -> failwith "non-numeric key" in
4242
let sorted_list = List.sort cmp l in
4343
let rec loop index l = match l with
4444
| [] -> []
45-
| (`Lua_Number i,v)::t when i = index ->
45+
| (Lua_Number i,v)::t when i = index ->
4646
v::(loop (index +. 1.0) t)
47-
| (`Lua_Number _,v)::_ -> failwith "unexpected numeric index"
47+
| (Lua_Number _,v)::_ -> failwith "unexpected numeric index"
4848
| _ -> failwith "non-numeric key" (* non-numeric keys can slip through if the user passes in a table with one element *)
4949
in
5050
loop 1.0 sorted_list;;

ocamlua.mli

+6-6
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
type lua_state
2020
(** An opaque datatype representing the underlying Lua state *)
2121

22-
type lua_value = [ `Lua_Table of lua_table
23-
| `Lua_Nil (** The empty value *)
24-
| `Lua_String of string
25-
| `Lua_Number of float (** The numeric type in Lua. Lua does not have a separate type for integers: all numeric values are of type float (this actually depends on the compile flags used for the Lua runtime, but this library will only compile if floats are used for Lua numbers *)
26-
| `Lua_Boolean of bool
27-
| `Lua_Closure of lua_closure ]
22+
type lua_value = Lua_Table of lua_table
23+
| Lua_Nil (** The empty value *)
24+
| Lua_String of string
25+
| Lua_Number of float (** The numeric type in Lua. Lua does not have a separate type for integers: all numeric values are of type float (this actually depends on the compile flags used for the Lua runtime, but this library will only compile if floats are used for Lua numbers *)
26+
| Lua_Boolean of bool
27+
| Lua_Closure of lua_closure
2828
(** Values that can be shared between the Lua runtime and OCaml code *)
2929
and lua_table = (lua_value * lua_value) list
3030
(** An associative list corresponding to a Lua table. As in Lua, keys

ocamlua_stubs.c

+30-24
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@
3434
#define OcamLuaState_tuple(v) (OcamLuaState_val(Field((v),0)))
3535
#define Is_state_live(v) (OcamLuaState_val((v))->L != NULL)
3636

37+
#define TABLE_TAG 0
38+
#define STRING_TAG 1
39+
#define NUMBER_TAG 2
40+
#define BOOLEAN_TAG 3
41+
#define CLOSURE_TAG 4
42+
#define NIL_VAL (Val_int(0))
43+
3744
typedef struct ocamlua_state {
3845
lua_State *L;
3946
int id;
@@ -112,29 +119,31 @@ static int get_sid(lua_State *L) {
112119
static void value_to_lua(lua_State *L, value v, int s_id, int *c_counter) {
113120
CAMLparam1(v);
114121
CAMLlocal1(it);
115-
if(Is_long(v) && v == hash_variant("Lua_Nil")) {
122+
if(Is_long(v) && v == NIL_VAL) {
116123
lua_pushnil(L);
117-
} else if(Field(v, 0) == hash_variant("Lua_String")) {
118-
lua_pushstring(L, String_val(Field(v, 1)));
119-
} else if(Field(v, 0) == hash_variant("Lua_Number")) {
120-
lua_pushnumber(L, Double_val(Field(v, 1)));
121-
} else if(Field(v, 0) == hash_variant("Lua_Boolean")) {
122-
lua_pushboolean(L, Bool_val(Field(v, 1)));
123-
} else if(Field(v, 0) == hash_variant("Lua_Closure")) {
124+
// TODO(jtoman): a switch/case might be more efficient
125+
// assuming the c compiler doesn't do that for us already
126+
} else if(Tag_val(v) == STRING_TAG) {
127+
lua_pushstring(L, String_val(Field(v, 0)));
128+
} else if(Tag_val(v) == NUMBER_TAG) {
129+
lua_pushnumber(L, Double_val(Field(v, 0)));
130+
} else if(Tag_val(v) == BOOLEAN_TAG) {
131+
lua_pushboolean(L, Bool_val(Field(v, 0)));
132+
} else if(Tag_val(v) == CLOSURE_TAG) {
124133
static value *register_closure_f = NULL;
125134
if(register_closure_f == NULL) {
126135
register_closure_f = caml_named_value("ocamlua.register_closure");
127136
}
128137
int c_id = (*c_counter)++;
129-
caml_callback3(*register_closure_f, Val_long(s_id), Val_long(c_id), Field(v, 1));
138+
caml_callback3(*register_closure_f, Val_long(s_id), Val_long(c_id), Field(v, 0));
130139
ocamlua_cb_t *cb = lua_newuserdata(L, sizeof(ocamlua_cb_t));
131140
cb->c_id = c_id;
132141
cb->s_id = s_id;
133142
luaL_setmetatable(L, FUNCTION_BRIDGE_METATABLE);
134143
} else {
135144
lua_newtable(L);
136145
int table_ind = lua_absindex(L, -1);
137-
it = Field(v, 1);
146+
it = Field(v, 0);
138147
while(it != Val_int(0)) {
139148
value_to_lua(L, Field(Field(it, 0), 0), s_id, c_counter);
140149
value_to_lua(L, Field(Field(it, 0), 1), s_id, c_counter);
@@ -173,29 +182,26 @@ static value lua_to_value(lua_State *L, int *error) {
173182
CAMLparam0();
174183
CAMLlocal1(ret);
175184
int type = lua_type(L, -1);
176-
if(type != LUA_TNIL) {
177-
ret = caml_alloc(2, 0);
178-
}
179185
if(type == LUA_TSTRING) {
180-
Store_field(ret, 0, hash_variant("Lua_String"));
181-
Store_field(ret, 1, caml_copy_string(lua_tostring(L, -1)));
186+
ret = caml_alloc(1, STRING_TAG);
187+
Store_field(ret, 0, caml_copy_string(lua_tostring(L, -1)));
182188
} else if(type == LUA_TNUMBER) {
183-
Store_field(ret, 0, hash_variant("Lua_Number"));
184-
Store_field(ret, 1, caml_copy_double(lua_tonumber(L, -1)));
189+
ret = caml_alloc(1, NUMBER_TAG);
190+
Store_field(ret, 0, caml_copy_double(lua_tonumber(L, -1)));
185191
} else if(type == LUA_TNIL) {
186-
ret = caml_hash_variant("Lua_Nil");
192+
ret = NIL_VAL;
187193
} else if(type == LUA_TBOOLEAN) {
188-
Store_field(ret, 0, hash_variant("Lua_Boolean"));
189-
Store_field(ret, 1, Val_bool(lua_toboolean(L, -1)));
194+
ret = caml_alloc(1, BOOLEAN_TAG);
195+
Store_field(ret, 0, Val_bool(lua_toboolean(L, -1)));
190196
} else if(type == LUA_TUSERDATA && lua_getmetatable(L, -1)) {
191197
luaL_getmetatable(L, FUNCTION_BRIDGE_METATABLE);
192198
int comp = lua_compare(L, -1, -2, LUA_OPEQ);
193199
lua_pop(L, 2);
194200
if(comp != 1) {
195201
*error = 1;
196202
} else {
197-
Store_field(ret, 0, hash_variant("Lua_Closure"));
198-
Store_field(ret, 1, recover_closure(L, -1));
203+
ret = caml_alloc(1, CLOSURE_TAG);
204+
Store_field(ret, 0, recover_closure(L, -1));
199205
}
200206
} else if(type == LUA_TTABLE) {
201207
lua_pushstring(L, RECURSION_SET); // stack is table | "ocamlua.recursion_check"
@@ -209,7 +215,7 @@ static value lua_to_value(lua_State *L, int *error) {
209215
lua_pushinteger(L, 1); // stack is table | recursion_set | table' | 1
210216
lua_rawset(L, -3); // set the recursion_set[table'] = 1
211217
lua_pop(L, 1); // pop off the recursion set, now we're left with the table as we started out
212-
Store_field(ret, 0, hash_variant("Lua_Table"));
218+
ret = caml_alloc(1, TABLE_TAG);
213219
lua_to_table(L, ret, error);
214220
} else {
215221
// we've seen this table before, error out and return
@@ -305,7 +311,7 @@ static void lua_to_table(lua_State *L, value ret, int *error) {
305311
lua_pop(L, 1);
306312
}
307313
}
308-
Store_field(ret, 1, it);
314+
Store_field(ret, 0, it);
309315
// We do not pop off the table here, it is taken care of at the end
310316
// of lua_to_value
311317
CAMLreturn0;

0 commit comments

Comments
 (0)