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 #include "PyrSymbolTable.h"
26 #include "InitAlloc.h"
27 #include "VMGlobals.h"
30 SC_DLLEXPORT_C PyrSymbol
* getsym(const char *name
)
32 PyrSymbol
* symbol
= gMainVMGlobals
->symbolTable
->Make(name
);
34 fprintf(stderr
, "getsym failed '%s'\n", name
);
40 SC_DLLEXPORT_C PyrSymbol
* getmetasym(const char *name
)
48 SC_DLLEXPORT_C PyrSymbol
* findsym(const char *name
)
50 PyrSymbol
* symbol
= gMainVMGlobals
->symbolTable
->Find(name
);
54 SymbolSpace::SymbolSpace(AllocPool
*inPool
)
57 mStringPool
.Init(inPool
, STRINGCHUNK
, STRINGCHUNK
, STRINGCHUNK
/5);
58 mSymbolPool
.Init(inPool
, SYMBOLCHUNK
, SYMBOLCHUNK
, SYMBOLCHUNK
/5);
62 PyrSymbol
* SymbolSpace::NewSymbol(const char *inName
, int inHash
, int inLength
)
65 sym
= (PyrSymbol
*)mSymbolPool
.Alloc(sizeof(PyrSymbol
));
67 sym
->name
= (char*)mStringPool
.Alloc(inLength
+1);
69 strcpy(sym
->name
, inName
);
71 sym
->length
= inLength
;
72 sym
->specialIndex
= -1;
74 if (inName
[0] >= 'A' && inName
[0] <= 'Z') sym
->flags
|= sym_Class
;
75 if (inLength
> 1 && inName
[0] == '_') sym
->flags
|= sym_Primitive
;
76 if (inLength
> 1 && inName
[inLength
-1] == '_') sym
->flags
|= sym_Setter
;
83 SymbolTable::SymbolTable(AllocPool
*inPool
, int inSize
)
84 : mPool(inPool
), mSpace(inPool
), mMaxItems(inSize
)
86 assert(ISPOWEROFTWO(inSize
));
92 void SymbolTable::CopyFrom(SymbolTable
& inTable
)
95 Rehash(inTable
.mTable
, inTable
.mMaxItems
);
98 int SymbolTable::StrHash(const char *inName
, int *outLength
)
100 return Hash(inName
, outLength
);
103 PyrSymbol
* SymbolTable::Find(const char *inName
)
106 int hash
= StrHash(inName
, &length
);
107 return Find(inName
, hash
);
110 PyrSymbol
* SymbolTable::Find(const char *inName
, int inHash
)
112 int index
= inHash
& mMask
;
113 PyrSymbol
* sym
= mTable
[index
];
114 while (sym
&& (sym
->hash
!= inHash
|| strcmp(inName
, sym
->name
)!=0)) {
115 index
= (index
+1) & mMask
;
121 void SymbolTable::Add(PyrSymbol
* inSymbol
)
123 if (mNumItems
+ 1 > (mMaxItems
>>1)) Grow();
125 int index
= inSymbol
->hash
& mMask
;
126 PyrSymbol
*testSymbol
= mTable
[index
];
127 while (testSymbol
&& testSymbol
!= inSymbol
) {
128 index
= (index
+ 1) & mMask
;
129 testSymbol
= mTable
[index
];
131 if (!testSymbol
) { // if it is not already in the table.
132 mTable
[index
] = inSymbol
;
137 PyrSymbol
* SymbolTable::MakeNew(const char *inName
, int inHash
, int inLength
)
139 PyrSymbol
* symbol
= mSpace
.NewSymbol(inName
, inHash
, inLength
);
145 PyrSymbol
* SymbolTable::Make(const char *inName
)
148 int hash
= StrHash(inName
, &length
);
149 PyrSymbol
* symbol
= Find(inName
, hash
);
150 if (!symbol
) symbol
= MakeNew(inName
, hash
, length
);
154 void SymbolTable::MakeEmpty()
156 int size
= mMaxItems
* sizeof(PyrSymbol
*);
157 memset(mTable
, 0, size
);
161 void SymbolTable::AllocTable()
163 int size
= mMaxItems
* sizeof(PyrSymbol
*);
164 mTable
= (PyrSymbol
**)mPool
->Alloc(size
);
168 mMask
= mMaxItems
- 1;
171 void SymbolTable::Rehash(PyrSymbol
** inTable
, int inSize
)
173 // rehash all entries from inTable into the new table
174 for (int i
=0; i
<inSize
; ++i
) {
175 if (inTable
[i
]) Add(inTable
[i
]);
179 void SymbolTable::Grow()
181 PyrSymbol
**oldtable
= mTable
;
182 int oldsize
= mMaxItems
;
185 mMaxItems
+= mMaxItems
;
188 Rehash(oldtable
, oldsize
);
190 mPool
->Free(oldtable
);
193 void SymbolTable::CheckSymbols()
195 for (int i
=0; i
<TableSize(); ++i
) {
196 PyrSymbol
*symbol
= Get(i
);
197 if (symbol
&& symbol
->u
.index
== 0) {
201 post("WARNING: Primitive '%s' used but not bound\n", symbol
->name
);
202 } else if (c
>= 'A' && c
<= 'Z') {
203 post("WARNING: Symbol '%s' used but not defined as a Class\n", symbol
->name
);
204 } else if ((symbol
->flags
& sym_Called
) && !(symbol
->flags
& sym_Selector
)) {
205 post("WARNING: Method '%s' called but not defined\n", symbol
->name
);