190 lines
5.1 KiB
Text
190 lines
5.1 KiB
Text
#module_parameters(STATIC := true);
|
|
|
|
c_context: #Context;
|
|
|
|
#scope_export;
|
|
|
|
using #import,file "../module.jai"(STATIC = STATIC);
|
|
|
|
expose :: (L: *State, proc: $T, $caller_code := #caller_code, $loc := #caller_location)
|
|
#modify {
|
|
return T.(*Type_Info).type == .PROCEDURE, "expose must take a procedure";
|
|
} #expand {
|
|
#insert -> string {
|
|
info := T.(*Type_Info_Procedure);
|
|
code := compiler_get_nodes(caller_code);
|
|
call := code.(*Code_Procedure_Call);
|
|
|
|
proc := call.arguments_sorted[1].(*Code_Ident);
|
|
basic.assert(proc.kind == .IDENT, "must be an identifier", loc = loc);
|
|
|
|
body_builder: basic.String_Builder;
|
|
args_builder: basic.String_Builder;
|
|
call_builder: basic.String_Builder;
|
|
rets_builder: basic.String_Builder;
|
|
|
|
if info.return_types.count != 0 {
|
|
basic.append(*call_builder, "\t\t\t\t");
|
|
|
|
for info.return_types {
|
|
basic.print_to_builder(*call_builder, "r%", it_index);
|
|
if it_index < info.return_types.count -1 {
|
|
basic.append(*call_builder, ", ");
|
|
}
|
|
}
|
|
|
|
basic.append(*call_builder, " := ");
|
|
}
|
|
|
|
basic.append(*call_builder, "proc(");
|
|
|
|
for < info.argument_types {
|
|
index := -(it_index + 1);
|
|
basic.print_to_builder(*args_builder, "\t\t\ta% := %;\n", it_index, gen_stack_pull(it, index));
|
|
|
|
basic.print_to_builder(*call_builder, "a%", it_index);
|
|
if it_index > 0 {
|
|
basic.append(*call_builder, ", ");
|
|
}
|
|
}
|
|
|
|
basic.append(*call_builder, ");");
|
|
|
|
for info.return_types {
|
|
basic.print_to_builder(*rets_builder, "\t\t\t\t%;", gen_stack_push(it, it_index));
|
|
if it_index < info.return_types.count - 1 {
|
|
basic.append(*rets_builder, "\n");
|
|
}
|
|
}
|
|
|
|
return basic.sprint(#string END
|
|
lua_name :: "%1";
|
|
lua_wrapper :: (L: *State) -> s32 #c_call {
|
|
%2
|
|
push_context c_context {
|
|
%3
|
|
%4
|
|
}
|
|
|
|
return %5;
|
|
}
|
|
END,
|
|
proc.name,
|
|
basic.builder_to_string(*args_builder),
|
|
basic.builder_to_string(*call_builder),
|
|
basic.builder_to_string(*rets_builder),
|
|
info.return_types.count,
|
|
);
|
|
}
|
|
|
|
info := T.(*Type_Info_Procedure);
|
|
pushcclosure(L, lua_wrapper, info.argument_types.count.(s32));
|
|
setfield(L, LUA_GLOBALSINDEX, lua_name);
|
|
}
|
|
|
|
|
|
#scope_file;
|
|
|
|
gen_stack_pull :: (info: *Type_Info, index: int) -> string {
|
|
if info.type == {
|
|
case .BOOL;
|
|
return basic.tprint("get_lua_bool(L, %)", index);
|
|
case .INTEGER;
|
|
return basic.tprint("tointeger(L, %)", index);
|
|
case .FLOAT;
|
|
return basic.tprint("tonumber(L, %)", index);
|
|
case .STRING;
|
|
return basic.tprint("get_lua_string(L, %)", index);
|
|
case .STRUCT;
|
|
return basic.tprint("get_lua_table(L, %, %)", info.(*Type_Info_Struct).name, index);
|
|
|
|
case;
|
|
basic.assert(false, "% (%)", info.type, index);
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
gen_stack_push :: (info: *Type_Info, index: int) -> string {
|
|
if info.type == {
|
|
case .BOOL;
|
|
return basic.tprint("pushboolean(L, r%.(s32))", index);
|
|
case .INTEGER;
|
|
return basic.tprint("pushinteger(L, r%)", index);
|
|
case;
|
|
basic.assert(false, "% (%)", info.type, index);
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
get_lua_string :: inline (L: *State, index: s32) -> string #c_call {
|
|
len: u64;
|
|
ptr := tolstring(L, index, *len);
|
|
return string.{ data = ptr, count = xx len };
|
|
}
|
|
|
|
get_lua_bool :: inline (L: *State, index: s32) -> bool #c_call {
|
|
return toboolean(L, index) == 1;
|
|
}
|
|
|
|
get_lua_table :: (L: *State, $T: Type, index: s32) -> T #c_call {
|
|
push_context c_context {
|
|
return get_lua_table(L, T.(*Type_Info_Struct), index).(*T).*;
|
|
}
|
|
}
|
|
|
|
temp_storage: [4096]u8;
|
|
temp_offset: int;
|
|
|
|
get_lua_table :: (L: *State, info: *Type_Info_Struct, index: s32) -> *void {
|
|
res := temp_storage.data + temp_offset;
|
|
memset(res, 0, info.runtime_size);
|
|
|
|
temp_offset = (temp_offset + info.runtime_size) % temp_storage.count;
|
|
|
|
for info.members {
|
|
defer settop(L, -2);
|
|
pushlstring(L, it.name.data, xx it.name.count);
|
|
rawget(L, -2);
|
|
|
|
vp: *void;
|
|
if it.type.type == {
|
|
case .BOOL;
|
|
v := get_lua_bool(L, -1);
|
|
vp = *v;
|
|
case .INTEGER;
|
|
v := tointeger(L, -1);
|
|
if it.type.runtime_size == {
|
|
case 1; vp = *(v.(u8, no_check));
|
|
case 2; vp = *(v.(u16, no_check));
|
|
case 4; vp = *(v.(u32, no_check));
|
|
case 8; vp = *(v.(u64, no_check));
|
|
}
|
|
case .FLOAT;
|
|
v := tonumber(L, -1);
|
|
if it.type.runtime_size == {
|
|
case 4; vp = *(v.(float32, no_check));
|
|
case 8; vp = *(v.(float64, no_check));
|
|
}
|
|
case .STRING;
|
|
v := get_lua_string(L, -1);
|
|
vp = *v;
|
|
case .STRUCT;
|
|
v := get_lua_table(L, it.type.(*Type_Info_Struct), -1);
|
|
vp = *v;
|
|
|
|
case;
|
|
basic.assert(false, "% (%)", info.type, index);
|
|
}
|
|
|
|
memcpy(res + it.offset_in_bytes, vp, it.type.runtime_size);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
basic :: #import "Basic"; // @future
|
|
|
|
#import "Compiler";
|