-
Notifications
You must be signed in to change notification settings - Fork 5
Embedding C
Since C is the intermediate language used when generating machine code, we can allow a subset of C as an embedded high performance language.
It does not need to be full blown C as that would be too risky. Instead the goal is to allow C to write snippets of high performance code.
Following features will not be provided:
- Preprocessor
- Ability to call functions or allocate memory; this rule may be relaxed to allow calls to simple C standard library functions for maths
- The interaction between Ravi and C is limited to userdata types, primitive types (
number
andinteger
), primitive arrays (integer[]
andnumber[]
) and strings. Access to Lua tables is not supported.
New keywords C__decl
, C__unsafe
, C__new
have been added.
-
C__decl
allows C type declarations via a string argument. A restriction is imposed that the declared types contain no pointers or unions. All type declarations in a chunk of Ravi code are amalgamated in the generated code, hence duplicate declarations are not allowed. Struct declarations can have a flexible array member. -
C__unsafe
takes a list of symbols and a C code in string argument. The restriction is imposed that code may not make function calls or attempt toreturn
orgoto
. -
C__new
allows a userdata type of given struct type to be created. A size argument is required; when the type has a flexible array member, the size specifies the dimension of this array member, otherwise the size defines whether a single object will be created or an array.
C__decl [[
typedef struct {
int i;
} MyStruct;
]]
local i: integer = 1
local j: integer = 2
C__unsafe(i,j) [[
long long k = i+j; // Okay as primitive types
]]
When accessing userdata, string or Ravi array types, following implicit types are used:
// For userdata and string types
typedef struct {
char *ptr;
unsigned int len;
} Ravi_StringOrUserData;
// For integer[]
typedef struct {
lua_Integer *ptr;
unsigned int len;
} Ravi_IntegerArray;
// For number[]
typedef struct {
lua_Number *ptr;
unsigned int len;
} Ravi_NumberArray;
Userdata, string or primitive arrays declared in Ravi code will be accessed in the C snippet as follows:
local narray: number[] = table.numarray(100)
local udata = C__new('MyStruct', 1) -- userdata object of type, with 1 element
C__unsafe(udata, narray) [[
// C code can cast the udata.ptr and narray.ptr to appropriate type
MyStruct *mystruct = (MyStruct *)udata.ptr;
mystruct->i = 42;
]]
Each symbol argument to C__unsafe
is made available in the C code.
- Primitive integer or floating point values have the types
lua_Integer
andlua_Number
respectively. - Userdata or string types are made available as
Ravi_StringOrUserData
structure. -
integer[]
andnumber[]
arrays are made available asRavi_IntegerArray
andRavi_NumberArray
respectively.
Values assigned to the primitive types are reflected in Ravi code. The other supported types are reference types anyway, however making changes to Lua strings is not permitted (although this is not yet enforced).
For string
, full userdata
, integer[]
and number[]
array types, a len
attribute is populated.
For lightweight userdata
, the len
attribute will be set to 0.
The keyword C__new
can be used to allocate a userdata
type. A structure type name (previously declared using C__decl
) can be provided, along with array size.
- This feature is under development; initial preview version is now available (12-Oct-2021)
- A custom version of
chibicc
is used to parse and validate the C code to enforce some of the rules above.