mirror of
https://github.com/lua/lua
synced 2024-11-22 12:51:30 +03:00
5ff408d218
Instead of an explicit value (field 'b'), true and false use different tag variants. This avoids reading an extra field and results in more direct code. (Most code that uses booleans needs to distinguish between true and false anyway.)
770 lines
21 KiB
C
770 lines
21 KiB
C
/*
|
|
** $Id: lobject.h $
|
|
** Type definitions for Lua objects
|
|
** See Copyright Notice in lua.h
|
|
*/
|
|
|
|
|
|
#ifndef lobject_h
|
|
#define lobject_h
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
#include "llimits.h"
|
|
#include "lua.h"
|
|
|
|
|
|
/*
|
|
** Extra tags for collectable non-values
|
|
*/
|
|
#define LUA_TUPVAL LUA_NUMTAGS /* upvalues */
|
|
#define LUA_TPROTO (LUA_NUMTAGS+1) /* function prototypes */
|
|
|
|
|
|
/*
|
|
** number of all possible tags (including LUA_TNONE)
|
|
*/
|
|
#define LUA_TOTALTAGS (LUA_TPROTO + 2)
|
|
|
|
|
|
/*
|
|
** tags for Tagged Values have the following use of bits:
|
|
** bits 0-3: actual tag (a LUA_T* constant)
|
|
** bits 4-5: variant bits
|
|
** bit 6: whether value is collectable
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
** Union of all Lua values
|
|
*/
|
|
typedef union Value {
|
|
struct GCObject *gc; /* collectable objects */
|
|
void *p; /* light userdata */
|
|
lua_CFunction f; /* light C functions */
|
|
lua_Integer i; /* integer numbers */
|
|
lua_Number n; /* float numbers */
|
|
} Value;
|
|
|
|
|
|
/*
|
|
** Tagged Values. This is the basic representation of values in Lua:
|
|
** an actual value plus a tag with its type.
|
|
*/
|
|
|
|
#define TValuefields Value value_; lu_byte tt_
|
|
|
|
typedef struct TValue {
|
|
TValuefields;
|
|
} TValue;
|
|
|
|
|
|
#define val_(o) ((o)->value_)
|
|
#define valraw(o) (&val_(o))
|
|
|
|
|
|
/* raw type tag of a TValue */
|
|
#define rawtt(o) ((o)->tt_)
|
|
|
|
/* tag with no variants (bits 0-3) */
|
|
#define novariant(t) ((t) & 0x0F)
|
|
|
|
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
|
|
#define withvariant(t) ((t) & 0x3F)
|
|
#define ttypetag(o) withvariant(rawtt(o))
|
|
|
|
/* type of a TValue */
|
|
#define ttype(o) (novariant(rawtt(o)))
|
|
|
|
|
|
/* Macros to test type */
|
|
#define checktag(o,t) (rawtt(o) == (t))
|
|
#define checktype(o,t) (ttype(o) == (t))
|
|
|
|
|
|
/* Macros for internal tests */
|
|
|
|
/* collectable object has the same tag as the original value */
|
|
#define righttt(obj) (ttypetag(obj) == gcvalue(obj)->tt)
|
|
|
|
/*
|
|
** Any value being manipulated by the program either is non
|
|
** collectable, or the collectable object has the right tag
|
|
** and it is not dead.
|
|
*/
|
|
#define checkliveness(L,obj) \
|
|
((void)L, lua_longassert(!iscollectable(obj) || \
|
|
(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))))
|
|
|
|
|
|
/* Macros to set values */
|
|
|
|
/* set a value's tag */
|
|
#define settt_(o,t) ((o)->tt_=(t))
|
|
|
|
|
|
/* main macro to copy values (from 'obj1' to 'obj2') */
|
|
#define setobj(L,obj1,obj2) \
|
|
{ TValue *io1=(obj1); const TValue *io2=(obj2); \
|
|
io1->value_ = io2->value_; settt_(io1, io2->tt_); \
|
|
checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); }
|
|
|
|
/*
|
|
** Different types of assignments, according to source and destination.
|
|
** (They are mostly equal now, but may be different in the future.)
|
|
*/
|
|
|
|
/* from stack to stack */
|
|
#define setobjs2s(L,o1,o2) setobj(L,s2v(o1),s2v(o2))
|
|
/* to stack (not from same stack) */
|
|
#define setobj2s(L,o1,o2) setobj(L,s2v(o1),o2)
|
|
/* from table to same table */
|
|
#define setobjt2t setobj
|
|
/* to new object */
|
|
#define setobj2n setobj
|
|
/* to table */
|
|
#define setobj2t setobj
|
|
|
|
|
|
/*
|
|
** Entries in the Lua stack
|
|
*/
|
|
typedef union StackValue {
|
|
TValue val;
|
|
} StackValue;
|
|
|
|
|
|
/* index to stack elements */
|
|
typedef StackValue *StkId;
|
|
|
|
/* convert a 'StackValue' to a 'TValue' */
|
|
#define s2v(o) (&(o)->val)
|
|
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Nil
|
|
** ===================================================================
|
|
*/
|
|
|
|
/* macro to test for (any kind of) nil */
|
|
#define ttisnil(v) checktype((v), LUA_TNIL)
|
|
|
|
/* macro to test for a "pure" nil */
|
|
#define ttisstrictnil(o) checktag((o), LUA_TNIL)
|
|
|
|
|
|
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
|
|
|
|
|
|
/*
|
|
** Variant tag, used only in tables to signal an empty slot
|
|
** (which might be different from a slot containing nil)
|
|
*/
|
|
#define LUA_TEMPTY (LUA_TNIL | (1 << 4))
|
|
|
|
/*
|
|
** Variant used only in the value returned for a key not found in a
|
|
** table (absent key).
|
|
*/
|
|
#define LUA_TABSTKEY (LUA_TNIL | (2 << 4))
|
|
|
|
|
|
#define isabstkey(v) checktag((v), LUA_TABSTKEY)
|
|
|
|
|
|
/*
|
|
** macro to detect non-standard nils (used only in assertions)
|
|
*/
|
|
#define isnonstrictnil(v) (ttisnil(v) && !ttisstrictnil(v))
|
|
|
|
|
|
/*
|
|
** By default, entries with any kind of nil are considered empty.
|
|
** (In any definition, values associated with absent keys must also
|
|
** be accepted as empty.)
|
|
*/
|
|
#define isempty(v) ttisnil(v)
|
|
|
|
|
|
/* macro defining a value corresponding to an absent key */
|
|
#define ABSTKEYCONSTANT {NULL}, LUA_TABSTKEY
|
|
|
|
|
|
/* mark an entry as empty */
|
|
#define setempty(v) settt_(v, LUA_TEMPTY)
|
|
|
|
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Booleans
|
|
** ===================================================================
|
|
*/
|
|
|
|
|
|
#define LUA_TFALSE (LUA_TBOOLEAN | (1 << 4))
|
|
#define LUA_TTRUE (LUA_TBOOLEAN | (2 << 4))
|
|
|
|
#define ttisboolean(o) checktype((o), LUA_TBOOLEAN)
|
|
#define ttisfalse(o) checktag((o), LUA_TFALSE)
|
|
#define ttistrue(o) checktag((o), LUA_TTRUE)
|
|
|
|
|
|
#define l_isfalse(o) (ttisfalse(o) || ttisnil(o))
|
|
|
|
|
|
#define setbfvalue(obj) settt_(obj, LUA_TFALSE)
|
|
#define setbtvalue(obj) settt_(obj, LUA_TTRUE)
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Threads
|
|
** ===================================================================
|
|
*/
|
|
|
|
#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
|
|
|
|
#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
|
|
|
|
#define setthvalue(L,obj,x) \
|
|
{ TValue *io = (obj); lua_State *x_ = (x); \
|
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
|
|
checkliveness(L,io); }
|
|
|
|
#define setthvalue2s(L,o,t) setthvalue(L,s2v(o),t)
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Collectable Objects
|
|
** ===================================================================
|
|
*/
|
|
|
|
/*
|
|
** Common Header for all collectable objects (in macro form, to be
|
|
** included in other objects)
|
|
*/
|
|
#define CommonHeader struct GCObject *next; lu_byte tt; lu_byte marked
|
|
|
|
|
|
/* Common type for all collectable objects */
|
|
typedef struct GCObject {
|
|
CommonHeader;
|
|
} GCObject;
|
|
|
|
|
|
/* Bit mark for collectable types */
|
|
#define BIT_ISCOLLECTABLE (1 << 6)
|
|
|
|
#define iscollectable(o) (rawtt(o) & BIT_ISCOLLECTABLE)
|
|
|
|
/* mark a tag as collectable */
|
|
#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
|
|
|
|
#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
|
|
|
|
#define gcvalueraw(v) ((v).gc)
|
|
|
|
#define setgcovalue(L,obj,x) \
|
|
{ TValue *io = (obj); GCObject *i_g=(x); \
|
|
val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); }
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Numbers
|
|
** ===================================================================
|
|
*/
|
|
|
|
/* Variant tags for numbers */
|
|
#define LUA_TNUMFLT (LUA_TNUMBER | (1 << 4)) /* float numbers */
|
|
#define LUA_TNUMINT (LUA_TNUMBER | (2 << 4)) /* integer numbers */
|
|
|
|
#define ttisnumber(o) checktype((o), LUA_TNUMBER)
|
|
#define ttisfloat(o) checktag((o), LUA_TNUMFLT)
|
|
#define ttisinteger(o) checktag((o), LUA_TNUMINT)
|
|
|
|
#define nvalue(o) check_exp(ttisnumber(o), \
|
|
(ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))
|
|
#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n)
|
|
#define ivalue(o) check_exp(ttisinteger(o), val_(o).i)
|
|
|
|
#define fltvalueraw(v) ((v).n)
|
|
#define ivalueraw(v) ((v).i)
|
|
|
|
#define setfltvalue(obj,x) \
|
|
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
|
|
|
|
#define chgfltvalue(obj,x) \
|
|
{ TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }
|
|
|
|
#define setivalue(obj,x) \
|
|
{ TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
|
|
|
|
#define chgivalue(obj,x) \
|
|
{ TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Strings
|
|
** ===================================================================
|
|
*/
|
|
|
|
/* Variant tags for strings */
|
|
#define LUA_TSHRSTR (LUA_TSTRING | (1 << 4)) /* short strings */
|
|
#define LUA_TLNGSTR (LUA_TSTRING | (2 << 4)) /* long strings */
|
|
|
|
#define ttisstring(o) checktype((o), LUA_TSTRING)
|
|
#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR))
|
|
#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR))
|
|
|
|
#define tsvalueraw(v) (gco2ts((v).gc))
|
|
|
|
#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc))
|
|
|
|
#define setsvalue(L,obj,x) \
|
|
{ TValue *io = (obj); TString *x_ = (x); \
|
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
|
|
checkliveness(L,io); }
|
|
|
|
/* set a string to the stack */
|
|
#define setsvalue2s(L,o,s) setsvalue(L,s2v(o),s)
|
|
|
|
/* set a string to a new object */
|
|
#define setsvalue2n setsvalue
|
|
|
|
|
|
/*
|
|
** Header for string value; string bytes follow the end of this structure
|
|
** (aligned according to 'UTString'; see next).
|
|
*/
|
|
typedef struct TString {
|
|
CommonHeader;
|
|
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
|
|
lu_byte shrlen; /* length for short strings */
|
|
unsigned int hash;
|
|
union {
|
|
size_t lnglen; /* length for long strings */
|
|
struct TString *hnext; /* linked list for hash table */
|
|
} u;
|
|
} TString;
|
|
|
|
|
|
|
|
/*
|
|
** Get the actual string (array of bytes) from a 'TString'.
|
|
** (Access to 'extra' ensures that value is really a 'TString'.)
|
|
*/
|
|
#define getstr(ts) \
|
|
check_exp(sizeof((ts)->extra), cast_charp((ts)) + sizeof(TString))
|
|
|
|
|
|
/* get the actual string (array of bytes) from a Lua value */
|
|
#define svalue(o) getstr(tsvalue(o))
|
|
|
|
/* get string length from 'TString *s' */
|
|
#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen)
|
|
|
|
/* get string length from 'TValue *o' */
|
|
#define vslen(o) tsslen(tsvalue(o))
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Userdata
|
|
** ===================================================================
|
|
*/
|
|
|
|
#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA)
|
|
#define ttisfulluserdata(o) checktype((o), LUA_TUSERDATA)
|
|
|
|
#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
|
|
#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
|
|
|
|
#define pvalueraw(v) ((v).p)
|
|
|
|
#define setpvalue(obj,x) \
|
|
{ TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); }
|
|
|
|
#define setuvalue(L,obj,x) \
|
|
{ TValue *io = (obj); Udata *x_ = (x); \
|
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
|
|
checkliveness(L,io); }
|
|
|
|
|
|
/* Ensures that addresses after this type are always fully aligned. */
|
|
typedef union UValue {
|
|
TValue uv;
|
|
LUAI_MAXALIGN; /* ensures maximum alignment for udata bytes */
|
|
} UValue;
|
|
|
|
|
|
/*
|
|
** Header for userdata with user values;
|
|
** memory area follows the end of this structure.
|
|
*/
|
|
typedef struct Udata {
|
|
CommonHeader;
|
|
unsigned short nuvalue; /* number of user values */
|
|
size_t len; /* number of bytes */
|
|
struct Table *metatable;
|
|
GCObject *gclist;
|
|
UValue uv[1]; /* user values */
|
|
} Udata;
|
|
|
|
|
|
/*
|
|
** Header for userdata with no user values. These userdata do not need
|
|
** to be gray during GC, and therefore do not need a 'gclist' field.
|
|
** To simplify, the code always use 'Udata' for both kinds of userdata,
|
|
** making sure it never accesses 'gclist' on userdata with no user values.
|
|
** This structure here is used only to compute the correct size for
|
|
** this representation. (The 'bindata' field in its end ensures correct
|
|
** alignment for binary data following this header.)
|
|
*/
|
|
typedef struct Udata0 {
|
|
CommonHeader;
|
|
unsigned short nuvalue; /* number of user values */
|
|
size_t len; /* number of bytes */
|
|
struct Table *metatable;
|
|
union {LUAI_MAXALIGN;} bindata;
|
|
} Udata0;
|
|
|
|
|
|
/* compute the offset of the memory area of a userdata */
|
|
#define udatamemoffset(nuv) \
|
|
((nuv) == 0 ? offsetof(Udata0, bindata) \
|
|
: offsetof(Udata, uv) + (sizeof(UValue) * (nuv)))
|
|
|
|
/* get the address of the memory block inside 'Udata' */
|
|
#define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue))
|
|
|
|
/* compute the size of a userdata */
|
|
#define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb))
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Prototypes
|
|
** ===================================================================
|
|
*/
|
|
|
|
/*
|
|
** Description of an upvalue for function prototypes
|
|
*/
|
|
typedef struct Upvaldesc {
|
|
TString *name; /* upvalue name (for debug information) */
|
|
lu_byte instack; /* whether it is in stack (register) */
|
|
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
|
|
lu_byte kind; /* kind of corresponding variable */
|
|
} Upvaldesc;
|
|
|
|
|
|
/*
|
|
** Description of a local variable for function prototypes
|
|
** (used for debug information)
|
|
*/
|
|
typedef struct LocVar {
|
|
TString *varname;
|
|
int startpc; /* first point where variable is active */
|
|
int endpc; /* first point where variable is dead */
|
|
} LocVar;
|
|
|
|
|
|
/*
|
|
** Associates the absolute line source for a given instruction ('pc').
|
|
** The array 'lineinfo' gives, for each instruction, the difference in
|
|
** lines from the previous instruction. When that difference does not
|
|
** fit into a byte, Lua saves the absolute line for that instruction.
|
|
** (Lua also saves the absolute line periodically, to speed up the
|
|
** computation of a line number: we can use binary search in the
|
|
** absolute-line array, but we must traverse the 'lineinfo' array
|
|
** linearly to compute a line.)
|
|
*/
|
|
typedef struct AbsLineInfo {
|
|
int pc;
|
|
int line;
|
|
} AbsLineInfo;
|
|
|
|
/*
|
|
** Function Prototypes
|
|
*/
|
|
typedef struct Proto {
|
|
CommonHeader;
|
|
lu_byte numparams; /* number of fixed (named) parameters */
|
|
lu_byte is_vararg;
|
|
lu_byte maxstacksize; /* number of registers needed by this function */
|
|
int sizeupvalues; /* size of 'upvalues' */
|
|
int sizek; /* size of 'k' */
|
|
int sizecode;
|
|
int sizelineinfo;
|
|
int sizep; /* size of 'p' */
|
|
int sizelocvars;
|
|
int sizeabslineinfo; /* size of 'abslineinfo' */
|
|
int linedefined; /* debug information */
|
|
int lastlinedefined; /* debug information */
|
|
TValue *k; /* constants used by the function */
|
|
Instruction *code; /* opcodes */
|
|
struct Proto **p; /* functions defined inside the function */
|
|
Upvaldesc *upvalues; /* upvalue information */
|
|
ls_byte *lineinfo; /* information about source lines (debug information) */
|
|
AbsLineInfo *abslineinfo; /* idem */
|
|
LocVar *locvars; /* information about local variables (debug information) */
|
|
TString *source; /* used for debug information */
|
|
GCObject *gclist;
|
|
} Proto;
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Closures
|
|
** ===================================================================
|
|
*/
|
|
|
|
/* Variant tags for functions */
|
|
#define LUA_TLCL (LUA_TFUNCTION | (1 << 4)) /* Lua closure */
|
|
#define LUA_TLCF (LUA_TFUNCTION | (2 << 4)) /* light C function */
|
|
#define LUA_TCCL (LUA_TFUNCTION | (3 << 4)) /* C closure */
|
|
|
|
#define ttisfunction(o) checktype(o, LUA_TFUNCTION)
|
|
#define ttisclosure(o) ((rawtt(o) & 0x1F) == LUA_TLCL)
|
|
#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL))
|
|
#define ttislcf(o) checktag((o), LUA_TLCF)
|
|
#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL))
|
|
|
|
#define isLfunction(o) ttisLclosure(o)
|
|
|
|
#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc))
|
|
#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
|
|
#define fvalue(o) check_exp(ttislcf(o), val_(o).f)
|
|
#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
|
|
|
|
#define fvalueraw(v) ((v).f)
|
|
|
|
#define setclLvalue(L,obj,x) \
|
|
{ TValue *io = (obj); LClosure *x_ = (x); \
|
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
|
|
checkliveness(L,io); }
|
|
|
|
#define setclLvalue2s(L,o,cl) setclLvalue(L,s2v(o),cl)
|
|
|
|
#define setfvalue(obj,x) \
|
|
{ TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); }
|
|
|
|
#define setclCvalue(L,obj,x) \
|
|
{ TValue *io = (obj); CClosure *x_ = (x); \
|
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
|
|
checkliveness(L,io); }
|
|
|
|
|
|
/*
|
|
** Upvalues for Lua closures
|
|
*/
|
|
typedef struct UpVal {
|
|
CommonHeader;
|
|
lu_byte tbc; /* true if it represents a to-be-closed variable */
|
|
TValue *v; /* points to stack or to its own value */
|
|
union {
|
|
struct { /* (when open) */
|
|
struct UpVal *next; /* linked list */
|
|
struct UpVal **previous;
|
|
} open;
|
|
TValue value; /* the value (when closed) */
|
|
} u;
|
|
} UpVal;
|
|
|
|
|
|
|
|
#define ClosureHeader \
|
|
CommonHeader; lu_byte nupvalues; GCObject *gclist
|
|
|
|
typedef struct CClosure {
|
|
ClosureHeader;
|
|
lua_CFunction f;
|
|
TValue upvalue[1]; /* list of upvalues */
|
|
} CClosure;
|
|
|
|
|
|
typedef struct LClosure {
|
|
ClosureHeader;
|
|
struct Proto *p;
|
|
UpVal *upvals[1]; /* list of upvalues */
|
|
} LClosure;
|
|
|
|
|
|
typedef union Closure {
|
|
CClosure c;
|
|
LClosure l;
|
|
} Closure;
|
|
|
|
|
|
#define getproto(o) (clLvalue(o)->p)
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
/*
|
|
** {==================================================================
|
|
** Tables
|
|
** ===================================================================
|
|
*/
|
|
|
|
#define ttistable(o) checktag((o), ctb(LUA_TTABLE))
|
|
|
|
#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
|
|
|
|
#define sethvalue(L,obj,x) \
|
|
{ TValue *io = (obj); Table *x_ = (x); \
|
|
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
|
|
checkliveness(L,io); }
|
|
|
|
#define sethvalue2s(L,o,h) sethvalue(L,s2v(o),h)
|
|
|
|
|
|
/*
|
|
** Nodes for Hash tables: A pack of two TValue's (key-value pairs)
|
|
** plus a 'next' field to link colliding entries. The distribution
|
|
** of the key's fields ('key_tt' and 'key_val') not forming a proper
|
|
** 'TValue' allows for a smaller size for 'Node' both in 4-byte
|
|
** and 8-byte alignments.
|
|
*/
|
|
typedef union Node {
|
|
struct NodeKey {
|
|
TValuefields; /* fields for value */
|
|
lu_byte key_tt; /* key type */
|
|
int next; /* for chaining */
|
|
Value key_val; /* key value */
|
|
} u;
|
|
TValue i_val; /* direct access to node's value as a proper 'TValue' */
|
|
} Node;
|
|
|
|
|
|
/* copy a value into a key */
|
|
#define setnodekey(L,node,obj) \
|
|
{ Node *n_=(node); const TValue *io_=(obj); \
|
|
n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \
|
|
checkliveness(L,io_); }
|
|
|
|
|
|
/* copy a value from a key */
|
|
#define getnodekey(L,obj,node) \
|
|
{ TValue *io_=(obj); const Node *n_=(node); \
|
|
io_->value_ = n_->u.key_val; io_->tt_ = n_->u.key_tt; \
|
|
checkliveness(L,io_); }
|
|
|
|
|
|
/*
|
|
** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the
|
|
** real size of 'array'. Otherwise, the real size of 'array' is the
|
|
** smallest power of two not smaller than 'alimit' (or zero iff 'alimit'
|
|
** is zero); 'alimit' is then used as a hint for #t.
|
|
*/
|
|
|
|
#define BITRAS (1 << 7)
|
|
#define isrealasize(t) (!((t)->marked & BITRAS))
|
|
#define setrealasize(t) ((t)->marked &= cast_byte(~BITRAS))
|
|
#define setnorealasize(t) ((t)->marked |= BITRAS)
|
|
|
|
|
|
typedef struct Table {
|
|
CommonHeader;
|
|
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
|
lu_byte lsizenode; /* log2 of size of 'node' array */
|
|
unsigned int alimit; /* "limit" of 'array' array */
|
|
TValue *array; /* array part */
|
|
Node *node;
|
|
Node *lastfree; /* any free position is before this position */
|
|
struct Table *metatable;
|
|
GCObject *gclist;
|
|
} Table;
|
|
|
|
|
|
/*
|
|
** Macros to manipulate keys inserted in nodes
|
|
*/
|
|
#define keytt(node) ((node)->u.key_tt)
|
|
#define keyval(node) ((node)->u.key_val)
|
|
|
|
#define keyisnil(node) (keytt(node) == LUA_TNIL)
|
|
#define keyisinteger(node) (keytt(node) == LUA_TNUMINT)
|
|
#define keyival(node) (keyval(node).i)
|
|
#define keyisshrstr(node) (keytt(node) == ctb(LUA_TSHRSTR))
|
|
#define keystrval(node) (gco2ts(keyval(node).gc))
|
|
|
|
#define setnilkey(node) (keytt(node) = LUA_TNIL)
|
|
|
|
#define keyiscollectable(n) (keytt(n) & BIT_ISCOLLECTABLE)
|
|
|
|
#define gckey(n) (keyval(n).gc)
|
|
#define gckeyN(n) (keyiscollectable(n) ? gckey(n) : NULL)
|
|
|
|
|
|
/*
|
|
** Use a "nil table" to mark dead keys in a table. Those keys serve
|
|
** to keep space for removed entries, which may still be part of
|
|
** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE
|
|
** set, so these values are considered not collectable and are different
|
|
** from any valid value.
|
|
*/
|
|
#define setdeadkey(n) (keytt(n) = LUA_TTABLE, gckey(n) = NULL)
|
|
|
|
/* }================================================================== */
|
|
|
|
|
|
|
|
/*
|
|
** 'module' operation for hashing (size is always a power of 2)
|
|
*/
|
|
#define lmod(s,size) \
|
|
(check_exp((size&(size-1))==0, (cast_int((s) & ((size)-1)))))
|
|
|
|
|
|
#define twoto(x) (1<<(x))
|
|
#define sizenode(t) (twoto((t)->lsizenode))
|
|
|
|
|
|
/* size of buffer for 'luaO_utf8esc' function */
|
|
#define UTF8BUFFSZ 8
|
|
|
|
LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
|
|
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
|
|
LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
|
|
const TValue *p2, TValue *res);
|
|
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
|
|
const TValue *p2, StkId res);
|
|
LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
|
|
LUAI_FUNC int luaO_hexavalue (int c);
|
|
LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj);
|
|
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
|
|
va_list argp);
|
|
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
|
|
LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
|
|
|
|
|
|
#endif
|
|
|