Datatypes
LSL integer
Used as a boolean value, with contants TRUE
and FALSE
is an SLua type boolean, with values true
and false
.
Used as an integer is an SLua type number (which has integer and float values all in the same datatype).
|
|
LSL float
It is an SLua type number (floats and integers all go in the datatype number). SLua numbers are stored in 64 bits.
|
|
LSL string
It is an SLua type string.
|
|
More about strings here: Strings.
LSL key
SLua adds the type uuid, which is the same than the LSL key.The change of name is to avoid confusion with the key of a table.
- We get a uuid using
myId = uuid("0f16c0e1-384e-4b5f-b7ce-886dda3bce41")
.
|
|
LSL vector
It is an SLua type vector. It uses the Luau library vector.
- We get a vector using
myVec = vector(50, 50, 0)
. - It’s not possible to assign a value to a component. We need to create a new vector.
- We can get a component from the return value of a function, not only from a variable.
- Components are stored in 32 bits (same as LSL).
|
|
LSL rotation
SLua adds the types rotation and quaternion. They are synonims, internally they are the same datatype quaternion.
- We get a rotation using
myRot = rotation(1, 1, 1, 0)
ormyRot = quaternion(1, 1, 1, 0)
. - It’s not possible to assign a value to a component. We need to create a new rotation.
- We can get a component from the return value of a function, not only from a variable.
- Components are stored in 32 bits (same as LSL).
- Vectors can use uppercase components (X, Y, Z) but rotations can’t. Let’s use always lowercase components.
|
|
LSL list
Lists are tables.
|
|
More about tables here: Tables.
The SLua datatype integer
SLua adds the type integer (32 bits). It exists only for compatibility reasons with a few LL functions.
It’s not to be used as an LSL integer, the LSL integer is an SLua number (which has integer and float values all in the same datatype).
The SLua type integer is only for a few uses that requires it. We can’t make operations with a number and an integer, they are different types. Integers must be casted to numbers to operate with numbers.
-- type integer (SLua)
local myInt = integer(42) -- don't use this type unless there is a good reason
The uses of “integer” are:
- Typecasting in LSL-style
integer("123abc") -- > 123
orinteger("aaa") -- > 0
- tonumber() returns nil in both cases.
- same as
string.match( "123abc", "^%s*([-+]?%d+)" ) or 0
integer(myBool) -- > 1 or 0
- same as
if myBool then 1 else 0
- same as
- ll.List2Integer() returns type integer.
- ll.DumpList2String() and ll.List2CSV() print type number always with six decimals and type integer without decimals
- the bit32 library functions return type integer when all the parameters have type integer.
Typecasting
- to boolean
- from number or integer:
myBool = (myNum ~= 0)
- from number or integer:
- to number
- from string:
- if the string is fully numeric:
myNum = tonumber("123") -- > 123
ormyNum = tonumber("1.75") -- > 1.75
- but
tonumber("123abc") --> nil
- if the string starts with an integer:
myNum = integer("123abc") -- > 123
orinteger("abc") -- > 0
- but
integer("1.75abc") -- > 1
- if the string is fully numeric:
- from integer:
myNum = tonumber(integer(42)) -- > 42
- from string:
- to string
- from any type:
myStr = tostring(myVar)
- from any type:
- to uuid
- from string:
myUuid = uuid("0f16c0e1-384e-4b5f-b7ce-886dda3bce41")
- from string:
- to vector
- from string:
myVec = tovector("<50, 50, 20>")
- from string:
- to rotation/quaternion
- from string:
myRot = torotation("<1, 1, 1, 0>")
myRot = toquaternion("<1, 1, 1, 0>")
- from string:
- to integer
- from boolean:
myInt = integer(isOk) -- > myInt will be 1 or 0
- from number:
myInt = integer(1.75)
- from string:
myInt = integer("123abc")
- from boolean:
The types integer and uuid haven’t got a “to” function because they already use or can use a string to create the value.
type() and typeof()
type( myVar ) returns the Lua base type of the variable. All the types added by SLua return “userdata”, which is an internal datatype used to define new types in the language itself. We can’t use “userdata”.
typeof( myVar ) returns the type of the variable, including the new types:
typeof( vector( 1, 2, 3 ) ) -- > vector
typeof( uuid( "0f16c0e1-384e-4b5f-b7ce-886dda3bce41" ) ) -- > uuid
typeof ( rotation ( 1, 2, 3, 4) ) -- > quaternion
We have the datatypes rotation and quaternion and the functions torotation() and toquaternion() to cast from string, but internally only exists the type quaternion, rotation is just an alias.
-- typeof() (SLua)
if typeof(myVar) == "quaternion" then -- NOT "rotation", it would never happen!
-- do rotations stuff
end
typeof( ZERO_ROTATION ) -- > quaternion
. There is no constant ZERO_QUATERNION.
Types in LL constants and functions
In SLua, LL constants, function return values, and the elements of lists returned by LL functions have the type number if their LSL type is integer or float.
- The only exception is ll.List2Integer(), which returns an SLua integer.
For LL function parameters that are integer or float in LSL, SLua accepts both number and integer types.
- If a number with decimals is passed to a parameter expecting an integer, the decimal part is truncated (not rounded).
- Many, but not all, of these functions also accept a boolean type, which is internally cast to an integer.
In SLua, LL constants that contain a uuid have type uuid. In LSL they have type string.
Use of memory
Every variable or literal value, of any type, is stored as a 16 bytes tagged value (TValue) that includes the type identifier.
- Primitive types (boolean, number, vector and nil) have their value in the TValue.
- Reference types (string, table, function, thread, buffer and userdata) have a pointer to the heap.
SLua vector is derived from Luau vector and is a primitive type.
SLua quaternion, uuid and integer are derived from userdata and are reference types.
The format of the TValue is:
- 8 bytes : value (for primitive types) or pointer (for reference types)
- 4 bytes : extra (used for Luau vectors to store their 3rd component)
- 4 bytes : type identifier
When used as a key in a table, it changes to a Tkey, with this format:
- 8 bytes : value
- 4 bytes : extra
- 4 bits : type identifier
- 28 bits : link to the next node in the table
Each node in a table has a TKey and a TValue.
Reference types have their data stored in the heap (pointed by the TValue) with a header with internal metadata:
- string has its length (in bytes) and data for string interning.
- table has the length of the array part, a pointer to its metatable, the read-only parameter and data to optimize search.
- userdata has the length and a pointer to its internal metatable.
Strings and uuids are stored as UTF-8. The characters ASCII 0-127 use 1 byte (instead of 2 bytes in LSL):
Bytes | Unicode Range | Character Types |
---|---|---|
1 | U+0000 to U+007F | ASCII characters (basic English letters, digits, etc.) |
2 | U+0080 to U+07FF | Extended Latin, Greek, Cyrillic, Hebrew, Arabic |
3 | U+0800 to U+FFFF | Chinese, Japanese, Korean, symbols, most emojis |
4 | U+10000 to U+10FFFF | Supplementary characters, rare scripts, more emojis |