最近读了《lua设计与实现》,配合着看了lua的源代码,把学习的心得做一个笔记记录下来。看的源代码版本是最新的v5.4-beta。

value

每一门动态语言中都会用一个通用的结构来存储数据,这样才能实现给一个变量赋不同类型的值,lua中这个数据结构是 TValue

(lobject.h)

/*
** Union of all Lua values
*/
typedef union Value {
  struct GCObject *gc;    /* collectable objects */
  void *p;         /* light userdata */
  int b;           /* booleans */
  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;

(llimits.h)

typedef unsigned char lu_byte;

可以看到TValue分成两个部分:value_ 是一个union 用来存储不同数据,tt_ 是一个无符号字节类型用于存储类型信息。

tt_中最低的0-3四位用于存储数据类型,4-5两位用于存储variant子类型,第6位用于标记是否可回收。

(lobject.h)

/*
** tags for Tagged Values have the following use of bits:
** bits 0-3: actual tag (a LUA_T* value)
** bits 4-5: variant bits
** bit 6: whether value is collectable
*/

actual tag

lua中一共八种基本类型 nilbooleannumberstringtablefunctionthreaduserdata。 其中lightuserdatauserdata的一种内部实现。另外三种类型noneupvalprototype为解释器内部的类型,每个类型的标志位如下。

(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

(lobject.h)

/*
** Extra tags for 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)

is collactable

tt_中第6位为可回收标志位,如果为1,value_的值作为一个GCObject的指针指向下一个垃圾回收(GC)中的下一个对象。用这个指针来实现垃圾回收中的链表。

(lobject.h)

/*
** 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)

从这可以看出来lua类型的继承关系。

lua relation

nil

基本nil类型的value_字段并没有保存数据,所有数据都保存在tt_字段中。nil 有两种特殊的值,variant为1 用作table中的空槽和 2 用作table的key没找到的返回值。

(lobject.h)

/*
** 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))

boolean

boolean类型没有特殊的子类型,只是使用了value_字段当作int b保存值。

(lobject.h)

#define ttisboolean(o)		checktag((o), LUA_TBOOLEAN)

#define bvalue(o)	check_exp(ttisboolean(o), val_(o).b)

number

number 类型使用 variant来区分 floatinteger,把value_当作不同类型来存储数据。

(lobject.h)

/* Variant tags for numbers */
#define LUA_TNUMFLT	(LUA_TNUMBER | (1 << 4))  /* float numbers */
#define LUA_TNUMINT	(LUA_TNUMBER | (2 << 4))  /* integer numbers */

#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)

以上就是lua保存三种基本数据类型的结构,下期分析一下string类型的数据结构和相关操作。