1. 程式人生 > >lua設計與實現(二)資料型別

lua設計與實現(二)資料型別

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的通用資料結構的組織圖 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; }