/src/moddable/xs/sources/xsSymbol.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2016-2017 Moddable Tech, Inc. |
3 | | * |
4 | | * This file is part of the Moddable SDK Runtime. |
5 | | * |
6 | | * The Moddable SDK Runtime is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * The Moddable SDK Runtime 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 Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with the Moddable SDK Runtime. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * This file incorporates work covered by the following copyright and |
20 | | * permission notice: |
21 | | * |
22 | | * Copyright (C) 2010-2016 Marvell International Ltd. |
23 | | * Copyright (C) 2002-2010 Kinoma, Inc. |
24 | | * |
25 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
26 | | * you may not use this file except in compliance with the License. |
27 | | * You may obtain a copy of the License at |
28 | | * |
29 | | * http://www.apache.org/licenses/LICENSE-2.0 |
30 | | * |
31 | | * Unless required by applicable law or agreed to in writing, software |
32 | | * distributed under the License is distributed on an "AS IS" BASIS, |
33 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
34 | | * See the License for the specific language governing permissions and |
35 | | * limitations under the License. |
36 | | */ |
37 | | |
38 | | #include "xsAll.h" |
39 | | |
40 | | static txSlot* fxCheckSymbol(txMachine* the, txSlot* it); |
41 | | |
42 | | void fxBuildSymbol(txMachine* the) |
43 | 33.4k | { |
44 | 33.4k | txSlot* slot; |
45 | 33.4k | mxPush(mxObjectPrototype); |
46 | 33.4k | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
47 | 33.4k | slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Symbol_prototype_get_description), C_NULL, mxID(_description), XS_DONT_ENUM_FLAG); |
48 | 33.4k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_prototype_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG); |
49 | 33.4k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_prototype_valueOf), 0, mxID(_valueOf), XS_DONT_ENUM_FLAG); |
50 | 33.4k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_prototype_toPrimitive), 1, mxID(_Symbol_toPrimitive), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
51 | 33.4k | slot = fxNextStringXProperty(the, slot, "Symbol", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
52 | 33.4k | mxSymbolPrototype = *the->stack; |
53 | 33.4k | slot = fxBuildHostConstructor(the, mxCallback(fx_Symbol), 0, mxID(_Symbol)); |
54 | 33.4k | mxSymbolConstructor = *the->stack; |
55 | 33.4k | slot = fxLastProperty(the, slot); |
56 | 33.4k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_for), 1, mxID(_for), XS_DONT_ENUM_FLAG); |
57 | 33.4k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_keyFor), 1, mxID(_keyFor), XS_DONT_ENUM_FLAG); |
58 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_asyncIterator), mxID(_asyncIterator), XS_GET_ONLY); |
59 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_hasInstance), mxID(_hasInstance), XS_GET_ONLY); |
60 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_isConcatSpreadable), mxID(_isConcatSpreadable), XS_GET_ONLY); |
61 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_iterator), mxID(_iterator), XS_GET_ONLY); |
62 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_match), mxID(_match), XS_GET_ONLY); |
63 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_matchAll), mxID(_matchAll), XS_GET_ONLY); |
64 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_replace), mxID(_replace), XS_GET_ONLY); |
65 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_search), mxID(_search), XS_GET_ONLY); |
66 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_species), mxID(_species), XS_GET_ONLY); |
67 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_split), mxID(_split), XS_GET_ONLY); |
68 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_toPrimitive), mxID(_toPrimitive), XS_GET_ONLY); |
69 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_toStringTag), mxID(_toStringTag), XS_GET_ONLY); |
70 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_unscopables), mxID(_unscopables), XS_GET_ONLY); |
71 | 33.4k | #if mxExplicitResourceManagement |
72 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_asyncDispose), mxID(_asyncDispose), XS_GET_ONLY); |
73 | 33.4k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_dispose), mxID(_dispose), XS_GET_ONLY); |
74 | 33.4k | #endif |
75 | 33.4k | mxPop(); |
76 | 33.4k | } |
77 | | |
78 | | txSlot* fxNewSymbolInstance(txMachine* the) |
79 | 276k | { |
80 | 276k | txSlot* instance; |
81 | 276k | instance = fxNewObjectInstance(the); |
82 | 276k | fxNextSymbolProperty(the, instance, XS_NO_ID, XS_NO_ID, XS_INTERNAL_FLAG); |
83 | 276k | return instance; |
84 | 276k | } |
85 | | |
86 | | void fx_Symbol(txMachine* the) |
87 | 1.59M | { |
88 | 1.59M | txSlot* instance; |
89 | 1.59M | txSlot* slot; |
90 | 1.59M | txSlot* property; |
91 | 1.59M | if (mxTarget->kind != XS_UNDEFINED_KIND) |
92 | 3 | mxTypeError("new: Symbol"); |
93 | 1.59M | instance = fxNewInstance(the); |
94 | 1.59M | property = fxNextUndefinedProperty(the, instance, XS_NO_ID, XS_INTERNAL_FLAG); |
95 | 1.59M | if ((mxArgc > 0) && (mxArgv(0)->kind != XS_UNDEFINED_KIND)) { |
96 | 1.34M | fxToString(the, mxArgv(0)); |
97 | 1.34M | fxNextSlotProperty(the, property, mxArgv(0), XS_NO_ID, XS_INTERNAL_FLAG); |
98 | 1.34M | } |
99 | 253k | else |
100 | 253k | fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG); |
101 | 1.59M | slot = fxFindKey(the); |
102 | 1.59M | slot->flag = XS_INTERNAL_FLAG; |
103 | 1.59M | slot->kind = XS_REFERENCE_KIND; |
104 | 1.59M | slot->value.reference = instance; |
105 | 1.59M | property->kind = XS_SYMBOL_KIND; |
106 | 1.59M | property->value.symbol = slot->ID; |
107 | 1.59M | mxPop(); |
108 | 1.59M | mxResult->kind = XS_SYMBOL_KIND; |
109 | 1.59M | mxResult->value.symbol = slot->ID; |
110 | 1.59M | } |
111 | | |
112 | | void fx_Symbol_for(txMachine* the) |
113 | 571 | { |
114 | 571 | txString string; |
115 | 571 | txU1* p; |
116 | 571 | txU4 sum; |
117 | 571 | txU4 modulo; |
118 | 571 | txSlot* result; |
119 | 571 | if (mxArgc < 1) |
120 | 0 | mxSyntaxError("no key"); |
121 | 571 | string = fxToString(the, mxArgv(0)); |
122 | 571 | p = (txU1*)string; |
123 | 571 | sum = 0; |
124 | 112k | while(*p != 0) { |
125 | 111k | sum = (sum << 1) + *p++; |
126 | 111k | } |
127 | 571 | sum &= 0x7FFFFFFF; |
128 | 571 | modulo = sum % the->symbolModulo; |
129 | 571 | result = the->symbolTable[modulo]; |
130 | 1.25k | while (result != C_NULL) { |
131 | 851 | if (result->value.key.sum == sum) |
132 | 822 | if (c_strcmp(result->value.key.string, string) == 0) |
133 | 167 | break; |
134 | 684 | result = result->next; |
135 | 684 | } |
136 | 571 | if (result == C_NULL) { |
137 | 404 | result = fxFindKey(the); |
138 | 404 | result->next = the->symbolTable[modulo]; |
139 | 404 | result->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG; |
140 | 404 | result->kind = (mxArgv(0)->kind == XS_STRING_X_KIND) ? XS_KEY_X_KIND : XS_KEY_KIND; |
141 | 404 | result->value.key.string = mxArgv(0)->value.string; |
142 | 404 | result->value.key.sum = sum; |
143 | 404 | the->symbolTable[modulo] = result; |
144 | 404 | } |
145 | 571 | mxResult->kind = XS_SYMBOL_KIND; |
146 | 571 | mxResult->value.symbol = result->ID; |
147 | 571 | } |
148 | | |
149 | | void fx_Symbol_keyFor(txMachine* the) |
150 | 25 | { |
151 | 25 | txSlot* key; |
152 | 25 | if ((mxArgc == 0) || (mxArgv(0)->kind != XS_SYMBOL_KIND)) |
153 | 21 | mxTypeError("sym: not a symbol"); |
154 | 4 | key = fxGetKey(the, mxArgv(0)->value.symbol); |
155 | 4 | if (((key->kind == XS_KEY_KIND) || (key->kind == XS_KEY_X_KIND)) && ((key->flag & XS_DONT_ENUM_FLAG) == 0)) { |
156 | 1 | mxResult->kind = (key->kind == XS_KEY_KIND) ? XS_STRING_KIND : XS_STRING_X_KIND; |
157 | 1 | mxResult->value.string = key->value.key.string; |
158 | 1 | } |
159 | 4 | } |
160 | | |
161 | | void fx_Symbol_prototype_get_description(txMachine* the) |
162 | 62 | { |
163 | 62 | txSlot* slot = fxCheckSymbol(the, mxThis); |
164 | 62 | if (!slot) mxTypeError("this: not a symbol"); |
165 | 31 | slot = fxGetKey(the, slot->value.symbol); |
166 | 31 | if ((slot->kind == XS_KEY_KIND) || (slot->kind == XS_KEY_X_KIND)) { |
167 | 3 | mxResult->kind = (slot->kind == XS_KEY_KIND) ? XS_STRING_KIND : XS_STRING_X_KIND; |
168 | 3 | mxResult->value.string = slot->value.key.string; |
169 | 3 | } |
170 | 28 | else if (slot->kind == XS_REFERENCE_KIND) { |
171 | 28 | slot = slot->value.reference->next->next; |
172 | 28 | mxResult->kind = slot->kind; |
173 | 28 | mxResult->value = slot->value; |
174 | 28 | } |
175 | 31 | } |
176 | | |
177 | | void fx_Symbol_prototype_toPrimitive(txMachine* the) |
178 | 4.98k | { |
179 | 4.98k | txSlot* slot = fxCheckSymbol(the, mxThis); |
180 | 4.98k | if (!slot) mxTypeError("this: not a symbol"); |
181 | 1.58k | mxResult->kind = slot->kind; |
182 | 1.58k | mxResult->value = slot->value; |
183 | 1.58k | } |
184 | | |
185 | | void fx_Symbol_prototype_toString(txMachine* the) |
186 | 9.41k | { |
187 | 9.41k | txSlot* slot = fxCheckSymbol(the, mxThis); |
188 | 9.41k | if (!slot) mxTypeError("this: not a symbol"); |
189 | 9.41k | mxResult->kind = slot->kind; |
190 | 9.41k | mxResult->value = slot->value; |
191 | 9.41k | fxSymbolToString(the, mxResult); |
192 | 9.41k | } |
193 | | |
194 | | void fx_Symbol_prototype_valueOf(txMachine* the) |
195 | 29.1k | { |
196 | 29.1k | txSlot* slot = fxCheckSymbol(the, mxThis); |
197 | 29.1k | if (!slot) mxTypeError("this: not a symbol"); |
198 | 29.0k | mxResult->kind = slot->kind; |
199 | 29.0k | mxResult->value = slot->value; |
200 | 29.0k | } |
201 | | |
202 | | txSlot* fxCheckSymbol(txMachine* the, txSlot* it) |
203 | 43.5k | { |
204 | 43.5k | txSlot* result = C_NULL; |
205 | 43.5k | if (it->kind == XS_SYMBOL_KIND) |
206 | 38.4k | result = it; |
207 | 5.07k | else if (it->kind == XS_REFERENCE_KIND) { |
208 | 5.03k | txSlot* instance = it->value.reference; |
209 | 5.03k | it = instance->next; |
210 | 5.03k | if ((it) && (it->flag & XS_INTERNAL_FLAG) && (it->kind == XS_SYMBOL_KIND)) |
211 | 1.62k | result = it; |
212 | 5.03k | } |
213 | 43.5k | return result; |
214 | 43.5k | } |
215 | | |
216 | | void fxSymbolToString(txMachine* the, txSlot* slot) |
217 | 9.44k | { |
218 | 9.44k | txSlot* key = fxGetKey(the, slot->value.symbol); |
219 | 9.44k | fxStringX(the, slot, "Symbol("); |
220 | 9.44k | if ((key->kind == XS_KEY_KIND) || (key->kind == XS_KEY_X_KIND)) |
221 | 4 | fxConcatString(the, slot, key); |
222 | 9.44k | else if (key->kind == XS_REFERENCE_KIND) { |
223 | 9.44k | key = key->value.reference->next->next; |
224 | 9.44k | if (key->kind != XS_UNDEFINED_KIND) |
225 | 9.40k | fxConcatString(the, slot, key); |
226 | 9.44k | } |
227 | 9.44k | fxConcatStringC(the, slot, ")"); |
228 | 9.44k | } |
229 | | |
230 | | txSlot* fxGetKey(txMachine* the, txID theID) |
231 | 40.4M | { |
232 | 40.4M | txSlot* key; |
233 | 40.4M | mxCheck(the, 0 < theID); |
234 | 40.4M | mxCheck(the, theID < the->keyIndex); |
235 | 40.4M | if (theID < the->keyOffset) |
236 | 0 | key = the->keyArrayHost[theID]; |
237 | 40.4M | else |
238 | 40.4M | key = the->keyArray[theID - the->keyOffset]; |
239 | 40.4M | mxCheck(the, key->kind != XS_UNDEFINED_KIND); |
240 | 40.4M | return key; |
241 | 40.4M | } |
242 | | |
243 | | char* fxGetKeyName(txMachine* the, txID theID) |
244 | 3.64M | { |
245 | 3.64M | txSlot* key = fxGetKey(the, theID); |
246 | 3.64M | if (key->flag & XS_DONT_ENUM_FLAG) |
247 | 3.64M | return key->value.string; |
248 | 0 | return C_NULL; |
249 | 3.64M | } |
250 | | |
251 | | char* fxGetKeyString(txMachine* the, txID theID, txBoolean* adorn) |
252 | 3.05M | { |
253 | 3.05M | txString result = mxEmptyString.value.string; |
254 | 3.05M | txSlot* key = fxGetKey(the, theID); |
255 | 3.05M | txKind kind = key->kind; |
256 | 3.05M | if ((kind == XS_KEY_KIND) || (kind == XS_KEY_X_KIND)) |
257 | 3.04M | result = key->value.key.string; |
258 | 3.57k | else if (key->kind == XS_REFERENCE_KIND) { |
259 | 3.57k | key = key->value.reference->next->next; |
260 | 3.57k | if (key->kind != XS_UNDEFINED_KIND) |
261 | 3.57k | result = key->value.string; |
262 | 3.57k | } |
263 | 3.05M | if (adorn) |
264 | 3.05M | *adorn = (key->flag & XS_DONT_ENUM_FLAG) ? 0 : 1; |
265 | 3.05M | return result; |
266 | 3.05M | } |
267 | | |
268 | | void fxPushKeyString(txMachine* the, txID theID, txBoolean* adorn) |
269 | 21.4M | { |
270 | 21.4M | txSlot* key = fxGetKey(the, theID); |
271 | 21.4M | txKind kind = key->kind; |
272 | 21.4M | if (adorn) |
273 | 21.0M | *adorn = (key->flag & XS_DONT_ENUM_FLAG) ? 0 : 1; |
274 | 21.4M | if (kind == XS_KEY_KIND) |
275 | 20.6M | mxPushString(key->value.key.string); |
276 | 859k | else if (kind == XS_KEY_X_KIND) |
277 | 0 | mxPushStringX(key->value.key.string); |
278 | 859k | else { |
279 | 859k | mxCheck(the, key->kind == XS_REFERENCE_KIND); |
280 | 859k | key = key->value.reference->next->next; |
281 | 859k | if (key->kind == XS_UNDEFINED_KIND) { |
282 | 5 | *adorn = 0; |
283 | 5 | mxPush(mxEmptyString); |
284 | 5 | } |
285 | 859k | else |
286 | 859k | mxPushSlot(key); |
287 | 859k | } |
288 | 21.4M | } |
289 | | |
290 | | txID fxFindName(txMachine* the, txString theString) |
291 | 3.40k | { |
292 | 3.40k | txU1* aString; |
293 | 3.40k | txU4 aSum; |
294 | 3.40k | txU4 aModulo; |
295 | 3.40k | txSlot* result; |
296 | | |
297 | 3.40k | aString = (txU1*)theString; |
298 | 3.40k | aSum = 0; |
299 | 50.8k | while (*aString != 0) { |
300 | 47.4k | aSum = (aSum << 1) + *aString++; |
301 | 47.4k | } |
302 | 3.40k | aSum &= 0x7FFFFFFF; |
303 | 3.40k | aModulo = aSum % the->nameModulo; |
304 | 3.40k | result = the->nameTable[aModulo]; |
305 | 4.15k | while (result != C_NULL) { |
306 | 2.60k | if (result->value.key.sum == aSum) |
307 | 2.14k | if (c_strcmp(result->value.key.string, theString) == 0) |
308 | 1.85k | return mxGetKeySlotID(result); |
309 | 753 | result = result->next; |
310 | 753 | } |
311 | 1.55k | return 0; |
312 | 3.40k | } |
313 | | |
314 | | txBoolean fxIsKeyName(txMachine* the, txID theID) |
315 | 10.9M | { |
316 | 10.9M | txSlot* key = fxGetKey(the, theID); |
317 | 10.9M | return (key->flag & XS_DONT_ENUM_FLAG) ? 1 : 0; |
318 | 10.9M | } |
319 | | |
320 | | txBoolean fxIsKeySymbol(txMachine* the, txID theID) |
321 | 247k | { |
322 | 247k | txSlot* key = fxGetKey(the, theID); |
323 | 247k | return (key->flag & XS_DONT_ENUM_FLAG) ? 0 : 1; |
324 | 247k | } |
325 | | |
326 | | txID fxNewName(txMachine* the, txSlot* theSlot) |
327 | 5.82M | { |
328 | 5.82M | txU1* string; |
329 | 5.82M | txU4 sum; |
330 | 5.82M | txU4 modulo; |
331 | 5.82M | txSlot* result; |
332 | | |
333 | 5.82M | string = (txU1*)theSlot->value.string; |
334 | 5.82M | sum = 0; |
335 | 106M | while(*string != 0) { |
336 | 100M | sum = (sum << 1) + *string++; |
337 | 100M | } |
338 | 5.82M | sum &= 0x7FFFFFFF; |
339 | 5.82M | modulo = sum % the->nameModulo; |
340 | 5.82M | result = the->nameTable[modulo]; |
341 | 24.0M | while (result != C_NULL) { |
342 | 22.3M | if (result->value.key.sum == sum) { |
343 | 21.4M | if (c_strcmp(result->value.key.string, theSlot->value.string) == 0) |
344 | 4.15M | return mxGetKeySlotID(result); |
345 | 21.4M | } |
346 | 18.2M | result = result->next; |
347 | 18.2M | } |
348 | 1.66M | result = fxFindKey(the); |
349 | 1.66M | result->next = the->nameTable[modulo]; |
350 | 1.66M | result->flag = XS_INTERNAL_FLAG | XS_DONT_ENUM_FLAG; |
351 | 1.66M | result->kind = XS_KEY_KIND; |
352 | 1.66M | result->value.key.string = theSlot->value.string; |
353 | 1.66M | result->value.key.sum = sum; |
354 | 1.66M | the->nameTable[modulo] = result; |
355 | 1.66M | return result->ID; |
356 | 5.82M | } |
357 | | |
358 | | txID fxNewNameC(txMachine* the, txString theString) |
359 | 19.9M | { |
360 | 19.9M | txU1* string; |
361 | 19.9M | txU4 sum; |
362 | 19.9M | txU4 modulo; |
363 | 19.9M | txSlot* result; |
364 | | |
365 | 19.9M | string = (txU1*)theString; |
366 | 19.9M | sum = 0; |
367 | 180M | while(c_read8(string) != 0) { |
368 | 160M | sum = (sum << 1) + c_read8(string++); |
369 | 160M | } |
370 | 19.9M | sum &= 0x7FFFFFFF; |
371 | 19.9M | modulo = sum % the->nameModulo; |
372 | 19.9M | result = the->nameTable[modulo]; |
373 | 47.2M | while (result != C_NULL) { |
374 | 28.8M | if (result->value.key.sum == sum) { |
375 | 24.2M | if (c_strcmp(result->value.key.string, theString) == 0) { |
376 | 1.52M | txID id = mxGetKeySlotID(result); |
377 | 1.52M | if (id >= the->keyOffset) |
378 | 1.52M | result->flag |= XS_DONT_DELETE_FLAG; |
379 | 1.52M | return id; |
380 | 1.52M | } |
381 | 24.2M | } |
382 | 27.3M | result = result->next; |
383 | 27.3M | } |
384 | 18.3M | result = fxFindKey(the); |
385 | 18.3M | result->next = the->nameTable[modulo]; |
386 | 18.3M | result->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG; |
387 | 18.3M | result->kind = XS_KEY_KIND; |
388 | 18.3M | result->value.key.string = C_NULL; |
389 | 18.3M | result->value.key.sum = sum; |
390 | 18.3M | the->nameTable[modulo] = result; |
391 | 18.3M | result->value.key.string = (txString)fxNewChunk(the, mxStringLength(theString) + 1); |
392 | 18.3M | c_strcpy(result->value.key.string, theString); |
393 | 18.3M | return result->ID; |
394 | 19.9M | } |
395 | | |
396 | | txID fxNewNameX(txMachine* the, txString theString) |
397 | 0 | { |
398 | 0 | txU1* string; |
399 | 0 | txU4 sum; |
400 | 0 | txU4 modulo; |
401 | 0 | txSlot* result; |
402 | | |
403 | 0 | string = (txU1*)theString; |
404 | 0 | sum = 0; |
405 | 0 | while (c_read8(string) != 0) { |
406 | 0 | sum = (sum << 1) + c_read8(string++); |
407 | 0 | } |
408 | 0 | sum &= 0x7FFFFFFF; |
409 | 0 | modulo = sum % the->nameModulo; |
410 | 0 | result = the->nameTable[modulo]; |
411 | 0 | while (result != C_NULL) { |
412 | 0 | if (result->value.key.sum == sum) { |
413 | 0 | if (c_strcmp(result->value.key.string, theString) == 0) { |
414 | 0 | txID id = mxGetKeySlotID(result); |
415 | 0 | if (id >= the->keyOffset) |
416 | 0 | result->flag |= XS_DONT_DELETE_FLAG; |
417 | 0 | return id; |
418 | 0 | } |
419 | 0 | } |
420 | 0 | result = result->next; |
421 | 0 | } |
422 | 0 | result = fxFindKey(the); |
423 | 0 | result->next = the->nameTable[modulo]; |
424 | 0 | result->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG; |
425 | 0 | result->kind = XS_KEY_X_KIND; |
426 | 0 | result->value.key.string = theString; |
427 | 0 | result->value.key.sum = sum; |
428 | 0 | the->nameTable[modulo] = result; |
429 | 0 | return result->ID; |
430 | 0 | } |
431 | | |
432 | | txSlot* fxAt(txMachine* the, txSlot* slot) |
433 | 31.3M | { |
434 | 31.3M | txIndex index; |
435 | 31.3M | txString string; |
436 | 31.3M | again: |
437 | 31.3M | if ((slot->kind == XS_INTEGER_KIND) && fxIntegerToIndex(the, slot->value.integer, &index)) { |
438 | 6.22M | slot->value.at.id = XS_NO_ID; |
439 | 6.22M | slot->value.at.index = index; |
440 | 6.22M | } |
441 | 25.1M | else if ((slot->kind == XS_NUMBER_KIND) && fxNumberToIndex(the, slot->value.number, &index)) { |
442 | 23.6M | slot->value.at.id = XS_NO_ID; |
443 | 23.6M | slot->value.at.index = index; |
444 | 23.6M | } |
445 | 1.49M | else if (slot->kind == XS_SYMBOL_KIND) { |
446 | 159k | slot->value.at.id = slot->value.symbol; |
447 | 159k | slot->value.at.index = 0; |
448 | 159k | } |
449 | 1.33M | else { |
450 | 1.33M | if (slot->kind == XS_REFERENCE_KIND) { |
451 | 13.1k | fxToPrimitive(the, slot, XS_STRING_HINT); |
452 | 13.1k | goto again; |
453 | 13.1k | } |
454 | 1.32M | string = fxToString(the, slot); |
455 | 1.32M | if (fxStringToIndex(the, string, &index)) { |
456 | 122k | slot->value.at.id = XS_NO_ID; |
457 | 122k | slot->value.at.index = index; |
458 | 122k | } |
459 | 1.20M | else { |
460 | 1.20M | txID id; |
461 | 1.20M | if (slot->kind == XS_STRING_X_KIND) |
462 | 0 | id = fxNewNameX(the, string); |
463 | 1.20M | else |
464 | 1.20M | id = fxNewName(the, slot); |
465 | 1.20M | slot->value.at.id = id; |
466 | 1.20M | slot->value.at.index = 0; |
467 | 1.20M | } |
468 | 1.32M | } |
469 | 31.3M | slot->kind = XS_AT_KIND; |
470 | 31.3M | return slot; |
471 | 31.3M | } |
472 | | |
473 | | void fxKeyAt(txMachine* the, txID id, txIndex index, txSlot* slot) |
474 | 10.6M | { |
475 | 10.6M | if (id) { |
476 | 772k | txSlot* key = fxGetKey(the, id); |
477 | 772k | if (key->flag & XS_DONT_ENUM_FLAG) { |
478 | 615k | if (key->kind == XS_KEY_KIND) { |
479 | 615k | slot->kind = XS_STRING_KIND; |
480 | 615k | slot->value.string = key->value.key.string; |
481 | 615k | } |
482 | 0 | else{ |
483 | 0 | slot->kind = XS_STRING_X_KIND; |
484 | 0 | slot->value.string = key->value.key.string; |
485 | 0 | } |
486 | 615k | } |
487 | 156k | else { |
488 | 156k | slot->kind = XS_SYMBOL_KIND; |
489 | 156k | slot->value.symbol = id; |
490 | 156k | } |
491 | 772k | } |
492 | 9.89M | else { |
493 | 9.89M | char buffer[16]; |
494 | 9.89M | fxCopyStringC(the, slot, fxNumberToString(the, index, buffer, sizeof(buffer), 0, 0)); |
495 | 9.89M | } |
496 | 10.6M | } |
497 | | |
498 | | void fxIDToString(txMachine* the, txID id, txString theBuffer, txSize theSize) |
499 | 1.03M | { |
500 | 1.03M | if (id != XS_NO_ID) { |
501 | 1.03M | txBoolean adorn; |
502 | 1.03M | txString string = fxGetKeyString(the, id, &adorn); |
503 | 1.03M | if (adorn) |
504 | 1 | c_snprintf(theBuffer, theSize, "[%s]", string); |
505 | 1.03M | else |
506 | 1.03M | c_snprintf(theBuffer, theSize, "%s", string); |
507 | 1.03M | } |
508 | 16 | else { |
509 | 16 | theBuffer[0] = '?'; |
510 | 16 | theBuffer[1] = 0; |
511 | 16 | } |
512 | 1.03M | } |