Hi Mike,
My further thought on C equivalents:
struct cell{
unsigned long _flag;
union {
struct {
char* _svalue;
long _keynum;
} _string;
struct {
union {
__int64 _ivalue;
double _rvalue;
} _value;
} _number;
struct {
struct cell* _car;
struct cell* _cdr;
} _cons;
} _object;
} cell;
typedef struct cell* pointer;
#define type(p) ((p)->_flag)
#define isfixnum(p) ((type(p) & T_FLONUM) == T_NUMBER)
#define isflonum(p) ((type(p) & T_FLONUM) == T_FLONUM)
#define ivalue(p) ((p)->_object._number._value._ivalue)
#define rvalue(p) ((p)->_object._number._value._rvalue)
#define num_ivalue(p) (isfixnum(p) ? ivalue(p) : (__int64)rvalue(p))
#define num_rvalue(p) (isflonum(p) ? rvalue(p) : (double)ivalue(p))
'CLARIFYING CELL STRUCTURE
==========================
type cell
sys flag
char* svalue
sys keynum
=
sys flag
quad ivalue
=
sys flag
double rvalue
=
sys flag
cell* car
cell* cdr
end type
'#recordof cell
typedef cell *pointer
enum types { T_NULL, T_NUMBER, T_FLONUM }
'print T_FLONUM
macro isfixnum(p) (p##.flag == T_NUMBER)
macro isflonum(p) (p##.flag == T_FLONUM)
macro ivalue(p) p##.ivalue
macro rvalue(p) p##.rvalue
'C STYLE FUNCTIONS
==================
quad num_ivalue(cell*p) {if isfixnum(p) {return p.ivalue} return p.rvalue }
double num_rvalue(cell*p) {if isfixnum(p) {return p.ivalue} return p.rvalue }
'OPTIMISED ASM FUNCTIONS: 32BIT MODE STDCALL
============================================
quad num_ivalue(cell*p) at num_ivalues_asm
double num_rvalue(cell*p) at num_rvalues_asm
'TEST
=====
double d
quad q
sys n=3
#show cell p at getmemory 100 * sizeof cell
#show q = num_ivalue p[n]
free memory @cell
'ASSEMBLY CODE
==============
jmp fwd over
.num_ivalues_asm
mov eax,[esp+4] 'first param
(
cmp [eax],T_NUMBER
jnz exit
fild qword [eax+8]
ret 4
)
fld qword [eax+8]
frndint 'ROUNDING
ret 4
.num_rvalues_asm
mov eax,[esp+4] 'first param
(
cmp [eax],T_NUMBER
jnz exit
fild qword [eax+8]
ret 4
)
fld qword [eax+8]
ret 4
.over
'USING THE IFF MACRO (DUAL 32/64)
=================================
deff iff
and al,1
(
jnz exit
fxch st1
)
fstp st0
end deff
macro num_ivalue(p) iff(isfixnum(p), p##.ivalue, p##.rvalue)
macro num_rvalue(p) iff(isfixnum(p), p##.ivalue, p##.rvalue)
'ROUNDING?
==========
'it may be desirable to truncate or round when returning num_ivalues
macro num_ivalue(p) iff(isfixnum(p), p##.ivalue, round(p##.rvalue) )
I think the optimised asm functions will give the shortest code stream and best performance:
quad num_ivalue(pointer p) at num_ivalues_asm
...
.num_ivalues_asm
mov eax,[esp+4] 'first param 'pointer'
(
cmp [eax],T_NUMBER
jnz exit
fild qword [eax+8]
ret 4
)
fld qword [eax+8]
frndint 'ROUNDING
ret 4