lua設計與實現(二)資料型別
阿新 • • 發佈:2018-12-18
lua中的資料型別
//lua.h
/*
** basic types
*/
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
#define LUA_NUMTAGS 9
巨集 | 型別 | 對應資料結構 |
---|---|---|
LUA_TNONE | 無型別 | 無 |
LUA_TNIL | 空型別 | 無 |
LUA_TBOOLEAN | 布林型別 | 無 |
LUA_TLIGHTUSERDATA | 指標 | void* |
LUA_TNUMBER | 資料 | lua_Number |
LUA_TSTRING | 字串 | TString |
LUA_TTABLE | 表 | table |
LUA_TFUNCTION | 函式 | CClosure,LClosure |
LUA_TUSERDATA | 指標 | void* |
LUA_TTHREAD | lua虛擬機器,協程 | lua_State |
LUA_NUMTAGS 表示多少種資料型別,這裡是9。 Lua內部用一個巨集來表示那些資料需要進行GC(Garbage Collection,垃圾回收)操作:
//lobject.h 189
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
可以看到,LUA TSTRING (包括LUA TSTRING )之後的資料型別都需要進行GC操作。這些需要進行GC操作的資料型別都會有一個CommonHeader巨集定義的成員,並且這個成員在結構體定義的最開始部分。
//lobject.h
/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
- next:下一個GC連結串列成員
- tt:表示資料型別
- marked:GC相關的標記位
於是lua中就是用GCObject聯合體將所有需要進行垃圾回收 的資料型別囊括了進來:
//lobject.h
/*
** Union of all collectable objects
*/
union GCObject {
GCheader gch;
union TString ts;
union Udata u;
union Closure cl;
struct Table h;
struct Proto p;
struct UpVal uv;
struct lua_State th; /* thread */
};
結構體GCheader 成員只有CommonHeader。
//lobject.h
/*
** Common header in struct form
*/
typedef struct GCheader {
CommonHeader;
} GCheader;
Lua將GCObject和其他不需要垃圾回收的資料型別一起放在聯合體Value中:
//lobject.h
/*
** Union of all Lua values
*/
typedef union {
GCObject *gc;
void *p;
lua_Number n;
int b;
} Value;
這樣就可以表示所有的資料型別了。 為了表示資料是什麼型別,Lua中又有了TValuefields,它用於將Value和型別結合在一起。
/*
** Tagged Values
*/
#define TValuefields Value value; int tt
最後形成了TValue結構體,Lua中任何資料都可以通過該結構體表示:
//lobject.h
typedef struct lua_TValue {
TValuefields;
} TValue;
Lua的通用資料結構的組織圖 在具體的程式碼中TValue用於統一的表示資料,而一旦知道了具體的型別,就需要使用具體的型別了,因此程式碼中不少涉及TValue與具體型別之間的轉換的程式碼,其主要邏輯都是將Tvalue中的tt,value與具體型別的資料進行轉換。比如將lua_Number轉換為TValue的巨集定義為:
#define setnvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }