Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / include / lang / PyrSlot32.h
blobb51aa9f6f9931e808f7931f5b08e7379949a63be
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 PyrSlot is a value holder for SC variables.
23 A PyrSlot is an 8-byte value which is either a double precision float or a
24 32-bit tag plus a 32-bit value.
28 #ifndef _PYRSLOT32_H_
29 #define _PYRSLOT32_H_
31 #include "SC_Endian.h"
32 #include "SC_Types.h"
33 #include "PyrErrors.h"
35 #include <cassert>
36 #include <cstddef>
38 struct PyrSymbol;
41 Pyrite slots are the size of an 8 byte double. If the upper bits
42 indicate that the double is a 'Not-A-Number' then the upper 32
43 bits are used as a tag to indicate one of a number of other types
44 whose data is in the lower 32 bits.
47 /* some DSPs like the TIC32 do not support 8 byte doubles */
48 /* on such CPUs, set DOUBLESLOTS to zero */
50 #define DOUBLESLOTS 1
52 /* use the high order bits of an IEEE double NaN as a tag */
53 enum {
54 tagObj = 0x7FF90001,
55 tagInt = 0x7FF90002,
56 tagSym = 0x7FF90003,
57 tagChar = 0x7FF90004,
58 tagNil = 0x7FF90005, // nil, false, and true are indicated by the tag alone.
59 tagFalse = 0x7FF90006, // the lower 32 bits are zero.
60 tagTrue = 0x7FF90007,
61 tagPtr = 0x7FF90008,
62 /* anything else is a double */
63 tagUnused = 0x7FF9000D
66 #if !DOUBLESLOTS
67 ,tagFloat = 0x7FF9000F /* used only to initialized 4 byte float tags, never compared with */
68 #endif
71 typedef union pyrslot {
72 double f;
73 struct {
74 #if BYTE_ORDER == BIG_ENDIAN
75 int tag;
76 #endif // BIG_ENDIAN
77 union {
78 int c; /* char */
79 int i;
80 float f;
81 void *ptr;
82 struct PyrObject *o;
83 PyrSymbol *s;
84 struct PyrMethod *om;
85 struct PyrBlock *oblk;
86 struct PyrClass *oc;
87 struct PyrFrame *of;
88 struct PyrList *ol;
89 struct PyrString *os;
90 struct PyrInt8Array *ob;
91 struct PyrDoubleArray *od;
92 struct PyrSymbolArray *osym;
93 struct PyrProcess *op;
94 struct PyrThread *ot;
95 struct PyrInterpreter *oi;
96 } u;
97 #if BYTE_ORDER == LITTLE_ENDIAN
98 // need to swap on intel <sk>
99 int tag;
100 #endif // LITTLE_ENDIAN
101 } s;
102 } PyrSlot;
105 these are some defines to make accessing the structure less verbose.
106 obviously it polutes the namespace of identifiers beginning with 'u'.
108 #define utag s.tag
109 //int
110 #define ui s.u.i
111 //PyrObject
112 #define uo s.u.o
113 //PyrSymbol
114 #define us s.u.s
115 #define uc s.u.c
116 #define uoc s.u.oc
117 #define uof s.u.of
118 #define uol s.u.ol
119 #define uod s.u.od
120 #define uob s.u.ob
121 #define uop s.u.op
122 #define uoi s.u.oi
123 #define uod s.u.od
124 //string
125 #define uos s.u.os
126 #define uot s.u.ot
127 //method
128 #define uom s.u.om
129 //symbol array
130 #define uosym s.u.osym
131 #define uoblk s.u.oblk
132 #define uptr s.u.ptr
134 #if DOUBLESLOTS
135 #define uf f
136 #else
137 #define uf s.u.f
138 #endif
141 Note that on the PowerPC, the fastest way to copy a slot is to
142 copy the double field, not the struct.
145 inline int GetTag(const PyrSlot* slot) { return slot->utag; }
147 /* some macros for setting values of slots */
148 inline void SetInt(PyrSlot* slot, int val) { (slot)->utag = tagInt; (slot)->ui = (val); }
149 inline void SetObject(PyrSlot* slot, struct PyrObjectHdr* val) { (slot)->utag = tagObj; (slot)->uo = (PyrObject*)(val); }
150 inline void SetSymbol(PyrSlot* slot, PyrSymbol *val) { (slot)->utag = tagSym; (slot)->us = (val); }
151 inline void SetChar(PyrSlot* slot, char val) { (slot)->utag = tagChar; (slot)->uc = (val); }
152 inline void SetPtr(PyrSlot* slot, void* val) { (slot)->utag = tagPtr; (slot)->uptr = (void*)(val); }
153 inline void SetObjectOrNil(PyrSlot* slot, PyrObject* val)
155 if (val) {
156 (slot)->utag = tagObj;
157 (slot)->uo = (val);
158 } else {
159 (slot)->utag = tagNil;
160 (slot)->ui = 0;
164 inline void SetTrue(PyrSlot* slot) { (slot)->utag = tagTrue; (slot)->ui = 0; }
165 inline void SetFalse(PyrSlot* slot) { (slot)->utag = tagFalse; (slot)->ui = 0; }
166 inline void SetBool(PyrSlot* slot, bool test) { (slot)->utag = ((test) ? tagTrue : tagFalse); (slot)->ui = 0; }
167 inline void SetNil(PyrSlot* slot) { (slot)->utag = tagNil; (slot)->ui = 0; }
169 #if DOUBLESLOTS
170 inline void SetFloat(PyrSlot* slot, double val) { (slot)->uf = (val); }
171 #else
172 inline void SetFloat(PyrSlot* slot, double val) { (slot)->utag = s_float; (slot)->uf = (val); }
173 #endif
176 inline bool IsObj(const PyrSlot* slot) { return ((slot)->utag == tagObj); }
177 inline bool NotObj(const PyrSlot* slot) { return ((slot)->utag != tagObj); }
179 inline bool IsNil(const PyrSlot* slot) { return ((slot)->utag == tagNil); }
180 inline bool NotNil(const PyrSlot* slot) { return ((slot)->utag != tagNil); }
182 inline bool IsFalse(const PyrSlot* slot) { return ((slot)->utag == tagFalse); }
183 inline bool IsTrue(const PyrSlot* slot) { return ((slot)->utag == tagTrue); }
185 inline bool SlotEq(PyrSlot* a, PyrSlot* b) { return ((a)->ui == (b)->ui && (a)->utag == (b)->utag); }
187 inline bool IsSym(const PyrSlot* slot) { return ((slot)->utag == tagSym); }
188 inline bool NotSym(const PyrSlot* slot) { return ((slot)->utag != tagSym); }
190 inline bool IsChar(const PyrSlot* slot) { return ((slot)->utag == tagChar); }
191 inline bool NotChar(const PyrSlot* slot) { return ((slot)->utag != tagChar); }
193 inline bool IsInt(const PyrSlot* slot) { return ((slot)->utag == tagInt); }
194 inline bool NotInt(const PyrSlot* slot) { return ((slot)->utag != tagInt); }
196 inline bool IsFloatTag(int tag) { return ((tag & 0xFFFFFFF0) != 0x7FF90000); }
197 inline bool IsFloat(const PyrSlot* slot) { return (((slot)->utag & 0xFFFFFFF0) != 0x7FF90000); }
198 inline bool NotFloat(const PyrSlot* slot) { return (((slot)->utag & 0xFFFFFFF0) == 0x7FF90000); }
200 inline bool IsPtr(const PyrSlot* slot) { return ((slot)->utag == tagPtr); }
201 inline bool NotPtr(const PyrSlot* slot) { return ((slot)->utag != tagPtr); }
203 inline void SetRawChar(PyrSlot* slot, int val) { assert(IsChar(slot)); slot->uc = val; }
204 inline void SetRaw(PyrSlot* slot, int val) { assert(IsInt(slot)); slot->ui = val; }
205 inline void SetRaw(PyrSlot* slot, long val) { assert(IsInt(slot)); slot->ui = val; }
206 inline void SetRaw(PyrSlot* slot, PyrObject * val) { assert(IsObj(slot)); slot->uo = val; }
207 inline void SetRaw(PyrSlot* slot, PyrSymbol * val) { assert(IsSym(slot)); slot->us = val; }
208 inline void SetRaw(PyrSlot* slot, void * val) { assert(IsPtr(slot)); slot->uptr = val; }
209 inline void SetRaw(PyrSlot* slot, double val) { assert(IsFloat(slot)); SetFloat(slot, val); }
211 inline void SetTagRaw(PyrSlot* slot, int tag) { slot->utag = tag; }
213 template <typename numeric_type>
214 inline int slotVal(PyrSlot * slot, numeric_type *value)
216 if (IsFloat(slot)) {
217 *value = static_cast<numeric_type>(slot->uf);
218 return errNone;
219 } else if (IsInt(slot)) {
220 *value = static_cast<numeric_type>(slot->ui);
221 return errNone;
223 return errWrongType;
227 inline int slotFloatVal(PyrSlot *slot, float *value)
229 return slotVal<float>(slot, value);
232 inline int slotIntVal(PyrSlot *slot, int *value)
234 return slotVal<int>(slot, value);
237 inline int slotDoubleVal(PyrSlot *slot, double *value)
239 return slotVal<double>(slot, value);
242 inline int slotSymbolVal(PyrSlot *slot, PyrSymbol **symbol)
244 if (!IsSym(slot)) return errWrongType;
245 *symbol = slot->us;
246 return errNone;
249 inline void* slotRawPtr(PyrSlot *slot)
251 assert(IsPtr(slot) || (slot->s.u.ptr == NULL && IsNil(slot)));
252 return slot->s.u.ptr;
255 inline PyrBlock* slotRawBlock(PyrSlot *slot)
257 return slot->s.u.oblk;
260 inline PyrSymbolArray* slotRawSymbolArray(PyrSlot *slot)
262 return slot->s.u.osym;
265 inline PyrDoubleArray* slotRawDoubleArray(PyrSlot *slot)
267 return slot->s.u.od;
270 inline PyrInt8Array* slotRawInt8Array(PyrSlot *slot)
272 return slot->s.u.ob;
275 inline PyrMethod* slotRawMethod(PyrSlot *slot)
277 return slot->s.u.om;
280 inline PyrThread* slotRawThread(PyrSlot *slot)
282 return slot->s.u.ot;
285 inline PyrString* slotRawString(PyrSlot *slot)
287 return slot->s.u.os;
290 inline PyrList* slotRawList(PyrSlot *slot)
292 return slot->s.u.ol;
295 inline PyrFrame* slotRawFrame(PyrSlot *slot)
297 return slot->s.u.of;
300 inline PyrClass* slotRawClass(PyrSlot *slot)
302 return slot->s.u.oc;
305 inline PyrInterpreter* slotRawInterpreter(PyrSlot *slot)
307 return slot->s.u.oi;
310 inline PyrSymbol* slotRawSymbol(PyrSlot *slot)
312 assert(IsSym(slot));
313 return slot->s.u.s;
316 inline int slotRawChar(const PyrSlot *slot)
318 assert(IsChar(slot));
319 return slot->s.u.c;
322 inline int slotRawInt(const PyrSlot *slot)
324 assert(IsInt(slot));
325 return slot->s.u.i;
328 inline double slotRawFloat(const PyrSlot *slot)
330 assert(IsFloat(slot));
331 return slot->uf;
334 inline PyrObject* slotRawObject(PyrSlot *slot)
336 assert(IsObj(slot));
337 return slot->s.u.o;
340 inline void slotCopy(PyrSlot *dst, const PyrSlot *src)
342 double *dstp = (double*)dst;
343 double *srcp = (double*)src;
344 *dstp = *srcp;
347 inline void slotCopy(PyrSlot *dst, const PyrSlot *src, int num)
349 double *dstp = (double*)dst - 1;
350 double *srcp = (double*)src - 1;
351 for (int i=0;i<num;++i) { *++dstp = *++srcp; }
354 #undef uptr
355 #undef uoblk
356 #undef uosym
357 #undef uom
358 #undef uot
359 #undef uos
360 #undef uod
361 #undef uob
362 #undef uol
363 #undef uof
364 #undef uoc
365 #undef utag
366 #undef us
367 #undef uc
368 #undef uo
369 #undef uoi
370 #undef ui
371 #undef uf
373 #undef uop
375 #endif