Gauche-0.9 のタグに関するメモ

重箱のスミをツツく。

intptr_t

gauche.h 見てていきなり以下の定義で躓く。

/*
 * A word large enough to hold a pointer
 */
typedef intptr_t ScmWord;

intptr_t って何だ。無論 M-t では出てこない。grep で探してみる。

$ find /usr/include gauche |xargs grep intptr_t|grep typedef
/usr/include/SDL/SDL_thread.h:typedef uintptr_t (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
/usr/include/unistd.h:typedef __intptr_t intptr_t;
/usr/include/stdint.h:typedef long int          intptr_t;
/usr/include/stdint.h:typedef unsigned long int uintptr_t;
/usr/include/stdint.h:typedef int                       intptr_t;
/usr/include/stdint.h:typedef unsigned int              uintptr_t;
/usr/include/cucul_types.h:typedef long int _cucul_intptr_t;
/usr/include/cucul_types.h:typedef unsigned long int _cucul_uintptr_t;
gauche/hash.h:typedef u_long ScmHashProc(const ScmHashCore *hc, intptr_t key);
gauche/hash.h:typedef int    ScmHashCompareProc(const ScmHashCore *hc, intptr_t key,
gauche/treemap.h:typedef int ScmTreeCoreCompareProc(ScmTreeCore*, intptr_t, intptr_t);
$

どうやら stdint.h らしい。これを include してるのは gauche/int64.h なのを grep で探して、その int64.h は gauche.h で include されてるのを確認。
int64.h での定義が以下。

/* Types for `void *' pointers.  */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int                intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned long int       uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int                     intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned int            uintptr_t;
#endif

BASIC TYPES

順に

/*
 * A word large enough to hold a pointer
 */
typedef intptr_t ScmWord;

ポインタをナニするのに十分でかい word

/*
 * A byte
 */
typedef unsigned char ScmByte;

/*
 * A character.
 */
typedef long ScmChar;

byte とか character とか。以下は一番てっぺんの抽象オブジェクト

/*
 * An opaque pointer.  All Scheme objects are represented by
 * this type.
 */
typedef struct ScmHeaderRec *ScmObj;

ScmHeaderRec 構造体の定義は同じ gauche.h にて以下。

/* A common header for heap-allocated objects */
typedef struct ScmHeaderRec {
    ScmByte *tag;                /* private.  should be accessed
                                    only via SCM_CLASS_OF and SCM_SET_CLASS
                                    macros. */
} ScmHeader;

#define SCM_HEADER       ScmHeader hdr /* for declaration */

heap-allocated なオブジェクトの共通なナニ。アクセサは以下との事。

/* Extract the class pointer from the tag.
   You can use these only if SCM_HOBJP(obj) != FALSE */
# define SCM_CLASS_OF(obj)      SCM_CLASS((SCM_OBJ(obj)->tag - 7))
# define SCM_SET_CLASS(obj, k)  (SCM_OBJ(obj)->tag = (ScmByte*)(k) + 7)

これって、reading Gauche で_クラスタグ_と呼んでるナニですな。0.8 系は以下な記述でした (0.8.7)

/* Extract the class pointer from the tag.
   You can use these only if SCM_HOBJP(obj) != FALSE */
#define SCM_CLASS_OF(obj)      SCM_CLASS((SCM_OBJ(obj)->tag - 3))
#define SCM_SET_CLASS(obj, k)  (SCM_OBJ(obj)->tag = (ScmByte*)(k) + 3)

2-bit から 3-bit になってるのが分かります。がしかし、ここはとりあえずこのあたりでスルー。

Gauche-0.9 でのタグなソレ

gauche.h での定義が以下。

/*
 * PRIMARY TAG IDENTIFICATION
 */

#define SCM_TAG1(obj)    (SCM_WORD(obj) & 0x01)
#define SCM_TAG2(obj)    (SCM_WORD(obj) & 0x03)
#define SCM_TAG3(obj)    (SCM_WORD(obj) & 0x07)
#define SCM_TAG8(obj)    (SCM_WORD(obj) & 0xff)

1, 2, 3, 8 bit なマスクの定義。気になったのはコメントでは 0x01 なマスクに関する記述が無かった事だったりして。とは言え以下ですぐ出てきます。てかここでしか出てこないみたい。

/* Check if the ScmObj is a 'pointer'---either to a pair,
   a heap object, or a ScmFlonum. */
#define SCM_PTRP(obj)    (SCM_TAG1(obj) == 0)

SCM_TAG1 マクロが出てくるのはここだけな模様。なんでケツ 0 が_pointer_なのか、なソレはコメント参照。

/* Check if the ScmObj is a pointer to either a pair or a heap
   (That is, we can safely take SCM_OBJ(obj)->tag) */
#define SCM_HPTRP(obj)   (SCM_TAG2(obj) == 0)

ケツ 00 は heap な ptr との事。

/* This macro further takes the lower three bits of the word pointed
   by OBJ, to distinguish whether it's a pair or a heap object. */
#define SCM_HTAG(obj)    (SCM_WORD(SCM_OBJ(obj)->tag)&7)

で、ここはちょっと保留。tag 属性を取り出して 7 と & とってるのは何故なのか、というあたりが微妙。