pull/81/head
Dibyendu Majumdar 9 years ago
commit d13dacce7d

@ -62,6 +62,7 @@ checkmessage('local t: integer = function() return "hell" end', 'Invalid local a
checkmessage('local function j() return "hell" end; local t: integer = j()', 'integer expected')
checkmessage('local t: integer = 5; local x=function() return "string" end; local f=function() t = x() end; f()', 'upvalue of integer type, cannot be set to non integer value')
checkmessage('local t: integer = 5.5', 'Invalid local assignment')
checkmessage('local function f() local t: number[] = {}; t[1] = 4.2; t[5] = 2.4; end; f()', 'array out of bounds')
checkmessage('local t: number[] = {}; local t2: number[] = {1.0}; t=t2[1]', 'Invalid assignment: number[] expected')
checkmessage('local t: number[] = {}; t=1', 'Invalid assignment: number[] expected')

@ -1,7 +1,7 @@
Ravi Programming Language
=========================
Ravi is a derivative/dialect of `Lua 5.3 <http://www.lua.org/>`_ with limited optional static typing and an `LLVM <http://www.llvm.org/>`_ based JIT compiler. The name Ravi comes from the Sanskrit word for the Sun.
Ravi is a derivative/dialect of `Lua 5.3 <http://www.lua.org/>`_ with limited optional static typing and an `LLVM <http://www.llvm.org/>`_ powered JIT compiler. The name Ravi comes from the Sanskrit word for the Sun.
Lua is perfect as a small embeddable dynamic language so why a derivative? Ravi extends Lua with static typing for greater performance under JIT compilation. However, the static typing is optional and therefore Lua programs are also valid Ravi programs.
@ -14,7 +14,7 @@ Goals
* Optional static typing for Lua
* Type specific bytecodes to improve performance
* Compatibility with Lua 5.3 (see Compatibility section below)
* `LLVM <http://www.llvm.org/>`_ based JIT compiler
* `LLVM <http://www.llvm.org/>`_ powered JIT compiler
* Additionally a `libgccjit <https://gcc.gnu.org/wiki/JIT>`_ based alternative JIT compiler is also available.
Documentation
@ -34,7 +34,7 @@ The LLVM JIT compiler is functional. The Lua and Ravi bytecodes currently implem
Ravi also provides an `LLVM binding <http://the-ravi-programming-language.readthedocs.org/en/latest/llvm-bindings.html>`_; this is still work in progress so please check documentation for the latest status.
As of July 2015 the `libgccjit <http://the-ravi-programming-language.readthedocs.org/en/latest/ravi-jit-libgccjit.html>`_ based JIT implementation is also functional but some byte codes are not yet compiled, and featurewise this implementation is somewhat behind the LLVM based implementation.
As of July 2015 the `libgccjit <http://the-ravi-programming-language.readthedocs.org/en/latest/ravi-jit-libgccjit.html>`_ based JIT implementation is also functional but some byte codes are not yet compiled, and featurewise this implementation is somewhat lagging behind the LLVM based implementation.
Performance Benchmarks
++++++++++++++++++++++
@ -63,8 +63,8 @@ Declaring the types of ``local`` variables and function parameters has following
* ``integer`` and ``number`` types are automatically initialized to zero
* Arithmetic operations on numeric types make use of type specific bytecodes which leads to more efficient JIT compilation
* Specialised operators to get/set from array types are implemented; this makes array access more efficient in JIT mode as the access can be inlined
* Declared tables allow specialized opcodes for usages involving integer and short string (literal only) keys; these opcodes result in more efficient JIT code
* Values assigned to typed variables are checked statically when possible; if the values are results from a function call then there runtime type checking is performed
* Declared tables allow specialized opcodes for usages involving integer and short literal string keys; these opcodes result in more efficient JIT code
* Values assigned to typed variables are checked statically when possible; if the values are results from a function call then runtime type checking is performed
* The standard table operations on arrays are checked to ensure that the type is not subverted
* Even if a typed variable is captured in a closure its type must be respected
* When function parameters are decorated with types, Ravi performs an implicit coersion of those parameters to the required types. If the coersion fails a runtime error occurs.
@ -76,29 +76,64 @@ The array types (``number[]`` and ``integer[]``) are specializations of Lua tabl
local t: table = {}
local t2: number[] = t -- error!
* Indices >= 1 should be used (note that Ravi arrays (and slices) have a hidden slot at index 0 for performance reasons, but this is not visible under ``pairs()`` or ``ipairs()``, or when initializing an array using a literal initializer; only direct access via the ``[]`` operator can see this slot)
local t3: number[] = {}
local t4: table = t3 -- error!
But following is okay::
local t5: number[] = {}
local t6 = t5 -- t6 treated as table
The reason for this discrepancy is that declared table types generate optimized JIT code which assumes that the keys are integers
or literal short strings. The generated code would be incorrect if this expectation was not met.
* Indices >= 1 should be used when accessing array elements. Ravi arrays (and slices) have a hidden slot at index 0 for performance reasons, but this is not visible under ``pairs()`` or ``ipairs()``, or when initializing an array using a literal initializer; only direct access via the ``[]`` operator can see this slot.
* Arrays must always be initialized::
local t: number[] = {} -- okay
local t2: number[] -- error!
* An array will grow automatically if user sets the element just past the array length
This restriction is placed as otherwise the JIT code would need to insert tests to validate that the variable is not nil.
* An array will grow automatically if user sets the element just past the array length::
local t: number[] = {}
t[1] = 4.2 -- okay, array grows by 1
t[5] = 2.4 -- error! as attempt to set value
* It is an error to attempt to set an element that is beyond len+1
* The current used length of the array is recorded and returned by len operations
* The array only permits the right type of value to be assigned (this is also checked at runtime to allow compatibility with Lua)
* Accessing out of bounds elements will cause an error, except for setting the len+1 element
* It is possible to pass arrays to functions and return arrays from functions. Arrays passed to functions appear as Lua tables inside those functions if the parameters are untyped - however the tables will still be subject to restrictions as above. If the parameters are typed then the arrays will be recognized at compile time.
* It is possible to pass arrays to functions and return arrays from functions. Arrays passed to functions appear as Lua tables inside
those functions if the parameters are untyped - however the tables will still be subject to restrictions as above. If the parameters are typed then the arrays will be recognized at compile time::
local function f(a, b: integer[], c)
-- Here a is dynamic type
-- b is declared as integer[]
-- c is also a dynamic type
b[1] = a[1] -- Okay only if a is actually also integer[]
b[1] = c[1] -- Will fail if c[1] cannot be converted to an integer
end
local a : integer[] = {1}
local b : integer[] = {}
local c = {1}
f(a,b,c) -- ok as c[1] is integer
f(a,b, {'hi'}) -- error!
* Arrays returned from functions can be stored into appropriately typed local variables - there is validation that the types match::
local t: number[] = f() -- type will be checked at runtime
* Operations on array types can be optimised to special bytecode and JIT only when the array type is statically known. Otherwise regular table access will be used subject to runtime checks.
* Array types may not have meta methods - this will be enforced at runtime (TODO)
* Array types may not have meta methods - this will be enforced at runtime (TODO).
* ``pairs()`` and ``ipairs()`` work on arrays as normal
* There is no way to delete an array element.
* The array data is stored in contiguous memory just like native C arrays; morever the garbage collector does not scan the array data
A declared table (as shown below) has some nuances::
A declared table (as shown below) has some additional nuances::
local t: table = {}
@ -335,7 +370,8 @@ Work Plan
* Jun-Jul 2015 - libgccjit based alternative JIT
* Jun-Nov 2015 - testing
* Dec 2015 - beta release
* 2016 - Focus on creating numeric library bindings - in particular:
* 2016 - Focus on creating numeric library bindings - in particular.
* BLAS and LAPACK
* GNU Scientific library
* symengine

@ -1126,7 +1126,7 @@ static void codeexpval (FuncState *fs, OpCode op,
e1->ravi_type = RAVI_TANY;
}
else {
if (op == OP_LEN || op == OP_BNOT)
if (op == OP_LEN /* || op == OP_BNOT - see issue #65 */)
e1->ravi_type = RAVI_TNUMINT;
}
luaK_fixline(fs, line);

@ -705,7 +705,7 @@ static int ravi_resize_array(lua_State *L, Table *t, unsigned int new_size,
return 0;
}
/* NOTE - relies upon lua_Number and lua_Integer being the same size */
lua_assert(sizeof(lua_Integer) == sizeof(lua_Number));
static_assert(sizeof(lua_Integer) == sizeof(lua_Number), "sizeof lua_Integer not same as sizeof lua_Number");
unsigned int size =
new_size < t->ravi_array.size + 10 ? t->ravi_array.size + 10 : new_size;
t->ravi_array.data = (char *)luaM_reallocv(

@ -1111,6 +1111,22 @@ newframe: /* reentry point when frame changes (call/return) */
}
} break;
case OP_RAVI_BNOT_I: {
/* On Win32 the following code generates a test failure
* at line 29 of bitwise.lua test. Specifically following fails:
* function x()
* local a= 0xF0000000
* local b=~a
* local c=~b
* local d=~~a
* print(a,b,c,d)
* print(~~a)
* end
* Inserting a prinf statement following the assignment to ib appears
* to cause the problem to go away so this is a case of incorrect
* optimization / code generation?
* To work around this issue, for now we can disable the type
* inference for OP_BNOT in line 1129 of lcode.c (codeexpval function)
*/
TValue *rb = RB(i);
lua_Integer ib = ivalue(rb);
setivalue(ra, intop(^, ~l_castS2U(0), ib));

@ -57,13 +57,14 @@ RaviJITStateImpl::RaviJITStateImpl()
init++;
}
triple_ = llvm::sys::getProcessTriple();
#if defined(_WIN32) && LLVM_VERSION_MINOR < 7
#if defined(_WIN32) && (!defined(_WIN64) || LLVM_VERSION_MINOR < 7)
// On Windows we get compilation error saying incompatible object format
// Reading posts on mailing lists I found that the issue is that COEFF
// format is not supported and therefore we need to set -elf as the object
// format; LLVM 3.7 onwards COEFF is supported
triple_ += "-elf";
#endif
context_ = new llvm::LLVMContext();
types_ = new LuaLLVMTypes(*context_);
}
@ -123,7 +124,7 @@ RaviJITFunctionImpl::RaviJITFunctionImpl(
// module per function
std::string moduleName = "ravi_module_" + name;
module_ = new llvm::Module(moduleName, owner->context());
#if defined(_WIN32) && LLVM_VERSION_MINOR < 7
#if defined(_WIN32) && (!defined(_WIN64) || LLVM_VERSION_MINOR < 7)
// On Windows we get error saying incompatible object format
// Reading posts on mailing lists I found that the issue is that COEFF
// format is not supported and therefore we need to set

Loading…
Cancel
Save