Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add support for complex numbers

  • Loading branch information...
commit 43f7560a3e16c3a58396e09253c31fc0384034f3 1 parent 74e621b
James McKaskill jmckaskill authored
2  Makefile
View
@@ -8,7 +8,7 @@ LUA=../lua-5.2.0/src/lua
LUA_CFLAGS=-I../lua-5.2.0/src
SOCFLAGS=-fPIC
SOCC=$(CC) -shared $(SOCFLAGS)
-CFLAGS=-fPIC -g -Wall -Werror $(LUA_CFLAGS) -fvisibility=hidden -Wno-unused-function
+CFLAGS=-O2 -fPIC -g -Wall -Werror $(LUA_CFLAGS) -fvisibility=hidden -Wno-unused-function --std=gnu99
MODNAME=ffi
MODSO=$(MODNAME).so
35 call.c
View
@@ -17,18 +17,6 @@ static void push_uint(lua_State* L, unsigned int val)
static void push_float(lua_State* L, float val)
{ lua_pushnumber(L, val); }
-static void print(lua_State* L, int** p, size_t sz)
-{
- size_t i;
- lua_getglobal(L, "print");
- lua_pushfstring(L, "%p", p);
- for (i = 0; i < sz; i++) {
- lua_pushfstring(L, " %p", p[i]);
- }
- lua_concat(L, (int) sz + 1);
- lua_call(L, 1, 0);
-}
-
#ifndef _WIN32
static int GetLastError(void)
{ return errno; }
@@ -157,17 +145,18 @@ static void* reserve_code(struct jit* jit, lua_State* L, size_t sz)
lua_pushcfunction(L, (lua_CFunction) func); \
lua_rawset(L, -3)
- ADDFUNC(NULL, print);
- ADDFUNC(NULL, to_double);
- ADDFUNC(NULL, to_float);
- ADDFUNC(NULL, to_uint64);
- ADDFUNC(NULL, to_int64);
- ADDFUNC(NULL, to_int32);
- ADDFUNC(NULL, to_uint32);
- ADDFUNC(NULL, to_uintptr);
- ADDFUNC(NULL, to_enum);
- ADDFUNC(NULL, to_typed_pointer);
- ADDFUNC(NULL, to_typed_cfunction);
+ ADDFUNC(NULL, check_double);
+ ADDFUNC(NULL, check_float);
+ ADDFUNC(NULL, check_uint64);
+ ADDFUNC(NULL, check_int64);
+ ADDFUNC(NULL, check_int32);
+ ADDFUNC(NULL, check_uint32);
+ ADDFUNC(NULL, check_uintptr);
+ ADDFUNC(NULL, check_enum);
+ ADDFUNC(NULL, check_typed_pointer);
+ ADDFUNC(NULL, check_typed_cfunction);
+ ADDFUNC(NULL, check_complex_double);
+ ADDFUNC(NULL, check_complex_float);
ADDFUNC(NULL, unpack_varargs_stack);
ADDFUNC(NULL, unpack_varargs_stack_skip);
ADDFUNC(NULL, unpack_varargs_reg);
218 call_x86.dasc
View
@@ -668,8 +668,7 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
lua_getuservalue(L, -1);
lua_rawseti(L, -3, ++num_upvals); /* mt */
lua_pop(L, 1);
- | call_r extern lua_pushnil, L_ARG
- | call_rrp extern push_cdata, L_ARG, -1, mt
+ | call_rrp extern push_cdata, L_ARG, 0, mt
get_int(Dst, ct, &reg, 1);
|.if X64
| mov [rax], rcx
@@ -677,18 +676,59 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
| mov [rax], ecx
| mov [rax+4], edx
|.endif
- | call_rr extern lua_remove, L_ARG, -2
break;
case UINTPTR_TYPE:
lua_getuservalue(L, -1);
lua_rawseti(L, -3, ++num_upvals); /* mt */
lua_pop(L, 1);
- | call_r extern lua_pushnil, L_ARG
- | call_rrp extern push_cdata, L_ARG, -1, mt
+ | call_rrp extern push_cdata, L_ARG, 0, mt
get_pointer(Dst, ct, &reg);
| mov [rax], rcx
- | call_rr extern lua_remove, L_ARG, -2
+ break;
+
+ case COMPLEX_FLOAT_TYPE:
+ /* complex floats are two floats packed into a double */
+ lua_pop(L, 1);
+ | call_rrp extern push_cdata, L_ARG, 0, mt
+ get_float(Dst, ct, &reg, 1);
+ |.if X64
+ | movq qword [rax], xmm0
+ |.else
+ | call_rp extern luaL_error, L_ARG, &"NYI: complex float on x32" //TODO
+ |.endif
+ break;
+
+ case COMPLEX_DOUBLE_TYPE:
+ lua_pop(L, 1);
+ | call_rrp extern push_cdata, L_ARG, 0, mt
+ get_float(Dst, ct, &reg, 1);
+ |.if X64
+ | movq qword [rax], xmm0
+ |.else
+ | call_rp extern luaL_error, L_ARG, &"NYI: complex float on x32" //TODO
+ |.endif
+ get_float(Dst, ct, &reg, 1);
+ |.if X64
+ | movq qword [rax+8], xmm0
+ |.else
+ | call_rp extern luaL_error, L_ARG, &"NYI: complex float on x32" //TODO
+ |.endif
+ break;
+
+ case FLOAT_TYPE:
+ case DOUBLE_TYPE:
+ lua_pop(L, 1);
+ get_float(Dst, ct, &reg, mt->type == DOUBLE_TYPE);
+ |.if X64WIN
+ | mov rcx, L_ARG
+ |.elif X64
+ | mov rdi, L_ARG
+ |.else
+ | fstp qword [rsp+4]
+ | mov [rsp], L_ARG
+ |.endif
+ | call extern lua_pushnumber
break;
case BOOL_TYPE:
@@ -738,21 +778,6 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
| call_rr extern push_uint, L_ARG, rcx
break;
- case FLOAT_TYPE:
- case DOUBLE_TYPE:
- lua_pop(L, 1);
- get_float(Dst, ct, &reg, mt->type == DOUBLE_TYPE);
- |.if X64WIN
- | mov rcx, L_ARG
- |.elif X64
- | mov rdi, L_ARG
- |.else
- | fstp qword [rsp+4]
- | mov [rsp], L_ARG
- |.endif
- | call extern lua_pushnumber
- break;
-
default:
luaL_error(L, "NYI: callback arg type");
}
@@ -772,7 +797,7 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
lua_rawseti(L, -3, ++num_upvals); /* usr value */
lua_rawseti(L, -2, ++num_upvals); /* mt */
| call_rrr extern lua_rawgeti, L_ARG, -2, num_upvals-1
- | call_rrrp extern to_typed_pointer, L_ARG, -2, -1, mt
+ | call_rrrp extern check_typed_pointer, L_ARG, -2, -1, mt
| mov [rsp+32], rax
| call_rr extern lua_settop, L_ARG, -4
| mov rax, [rsp+32]
@@ -784,7 +809,7 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
lua_rawseti(L, -3, ++num_upvals); /* usr value */
lua_rawseti(L, -2, ++num_upvals); /* mt */
| call_rrr extern lua_rawgeti, L_ARG, -2, num_upvals-1
- | call_rrrp, extern to_enum, L_ARG, -2, -1, mt
+ | call_rrrp, extern check_enum, L_ARG, -2, -1, mt
| mov [rsp+32], eax
| call_rr extern lua_settop, L_ARG, -4
| mov eax, [rsp+32]
@@ -800,7 +825,7 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
case INT16_TYPE:
case INT32_TYPE:
lua_pop(L, 1);
- | call_rr extern to_int32, L_ARG, -1
+ | call_rr extern check_int32, L_ARG, -1
| mov [rsp+32], eax
| call_rr extern lua_settop, L_ARG, -3
| mov eax, [rsp+32]
@@ -810,18 +835,18 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
case UINT16_TYPE:
case UINT32_TYPE:
lua_pop(L, 1);
- | call_rr extern to_uint32, L_ARG, -1
+ | call_rr extern check_uint32, L_ARG, -1
| mov [rsp+32], eax
| call_rr extern lua_settop, L_ARG, -3
| mov eax, [rsp+32]
break;
case INT64_TYPE:
- | call_rr extern to_int64, L_ARG, -1
+ | call_rr extern check_int64, L_ARG, -1
goto ret64;
case UINT64_TYPE:
- | call_rr extern to_uint64, L_ARG, -1
+ | call_rr extern check_uint64, L_ARG, -1
goto ret64;
ret64:
@@ -843,7 +868,7 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
case UINTPTR_TYPE:
lua_pop(L, 1);
- | call_rr extern to_uintptr, L_ARG, -1
+ | call_rr extern check_uintptr, L_ARG, -1
| mov [rsp+32], rax
| call_rr extern lua_settop, L_ARG, -3
| mov rax, [rsp+32]
@@ -852,7 +877,7 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
case FLOAT_TYPE:
case DOUBLE_TYPE:
lua_pop(L, 1);
- | call_rr extern to_double, L_ARG, -1
+ | call_rr extern check_double, L_ARG, -1
|.if X64
| movq qword [rsp+32], xmm0
| call_rr extern lua_settop, L_ARG, -3
@@ -868,6 +893,33 @@ cfunction compile_callback(lua_State* L, int fidx, int ct_usr, const struct ctyp
|.endif
break;
+ case COMPLEX_FLOAT_TYPE:
+ /* complex floats are two floats packed into a double */
+ lua_pop(L, 1);
+ | call_rr extern check_complex_float, L_ARG, -1
+ |.if X64
+ | movq qword [rsp+32], xmm0
+ | call_rr extern lua_settop, L_ARG, -3
+ | movq xmm0, qword [rsp+32]
+ |.else
+ | call_rp extern luaL_error, L_ARG, &"NYI: complex float on x32" //TODO
+ |.endif
+ break;
+
+ case COMPLEX_DOUBLE_TYPE:
+ lua_pop(L, 1);
+ | call_rr extern check_complex_double, L_ARG, -1
+ |.if X64
+ | movq qword [rsp+32], xmm0
+ | movq qword [rsp+40], xmm1
+ | call_rr extern lua_settop, L_ARG, -3
+ | movq xmm0, qword [rsp+32]
+ | movq xmm1, qword [rsp+40]
+ |.else
+ | call_rp extern luaL_error, L_ARG, &"NYI: complex float on x32" //TODO
+ |.endif
+ break;
+
default:
luaL_error(L, "NYI: callback return type");
}
@@ -967,54 +1019,54 @@ void compile_function(lua_State* L, cfunction func, int ct_usr, const struct cty
if (mbr_ct->pointers) {
lua_getuservalue(L, -1);
num_upvals += 2;
- | call_rrrp extern to_typed_pointer, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct
+ | call_rrrp extern check_typed_pointer, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct
add_pointer(Dst, ct, &reg);
} else {
switch (mbr_ct->type) {
case FUNCTION_TYPE:
lua_getuservalue(L, -1);
num_upvals += 2;
- | call_rrrp extern to_typed_cfunction, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct
+ | call_rrrp extern check_typed_cfunction, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct
add_pointer(Dst, ct, &reg);
break;
case ENUM_TYPE:
lua_getuservalue(L, -1);
num_upvals += 2;
- | call_rrrp, extern to_enum, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct
+ | call_rrrp, extern check_enum, L_ARG, i, lua_upvalueindex(num_upvals), mbr_ct
add_int(Dst, ct, &reg, 0);
break;
case INT8_TYPE:
- | call_rr extern to_int32, L_ARG, i
+ | call_rr extern check_int32, L_ARG, i
| movsx eax, al
add_int(Dst, ct, &reg, 0);
lua_pop(L, 1);
break;
case UINT8_TYPE:
- | call_rr extern to_uint32, L_ARG, i
+ | call_rr extern check_uint32, L_ARG, i
| movzx eax, al
add_int(Dst, ct, &reg, 0);
lua_pop(L, 1);
break;
case INT16_TYPE:
- | call_rr extern to_int32, L_ARG, i
+ | call_rr extern check_int32, L_ARG, i
| movsx eax, ax
add_int(Dst, ct, &reg, 0);
lua_pop(L, 1);
break;
case UINT16_TYPE:
- | call_rr extern to_uint32, L_ARG, i
+ | call_rr extern check_uint32, L_ARG, i
| movzx eax, ax
add_int(Dst, ct, &reg, 0);
lua_pop(L, 1);
break;
case BOOL_TYPE:
- | call_rr extern to_int32, L_ARG, i
+ | call_rr extern check_int32, L_ARG, i
| cmp eax, 0
| setne al
| movzx eax, al
@@ -1023,47 +1075,62 @@ void compile_function(lua_State* L, cfunction func, int ct_usr, const struct cty
break;
case INT32_TYPE:
- | call_rr extern to_int32, L_ARG, i
+ | call_rr extern check_int32, L_ARG, i
add_int(Dst, ct, &reg, 0);
lua_pop(L, 1);
break;
case UINT32_TYPE:
- | call_rr extern to_uint32, L_ARG, i
+ | call_rr extern check_uint32, L_ARG, i
add_int(Dst, ct, &reg, 0);
lua_pop(L, 1);
break;
case UINTPTR_TYPE:
- | call_rr extern to_uintptr, L_ARG, i
+ | call_rr extern check_uintptr, L_ARG, i
add_pointer(Dst, ct, &reg);
lua_pop(L, 1);
break;
case INT64_TYPE:
- | call_rr extern to_int64, L_ARG, i
+ | call_rr extern check_int64, L_ARG, i
add_int(Dst, ct, &reg, 1);
lua_pop(L, 1);
break;
case UINT64_TYPE:
- | call_rr extern to_uint64, L_ARG, i
+ | call_rr extern check_uint64, L_ARG, i
add_int(Dst, ct, &reg, 1);
lua_pop(L, 1);
break;
case DOUBLE_TYPE:
- | call_rr extern to_double, L_ARG, i
+ | call_rr extern check_double, L_ARG, i
+ add_float(Dst, ct, &reg, 1);
+ lua_pop(L, 1);
+ break;
+
+ case COMPLEX_DOUBLE_TYPE:
+ | call_rr extern check_complex_double, L_ARG, i
+ add_float(Dst, ct, &reg, 1);
+ | movq xmm0, xmm1
add_float(Dst, ct, &reg, 1);
lua_pop(L, 1);
break;
case FLOAT_TYPE:
- | call_rr extern to_double, L_ARG, i
+ | call_rr extern check_double, L_ARG, i
add_float(Dst, ct, &reg, 0);
lua_pop(L, 1);
break;
+ case COMPLEX_FLOAT_TYPE:
+ | call_rr extern check_complex_float, L_ARG, i
+ /* complex floats are two floats packed into a double */
+ add_float(Dst, ct, &reg, 1);
+ lua_pop(L, 1);
+ break;
+
default:
luaL_error(L, "NYI: call arg type");
}
@@ -1296,8 +1363,7 @@ void compile_function(lua_State* L, cfunction func, int ct_usr, const struct cty
|.endif
|
| get_errno
- | call_r extern lua_pushnil, L_ARG
- | call_rrp extern push_cdata, L_ARG, -1, mbr_ct
+ | call_rrp extern push_cdata, L_ARG, 0, mbr_ct
|
| // *(int64_t*) cdata = val
|.if X64
@@ -1313,6 +1379,66 @@ void compile_function(lua_State* L, cfunction func, int ct_usr, const struct cty
| jmp ->lua_return_arg
break;
+ case COMPLEX_FLOAT_TYPE:
+ num_upvals++;
+ |.if X64
+ | movq qword [rsp+32], xmm0 // complex floats are two floats packed into a single register
+ |.else
+ | call_rp extern luaL_error, L_ARG, &"NYI: complex float on x32" //TODO
+ |.endif
+ |
+ | get_errno
+ | call_rrp extern push_cdata, L_ARG, 0, mbr_ct
+ |
+ | // ((complex_float*) cdata) = val
+ |.if X64
+ | mov rcx, [rsp+32]
+ | mov [rax], rcx
+ |.else
+ | mov rcx, [rsp+8]
+ | mov [rax+4], rcx
+ | mov rcx, [rsp+4]
+ | mov [rax], rcx
+ |.endif
+ |
+ | jmp ->lua_return_arg
+ break;
+
+ case COMPLEX_DOUBLE_TYPE:
+ num_upvals++;
+ |.if X64
+ | movq qword [rsp+40], xmm1
+ | movq qword [rsp+32], xmm0
+ |.else
+ | call_rp extern luaL_error, L_ARG, &"NYI: complex double on x32" //TODO
+ | fstp qword [rsp+4] // note get_errno doesn't require any stack on x86
+ | fstp qword [rsp+12]
+ |.endif
+ |
+ | get_errno
+ | call_rrp extern push_cdata, L_ARG, 0, mbr_ct
+ |
+ | // ((complex_double*) cdata)->real = val0
+ | // ((complex_double*) cdata)->imag = val1
+ |.if X64
+ | mov rcx, [rsp+40]
+ | mov [rax+8], rcx
+ | mov rcx, [rsp+32]
+ | mov [rax], rcx
+ |.else
+ | mov rcx, [rsp+16]
+ | mov [rax+12], rcx
+ | mov rcx, [rsp+12]
+ | mov [rax+8], rcx
+ | mov rcx, [rsp+8]
+ | mov [rax+4], rcx
+ | mov rcx, [rsp+4]
+ | mov [rax], rcx
+ |.endif
+ |
+ | jmp ->lua_return_arg
+ break;
+
case VOID_TYPE:
| jmp ->lua_return_void
lua_pop(L, 1);
6 ctype.c
View
@@ -137,13 +137,13 @@ void* push_cdata(lua_State* L, int ct_usr, const struct ctype* ct)
memset(cd+1, 0, sz);
#if LUA_VERSION_NUM == 501
- if (lua_isnil(L, ct_usr)) {
+ if (ct_usr && lua_isnil(L, ct_usr)) {
push_upval(L, &niluv_key);
lua_setfenv(L, -2);
}
#endif
- if (!lua_isnil(L, ct_usr)) {
+ if (ct_usr && !lua_isnil(L, ct_usr)) {
lua_pushvalue(L, ct_usr);
lua_setuservalue(L, -2);
}
@@ -208,7 +208,7 @@ void* to_cdata(lua_State* L, int idx, struct ctype* ct)
struct cdata* cd;
ct->type = INVALID_TYPE;
- if (!lua_getmetatable(L, idx)) {
+ if (!lua_isuserdata(L, idx) || !lua_getmetatable(L, idx)) {
lua_pushnil(L);
return NULL;
}
785 ffi.c
View
@@ -91,90 +91,121 @@ static int type_error(lua_State* L, int idx, const char* to_type, int to_usr, co
}
#define TO_NUMBER(TYPE, ALLOW_POINTERS) \
+ TYPE real, imag = 0; \
void* p; \
- struct ctype ct; \
+ struct ctype ct; \
\
switch (lua_type(L, idx)) { \
case LUA_TBOOLEAN: \
- return (TYPE) lua_toboolean(L, idx); \
+ real = (TYPE) lua_toboolean(L, idx); \
+ break; \
\
case LUA_TNUMBER: \
- return (TYPE) lua_tonumber(L, idx); \
+ real = (TYPE) lua_tonumber(L, idx); \
+ break; \
\
case LUA_TSTRING: \
- if (ALLOW_POINTERS) { \
- return (TYPE) (intptr_t) lua_tostring(L, idx); \
- } else { \
- goto err; \
+ if (!ALLOW_POINTERS) { \
+ type_error(L, idx, #TYPE, 0, NULL); \
} \
+ real = (TYPE) (intptr_t) lua_tostring(L, idx); \
+ break; \
\
case LUA_TLIGHTUSERDATA: \
- if (ALLOW_POINTERS) { \
- return (TYPE) (intptr_t) lua_topointer(L, idx); \
- } else { \
- goto err; \
+ if (!ALLOW_POINTERS) { \
+ type_error(L, idx, #TYPE, 0, NULL); \
} \
+ real = (TYPE) (intptr_t) lua_topointer(L, idx); \
+ break; \
\
case LUA_TUSERDATA: \
p = to_cdata(L, idx, &ct); \
\
if (ct.type == INVALID_TYPE) { \
- if (ALLOW_POINTERS) { \
- return (TYPE) (intptr_t) p; \
- } else { \
- goto err; \
+ if (!ALLOW_POINTERS) { \
+ type_error(L, idx, #TYPE, 0, NULL); \
} \
+ real = (TYPE) (intptr_t) p; \
} \
\
lua_pop(L, 1); \
\
if (ct.pointers || ct.type == STRUCT_TYPE || ct.type == UNION_TYPE) {\
- if (ALLOW_POINTERS) { \
- return (TYPE) (intptr_t) p; \
- } else { \
- goto err; \
+ if (!ALLOW_POINTERS) { \
+ type_error(L, idx, #TYPE, 0, NULL); \
} \
+ real = (TYPE) (intptr_t) p; \
} else if (ct.type == UINTPTR_TYPE) { \
- return (TYPE) *(intptr_t*) p; \
+ real = (TYPE) *(intptr_t*) p; \
} else if (ct.type == INT64_TYPE) { \
- return (TYPE) *(int64_t*) p; \
+ real = (TYPE) *(int64_t*) p; \
} else if (ct.type == UINT64_TYPE) { \
- return (TYPE) *(uint64_t*) p; \
+ real = (TYPE) *(uint64_t*) p; \
+ } else if (ct.type == COMPLEX_DOUBLE_TYPE) { \
+ real = (TYPE) creal(*(complex_double*) p); \
+ imag = (TYPE) cimag(*(complex_double*) p); \
+ } else if (ct.type == COMPLEX_FLOAT_TYPE) { \
+ real = (TYPE) crealf(*(complex_float*) p); \
+ imag = (TYPE) cimagf(*(complex_float*) p); \
} else { \
- goto err; \
+ type_error(L, idx, #TYPE, 0, NULL); \
} \
+ break; \
\
case LUA_TNIL: \
- return (TYPE) 0; \
+ real = (TYPE) 0; \
+ break; \
\
default: \
- goto err; \
+ type_error(L, idx, #TYPE, 0, NULL); \
} \
- \
-err: \
- type_error(L, idx, #TYPE, 0, NULL); \
- return 0
-int32_t to_int32(lua_State* L, int idx)
-{ TO_NUMBER(int32_t, 0); }
+int32_t check_int32(lua_State* L, int idx)
+{ TO_NUMBER(int32_t, 0); return real; }
+
+uint32_t check_uint32(lua_State* L, int idx)
+{ TO_NUMBER(uint32_t, 0); return real; }
-uint32_t to_uint32(lua_State* L, int idx)
-{ TO_NUMBER(uint32_t, 0); }
+int64_t check_int64(lua_State* L, int idx)
+{ TO_NUMBER(int64_t, 0); return real; }
-int64_t to_int64(lua_State* L, int idx)
-{ TO_NUMBER(int64_t, 0); }
+uint64_t check_uint64(lua_State* L, int idx)
+{ TO_NUMBER(uint64_t, 0); return real; }
-uint64_t to_uint64(lua_State* L, int idx)
-{ TO_NUMBER(uint64_t, 0); }
+double check_double(lua_State* L, int idx)
+{ TO_NUMBER(double, 0); return real; }
-double to_double(lua_State* L, int idx)
-{ TO_NUMBER(double, 0); }
+float check_float(lua_State* L, int idx)
+{ TO_NUMBER(float, 0); return real; }
-float to_float(lua_State* L, int idx)
-{ TO_NUMBER(float, 0); }
+uintptr_t check_uintptr(lua_State* L, int idx)
+{ TO_NUMBER(uintptr_t, 1); return real; }
-uintptr_t to_uintptr(lua_State* L, int idx)
-{ TO_NUMBER(uintptr_t, 1); }
+#ifdef HAVE_COMPLEX
+complex_double check_complex_double(lua_State* L, int idx)
+{ TO_NUMBER(double, 0); return real + imag * 1i; }
+
+complex_float check_complex_float(lua_State* L, int idx)
+{ TO_NUMBER(float, 0); return real + imag * 1i; }
+#else
+complex_double check_complex_double(lua_State* L, int idx)
+{
+ complex_double c;
+ TO_NUMBER(double, 0);
+ c.real = real;
+ c.imag = imag;
+ return c;
+}
+
+complex_float check_complex_float(lua_State* L, int idx)
+{
+ complex_float c;
+ TO_NUMBER(float, 0);
+ c.real = real;
+ c.imag = imag;
+ return c;
+}
+#endif
static size_t unpack_vararg(lua_State* L, int i, char* to)
{
@@ -301,7 +332,7 @@ void unpack_varargs_reg(lua_State* L, int first, int last, char* to)
* enum type. It leaves the stack unchanged. Will throw an error if the type
* at idx can't be conerted.
*/
-int32_t to_enum(lua_State* L, int idx, int to_usr, const struct ctype* to_ct)
+int32_t check_enum(lua_State* L, int idx, int to_usr, const struct ctype* to_ct)
{
int32_t ret;
@@ -321,7 +352,7 @@ int32_t to_enum(lua_State* L, int idx, int to_usr, const struct ctype* to_ct)
return ret;
case LUA_TUSERDATA:
- return to_int32(L, idx);
+ return check_int32(L, idx);
case LUA_TNIL:
return (int32_t) 0;
@@ -337,7 +368,7 @@ int32_t to_enum(lua_State* L, int idx, int to_usr, const struct ctype* to_ct)
/* to_pointer tries converts a value at idx to a pointer. It fills out ct and
* pushes the uv of the found type. It will throw a lua error if it can not
* convert the value to a pointer. */
-static void* to_pointer(lua_State* L, int idx, struct ctype* ct)
+static void* check_pointer(lua_State* L, int idx, struct ctype* ct)
{
void* p;
memset(ct, 0, sizeof(*ct));
@@ -392,8 +423,7 @@ static int is_void_ptr(const struct ctype* ct)
static int is_same_type(lua_State* L, int usr1, int usr2, const struct ctype* t1, const struct ctype* t2)
{
- return t1->type == t2->type
- && (!IS_COMPLEX(t1->type) || lua_rawequal(L, usr1, usr2));
+ return t1->type == t2->type && lua_rawequal(L, usr1, usr2);
}
static void set_struct(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers);
@@ -401,7 +431,7 @@ static void set_struct(lua_State* L, int idx, void* to, int to_usr, const struct
/* to_typed_pointer converts a value at idx to a type tt with target uv to_usr
* checking all types. May push a temporary value so that it can create
* structs on the fly. */
-void* to_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt)
+void* check_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt)
{
struct ctype ft;
void* p;
@@ -418,7 +448,7 @@ void* to_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt
return p;
}
- p = to_pointer(L, idx, &ft);
+ p = check_pointer(L, idx, &ft);
if (tt->pointers == 1 && ft.pointers == 0 && (ft.type == STRUCT_TYPE || ft.type == UNION_TYPE)) {
/* auto dereference structs */
@@ -458,7 +488,7 @@ void* to_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt
/* to_cfunction converts a value at idx with usr table at to_usr and type tt
* into a function. Leaves the stack unchanged. */
-static cfunction to_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt, int check_pointers)
+static cfunction check_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt, int check_pointers)
{
void* p;
struct ctype ft;
@@ -538,8 +568,8 @@ static cfunction to_cfunction(lua_State* L, int idx, int to_usr, const struct ct
/* to_type_cfunction converts a value at idx with uv at to_usr and type tt to
* a cfunction. Leaves the stack unchanged. */
-cfunction to_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt)
-{ return to_cfunction(L, idx, to_usr, tt, 1); }
+cfunction check_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt)
+{ return check_cfunction(L, idx, to_usr, tt, 1); }
static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct ctype* tt, int check_pointers);
@@ -720,10 +750,10 @@ static void set_struct(lua_State* L, int idx, void* to, int to_usr, const struct
case LUA_TUSERDATA:
if (check_pointers) {
- p = to_typed_pointer(L, idx, to_usr, tt);
+ p = check_typed_pointer(L, idx, to_usr, tt);
} else {
struct ctype ct;
- p = to_pointer(L, idx, &ct);
+ p = check_pointer(L, idx, &ct);
}
memcpy(to, p, tt->base_size);
lua_pop(L, 1);
@@ -757,10 +787,10 @@ static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct
}
if (check_pointers) {
- u.p = to_typed_pointer(L, idx, to_usr, tt);
+ u.p = check_typed_pointer(L, idx, to_usr, tt);
} else {
struct ctype ct;
- u.p = to_pointer(L, idx, &ct);
+ u.p = check_pointer(L, idx, &ct);
}
#ifndef ALLOW_MISALIGNED_ACCESS
@@ -778,7 +808,7 @@ static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct
uint64_t hi_mask = UINT64_C(0) - (UINT64_C(1) << (tt->bit_offset + tt->bit_size));
uint64_t low_mask = (UINT64_C(1) << tt->bit_offset) - UINT64_C(1);
- uint64_t val = to_uint64(L, idx);
+ uint64_t val = check_uint64(L, idx);
val &= (UINT64_C(1) << tt->bit_size) - 1;
val <<= tt->bit_offset;
*(uint64_t*) to = val | (*(uint64_t*) to & (hi_mask | low_mask));
@@ -807,46 +837,52 @@ static void set_value(lua_State* L, int idx, void* to, int to_usr, const struct
switch (tt->type) {
case BOOL_TYPE:
- *(_Bool*) to = (to_int32(L, idx) != 0);
+ *(_Bool*) to = (check_int32(L, idx) != 0);
break;
case UINT8_TYPE:
- *(uint8_t*) to = (uint8_t) to_uint32(L, idx);
+ *(uint8_t*) to = (uint8_t) check_uint32(L, idx);
break;
case INT8_TYPE:
- *(int8_t*) to = (int8_t) to_int32(L, idx);
+ *(int8_t*) to = (int8_t) check_int32(L, idx);
break;
case UINT16_TYPE:
- *(uint16_t*) to = (uint16_t) to_uint32(L, idx);
+ *(uint16_t*) to = (uint16_t) check_uint32(L, idx);
break;
case INT16_TYPE:
- *(int16_t*) to = (int16_t) to_int32(L, idx);
+ *(int16_t*) to = (int16_t) check_int32(L, idx);
break;
case UINT32_TYPE:
- *(uint32_t*) to = to_uint32(L, idx);
+ *(uint32_t*) to = check_uint32(L, idx);
break;
case INT32_TYPE:
- *(int32_t*) to = to_int32(L, idx);
+ *(int32_t*) to = check_int32(L, idx);
break;
case UINT64_TYPE:
- *(uint64_t*) to = to_uint64(L, idx);
+ *(uint64_t*) to = check_uint64(L, idx);
break;
case INT64_TYPE:
- *(int64_t*) to = to_int64(L, idx);
+ *(int64_t*) to = check_int64(L, idx);
break;
case FLOAT_TYPE:
- *(float*) to = (float) to_double(L, idx);
+ *(float*) to = (float) check_double(L, idx);
break;
case DOUBLE_TYPE:
- *(double*) to = to_double(L, idx);
+ *(double*) to = check_double(L, idx);
+ break;
+ case COMPLEX_FLOAT_TYPE:
+ *(complex_float*) to = check_complex_float(L, idx);
+ break;
+ case COMPLEX_DOUBLE_TYPE:
+ *(complex_double*) to = check_complex_double(L, idx);
break;
case UINTPTR_TYPE:
- *(uintptr_t*) to = to_uintptr(L, idx);
+ *(uintptr_t*) to = check_uintptr(L, idx);
break;
case ENUM_TYPE:
- *(int32_t*) to = to_enum(L, idx, to_usr, tt);
+ *(int32_t*) to = check_enum(L, idx, to_usr, tt);
break;
case FUNCTION_TYPE:
- *(cfunction*) to = to_cfunction(L, idx, to_usr, tt, check_pointers);
+ *(cfunction*) to = check_cfunction(L, idx, to_usr, tt, check_pointers);
break;
default:
goto err;
@@ -1476,52 +1512,74 @@ static int cdata_index(lua_State* L)
}
}
-static int64_t to_intptr(lua_State* L, int idx, struct ctype* ct)
+static int64_t check_intptr(lua_State* L, int idx, void* p, struct ctype* ct)
{
- void* p;
- int64_t ret;
-
- switch (lua_type(L, idx)) {
- case LUA_TNUMBER:
+ if (ct->type == INVALID_TYPE) {
+ int64_t ret;
memset(ct, 0, sizeof(*ct));
ct->base_size = 8;
ct->type = INT64_TYPE;
- ret = lua_tonumber(L, idx);
- lua_pushnil(L);
+ ct->is_defined = 1;
+ ret = luaL_checknumber(L, idx);
return ret;
- case LUA_TUSERDATA:
- p = check_cdata(L, idx, ct);
-
- if (ct->pointers) {
- return (intptr_t) p;
- } else if (ct->type == UINTPTR_TYPE) {
- return *(intptr_t*) p;
- } else if (ct->type == INT64_TYPE) {
- return *(int64_t*) p;
- } else if (ct->type == UINT64_TYPE) {
- return *(int64_t*) p;
- } else if (ct->type == FUNCTION_TYPE) {
- return (intptr_t) *(cfunction*) p;
- } else {
- lua_pop(L, 1);
- goto err;
- }
-
- default:
- goto err;
+ } else if (ct->pointers) {
+ return (intptr_t) p;
+ } else if (ct->type == UINTPTR_TYPE || ct->type == FUNCTION_TYPE) {
+ return *(intptr_t*) p;
+ } else if (ct->type == INT64_TYPE || ct->type == UINT64_TYPE) {
+ return *(int64_t*) p;
+ } else {
+ type_error(L, idx, "intptr_t", 0, NULL);
+ return 0;
}
+}
-err:
- type_error(L, idx, "intptr_t", 0, NULL);
- return 0;
+static complex_double check_complex(lua_State* L, int idx, void* p, struct ctype* ct)
+{
+ if (ct->type == INVALID_TYPE) {
+ double d = luaL_checknumber(L, idx);
+#ifdef HAVE_COMPLEX
+ return d;
+#else
+ complex_double c;
+ c.real = d;
+ c.imag = 0;
+ return c;
+#endif
+ } else if (ct->type == COMPLEX_DOUBLE_TYPE) {
+ return *(complex_double*) p;
+ } else if (ct->type == COMPLEX_FLOAT_TYPE) {
+ complex_float* f = (complex_float*) p;
+#ifdef HAVE_COMPLEX
+ return *f;
+#else
+ complex_double d;
+ d.real = f->real;
+ d.imag = f->imag;
+ return d;
+#endif
+ } else {
+ complex_double dummy;
+ type_error(L, idx, "complex", 0, NULL);
+ memset(&dummy, 0, sizeof(dummy));
+ return dummy;
+ }
}
-static int rank(int type)
+static int rank(const struct ctype* ct)
{
- switch (type) {
+ if (ct->pointers) {
+ return 5;
+ }
+
+ switch (ct->type) {
+ case COMPLEX_DOUBLE_TYPE:
+ return 7;
+ case COMPLEX_FLOAT_TYPE:
+ return 6;
case UINTPTR_TYPE:
- return sizeof(uintptr_t) >= 8 ? 4 : 1;
+ return sizeof(uintptr_t) >= sizeof(uint64_t) ? 4 : 1;
case INT64_TYPE:
return 2;
case UINT64_TYPE:
@@ -1531,48 +1589,77 @@ static int rank(int type)
}
}
-static void push_number(lua_State* L, int usr, const struct ctype* ct, int64_t val)
+static void push_complex(lua_State* L, complex_double res, int ct_usr, const struct ctype* ct)
{
- void* to = push_cdata(L, usr, ct);
-
- if (ct->type == UINTPTR_TYPE) {
- *(intptr_t*) to = val;
+ if (ct->type == COMPLEX_DOUBLE_TYPE) {
+ complex_double* p = (complex_double*) push_cdata(L, ct_usr, ct);
+ *p = res;
} else {
- *(int64_t*) to = val;
+ complex_float* p = (complex_float*) push_cdata(L, ct_usr, ct);
+#ifdef HAVE_COMPLEX
+ *p = (complex float) res;
+#else
+ p->real = (float) res.real;
+ p->imag = (float) res.imag;
+#endif
}
}
-static int cdata_unm(lua_State* L)
+static void push_number(lua_State* L, int64_t val, int ct_usr, const struct ctype* ct)
{
- struct ctype ct;
- void* to;
- int64_t val;
+ if ((ct->pointers || ct->type == UINTPTR_TYPE) && sizeof(intptr_t) != sizeof(int64_t)) {
+ intptr_t* p = (intptr_t*) push_cdata(L, ct_usr, ct);
+ *p = val;
+ } else {
+ int64_t* p = (int64_t*) push_cdata(L, ct_usr, ct);
+ *p = val;
+ }
+}
- lua_settop(L, 1);
- to_cdata(L, 1, &ct);
+static int call_user_op(lua_State* L, const char* opfield, int idx, int ct_usr, const struct ctype* ct)
+{
+ idx = lua_absindex(L, idx);
- if (push_user_mt(L, -1, &ct)) {
- lua_pushliteral(L, "__unm");
+ if (push_user_mt(L, ct_usr, ct)) {
+ lua_pushstring(L, opfield);
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
int top = lua_gettop(L);
- lua_pushvalue(L, 1);
+ lua_pushvalue(L, idx);
lua_call(L, 1, LUA_MULTRET);
return lua_gettop(L) - top + 1;
}
}
- val = to_intptr(L, 1, &ct);
+ return -1;
+}
+
+static int cdata_unm(lua_State* L)
+{
+ struct ctype ct;
+ void* p;
+ int64_t val;
+ int ret;
+
+ lua_settop(L, 1);
+ p = to_cdata(L, 1, &ct);
+
+ ret = call_user_op(L, "__unm", 1, 2, &ct);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ val = check_intptr(L, 1, p, &ct);
if (ct.pointers) {
luaL_error(L, "can't negate a pointer value");
} else {
- lua_pushnil(L);
+ memset(&ct, 0, sizeof(ct));
ct.type = INT64_TYPE;
ct.base_size = 8;
- to = push_cdata(L, -1, &ct);
- *(int64_t*) to = -val;
+ ct.is_defined = 1;
+ push_number(L, -val, 0, &ct);
}
return 1;
@@ -1580,20 +1667,12 @@ static int cdata_unm(lua_State* L)
/* returns -ve if no binop was called otherwise returns the number of return
* arguments */
-static int call_user_binop(lua_State* L, const char* opfield, int lidx, int ridx)
+static int call_user_binop(lua_State* L, const char* opfield, int lidx, int lusr, const struct ctype* lt, int ridx, int rusr, const struct ctype* rt)
{
- struct ctype lt, rt;
-
lidx = lua_absindex(L, lidx);
ridx = lua_absindex(L, ridx);
- to_cdata(L, lidx, &lt);
- to_cdata(L, ridx, &rt);
-
- push_type_name(L, -2, &lt);
- lua_pop(L, 1);
-
- if (push_user_mt(L, -2, &lt)) {
+ if (push_user_mt(L, lusr, lt)) {
lua_pushstring(L, opfield);
lua_rawget(L, -2);
@@ -1608,7 +1687,7 @@ static int call_user_binop(lua_State* L, const char* opfield, int lidx, int ridx
lua_pop(L, 2); /* user_mt and user_mt.op */
}
- if (push_user_mt(L, -1, &rt)) {
+ if (push_user_mt(L, rusr, rt)) {
lua_pushstring(L, opfield);
lua_rawget(L, -2);
@@ -1623,17 +1702,19 @@ static int call_user_binop(lua_State* L, const char* opfield, int lidx, int ridx
lua_pop(L, 2); /* user_mt and user_mt.op */
}
- lua_pop(L, 2); /* user values */
return -1;
}
static int cdata_concat(lua_State* L)
{
+ struct ctype lt, rt;
int ret;
lua_settop(L, 2);
+ to_cdata(L, 1, &lt);
+ to_cdata(L, 2, &rt);
- ret = call_user_binop(L, "__concat", 1, 2);
+ ret = call_user_binop(L, "__concat", 1, 3, &lt, 2, 4, &rt);
if (ret >= 0) {
return ret;
}
@@ -1646,208 +1727,297 @@ static int cdata_len(lua_State* L)
struct ctype ct;
int ret;
- lua_settop(L, 2);
+ lua_settop(L, 1);
+ to_cdata(L, 1, &ct);
- ret = call_user_binop(L, "__len", 1, 2);
+ ret = call_user_op(L, "__len", 1, 2, &ct);
if (ret >= 0) {
return ret;
}
- check_cdata(L, 1, &ct);
- push_type_name(L, -1, &ct);
+ push_type_name(L, 2, &ct);
return luaL_error(L, "type %s does not implement the __len metamethod", lua_tostring(L, -1));
}
static int cdata_add(lua_State* L)
{
- struct ctype lt, rt;
- int64_t left, right, res;
- void* to;
+ struct ctype lt, rt, ct;
+ void *lp, *rp;
+ int ct_usr;
int ret;
lua_settop(L, 2);
- ret = call_user_binop(L, "__add", 1, 2);
+ lp = to_cdata(L, 1, &lt);
+ rp = to_cdata(L, 2, &rt);
+ assert(lua_gettop(L) == 4);
+
+ ret = call_user_binop(L, "__add", 1, 3, &lt, 2, 4, &rt);
if (ret >= 0) {
return ret;
}
-
- left = to_intptr(L, 1, &lt);
- right = to_intptr(L, 2, &rt);
assert(lua_gettop(L) == 4);
- /* note due to 2s complement it doesn't matter if we do the addition as int or uint,
- * but the result needs to be uint64_t if either of the sources are */
-
- if (lt.pointers && rt.pointers) {
- luaL_error(L, "can't add two pointers");
+ ct_usr = rank(&lt) > rank(&rt) ? 3 : 4;
+ ct = rank(&lt) > rank(&rt) ? lt : rt;
- } else if (lt.pointers) {
- lt.is_array = 0;
- res = left + (lt.pointers > 1 ? sizeof(void*) : lt.base_size) * right;
- to = push_cdata(L, 3, &lt);
- *(intptr_t*) to = res;
+ if (IS_COMPLEX(ct.type)) {
+ complex_double left, right, res;
- } else if (rt.pointers) {
- rt.is_array = 0;
- res = right + (rt.pointers > 1 ? sizeof(void*) : rt.base_size) * left;
- to = push_cdata(L, 4, &rt);
- *(intptr_t*) to = res;
+ left = check_complex(L, 1, lp, &lt);
+ right = check_complex(L, 2, rp, &rt);
+ assert(lua_gettop(L) == 4);
- } else if (rank(lt.type) > rank(rt.type)) {
+#ifdef HAVE_COMPLEX
res = left + right;
- push_number(L, 3, &lt, res);
+#else
+ res.real = left.real + right.real;
+ res.imag = left.imag + right.imag;
+#endif
+
+ push_complex(L, res, ct_usr, &ct);
+ return 1;
} else {
- res = left + right;
- push_number(L, 4, &rt, res);
- }
+ int64_t left = check_intptr(L, 1, lp, &lt);
+ int64_t right = check_intptr(L, 2, rp, &rt);
+ assert(lua_gettop(L) == 4);
- return 1;
+ /* note due to 2s complement it doesn't matter if we do the addition as int or uint,
+ * but the result needs to be uint64_t if either of the sources are */
+
+ if (lt.pointers && rt.pointers) {
+ luaL_error(L, "can't add two pointers");
+
+ } else if (lt.pointers) {
+ int64_t res = left + (lt.pointers > 1 ? sizeof(void*) : lt.base_size) * right;
+ lt.is_array = 0;
+ push_number(L, res, 3, &lt);
+
+ } else if (rt.pointers) {
+ int64_t res = right + (rt.pointers > 1 ? sizeof(void*) : rt.base_size) * left;
+ rt.is_array = 0;
+ push_number(L, res, 4, &rt);
+
+ } else {
+ push_number(L, left + right, ct_usr, &ct);
+ }
+
+ return 1;
+ }
}
static int cdata_sub(lua_State* L)
{
- struct ctype lt, rt;
- int64_t left, right, res;
- void* to;
+ struct ctype lt, rt, ct;
+ void *lp, *rp;
+ int ct_usr;
int ret;
lua_settop(L, 2);
- ret = call_user_binop(L, "__sub", 1, 2);
+ lp = to_cdata(L, 1, &lt);
+ rp = to_cdata(L, 2, &rt);
+
+ ret = call_user_binop(L, "__sub", 1, 3, &lt, 2, 4, &rt);
if (ret >= 0) {
return ret;
}
- left = to_intptr(L, 1, &lt);
- right = to_intptr(L, 2, &rt);
+ ct_usr = rank(&lt) > rank(&rt) ? 3 : 4;
+ ct = rank(&lt) > rank(&rt) ? lt : rt;
- if (rt.pointers) {
- luaL_error(L, "can't subtract a pointer value");
+ if (IS_COMPLEX(ct.type)) {
+ complex_double left, right, res;
- } else if (lt.pointers) {
- lt.is_array = 0;
- res = left - (lt.pointers > 1 ? sizeof(void*) : lt.base_size) * right;
- to = push_cdata(L, 3, &lt);
- *(intptr_t*) to = res;
+ left = check_complex(L, 1, lp, &lt);
+ right = check_complex(L, 2, rp, &rt);
- } else if (rank(lt.type) > rank(rt.type)) {
+#ifdef HAVE_COMPLEX
res = left - right;
- push_number(L, 3, &lt, res);
+#else
+ res.real = left.real - right.real;
+ res.imag = left.imag - right.imag;
+#endif
+
+ push_complex(L, res, ct_usr, &ct);
+ return 1;
} else {
- res = left - right;
- push_number(L, 4, &rt, res);
- }
+ int64_t left = check_intptr(L, 1, lp, &lt);
+ int64_t right = check_intptr(L, 2, rp, &rt);
- return 1;
+ if (rt.pointers) {
+ luaL_error(L, "NYI: can't subtract a pointer value");
+
+ } else if (lt.pointers) {
+ int64_t res = left - (lt.pointers > 1 ? sizeof(void*) : lt.base_size) * right;
+ lt.is_array = 0;
+ push_number(L, res, 3, &lt);
+
+ } else {
+ int64_t res = left - right;
+ push_number(L, res, ct_usr, &ct);
+ }
+
+ return 1;
+ }
}
/* TODO fix for unsigned */
-#define NUMBER_ONLY_BINOP(OP, OPSTR) \
- struct ctype lt, rt; \
- int64_t left, right, res; \
+#define NUMBER_ONLY_BINOP(OPSTR, DO_NORMAL, DO_COMPLEX) \
+ struct ctype lt, rt, ct; \
+ void *lp, *rp; \
+ int ct_usr; \
int ret; \
\
lua_settop(L, 2); \
\
- ret = call_user_binop(L, OPSTR, 1, 2); \
+ lp = to_cdata(L, 1, &lt); \
+ rp = to_cdata(L, 2, &rt); \
+ \
+ ret = call_user_binop(L, OPSTR, 1, 3, &lt, 2, 4, &rt); \
if (ret >= 0) { \
return ret; \
} \
\
- left = to_intptr(L, 1, &lt); \
- right = to_intptr(L, 2, &rt); \
- res = OP(left, right); \
+ ct_usr = rank(&lt) > rank(&rt) ? 3 : 4; \
+ ct = rank(&lt) > rank(&rt) ? lt : rt; \
+ \
+ if (IS_COMPLEX(ct.type)) { \
+ complex_double res; \
+ complex_double left = check_complex(L, 1, lp, &lt); \
+ complex_double right = check_complex(L, 2, rp, &rt); \
+ \
+ DO_COMPLEX(left, right, res); \
+ push_complex(L, res, ct_usr, &ct); \
\
- if (lt.pointers || rt.pointers) { \
+ } else if (lt.pointers || rt.pointers) { \
luaL_error(L, "can't operate on a pointer value"); \
- } else if (rank(lt.type) > rank(rt.type)) { \
- push_number(L, 3, &lt, res); \
+ \
} else { \
- push_number(L, 4, &rt, res); \
+ int64_t res; \
+ int64_t left = check_intptr(L, 1, lp, &lt); \
+ int64_t right = check_intptr(L, 2, rp, &rt); \
+ \
+ DO_NORMAL(left, right, res); \
+ push_number(L, res, ct_usr, &ct); \
} \
\
return 1
-#define MUL(l,r) l * r
-#define DIV(l,r) l / r
-#define MOD(l,r) l % r
-#define POW(l,r) pow(l, r)
+#define MUL(l,r,s) s = l * r
+#define DIV(l,r,s) s = l / r
+#define MOD(l,r,s) s = l % r
+#define POW(l,r,s) s = pow(l, r)
+
+#ifdef HAVE_COMPLEX
+#define MULC(l,r,s) s = l * r
+#define DIVC(l,r,s) s = l / r
+#define MODC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex mod")
+#define POWC(l,r,s) s = cpow(l, r)
+#else
+#define MULC(l,r,s) s.real = l.real * r.real - l.imag * r.imag, s.imag = l.real * r.imag + l.imag * r.real
+#define DIVC(l,r,s) s.real = (l.real * r.real + l.imag * r.imag) / (r.real * r.real + r.imag * r.imag), \
+ s.imag = (l.imag * r.real - l.real * r.imag) / (r.real * r.real + r.imag * r.imag)
+#define MODC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex mod")
+#define POWC(l,r,s) (void) l, (void) r, memset(&s, 0, sizeof(s)), luaL_error(L, "NYI: complex pow")
+#endif
static int cdata_mul(lua_State* L)
-{ NUMBER_ONLY_BINOP(MUL, "__mul"); }
+{ NUMBER_ONLY_BINOP("__mul", MUL, MULC); }
static int cdata_div(lua_State* L)
-{ NUMBER_ONLY_BINOP(DIV, "__div"); }
+{ NUMBER_ONLY_BINOP("__div", DIV, DIVC); }
static int cdata_mod(lua_State* L)
-{ NUMBER_ONLY_BINOP(MOD, "__mod"); }
+{ NUMBER_ONLY_BINOP("__mod", MOD, MODC); }
static int cdata_pow(lua_State* L)
-{ NUMBER_ONLY_BINOP(POW, "__pow"); }
+{ NUMBER_ONLY_BINOP("__pow", POW, POWC); }
-#define COMPARE_BINOP(OP, OPSTR) \
+#define COMPARE_BINOP(OPSTR, OP, OPC) \
struct ctype lt, rt; \
- int64_t left, right; \
- int res; \
+ void *lp, *rp; \
+ int ret, res; \
\
lua_settop(L, 2); \
\
- res = call_user_binop(L, OPSTR, 1, 2); \
- if (res >= 0) { \
- return res; \
+ lp = to_cdata(L, 1, &lt); \
+ rp = to_cdata(L, 2, &rt); \
+ \
+ ret = call_user_binop(L, OPSTR, 1, 3, &lt, 2, 4, &rt); \
+ if (ret >= 0) { \
+ return ret; \
} \
\
- left = to_intptr(L, 1, &lt); \
- right = to_intptr(L, 2, &rt); \
+ if (IS_COMPLEX(lt.type) || IS_COMPLEX(rt.type)) { \
+ complex_double left = check_complex(L, 1, lp, &lt); \
+ complex_double right = check_complex(L, 2, rp, &rt); \
+ \
+ res = OPC(left, right); \
+ \
+ lua_pushboolean(L, res); \
\
- if (lt.pointers && rt.pointers) { \
- if (is_void_ptr(&lt) || is_void_ptr(&rt) || is_same_type(L, 3, 4, &lt, &rt)) { \
+ } else { \
+ int64_t left = check_intptr(L, 1, lp, &lt); \
+ int64_t right = check_intptr(L, 2, rp, &rt); \
+ \
+ if (lt.pointers && rt.pointers) { \
+ if (is_void_ptr(&lt) || is_void_ptr(&rt) || is_same_type(L, 3, 4, &lt, &rt)) { \
+ res = OP((uint64_t) left, (uint64_t) right); \
+ } else { \
+ goto err; \
+ } \
+ \
+ } else if (lt.is_null && rt.type == FUNCTION_TYPE) { \
res = OP((uint64_t) left, (uint64_t) right); \
- } else { \
- goto err; \
- } \
\
- } else if (lt.is_null && rt.type == FUNCTION_TYPE) { \
- res = OP((uint64_t) left, (uint64_t) right); \
+ } else if (rt.is_null && lt.type == FUNCTION_TYPE) { \
+ res = OP((uint64_t) left, (uint64_t) right); \
\
- } else if (rt.is_null && lt.type == FUNCTION_TYPE) { \
- res = OP((uint64_t) left, (uint64_t) right); \
+ } else if (lt.pointers && rt.type == UINTPTR_TYPE) { \
+ res = OP((uint64_t) left, (uint64_t) right); \
\
- } else if (lt.pointers && rt.type == UINTPTR_TYPE) { \
- res = OP((uint64_t) left, (uint64_t) right); \
+ } else if (rt.pointers && lt.type == UINTPTR_TYPE) { \
+ res = OP((uint64_t) left, (uint64_t) right); \
\
- } else if (rt.pointers && lt.type == UINTPTR_TYPE) { \
- res = OP((uint64_t) left, (uint64_t) right); \
+ } else if (rt.pointers || lt.pointers) { \
+ goto err; \
\
- } else if (rt.pointers || lt.pointers) { \
- goto err; \
+ } else if (lt.type != INT64_TYPE && rt.type != INT64_TYPE) { \
+ res = OP((uint64_t) left, (uint64_t) right); \
\
- } else if (lt.type != INT64_TYPE && rt.type != INT64_TYPE) { \
- res = OP((uint64_t) left, (uint64_t) right); \
+ } else if (lt.type != INT64_TYPE) { \
+ res = OP((int64_t) (uint64_t) left, right); \
\
- } else if (lt.type != INT64_TYPE) { \
- res = OP((int64_t) (uint64_t) left, right); \
+ } else if (rt.type != INT64_TYPE) { \
+ res = OP(left, (int64_t) (uint64_t) right); \
\
- } else if (rt.type != INT64_TYPE) { \
- res = OP(left, (int64_t) (uint64_t) right); \
+ } else { \
+ res = OP(left, right); \
+ } \
\
- } else { \
- res = OP(left, right); \
+ lua_pushboolean(L, res); \
} \
- \
- lua_pushboolean(L, res); \
return 1
#define EQ(l, r) (l) == (r)
#define LT(l, r) (l) < (r)
#define LE(l, r) (l) <= (r)
+#ifdef HAVE_COMPLEX
+#define EQC(l, r) (l) == (r)
+#else
+#define EQC(l, r) (l).real == (r).real && (l).imag == (r).imag
+#endif
+
+#define LEC(l, r) EQC(l, r), luaL_error(L, "complex numbers are non-orderable")
+#define LTC(l, r) EQC(l, r), luaL_error(L, "complex numbers are non-orderable")
+
static int cdata_eq(lua_State* L)
{
- COMPARE_BINOP(EQ, "__eq");
+ COMPARE_BINOP("__eq", EQ, EQC);
err:
lua_pushboolean(L, 0);
return 1;
@@ -1855,7 +2025,7 @@ static int cdata_eq(lua_State* L)
static int cdata_lt(lua_State* L)
{
- COMPARE_BINOP(LT, "__lt");
+ COMPARE_BINOP("__lt", LT, LTC);
err:
lua_getuservalue(L, 1);
lua_getuservalue(L, 2);
@@ -1866,7 +2036,7 @@ static int cdata_lt(lua_State* L)
static int cdata_le(lua_State* L)
{
- COMPARE_BINOP(LE, "__le");
+ COMPARE_BINOP("__le", LE, LEC);
err:
lua_getuservalue(L, 1);
lua_getuservalue(L, 2);
@@ -1905,6 +2075,22 @@ static int cdata_tostring(lua_State* L)
} else if (ct.pointers == 0 && ct.type == UINTPTR_TYPE) {
lua_pushfstring(L, "%p", *(uintptr_t*) p);
+ } else if (ct.pointers == 0 && ct.type == COMPLEX_DOUBLE_TYPE) {
+ complex_double c = *(complex_double*) p;
+ if (cimag(c) != 0) {
+ lua_pushfstring(L, "%f+%fi", creal(c), cimag(c));
+ } else {
+ lua_pushfstring(L, "%f", creal(c));
+ }
+
+ } else if (ct.pointers == 0 && ct.type == COMPLEX_FLOAT_TYPE) {
+ complex_float c = *(complex_float*) p;
+ if (cimagf(c) != 0) {
+ lua_pushfstring(L, "%f+%fi", crealf(c), cimagf(c));
+ } else {
+ lua_pushfstring(L, "%f", crealf(c));
+ }
+
} else {
push_type_name(L, -1, &ct);
lua_pushfstring(L, "cdata<%s>: %p", lua_tostring(L, -1), p);
@@ -1998,8 +2184,8 @@ static int ffi_string(lua_State* L)
static int ffi_copy(lua_State* L)
{
struct ctype ft, tt;
- char* to = (char*) to_pointer(L, 1, &tt);
- char* from = (char*) to_pointer(L, 2, &ft);
+ char* to = (char*) check_pointer(L, 1, &tt);
+ char* from = (char*) check_pointer(L, 2, &ft);
if (!lua_isnoneornil(L, 3)) {
memcpy(to, from, (size_t) luaL_checknumber(L, 3));
@@ -2016,7 +2202,7 @@ static int ffi_copy(lua_State* L)
static int ffi_fill(lua_State* L)
{
struct ctype ct;
- void* to = to_pointer(L, 1, &ct);
+ void* to = check_pointer(L, 1, &ct);
size_t sz = (size_t) luaL_checknumber(L, 2);
int val = 0;
@@ -2203,6 +2389,43 @@ static int ffi_debug(lua_State* L)
return 1;
}
+static int do64(lua_State* L, int issigned)
+{
+ lua_Number low, high;
+ struct ctype ct;
+ int64_t val;
+
+ lua_settop(L, 2);
+
+ if (!lua_isnil(L, 2)) {
+ high = luaL_checknumber(L, 1);
+ low = luaL_checknumber(L, 2);
+ } else {
+ high = 0;
+ low = luaL_checknumber(L, 1);
+ }
+
+ val = ((int64_t) (uint32_t) high << 32) | (int64_t) (uint32_t) low;
+
+ if (issigned && (high < 0 || low < 0)) {
+ val = -val;
+ }
+
+ memset(&ct, 0, sizeof(ct));
+ ct.type = issigned ? INT64_TYPE : UINT64_TYPE;
+ ct.is_defined = 0;
+ ct.base_size = sizeof(uint64_t);
+ push_number(L, (int64_t) val, 0, &ct);
+
+ return 1;
+}
+
+static int ffi_i64(lua_State* L)
+{ return do64(L, 1); }
+
+static int ffi_u64(lua_State* L)
+{ return do64(L, 0); }
+
static const luaL_Reg cdata_mt[] = {
{"__gc", &cdata_gc},
{"__call", &cdata_call},
@@ -2265,6 +2488,8 @@ static const luaL_Reg ffi_reg[] = {
{"fill", &ffi_fill},
{"abi", &ffi_abi},
{"debug", &ffi_debug},
+ {"i64", &ffi_i64},
+ {"u64", &ffi_u64},
{NULL, NULL}
};
@@ -2386,6 +2611,7 @@ static int setup_upvals(lua_State* L)
/* setup builtin types */
{
+ complex_double* pc;
struct {char ch; uint16_t v;} a16;
struct {char ch; uint32_t v;} a32;
struct {char ch; uint64_t v;} a64;
@@ -2393,35 +2619,57 @@ static int setup_upvals(lua_State* L)
struct {char ch; double v;} ad;
struct {char ch; uintptr_t v;} aptr;
struct ctype ct;
- /* add void type and NULL constant */
+ struct {char ch; complex_float v;} cf;
+ struct {char ch; complex_double v;} cd;
+
+#define ALIGNOF(S) ((int) ((char*) &S.v - (char*) &S - 1))
+
push_builtin(L, &ct, "void", VOID_TYPE, 0, 0);
+ push_builtin(L, &ct, "bool", BOOL_TYPE, sizeof(_Bool), sizeof(_Bool) -1);
+ push_builtin(L, &ct, "uint8_t", UINT8_TYPE, sizeof(uint8_t), 0);
+ push_builtin(L, &ct, "int8_t", INT8_TYPE, sizeof(int8_t), 0);
+ push_builtin(L, &ct, "uint16_t", UINT16_TYPE, sizeof(uint16_t), ALIGNOF(a16));
+ push_builtin(L, &ct, "int16_t", INT16_TYPE, sizeof(int16_t), ALIGNOF(a16));
+ push_builtin(L, &ct, "uint32_t", UINT32_TYPE, sizeof(uint32_t), ALIGNOF(a32));
+ push_builtin(L, &ct, "int32_t", INT32_TYPE, sizeof(int32_t), ALIGNOF(a32));
+ push_builtin(L, &ct, "uint64_t", UINT64_TYPE, sizeof(uint64_t), ALIGNOF(a64));
+ push_builtin(L, &ct, "int64_t", INT64_TYPE, sizeof(int64_t), ALIGNOF(a64));
+ push_builtin(L, &ct, "float", FLOAT_TYPE, sizeof(float), ALIGNOF(af));
+ push_builtin(L, &ct, "double", DOUBLE_TYPE, sizeof(double), ALIGNOF(ad));
+ push_builtin(L, &ct, "uintptr_t", UINTPTR_TYPE, sizeof(uintptr_t), ALIGNOF(aptr));
+ push_builtin(L, &ct, "complex float", COMPLEX_FLOAT_TYPE, sizeof(complex_float), ALIGNOF(cf));
+ push_builtin(L, &ct, "complex double", COMPLEX_DOUBLE_TYPE, sizeof(complex_double), ALIGNOF(cd));
+
+ /* add NULL and i constants */
+ push_upval(L, &constants_key);
+ memset(&ct, 0, sizeof(ct));
+ ct.type = VOID_TYPE;
+ ct.is_defined = 1;
ct.pointers = 1;
ct.is_null = 1;
- lua_pushnil(L);
- push_upval(L, &constants_key);
- push_cdata(L, -2, &ct);
+ push_cdata(L, 0, &ct);
lua_setfield(L, -2, "NULL");
- lua_pop(L, 2); /* nil uv, constants */
-#define ALIGNOF(S) ((int) ((char*) &S.v - (char*) &S - 1))
+ memset(&ct, 0, sizeof(ct));
+ ct.type = COMPLEX_DOUBLE_TYPE;
+ ct.is_defined = 1;
+ ct.base_size = sizeof(complex_double);
+ pc = (complex_double*) push_cdata(L, 0, &ct);
+#ifdef HAVE_COMPLEX
+ *pc = 1i;
+#else
+ pc->real = 0;
+ pc->imag = 1;
+#endif
+ lua_setfield(L, -2, "i");
- /* add the rest of the builtin types */
- push_builtin(L, &ct, "bool", BOOL_TYPE, sizeof(_Bool), sizeof(_Bool) -1);
- push_builtin(L, &ct, "uint8_t", UINT8_TYPE, 1, 0);
- push_builtin(L, &ct, "int8_t", INT8_TYPE, 1, 0);
- push_builtin(L, &ct, "uint16_t", UINT16_TYPE, 2, ALIGNOF(a16));
- push_builtin(L, &ct, "int16_t", INT16_TYPE, 2, ALIGNOF(a16));
- push_builtin(L, &ct, "uint32_t", UINT32_TYPE, 4, ALIGNOF(a32));
- push_builtin(L, &ct, "int32_t", INT32_TYPE, 4, ALIGNOF(a32));
- push_builtin(L, &ct, "uint64_t", UINT64_TYPE, 8, ALIGNOF(a64));
- push_builtin(L, &ct, "int64_t", INT64_TYPE, 8, ALIGNOF(a64));
- push_builtin(L, &ct, "float", FLOAT_TYPE, 4, ALIGNOF(af));
- push_builtin(L, &ct, "double", DOUBLE_TYPE, 8, ALIGNOF(ad));
- push_builtin(L, &ct, "uintptr_t", UINTPTR_TYPE, sizeof(uintptr_t), ALIGNOF(aptr));
+ lua_pop(L, 1); /* constants */
}
+ assert(lua_gettop(L) == 1);
+
/* setup builtin typedefs */
{
add_typedef(L, "bool", "_Bool");
@@ -2455,6 +2703,8 @@ static int setup_upvals(lua_State* L)
}
}
+ assert(lua_gettop(L) == 1);
+
/* setup ABI params table */
push_upval(L, &abi_key);
@@ -2493,6 +2743,7 @@ static int setup_upvals(lua_State* L)
lua_pushliteral(L, "k");
lua_setfield(L, -2, "__mode");
lua_setmetatable(L, -2);
+ lua_pop(L, 1); /* gc table */
/* ffi.os */
@@ -2526,7 +2777,7 @@ static int setup_upvals(lua_State* L)
#endif
lua_setfield(L, 1, "arch");
-
+ assert(lua_gettop(L) == 1);
return 0;
}
68 ffi.h
View
@@ -58,6 +58,11 @@ extern "C" {
#include <sys/mman.h>
#endif
+#if __STDC_VERSION__+0 >= 199901L
+#include <complex.h>
+#define HAVE_COMPLEX
+#endif
+
#ifndef NDEBUG
#define DASM_CHECKS
#endif
@@ -79,12 +84,15 @@ struct jit;
EXTERN_C EXPORT int luaopen_ffi(lua_State* L);
-#if LUA_VERSION_NUM == 501
-static int lua_absindex(lua_State* L, int idx) {
+static int lua_absindex2(lua_State* L, int idx) {
return (LUA_REGISTRYINDEX <= idx && idx < 0)
? lua_gettop(L) + idx + 1
: idx;
}
+/* use our own version of lua_absindex such that lua_absindex(L, 0) == 0 */
+#define lua_absindex(L, idx) lua_absindex2(L, idx)
+
+#if LUA_VERSION_NUM == 501
static void lua_callk(lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k)
{
lua_call(L, nargs, nresults);
@@ -254,6 +262,8 @@ enum {
VOID_TYPE,
DOUBLE_TYPE,
FLOAT_TYPE,
+ COMPLEX_DOUBLE_TYPE,
+ COMPLEX_FLOAT_TYPE,
BOOL_TYPE,
INT8_TYPE,
INT16_TYPE,
@@ -271,7 +281,7 @@ enum {
};
#define IS_CHAR(type) ((type) == INT8_TYPE || (type) == UINT8_TYPE)
-#define IS_COMPLEX(type) ((type) == STRUCT_TYPE || (type) == UNION_TYPE || (type) == ENUM_TYPE || (type) == FUNCTION_TYPE)
+#define IS_COMPLEX(type) ((type) == COMPLEX_FLOAT_TYPE || (type) == COMPLEX_DOUBLE_TYPE)
#define POINTER_BITS 2
#define POINTER_MAX ((1 << POINTER_BITS) - 1)
@@ -335,6 +345,33 @@ struct cdata {
typedef void (*cfunction)(void);
+#ifdef HAVE_COMPLEX
+typedef double complex complex_double;
+typedef float complex complex_float;
+#else
+typedef struct {
+ double real, imag;
+} complex_double;
+
+typedef struct {
+ float real, imag;
+} complex_float;
+
+static double creal(complex_double c) {
+ return c.real;
+}
+static float crealf(complex_float c) {
+ return c.real;
+}
+
+static double cimag(complex_double c) {
+ return c.imag;
+}
+static float cimagf(complex_float c) {
+ return c.imag;
+}
+#endif
+
#define CALLBACK_FUNC_USR_IDX 1
void set_defined(lua_State* L, int ct_usr, struct ctype* ct);
@@ -363,18 +400,21 @@ void compile_globals(struct jit* jit, lua_State* L);
int get_extern(struct jit* jit, uint8_t* addr, int idx, int type);
/* WARNING: assembly needs to be updated for prototype changes of these functions */
-int to_bool(lua_State* L, int idx);
-double to_double(lua_State* L, int idx);
-float to_float(lua_State* L, int idx);
-uint64_t to_uint64(lua_State* L, int idx);
-int64_t to_int64(lua_State* L, int idx);
-int32_t to_int32(lua_State* L, int idx);
-uint32_t to_uint32(lua_State* L, int idx);
-uintptr_t to_uintptr(lua_State* L, int idx);
-int32_t to_enum(lua_State* L, int idx, int to_usr, const struct ctype* tt);
+int check_bool(lua_State* L, int idx);
+double check_double(lua_State* L, int idx);
+double check_complex_imag(lua_State* L, int idx);
+float check_float(lua_State* L, int idx);
+uint64_t check_uint64(lua_State* L, int idx);
+int64_t check_int64(lua_State* L, int idx);
+int32_t check_int32(lua_State* L, int idx);
+uint32_t check_uint32(lua_State* L, int idx);
+uintptr_t check_uintptr(lua_State* L, int idx);
+int32_t check_enum(lua_State* L, int idx, int to_usr, const struct ctype* tt);
/* these two will always push a value so that we can create structs/functions on the fly */
-void* to_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt);
-cfunction to_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt);
+void* check_typed_pointer(lua_State* L, int idx, int to_usr, const struct ctype* tt);
+cfunction check_typed_cfunction(lua_State* L, int idx, int to_usr, const struct ctype* tt);
+complex_double check_complex_double(lua_State* L, int idx);
+complex_float check_complex_float(lua_State* L, int idx);
void unpack_varargs_stack(lua_State* L, int first, int last, char* to);
void unpack_varargs_reg(lua_State* L, int first, int last, char* to);
4 msvcbuild.bat
View
@@ -7,7 +7,7 @@
rem These should not have quotes
@set LUA_INCLUDE=Z:\c\lua-5.2.0\src
@set LUA_LIB=Z:\c\lua-5.2.0\lua5.2.lib
-@set LUA_EXE=Z:\c\lua-5.2.0\lua5.2.exe
+@set LUA_EXE=Z:\c\lua-5.2.0\lua.exe
rem This the name of the dll that can be handed to LoadLibrary. This should not have a path.
@set LUA_DLL=lua5.2.dll
@goto :DEBUG
@@ -15,7 +15,7 @@ rem This the name of the dll that can be handed to LoadLibrary. This should not
:DEBUG_5_1
@set LUA_INCLUDE=Z:\c\lua-5.1.4\src
@set LUA_LIB=Z:\c\lua-5.1.4\lua5.1.lib
-@set LUA_EXE=Z:\c\lua-5.1.4\lua5.1.exe
+@set LUA_EXE=Z:\c\lua-5.1.4\lua.exe
@set LUA_DLL=lua5.1.dll
:DEBUG
16 parser.c
View
@@ -838,7 +838,7 @@ static int parse_type_name(lua_State* L, struct parser* P)
flags |= DOUBLE;
} else if (IS_LITERAL(tok, "float")) {
flags |= FLOAT;
- } else if (IS_LITERAL(tok, "complex")) {
+ } else if (IS_LITERAL(tok, "complex") || IS_LITERAL(tok, "_Complex")) {
flags |= COMPLEX;
} else {
break;
@@ -870,7 +870,13 @@ static int parse_type_name(lua_State* L, struct parser* P)
}
} else if (flags & COMPLEX) {
- luaL_error(L, "NYI complex");
+ if (flags & LONG) {
+ luaL_error(L, "NYI: long complex double");
+ } else if (flags & FLOAT) {
+ lua_pushliteral(L, "complex float");
+ } else {
+ lua_pushliteral(L, "complex double");
+ }
} else if (flags & DOUBLE) {
if (flags & LONG) {
@@ -1054,6 +1060,12 @@ static void append_type_name(luaL_Buffer* B, int usr, const struct ctype* ct)
case FLOAT_TYPE:
luaL_addstring(B, "float");
break;
+ case COMPLEX_DOUBLE_TYPE:
+ luaL_addstring(B, "double complex");
+ break;
+ case COMPLEX_FLOAT_TYPE:
+ luaL_addstring(B, "float complex");
+ break;
case INT8_TYPE:
luaL_addstring(B, "char");
break;
54 test.c
View
@@ -13,6 +13,11 @@
#include <errno.h>
#endif
+#if __STDC_VERSION__+0 >= 199901L
+#include <complex.h>
+#define HAVE_COMPLEX
+#endif
+
#ifdef __cplusplus
# define EXTERN_C extern "C"
#else
@@ -27,6 +32,17 @@
#define EXPORT EXTERN_C
#endif
+EXPORT bool have_complex();
+
+bool have_complex()
+{
+#ifdef HAVE_COMPLEX
+ return 1;
+#else
+ return 0;
+#endif
+}
+
#define ADD(TYPE, NAME) \
EXPORT TYPE NAME(TYPE a, TYPE b); \
TYPE NAME(TYPE a, TYPE b) { return a + b; }
@@ -41,12 +57,22 @@ ADD(int64_t, add_i64)
ADD(uint64_t, add_u64)
ADD(double, add_d)
ADD(float, add_f)
+#ifdef HAVE_COMPLEX
+ADD(double complex, add_dc)
+//ADD(float complex, add_fc)
+EXPORT float complex add_fc(float complex a, float complex b);
+float complex add_fc(float complex a, float complex b)
+{
+ //fprintf(stderr, "%g+%gi %g+%gi\n", creal(a), cimag(a), creal(b), cimag(b));
+ return a + b;
+}
+#endif
-EXPORT _Bool ret_b(_Bool v);
-EXPORT _Bool ret_b2(_Bool v);
+EXPORT _Bool not_b(_Bool v);
+EXPORT _Bool not_b2(_Bool v);
-_Bool ret_b(_Bool v) {return !v;}
-_Bool ret_b2(_Bool v) {return !v;}
+_Bool not_b(_Bool v) {return !v;}
+_Bool not_b2(_Bool v) {return !v;}
#define PRINT(TYPE, NAME, FORMAT) \
EXPORT int NAME(char* buf, TYPE val); \
@@ -65,6 +91,13 @@ PRINT(float, print_f, "g")
PRINT(const char*, print_s, "s")
PRINT(void*, print_p, "p")
+#ifdef HAVE_COMPLEX
+EXPORT int print_dc(char* buf, double complex val);
+EXPORT int print_fc(char* buf, float complex val);
+int print_dc(char* buf, double complex val) {return sprintf(buf, "%g+%gi", creal(val), cimag(val));}
+int print_fc(char* buf, float complex val) {return sprintf(buf, "%g+%gi", creal(val), cimag(val));}
+#endif
+
EXPORT int print_b(char* buf, _Bool val);
EXPORT int print_b2(char* buf, _Bool val);
int print_b(char* buf, _Bool val) {return sprintf(buf, "%s", val ? "true" : "false");}
@@ -80,6 +113,14 @@ int print_b2(char* buf, _Bool val) {return sprintf(buf, "%s", val ? "true" : "fa
return print_##SUFFIX(buf, p->v); \
}
+#ifdef HAVE_COMPLEX
+#define COMPLEX_ALIGN(ALIGNMENT) \
+ ALIGN_UP(double complex, ALIGNMENT, dc) \
+ ALIGN_UP(float complex, ALIGNMENT, fc)
+#else
+#define COMPLEX_ALIGN(ALIGNMENT)
+#endif
+
#define ALIGN2(ALIGNMENT) \
ALIGN_UP(uint16_t, ALIGNMENT, u16) \
ALIGN_UP(uint32_t, ALIGNMENT, u32) \
@@ -90,6 +131,7 @@ int print_b2(char* buf, _Bool val) {return sprintf(buf, "%s", val ? "true" : "fa
ALIGN_UP(void*, ALIGNMENT, p) \
ALIGN_UP(_Bool, ALIGNMENT, b) \
ALIGN_UP(_Bool, ALIGNMENT, b2) \
+ COMPLEX_ALIGN(ALIGNMENT)
ALIGN2(0)
@@ -265,6 +307,10 @@ CALL(float, f)
CALL(double, d)
CALL(const char*, s)
CALL(_Bool, b)
+#ifdef HAVE_COMPLEX
+CALL(double complex, dc)
+CALL(float complex, fc)
+#endif
struct fptr {
#ifdef _MSC_VER
52 test.lua
View
@@ -20,6 +20,8 @@ end
print('Running test')
ffi.cdef [[
+bool have_complex();
+
int8_t add_i8(int8_t a, int8_t b);
uint8_t add_u8(uint8_t a, uint8_t b);
int16_t add_i16(int16_t a, int16_t b);
@@ -30,8 +32,10 @@ int64_t add_i64(int64_t a, int64_t b);
uint64_t add_u64(uint64_t a, uint64_t b);
double add_d(double a, double b);
float add_f(float a, float b);
-bool ret_b(bool v);
-_Bool ret_b2(_Bool v);
+double complex add_dc(double complex a, double complex b);
+float complex add_fc(float complex a, float complex b);
+bool not_b(bool v);
+_Bool not_b2(_Bool v);
int print_i8(char* buf, int8_t val);
int print_u8(char* buf, uint8_t val);
@@ -47,6 +51,8 @@ int print_b2(char* buf, _Bool val);
int print_d(char* buf, double val);
int print_f(char* buf, float val);
int print_p(char* buf, void* val);
+int print_dc(char* buf, double complex val);
+int print_fc(char* buf, float complex val);
int sprintf(char* buf, const char* format, ...);
// Examples from MSDN
@@ -156,6 +162,7 @@ local palign = [[
#pragma pack(pop)
]]
+local i = ffi.C.i
local test_values = {
['void*'] = ffi.new('char[3]'),
['const char*'] = 'foo',
@@ -166,6 +173,20 @@ local test_values = {
uint64_t = 12345678901234,
bool = true,
_Bool = false,
+ ['float complex'] = 3+4*i,
+ ['double complex'] = 5+6*i,
+}
+
+local types = {
+ b = 'bool',
+ b2 = '_Bool',
+ d = 'double',
+ f = 'float',
+ u64 = 'uint64_t',
+ u32 = 'uint32_t',
+ u16 = 'uint16_t',
+ s = 'const char*',
+ p = 'void*'
}
local buf = ffi.new('char[256]')
@@ -188,10 +209,20 @@ for convention,c in pairs(dlls) do
check(c.add_i16(2000,4000), 6000)
check(c.add_d(20, 12), 32)
check(c.add_f(40, 32), 72)
- check(c.ret_b(true), false)
- check(c.ret_b2(false), true)
+ check(c.not_b(true), false)
+ check(c.not_b2(false), true)
+
+ if c.have_complex() then
+ check(c.add_dc(3+4*i, 4+5*i), 7+9*i)
+ check(c.add_fc(2+4*i, 6+8*i), 8+12*i)
+ types.dc = 'double complex'
+ types.fc = 'float complex'
+ else
+ types.dc = nil
+ types.fc = nil
+ end
- for suffix, type in pairs{b = 'bool', b2 = '_Bool', d = 'double', f = 'float', u64 = 'uint64_t', u32 = 'uint32_t', u16 = 'uint16_t', s = 'const char*', p = 'void*'} do
+ for suffix, type in pairs(types) do
local test = test_values[type]
--print('checkbuf', suffix, type, buf, test)
checkbuf(type, suffix, c['print_' .. suffix](buf, test))
@@ -241,6 +272,8 @@ for convention,c in pairs(dlls) do
double call_d(double (*__cdecl func)(double), double arg);
const char* call_s(sfunc func, const char* arg);
_Bool call_b(_Bool (*__cdecl func)(_Bool), _Bool arg);
+ double complex call_dc(double complex (*__cdecl func)(double complex), double complex arg);
+ float complex call_fc(float complex (*__cdecl func)(float complex), float complex arg);
]]
ffi.cdef(cbs:gsub('__cdecl', convention))
@@ -252,6 +285,11 @@ for convention,c in pairs(dlls) do
check(ffi.string(c.call_s(function(s) return s + u3 end, 'foobar')), 'bar')
check(c.call_b(function(v) return not v end, true), false)
+ if c.have_complex() then
+ check(c.call_dc(function(v) return v + 2+3*i end, 4+6*i), 6+9*i)
+ check(c.call_fc(function(v) return v + 1+2*i end, 7+4*i), 8+6*i)
+ end
+
local u2 = ffi.new('uint64_t', 2)
local cb = ffi.new('sfunc', function(s) return s + u3 end)
check(ffi.string(cb('foobar')), 'bar')
@@ -385,5 +423,9 @@ if _VERSION ~= 'Lua 5.1' then
check(#vls, 5)
end
+check(tostring(1+3*i), '1+3i')
+check(tostring((1+3*i)*(2+4*i)), '-10+10i')
+check(tostring((3+2*i)*(3-2*i)), '13')
+
print('Test PASSED')
Please sign in to comment.
Something went wrong with that request. Please try again.