allow ravi arrays to hold value at slot [0]; Lua core C api fixes for arrays; fix for ipairs()

pull/81/head
Dibyendu Majumdar 9 years ago
parent c5d917dead
commit 98bca6e083

@ -88,6 +88,9 @@ else()
endif()
llvm_map_components_to_libnames(llvm_libs all)
#llvm_map_components_to_libnames(llvm_libs Support Core CodeGen AsmPrinter BitReader TransformUtils
# InstCombine ScalarOpts Analysis ipa Object ExecutionEngine MC MCParser MCJIT ProfileData ipo
# RuntimeDyld Target X86CodeGen X86AsmParser X86Disassembler X86AsmPrinter X86Desc X86Info X86Utils AsmParser)
message(STATUS "llvm_libs ${llvm_libs}")
#Main library

@ -50,7 +50,7 @@ LUAI_FUNC void raviH_set_int(lua_State *L, Table *t, lua_Unsigned key, lua_Integ
LUAI_FUNC void raviH_set_float(lua_State *L, Table *t, lua_Unsigned key, lua_Number value); /* RAVI array specialization */
#define raviH_get_int_inline(L, t, key, v) \
{ unsigned ukey = (unsigned)((key)-1); \
{ unsigned ukey = (unsigned)((key)); \
lua_Integer *data = (lua_Integer *)t->ravi_array.data; \
if (ukey < t->ravi_array.len) {\
setivalue(v, data[ukey]); \
@ -59,7 +59,7 @@ LUAI_FUNC void raviH_set_float(lua_State *L, Table *t, lua_Unsigned key, lua_Num
}
#define raviH_get_float_inline(L, t, key, v) \
{ unsigned ukey = (unsigned)((key)-1); \
{ unsigned ukey = (unsigned)((key)); \
lua_Number *data = (lua_Number *)t->ravi_array.data; \
if (ukey < t->ravi_array.len) {\
setfltvalue(v, data[ukey]); \
@ -68,7 +68,7 @@ LUAI_FUNC void raviH_set_float(lua_State *L, Table *t, lua_Unsigned key, lua_Num
}
#define raviH_set_int_inline(L, t, key, value) \
{ unsigned ukey = (unsigned)((key)-1); \
{ unsigned ukey = (unsigned)((key)); \
lua_Integer *data = (lua_Integer *)t->ravi_array.data; \
if (ukey < t->ravi_array.len) { \
data[ukey] = value; \
@ -77,7 +77,7 @@ LUAI_FUNC void raviH_set_float(lua_State *L, Table *t, lua_Unsigned key, lua_Num
}
#define raviH_set_float_inline(L, t, key, value) \
{ unsigned ukey = (unsigned)((key)-1); \
{ unsigned ukey = (unsigned)((key)); \
lua_Number *data = (lua_Number *)t->ravi_array.data; \
if (ukey < t->ravi_array.len) { \
data[ukey] = value; \

@ -560,3 +560,21 @@ assert(ravi.compile(f))
assert(not pcall(f))
print("test 40 OK")
-- test 41
-- Ravi arrays support for ipairs()
-- Plus special slot at [0]
x = function()
local nums: integer[] = {1, 2, 3, 4, 5, 6, 7}
local t = 0
assert(#nums == 7)
nums[0] = 558
for k,v in ipairs(nums) do
t = t + v
end
assert(nums[0] == 558)
return t
end
assert(ravi.compile(x))
assert(x() == 28)
print("test 41 OK")

@ -93,11 +93,14 @@ Compatibility with Lua
----------------------
Ravi should be able to run all Lua 5.3 programs in interpreted mode. When JIT compilation is enabled some things will not work:
* You cannot yield from a compiled function, so if you use coroutines then it is better to use the interpreter, as compiled code does not support coroutines
* The debugger doesn't work when JIT compilation is turned on as information it requires is not available; the debugger also does not support Ravi's extended opcodes
* Functions using bit-wise operations cannot be JIT compiled as yet (to be implemented)
* You cannot yield from a compiled function, so if you use coroutines then it is better to use the interpreter, as compiled code does not support coroutines (issue 14)
* The debugger doesn't work when JIT compilation is turned on as information it requires is not available; the debugger also does not support Ravi's extended opcodes (issue 15)
* Functions using bit-wise operations cannot be JIT compiled as yet (issue 27)
* Ravi supports optional typing and enhanced types such as arrays (described later). Programs using these features cannot be run by standard Lua. However all types in Ravi can be passed to Lua functions - there are some restrictions on arrays that are described in a later section. Values crossing from Lua to Ravi may be subjected to typechecks.
* In JITed code tailcalls are implemented as regular calls so unlike Lua VM which supports infinite tail recursion JIT compiled code only supports tail recursion to a depth of about 110.
* In JITed code tailcalls are implemented as regular calls so unlike Lua VM which supports infinite tail recursion JIT compiled code only supports tail recursion to a depth of about 110 (issue 17)
* pairs() and ipairs() do not work on ravi arrays yet (issues 24 and 25)
* Up-values can subvert the static typing of local variables (issue 26)
* Lua C API doesn't work correctly for Ravi arrays (issue 9)
Documentation
--------------

@ -392,7 +392,13 @@ LUA_API size_t lua_rawlen (lua_State *L, int idx) {
switch (ttnov(o)) {
case LUA_TSTRING: return tsvalue(o)->len;
case LUA_TUSERDATA: return uvalue(o)->len;
case LUA_TTABLE: return luaH_getn(hvalue(o));
case LUA_TTABLE: {
Table *h = hvalue(o);
switch (h->ravi_array.type) {
case RAVI_TTABLE: return luaH_getn(h);
default: return raviH_getn(h);
}
}
default: return 0;
}
}
@ -626,10 +632,44 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
LUA_API int lua_rawget (lua_State *L, int idx) {
StkId t;
Table *h;
lua_lock(L);
t = index2addr(L, idx);
api_check(ttistable(t), "table expected");
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
h = hvalue(t);
switch (h->ravi_array.type) {
case RAVI_TTABLE: {
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
} break;
case RAVI_TARRAYINT: {
TValue *key = L->top - 1;
api_check(ttisinteger(key), "key must be integer");
if (ttisinteger(key)) {
lua_Integer n = ivalue(key);
if (n <= raviH_getn(h)) {
raviH_get_int_inline(L, h, n, key);
} else {
setnilvalue(key);
}
} else {
setnilvalue(key);
}
} break;
case RAVI_TARRAYFLT: {
TValue *key = L->top - 1;
api_check(ttisinteger(key), "key must be integer");
if (ttisinteger(key)) {
lua_Integer n = ivalue(key);
if (n <= raviH_getn(h)) {
raviH_get_float_inline(L, h, n, key);
} else {
setnilvalue(key);
}
} else {
setnilvalue(key);
}
} break;
}
lua_unlock(L);
return ttnov(L->top - 1);
}
@ -637,10 +677,30 @@ LUA_API int lua_rawget (lua_State *L, int idx) {
LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
StkId t;
Table *h;
lua_lock(L);
t = index2addr(L, idx);
api_check(ttistable(t), "table expected");
setobj2s(L, L->top, luaH_getint(hvalue(t), n));
h = hvalue(t);
switch (h->ravi_array.type) {
case RAVI_TTABLE: {
setobj2s(L, L->top, luaH_getint(hvalue(t), n));
} break;
case RAVI_TARRAYINT: {
if (n <= raviH_getn(h)) {
raviH_get_int_inline(L, h, n, L->top);
} else {
setnilvalue(L->top);
}
} break;
case RAVI_TARRAYFLT: {
if (n <= raviH_getn(h)) {
raviH_get_float_inline(L, h, n, L->top);
} else {
setnilvalue(L->top);
}
} break;
}
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
@ -774,7 +834,43 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
o = index2addr(L, idx);
api_check(ttistable(o), "table expected");
t = hvalue(o);
setobj2t(L, luaH_set(L, t, L->top-2), L->top-1);
switch (t->ravi_array.type) {
case RAVI_TTABLE: {
setobj2t(L, luaH_set(L, t, L->top-2), L->top-1);
} break;
case RAVI_TARRAYINT: {
TValue *key = L->top - 2;
TValue *val = L->top - 1;
if (!ttisinteger(key))
luaG_typeerror(L, key, "index");
if (ttisinteger(val)) {
raviH_set_int_inline(L, t, ivalue(key), ivalue(val));
} else {
lua_Integer i = 0;
if (luaV_tointeger_(val, &i)) {
raviH_set_int_inline(L, t, ivalue(key), i);
} else
luaG_runerror(L, "value cannot be converted to integer");
}
} break;
case RAVI_TARRAYFLT: {
TValue *key = L->top - 2;
TValue *val = L->top - 1;
if (!ttisinteger(key))
luaG_typeerror(L, key, "index");
if (ttisfloat(val)) {
raviH_set_float_inline(L, t, ivalue(key), fltvalue(val));
} else if (ttisinteger(val)) {
raviH_set_float_inline(L, t, ivalue(key), (lua_Number)(ivalue(val)));
} else {
lua_Number d = 0.0;
if (luaV_tonumber_(val, &d)) {
raviH_set_float_inline(L, t, ivalue(key), d);
} else
luaG_runerror(L, "value cannot be converted to number");
}
} break;
}
invalidateTMcache(t);
luaC_barrierback(L, t, L->top-1);
L->top -= 2;
@ -790,7 +886,37 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
o = index2addr(L, idx);
api_check(ttistable(o), "table expected");
t = hvalue(o);
luaH_setint(L, t, n, L->top - 1);
switch (t->ravi_array.type) {
case RAVI_TTABLE: {
luaH_setint(L, t, n, L->top - 1);
} break;
case RAVI_TARRAYINT: {
TValue *val = L->top - 1;
if (ttisinteger(val)) {
raviH_set_int_inline(L, t, n, ivalue(val));
} else {
lua_Integer i = 0;
if (luaV_tointeger_(val, &i)) {
raviH_set_int_inline(L, t, n, i);
} else
luaG_runerror(L, "value cannot be converted to integer");
}
} break;
case RAVI_TARRAYFLT: {
TValue *val = L->top - 1;
if (ttisfloat(val)) {
raviH_set_float_inline(L, t, n, fltvalue(val));
} else if (ttisinteger(val)) {
raviH_set_float_inline(L, t, n, (lua_Number)(ivalue(val)));
} else {
lua_Number d = 0.0;
if (luaV_tonumber_(val, &d)) {
raviH_set_float_inline(L, t, n, d);
} else
luaG_runerror(L, "value cannot be converted to number");
}
} break;
}
luaC_barrierback(L, t, L->top-1);
L->top--;
lua_unlock(L);

@ -652,7 +652,7 @@ int luaH_getn (Table *t) {
/* RAVI array specialization */
int raviH_getn(Table *t) {
lua_assert(t->ravi_array.type != RAVI_TTABLE);
return t->ravi_array.len;
return t->ravi_array.len-1;
}
static void ravi_resize_array(lua_State *L, Table *t) {
@ -714,6 +714,12 @@ Table *raviH_new(lua_State *L, ravitype_t tt) {
Table *t = luaH_new(L);
lua_assert(tt == RAVI_TARRAYFLT || tt == RAVI_TARRAYINT);
t->ravi_array.type = tt;
if (tt == RAVI_TARRAYFLT) {
raviH_set_float_inline(L, t, 0, 0.0);
}
else {
raviH_set_int_inline(L, t, 0, 0);
}
return t;
}

@ -1180,7 +1180,7 @@ newframe: /* reentry point when frame changes (call/return) */
int i = last-n+1;
for (; i <= (int)last; i++) {
TValue *val = ra + i;
lua_Unsigned u = (lua_Unsigned)(i - 1);
lua_Unsigned u = (lua_Unsigned)(i);
switch (h->ravi_array.type) {
case RAVI_TARRAYINT: {
if (ttisinteger(val))
@ -1605,7 +1605,7 @@ void raviV_op_setlist(lua_State *L, CallInfo *ci, TValue *ra, int b, int c) {
int i = last - n + 1;
for (; i <= (int)last; i++) {
TValue *val = ra + i;
lua_Unsigned u = (lua_Unsigned)(i - 1);
lua_Unsigned u = (lua_Unsigned)(i);
switch (h->ravi_array.type) {
case RAVI_TARRAYINT: {
if (ttisinteger(val))

@ -75,7 +75,7 @@ void RaviCodeGenerator::emit_GETTABLE_AF(RaviFunctionDef *def,
llvm::Value *L_ci, llvm::Value *proto,
int A, int B, int C) {
//#define raviH_get_float_inline(L, t, key, v) \
//{ unsigned ukey = (unsigned)((key)-1); \
//{ unsigned ukey = (unsigned)((key)); \
// lua_Number *data = (lua_Number *)t->ravi_array.data; \
// if (ukey < t->ravi_array.len) {\
// setfltvalue(v, data[ukey]); \
@ -97,10 +97,8 @@ void RaviCodeGenerator::emit_GETTABLE_AF(RaviFunctionDef *def,
llvm::Instruction *t = emit_load_reg_h(def, rb);
llvm::Instruction *data = emit_load_reg_h_floatarray(def, t);
llvm::Instruction *len = emit_load_ravi_arraylength(def, t);
llvm::Value *key_minus_1 =
def->builder->CreateSub(key, def->types->kluaInteger[1]);
llvm::Value *ukey =
def->builder->CreateTrunc(key_minus_1, def->types->C_intT);
def->builder->CreateTrunc(key, def->types->C_intT);
llvm::Value *cmp = def->builder->CreateICmpULT(ukey, len);
llvm::BasicBlock *then_block =
@ -138,7 +136,7 @@ void RaviCodeGenerator::emit_GETTABLE_AI(RaviFunctionDef *def,
int A, int B, int C) {
//#define raviH_get_int_inline(L, t, key, v) \
//{ unsigned ukey = (unsigned)((key)-1); \
//{ unsigned ukey = (unsigned)((key)); \
// lua_Integer *data = (lua_Integer *)t->ravi_array.data; \
// if (ukey < t->ravi_array.len) {\
// setivalue(v, data[ukey]); \
@ -160,10 +158,8 @@ void RaviCodeGenerator::emit_GETTABLE_AI(RaviFunctionDef *def,
llvm::Instruction *t = emit_load_reg_h(def, rb);
llvm::Instruction *data = emit_load_reg_h_intarray(def, t);
llvm::Instruction *len = emit_load_ravi_arraylength(def, t);
llvm::Value *key_minus_1 =
def->builder->CreateSub(key, def->types->kluaInteger[1]);
llvm::Value *ukey =
def->builder->CreateTrunc(key_minus_1, def->types->C_intT);
def->builder->CreateTrunc(key, def->types->C_intT);
llvm::Value *cmp = def->builder->CreateICmpULT(ukey, len);
llvm::BasicBlock *then_block =
@ -201,7 +197,7 @@ void RaviCodeGenerator::emit_SETTABLE_AI(RaviFunctionDef *def,
int A, int B, int C) {
//#define raviH_set_int_inline(L, t, key, value) \
//{ unsigned ukey = (unsigned)((key)-1); \
//{ unsigned ukey = (unsigned)((key)); \
// lua_Integer *data = (lua_Integer *)t->ravi_array.data; \
// if (ukey < t->ravi_array.len) { \
// data[ukey] = value; \
@ -225,10 +221,8 @@ void RaviCodeGenerator::emit_SETTABLE_AI(RaviFunctionDef *def,
llvm::Instruction *t = emit_load_reg_h(def, ra);
llvm::Instruction *data = emit_load_reg_h_intarray(def, t);
llvm::Instruction *len = emit_load_ravi_arraylength(def, t);
llvm::Value *key_minus_1 =
def->builder->CreateSub(key, def->types->kluaInteger[1]);
llvm::Value *ukey =
def->builder->CreateTrunc(key_minus_1, def->types->C_intT);
def->builder->CreateTrunc(key, def->types->C_intT);
llvm::Value *cmp = def->builder->CreateICmpULT(ukey, len);
llvm::BasicBlock *then_block =
@ -263,7 +257,7 @@ void RaviCodeGenerator::emit_SETTABLE_AF(RaviFunctionDef *def,
int A, int B, int C) {
//#define raviH_set_float_inline(L, t, key, value) \
//{ unsigned ukey = (unsigned)((key)-1); \
//{ unsigned ukey = (unsigned)((key)); \
// lua_Number *data = (lua_Number *)t->ravi_array.data; \
// if (ukey < t->ravi_array.len) { \
// data[ukey] = value; \
@ -337,10 +331,8 @@ void RaviCodeGenerator::emit_SETTABLE_AF(RaviFunctionDef *def,
llvm::Instruction *t = emit_load_reg_h(def, ra);
llvm::Instruction *data = emit_load_reg_h_floatarray(def, t);
llvm::Instruction *len = emit_load_ravi_arraylength(def, t);
llvm::Value *key_minus_1 =
def->builder->CreateSub(key, def->types->kluaInteger[1]);
llvm::Value *ukey =
def->builder->CreateTrunc(key_minus_1, def->types->C_intT);
def->builder->CreateTrunc(key, def->types->C_intT);
cmp = def->builder->CreateICmpULT(ukey, len);
llvm::BasicBlock *then_block =

Loading…
Cancel
Save