lua.5.2.3源码阅读(03):TValue通用变量
lua的堆栈中存放的是通用变量,通用变量实际上就是一个union内存块,根据不同的类型,采用不同的组织方式,
看一下通用类型的相关定义,截取了lobject.h相关代码,从代码上看,不太清楚numfield为什么会有两个相关定义。
堆栈中可以根据情况分为一下几种类型:
1、双精度浮点数:double d__;
2、复合类型,通过tt__来表示类型;
3、复合类型中分为两种:可回收类型和不可回收类型;
4、可回收类型可以是:TString、Udata、Closure、Table、Proto、UpVal、lua_State
5、不可回收类型可以是:light userdata、booleans、light C functions
1 typedef TValue *StkId; /* 堆栈中的元素 */ 2 typedef struct lua_TValue TValue; 3 4 struct lua_TValue { 5 TValuefields; /* 堆栈中的元素 */ 6 }; 7 8 // 定义了双精度浮点或者通用类型定义 9 #define TValuefields \ 10 union { struct { Value v__; int tt__; } i; double d__; } u 11 12 #define LUA_NUMBER double 13 typedef LUA_NUMBER lua_Number; 14 #define numfield lua_Number n; /* 双精度浮点数 */ 15 #define numfield /* no such field; numbers are the entire struct(另外一种定义) */ 16 17 // Value包括可回收对象和不可回收对象两种类型 18 // 不可回收对象包括:bool、 19 union Value { 20 GCObject *gc; /* collectable objects */ 21 void *p; /* light userdata */ 22 int b; /* booleans */ 23 lua_CFunction f; /* light C functions */ 24 numfield /* 双精度浮点数,实际上可能为空 */ 25 }; 26 27 /* 28 ** Union of all collectable objects 29 */ 30 union GCObject { 31 GCheader gch; /* common header */ 32 union TString ts; /* 字符串 */ 33 union Udata u; /* 用户自定义数据 */ 34 union Closure cl; /* 函数闭包,其实似乎Proto的一个实例 */ 35 struct Table h; /* 表结构 */ 36 struct Proto p; /* 函数原型,被闭包共享同一个定义 */ 37 struct UpVal uv; /* 闭包所引用的变量 */ 38 struct lua_State th; /* thread */ 39 };
为了方便复合结构的类型判断增加了一些宏的定义,复合结构中的t__类型定义:
1、0~3未表示类型;
2、4~5用来 表示类型的变体,例如:字符串LUA_TSTRING有两种变体(短字符串:LUA_TSHRSTR和长字符串:LUA_TLNGSTR)
3、6未用来表示是否是垃圾回收类型,其中短字符串不是可回收(#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) ),
而长字符串为可回收类型(#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) )。
类型判断相关的宏如下:
1 /* raw type tag of a TValue */ 2 #define rttype(o) ((o)->tt_) 3 4 /* tag with no variants (bits 0-3) */ 5 #define novariant(x) ((x) & 0x0F) 6 7 /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ 8 #define ttype(o) (rttype(o) & 0x3F) 9 10 /* type tag of a TValue with no variants (bits 0-3) */ 11 #define ttypenv(o) (novariant(rttype(o))) 12 13 /* mark a tag as collectable */ 14 #define ctb(t) ((t) | BIT_ISCOLLECTABLE) 15 16 /* Macros to test type */ 17 #define checktag(o,t) (rttype(o) == (t)) 18 #define checktype(o,t) (ttypenv(o) == (t)) 19 #define ttisnumber(o) checktag((o), LUA_TNUMBER) 20 #define ttisnil(o) checktag((o), LUA_TNIL) 21 #define ttisboolean(o) checktag((o), LUA_TBOOLEAN) 22 #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) 23 #define ttisstring(o) checktype((o), LUA_TSTRING) 24 #define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) 25 #define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) 26 #define ttistable(o) checktag((o), ctb(LUA_TTABLE)) 27 #define ttisfunction(o) checktype(o, LUA_TFUNCTION) 28 #define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) 29 #define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) 30 #define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) 31 #define ttislcf(o) checktag((o), LUA_TLCF) 32 #define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) 33 #define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) 34 #define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) 35 36 #define ttisequal(o1,o2) (rttype(o1) == rttype(o2))
复合类型的值获取相关宏定义:
1 /* Macros to access values */ 2 #define val_(o) ((o)->value_) 3 #define num_(o) (val_(o).n) 4 5 /* internal assertions for in-house debugging */ 6 #if defined(lua_assert) 7 #define check_exp(c,e) (lua_assert(c), (e)) 8 /* to avoid problems with conditions too long */ 9 #define lua_longassert(c) { if (!(c)) lua_assert(0); } 10 #else 11 #define lua_assert(c) ((void)0) 12 #define check_exp(c,e) (e) 13 #define lua_longassert(c) ((void)0) 14 #endif 15 16 #define nvalue(o) check_exp(ttisnumber(o), num_(o)) 17 #define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) 18 #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) 19 #define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) 20 #define tsvalue(o) (&rawtsvalue(o)->tsv) 21 #define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) 22 #define uvalue(o) (&rawuvalue(o)->uv) 23 #define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) 24 #define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) 25 #define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) 26 #define fvalue(o) check_exp(ttislcf(o), val_(o).f) 27 #define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) 28 #define bvalue(o) check_exp(ttisboolean(o), val_(o).b) 29 #define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th)
复合类型值设置相关宏定义:
1 /* Macros to set values */ 2 #define settt_(o,t) ((o)->tt_=(t)) 3 #define val_(o) ((o)->value_) 4 #define num_(o) (val_(o).n) 5 6 #define setnvalue(obj,x) \ 7 { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } 8 9 #define setnilvalue(obj) settt_(obj, LUA_TNIL) 10 11 #define setfvalue(obj,x) \ 12 { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } 13 14 #define setpvalue(obj,x) \ 15 { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } 16 17 #define setbvalue(obj,x) \ 18 { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } 19 20 #define setgcovalue(L,obj,x) \ 21 { TValue *io=(obj); GCObject *i_g=(x); \ 22 val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); } 23 24 #define setsvalue(L,obj,x) \ 25 { TValue *io=(obj); \ 26 TString *x_ = (x); \ 27 val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \ 28 checkliveness(G(L),io); } 29 30 #define setuvalue(L,obj,x) \ 31 { TValue *io=(obj); \ 32 val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \ 33 checkliveness(G(L),io); } 34 35 #define setthvalue(L,obj,x) \ 36 { TValue *io=(obj); \ 37 val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \ 38 checkliveness(G(L),io); } 39 40 #define setclLvalue(L,obj,x) \ 41 { TValue *io=(obj); \ 42 val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \ 43 checkliveness(G(L),io); } 44 45 #define setclCvalue(L,obj,x) \ 46 { TValue *io=(obj); \ 47 val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \ 48 checkliveness(G(L),io); } 49 50 #define sethvalue(L,obj,x) \ 51 { TValue *io=(obj); \ 52 val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ 53 checkliveness(G(L),io); }