supernova: fix for small audio vector sizes
[supercollider.git] / lang / LangSource / PyrSymbolTable.cpp
blobb12f2b970a8d96ebce22d3dac70e1a87cf99c1f1
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
21 #include "SCBase.h"
22 #include "PyrSymbolTable.h"
23 #include "clz.h"
24 #include <stdlib.h>
25 #include <string.h>
26 #include "InitAlloc.h"
27 #include "VMGlobals.h"
28 #include "Hash.h"
30 SC_DLLEXPORT_C PyrSymbol* getsym(const char *name)
32 PyrSymbol* symbol = gMainVMGlobals->symbolTable->Make(name);
33 if (!symbol) {
34 fprintf(stderr, "getsym failed '%s'\n", name);
35 exit(-1);
37 return symbol;
40 SC_DLLEXPORT_C PyrSymbol* getmetasym(const char *name)
42 char str[256];
43 strcpy(str, "Meta_");
44 strcat(str, name);
45 return getsym(str);
48 SC_DLLEXPORT_C PyrSymbol* findsym(const char *name)
50 PyrSymbol* symbol = gMainVMGlobals->symbolTable->Find(name);
51 return symbol;
54 SymbolSpace::SymbolSpace(AllocPool *inPool)
56 mPool = 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)
64 PyrSymbol *sym;
65 sym = (PyrSymbol*)mSymbolPool.Alloc(sizeof(PyrSymbol));
66 MEMFAIL(sym);
67 sym->name = (char*)mStringPool.Alloc(inLength+1);
68 MEMFAIL(sym->name);
69 strcpy(sym->name, inName);
70 sym->hash = inHash;
71 sym->length = inLength;
72 sym->specialIndex = -1;
73 sym->flags = 0;
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;
77 sym->u.index = 0;
78 sym->classdep = NULL;
79 return sym;
83 SymbolTable::SymbolTable(AllocPool *inPool, int inSize)
84 : mPool(inPool), mSpace(inPool), mMaxItems(inSize)
86 assert(ISPOWEROFTWO(inSize));
88 AllocTable();
92 void SymbolTable::CopyFrom(SymbolTable& inTable)
94 MakeEmpty();
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)
105 int length;
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;
116 sym = mTable[index];
118 return sym;
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;
133 mNumItems ++ ;
137 PyrSymbol* SymbolTable::MakeNew(const char *inName, int inHash, int inLength)
139 PyrSymbol* symbol = mSpace.NewSymbol(inName, inHash, inLength);
140 Add(symbol);
142 return symbol;
145 PyrSymbol* SymbolTable::Make(const char *inName)
147 int length;
148 int hash = StrHash(inName, &length);
149 PyrSymbol* symbol = Find(inName, hash);
150 if (!symbol) symbol = MakeNew(inName, hash, length);
151 return symbol;
154 void SymbolTable::MakeEmpty()
156 int size = mMaxItems * sizeof(PyrSymbol*);
157 memset(mTable, 0, size);
158 mNumItems = 0 ;
161 void SymbolTable::AllocTable()
163 int size = mMaxItems * sizeof(PyrSymbol*);
164 mTable = (PyrSymbol**)mPool->Alloc(size);
165 MEMFAIL(mTable);
167 MakeEmpty();
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;
184 // create new table
185 mMaxItems += mMaxItems;
186 AllocTable();
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) {
198 int c;
199 c = symbol->name[0];
200 if (c == '_') {
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);