/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 | 31.5k | { |
44 | 31.5k | txSlot* slot; |
45 | 31.5k | mxPush(mxObjectPrototype); |
46 | 31.5k | slot = fxLastProperty(the, fxNewObjectInstance(the)); |
47 | 31.5k | slot = fxNextHostAccessorProperty(the, slot, mxCallback(fx_Symbol_prototype_get_description), C_NULL, mxID(_description), XS_DONT_ENUM_FLAG); |
48 | 31.5k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_prototype_toString), 0, mxID(_toString), XS_DONT_ENUM_FLAG); |
49 | 31.5k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_prototype_valueOf), 0, mxID(_valueOf), XS_DONT_ENUM_FLAG); |
50 | 31.5k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_prototype_toPrimitive), 1, mxID(_Symbol_toPrimitive), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
51 | 31.5k | slot = fxNextStringXProperty(the, slot, "Symbol", mxID(_Symbol_toStringTag), XS_DONT_ENUM_FLAG | XS_DONT_SET_FLAG); |
52 | 31.5k | mxSymbolPrototype = *the->stack; |
53 | 31.5k | slot = fxBuildHostConstructor(the, mxCallback(fx_Symbol), 0, mxID(_Symbol)); |
54 | 31.5k | mxSymbolConstructor = *the->stack; |
55 | 31.5k | slot = fxLastProperty(the, slot); |
56 | 31.5k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_for), 1, mxID(_for), XS_DONT_ENUM_FLAG); |
57 | 31.5k | slot = fxNextHostFunctionProperty(the, slot, mxCallback(fx_Symbol_keyFor), 1, mxID(_keyFor), XS_DONT_ENUM_FLAG); |
58 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_asyncIterator), mxID(_asyncIterator), XS_GET_ONLY); |
59 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_hasInstance), mxID(_hasInstance), XS_GET_ONLY); |
60 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_isConcatSpreadable), mxID(_isConcatSpreadable), XS_GET_ONLY); |
61 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_iterator), mxID(_iterator), XS_GET_ONLY); |
62 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_match), mxID(_match), XS_GET_ONLY); |
63 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_matchAll), mxID(_matchAll), XS_GET_ONLY); |
64 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_replace), mxID(_replace), XS_GET_ONLY); |
65 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_search), mxID(_search), XS_GET_ONLY); |
66 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_species), mxID(_species), XS_GET_ONLY); |
67 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_split), mxID(_split), XS_GET_ONLY); |
68 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_toPrimitive), mxID(_toPrimitive), XS_GET_ONLY); |
69 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_toStringTag), mxID(_toStringTag), XS_GET_ONLY); |
70 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_unscopables), mxID(_unscopables), XS_GET_ONLY); |
71 | 31.5k | #if mxExplicitResourceManagement |
72 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_asyncDispose), mxID(_asyncDispose), XS_GET_ONLY); |
73 | 31.5k | slot = fxNextSymbolProperty(the, slot, mxID(_Symbol_dispose), mxID(_dispose), XS_GET_ONLY); |
74 | 31.5k | #endif |
75 | 31.5k | mxPop(); |
76 | 31.5k | } |
77 | | |
78 | | txSlot* fxNewSymbolInstance(txMachine* the) |
79 | 509k | { |
80 | 509k | txSlot* instance; |
81 | 509k | instance = fxNewObjectInstance(the); |
82 | 509k | fxNextSymbolProperty(the, instance, XS_NO_ID, XS_NO_ID, XS_INTERNAL_FLAG); |
83 | 509k | return instance; |
84 | 509k | } |
85 | | |
86 | | void fx_Symbol(txMachine* the) |
87 | 1.21M | { |
88 | 1.21M | txSlot* instance; |
89 | 1.21M | txSlot* slot; |
90 | 1.21M | txSlot* property; |
91 | 1.21M | if (mxHasTarget) |
92 | 3 | mxTypeError("new: Symbol"); |
93 | 1.21M | instance = fxNewInstance(the); |
94 | 1.21M | property = fxNextUndefinedProperty(the, instance, XS_NO_ID, XS_INTERNAL_FLAG); |
95 | 1.21M | if ((mxArgc > 0) && (mxArgv(0)->kind != XS_UNDEFINED_KIND)) { |
96 | 1.08M | fxToString(the, mxArgv(0)); |
97 | 1.08M | fxNextSlotProperty(the, property, mxArgv(0), XS_NO_ID, XS_INTERNAL_FLAG); |
98 | 1.08M | } |
99 | 130k | else |
100 | 130k | fxNextUndefinedProperty(the, property, XS_NO_ID, XS_INTERNAL_FLAG); |
101 | 1.21M | slot = fxFindKey(the); |
102 | 1.21M | slot->flag = XS_INTERNAL_FLAG; |
103 | 1.21M | slot->kind = XS_REFERENCE_KIND; |
104 | 1.21M | slot->value.reference = instance; |
105 | 1.21M | property->kind = XS_SYMBOL_KIND; |
106 | 1.21M | property->value.symbol = slot->ID; |
107 | 1.21M | mxPop(); |
108 | 1.21M | mxResult->kind = XS_SYMBOL_KIND; |
109 | 1.21M | mxResult->value.symbol = slot->ID; |
110 | 1.21M | } |
111 | | |
112 | | void fx_Symbol_for(txMachine* the) |
113 | 1.20k | { |
114 | 1.20k | txSlot* arg; |
115 | 1.20k | txString string; |
116 | 1.20k | txU1* p; |
117 | 1.20k | txU4 sum; |
118 | 1.20k | txU4 modulo; |
119 | 1.20k | txSlot* result; |
120 | 1.20k | if (mxArgc < 1) |
121 | 1 | arg = &mxUndefinedString; |
122 | 1.20k | else |
123 | 1.20k | arg = mxArgv(0); |
124 | 1.20k | string = fxToString(the, arg); |
125 | 1.20k | p = (txU1*)string; |
126 | 1.20k | sum = 0; |
127 | 255k | while(*p != 0) { |
128 | 254k | sum = (sum << 1) + *p++; |
129 | 254k | } |
130 | 1.20k | sum &= 0x7FFFFFFF; |
131 | 1.20k | modulo = sum % the->symbolModulo; |
132 | 1.20k | result = the->symbolTable[modulo]; |
133 | 2.86k | while (result != C_NULL) { |
134 | 2.16k | if (result->value.key.sum == sum) |
135 | 1.87k | if (c_strcmp(result->value.key.string, string) == 0) |
136 | 499 | break; |
137 | 1.66k | result = result->next; |
138 | 1.66k | } |
139 | 1.20k | if (result == C_NULL) { |
140 | 703 | result = fxFindKey(the); |
141 | 703 | result->next = the->symbolTable[modulo]; |
142 | 703 | result->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG; |
143 | 703 | result->kind = (arg->kind == XS_STRING_X_KIND) ? XS_KEY_X_KIND : XS_KEY_KIND; |
144 | 703 | result->value.key.string = arg->value.string; |
145 | 703 | result->value.key.sum = sum; |
146 | 703 | the->symbolTable[modulo] = result; |
147 | 703 | } |
148 | 1.20k | mxResult->kind = XS_SYMBOL_KIND; |
149 | 1.20k | mxResult->value.symbol = result->ID; |
150 | 1.20k | } |
151 | | |
152 | | void fx_Symbol_keyFor(txMachine* the) |
153 | 23 | { |
154 | 23 | txSlot* key; |
155 | 23 | if ((mxArgc == 0) || (mxArgv(0)->kind != XS_SYMBOL_KIND)) |
156 | 19 | mxTypeError("sym: not a symbol"); |
157 | 4 | key = fxGetKey(the, mxArgv(0)->value.symbol); |
158 | 4 | if (((key->kind == XS_KEY_KIND) || (key->kind == XS_KEY_X_KIND)) && ((key->flag & XS_DONT_ENUM_FLAG) == 0)) { |
159 | 1 | mxResult->kind = (key->kind == XS_KEY_KIND) ? XS_STRING_KIND : XS_STRING_X_KIND; |
160 | 1 | mxResult->value.string = key->value.key.string; |
161 | 1 | } |
162 | 4 | } |
163 | | |
164 | | void fx_Symbol_prototype_get_description(txMachine* the) |
165 | 58 | { |
166 | 58 | txSlot* slot = fxCheckSymbol(the, mxThis); |
167 | 58 | if (!slot) mxTypeError("this: not a symbol"); |
168 | 35 | slot = fxGetKey(the, slot->value.symbol); |
169 | 35 | if ((slot->kind == XS_KEY_KIND) || (slot->kind == XS_KEY_X_KIND)) { |
170 | 2 | mxResult->kind = (slot->kind == XS_KEY_KIND) ? XS_STRING_KIND : XS_STRING_X_KIND; |
171 | 2 | mxResult->value.string = slot->value.key.string; |
172 | 2 | } |
173 | 33 | else if (slot->kind == XS_REFERENCE_KIND) { |
174 | 33 | slot = slot->value.reference->next->next; |
175 | 33 | mxResult->kind = slot->kind; |
176 | 33 | mxResult->value = slot->value; |
177 | 33 | } |
178 | 35 | } |
179 | | |
180 | | void fx_Symbol_prototype_toPrimitive(txMachine* the) |
181 | 483 | { |
182 | 483 | txSlot* slot = fxCheckSymbol(the, mxThis); |
183 | 483 | if (!slot) mxTypeError("this: not a symbol"); |
184 | 469 | mxResult->kind = slot->kind; |
185 | 469 | mxResult->value = slot->value; |
186 | 469 | } |
187 | | |
188 | | void fx_Symbol_prototype_toString(txMachine* the) |
189 | 25 | { |
190 | 25 | txSlot* slot = fxCheckSymbol(the, mxThis); |
191 | 25 | if (!slot) mxTypeError("this: not a symbol"); |
192 | 23 | mxResult->kind = slot->kind; |
193 | 23 | mxResult->value = slot->value; |
194 | 23 | fxSymbolToString(the, mxResult); |
195 | 23 | } |
196 | | |
197 | | void fx_Symbol_prototype_valueOf(txMachine* the) |
198 | 72 | { |
199 | 72 | txSlot* slot = fxCheckSymbol(the, mxThis); |
200 | 72 | if (!slot) mxTypeError("this: not a symbol"); |
201 | 58 | mxResult->kind = slot->kind; |
202 | 58 | mxResult->value = slot->value; |
203 | 58 | } |
204 | | |
205 | | txSlot* fxCheckSymbol(txMachine* the, txSlot* it) |
206 | 638 | { |
207 | 638 | txSlot* result = C_NULL; |
208 | 638 | if (it->kind == XS_SYMBOL_KIND) |
209 | 76 | result = it; |
210 | 562 | else if (it->kind == XS_REFERENCE_KIND) { |
211 | 524 | txSlot* instance = it->value.reference; |
212 | 524 | it = instance->next; |
213 | 524 | if ((it) && (it->flag & XS_INTERNAL_FLAG) && (it->kind == XS_SYMBOL_KIND)) |
214 | 509 | result = it; |
215 | 524 | } |
216 | 638 | return result; |
217 | 638 | } |
218 | | |
219 | | void fxSymbolToString(txMachine* the, txSlot* slot) |
220 | 49 | { |
221 | 49 | txSlot* key = fxGetKey(the, slot->value.symbol); |
222 | 49 | fxStringX(the, slot, "Symbol("); |
223 | 49 | if ((key->kind == XS_KEY_KIND) || (key->kind == XS_KEY_X_KIND)) |
224 | 2 | fxConcatString(the, slot, key); |
225 | 47 | else if (key->kind == XS_REFERENCE_KIND) { |
226 | 47 | key = key->value.reference->next->next; |
227 | 47 | if (key->kind != XS_UNDEFINED_KIND) |
228 | 17 | fxConcatString(the, slot, key); |
229 | 47 | } |
230 | 49 | fxConcatStringC(the, slot, ")"); |
231 | 49 | } |
232 | | |
233 | | txSlot* fxGetKey(txMachine* the, txID theID) |
234 | 52.1M | { |
235 | 52.1M | txSlot* key; |
236 | 52.1M | mxCheck(the, 0 < theID); |
237 | 52.1M | mxCheck(the, theID < the->keyIndex); |
238 | 52.1M | if (theID < the->keyOffset) |
239 | 0 | key = the->keyArrayHost[theID]; |
240 | 52.1M | else |
241 | 52.1M | key = the->keyArray[theID - the->keyOffset]; |
242 | 52.1M | mxCheck(the, key->kind != XS_UNDEFINED_KIND); |
243 | 52.1M | return key; |
244 | 52.1M | } |
245 | | |
246 | | char* fxGetKeyName(txMachine* the, txID theID) |
247 | 3.67M | { |
248 | 3.67M | txSlot* key = fxGetKey(the, theID); |
249 | 3.67M | if (key->flag & XS_DONT_ENUM_FLAG) |
250 | 3.67M | return key->value.string; |
251 | 0 | return C_NULL; |
252 | 3.67M | } |
253 | | |
254 | | char* fxGetKeyString(txMachine* the, txID theID, txBoolean* adorn) |
255 | 3.92M | { |
256 | 3.92M | txString result = mxEmptyString.value.string; |
257 | 3.92M | txSlot* key = fxGetKey(the, theID); |
258 | 3.92M | txKind kind = key->kind; |
259 | 3.92M | if ((kind == XS_KEY_KIND) || (kind == XS_KEY_X_KIND)) |
260 | 3.92M | result = key->value.key.string; |
261 | 200 | else if (key->kind == XS_REFERENCE_KIND) { |
262 | 200 | key = key->value.reference->next->next; |
263 | 200 | if (key->kind != XS_UNDEFINED_KIND) |
264 | 198 | result = key->value.string; |
265 | 200 | } |
266 | 3.92M | if (adorn) |
267 | 3.92M | *adorn = (key->flag & XS_DONT_ENUM_FLAG) ? 0 : 1; |
268 | 3.92M | return result; |
269 | 3.92M | } |
270 | | |
271 | | void fxPushKeyString(txMachine* the, txID theID, txBoolean* adorn) |
272 | 21.5M | { |
273 | 21.5M | txSlot* key = fxGetKey(the, theID); |
274 | 21.5M | txKind kind = key->kind; |
275 | 21.5M | if (adorn) |
276 | 21.0M | *adorn = (key->flag & XS_DONT_ENUM_FLAG) ? 0 : 1; |
277 | 21.5M | if (kind == XS_KEY_KIND) |
278 | 20.6M | mxPushString(key->value.key.string); |
279 | 814k | else if (kind == XS_KEY_X_KIND) |
280 | 0 | mxPushStringX(key->value.key.string); |
281 | 814k | else { |
282 | 814k | mxCheck(the, key->kind == XS_REFERENCE_KIND); |
283 | 814k | key = key->value.reference->next->next; |
284 | 814k | if (key->kind == XS_UNDEFINED_KIND) { |
285 | 2 | *adorn = 0; |
286 | 2 | mxPush(mxEmptyString); |
287 | 2 | } |
288 | 814k | else |
289 | 814k | mxPushSlot(key); |
290 | 814k | } |
291 | 21.5M | } |
292 | | |
293 | | txID fxFindName(txMachine* the, txString theString) |
294 | 3.11k | { |
295 | 3.11k | txU1* aString; |
296 | 3.11k | txU4 aSum; |
297 | 3.11k | txU4 aModulo; |
298 | 3.11k | txSlot* result; |
299 | | |
300 | 3.11k | aString = (txU1*)theString; |
301 | 3.11k | aSum = 0; |
302 | 75.5k | while (*aString != 0) { |
303 | 72.4k | aSum = (aSum << 1) + *aString++; |
304 | 72.4k | } |
305 | 3.11k | aSum &= 0x7FFFFFFF; |
306 | 3.11k | aModulo = aSum % the->nameModulo; |
307 | 3.11k | result = the->nameTable[aModulo]; |
308 | 4.04k | while (result != C_NULL) { |
309 | 2.15k | if (result->value.key.sum == aSum) |
310 | 1.37k | if (c_strcmp(result->value.key.string, theString) == 0) |
311 | 1.22k | return mxGetKeySlotID(result); |
312 | 931 | result = result->next; |
313 | 931 | } |
314 | 1.88k | return 0; |
315 | 3.11k | } |
316 | | |
317 | | txBoolean fxIsKeyName(txMachine* the, txID theID) |
318 | 22.2M | { |
319 | 22.2M | txSlot* key = fxGetKey(the, theID); |
320 | 22.2M | return (key->flag & XS_DONT_ENUM_FLAG) ? 1 : 0; |
321 | 22.2M | } |
322 | | |
323 | | txBoolean fxIsKeySymbol(txMachine* the, txID theID) |
324 | 148k | { |
325 | 148k | txSlot* key = fxGetKey(the, theID); |
326 | 148k | return (key->flag & XS_DONT_ENUM_FLAG) ? 0 : 1; |
327 | 148k | } |
328 | | |
329 | | txID fxNewName(txMachine* the, txSlot* theSlot) |
330 | 5.37M | { |
331 | 5.37M | txU1* string; |
332 | 5.37M | txU4 sum; |
333 | 5.37M | txU4 modulo; |
334 | 5.37M | txSlot* result; |
335 | | |
336 | 5.37M | string = (txU1*)theSlot->value.string; |
337 | 5.37M | sum = 0; |
338 | 85.6M | while(*string != 0) { |
339 | 80.3M | sum = (sum << 1) + *string++; |
340 | 80.3M | } |
341 | 5.37M | sum &= 0x7FFFFFFF; |
342 | 5.37M | modulo = sum % the->nameModulo; |
343 | 5.37M | result = the->nameTable[modulo]; |
344 | 9.96M | while (result != C_NULL) { |
345 | 7.20M | if (result->value.key.sum == sum) { |
346 | 5.89M | if (c_strcmp(result->value.key.string, theSlot->value.string) == 0) |
347 | 2.61M | return mxGetKeySlotID(result); |
348 | 5.89M | } |
349 | 4.59M | result = result->next; |
350 | 4.59M | } |
351 | 2.75M | result = fxFindKey(the); |
352 | 2.75M | result->next = the->nameTable[modulo]; |
353 | 2.75M | result->flag = XS_INTERNAL_FLAG | XS_DONT_ENUM_FLAG; |
354 | 2.75M | result->kind = XS_KEY_KIND; |
355 | 2.75M | result->value.key.string = theSlot->value.string; |
356 | 2.75M | result->value.key.sum = sum; |
357 | 2.75M | the->nameTable[modulo] = result; |
358 | 2.75M | return result->ID; |
359 | 5.37M | } |
360 | | |
361 | | txID fxNewNameC(txMachine* the, txString theString) |
362 | 21.1M | { |
363 | 21.1M | txU1* string; |
364 | 21.1M | txU4 sum; |
365 | 21.1M | txU4 modulo; |
366 | 21.1M | txSlot* result; |
367 | | |
368 | 21.1M | string = (txU1*)theString; |
369 | 21.1M | sum = 0; |
370 | 195M | while(c_read8(string) != 0) { |
371 | 174M | sum = (sum << 1) + c_read8(string++); |
372 | 174M | } |
373 | 21.1M | sum &= 0x7FFFFFFF; |
374 | 21.1M | modulo = sum % the->nameModulo; |
375 | 21.1M | result = the->nameTable[modulo]; |
376 | 51.6M | while (result != C_NULL) { |
377 | 34.0M | if (result->value.key.sum == sum) { |
378 | 26.9M | if (c_strcmp(result->value.key.string, theString) == 0) { |
379 | 3.47M | txID id = mxGetKeySlotID(result); |
380 | 3.47M | if (id >= the->keyOffset) |
381 | 3.47M | result->flag |= XS_DONT_DELETE_FLAG; |
382 | 3.47M | return id; |
383 | 3.47M | } |
384 | 26.9M | } |
385 | 30.5M | result = result->next; |
386 | 30.5M | } |
387 | 17.6M | result = fxFindKey(the); |
388 | 17.6M | result->next = the->nameTable[modulo]; |
389 | 17.6M | result->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG; |
390 | 17.6M | result->kind = XS_KEY_KIND; |
391 | 17.6M | result->value.key.string = C_NULL; |
392 | 17.6M | result->value.key.sum = sum; |
393 | 17.6M | the->nameTable[modulo] = result; |
394 | 17.6M | result->value.key.string = (txString)fxNewChunk(the, mxStringLength(theString) + 1); |
395 | 17.6M | c_strcpy(result->value.key.string, theString); |
396 | 17.6M | return result->ID; |
397 | 21.1M | } |
398 | | |
399 | | txID fxNewNameX(txMachine* the, txString theString) |
400 | 0 | { |
401 | 0 | txU1* string; |
402 | 0 | txU4 sum; |
403 | 0 | txU4 modulo; |
404 | 0 | txSlot* result; |
405 | | |
406 | 0 | string = (txU1*)theString; |
407 | 0 | sum = 0; |
408 | 0 | while (c_read8(string) != 0) { |
409 | 0 | sum = (sum << 1) + c_read8(string++); |
410 | 0 | } |
411 | 0 | sum &= 0x7FFFFFFF; |
412 | 0 | modulo = sum % the->nameModulo; |
413 | 0 | result = the->nameTable[modulo]; |
414 | 0 | while (result != C_NULL) { |
415 | 0 | if (result->value.key.sum == sum) { |
416 | 0 | if (c_strcmp(result->value.key.string, theString) == 0) { |
417 | 0 | txID id = mxGetKeySlotID(result); |
418 | 0 | if (id >= the->keyOffset) |
419 | 0 | result->flag |= XS_DONT_DELETE_FLAG; |
420 | 0 | return id; |
421 | 0 | } |
422 | 0 | } |
423 | 0 | result = result->next; |
424 | 0 | } |
425 | 0 | result = fxFindKey(the); |
426 | 0 | result->next = the->nameTable[modulo]; |
427 | 0 | result->flag = XS_INTERNAL_FLAG | XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG; |
428 | 0 | result->kind = XS_KEY_X_KIND; |
429 | 0 | result->value.key.string = theString; |
430 | 0 | result->value.key.sum = sum; |
431 | 0 | the->nameTable[modulo] = result; |
432 | 0 | return result->ID; |
433 | 0 | } |
434 | | |
435 | | txSlot* fxAt(txMachine* the, txSlot* slot) |
436 | 42.8M | { |
437 | 42.8M | txIndex index; |
438 | 42.8M | txString string; |
439 | 42.8M | again: |
440 | 42.8M | if ((slot->kind == XS_INTEGER_KIND) && fxIntegerToIndex(the, slot->value.integer, &index)) { |
441 | 9.55M | slot->value.at.id = XS_NO_ID; |
442 | 9.55M | slot->value.at.index = index; |
443 | 9.55M | } |
444 | 33.3M | else if ((slot->kind == XS_NUMBER_KIND) && fxNumberToIndex(the, slot->value.number, &index)) { |
445 | 32.7M | slot->value.at.id = XS_NO_ID; |
446 | 32.7M | slot->value.at.index = index; |
447 | 32.7M | } |
448 | 563k | else if (slot->kind == XS_SYMBOL_KIND) { |
449 | 23.9k | slot->value.at.id = slot->value.symbol; |
450 | 23.9k | slot->value.at.index = 0; |
451 | 23.9k | } |
452 | 539k | else { |
453 | 539k | if (slot->kind == XS_REFERENCE_KIND) { |
454 | 9.02k | fxToPrimitive(the, slot, XS_STRING_HINT); |
455 | 9.02k | goto again; |
456 | 9.02k | } |
457 | 530k | string = fxToString(the, slot); |
458 | 530k | if (fxStringToIndex(the, string, &index)) { |
459 | 9.03k | slot->value.at.id = XS_NO_ID; |
460 | 9.03k | slot->value.at.index = index; |
461 | 9.03k | } |
462 | 521k | else { |
463 | 521k | txID id; |
464 | 521k | if (slot->kind == XS_STRING_X_KIND) |
465 | 0 | id = fxNewNameX(the, string); |
466 | 521k | else |
467 | 521k | id = fxNewName(the, slot); |
468 | 521k | slot->value.at.id = id; |
469 | 521k | slot->value.at.index = 0; |
470 | 521k | } |
471 | 530k | } |
472 | 42.8M | slot->kind = XS_AT_KIND; |
473 | 42.8M | return slot; |
474 | 42.8M | } |
475 | | |
476 | | void fxKeyAt(txMachine* the, txID id, txIndex index, txSlot* slot) |
477 | 9.27M | { |
478 | 9.27M | if (id) { |
479 | 182k | txSlot* key = fxGetKey(the, id); |
480 | 182k | if (key->flag & XS_DONT_ENUM_FLAG) { |
481 | 171k | if (key->kind == XS_KEY_KIND) { |
482 | 171k | slot->kind = XS_STRING_KIND; |
483 | 171k | slot->value.string = key->value.key.string; |
484 | 171k | } |
485 | 0 | else{ |
486 | 0 | slot->kind = XS_STRING_X_KIND; |
487 | 0 | slot->value.string = key->value.key.string; |
488 | 0 | } |
489 | 171k | } |
490 | 11.6k | else { |
491 | 11.6k | slot->kind = XS_SYMBOL_KIND; |
492 | 11.6k | slot->value.symbol = id; |
493 | 11.6k | } |
494 | 182k | } |
495 | 9.09M | else { |
496 | 9.09M | char buffer[16]; |
497 | 9.09M | fxCopyStringC(the, slot, fxNumberToString(the, index, buffer, sizeof(buffer), 0, 0)); |
498 | 9.09M | } |
499 | 9.27M | } |
500 | | |
501 | | void fxIDToString(txMachine* the, txID id, txString theBuffer, txSize theSize) |
502 | 1.12M | { |
503 | 1.12M | if (id != XS_NO_ID) { |
504 | 1.12M | txBoolean adorn; |
505 | 1.12M | txString string = fxGetKeyString(the, id, &adorn); |
506 | 1.12M | if (adorn) |
507 | 2 | c_snprintf(theBuffer, theSize, "[%s]", string); |
508 | 1.12M | else |
509 | 1.12M | c_snprintf(theBuffer, theSize, "%s", string); |
510 | 1.12M | } |
511 | 28 | else { |
512 | 28 | theBuffer[0] = '?'; |
513 | 28 | theBuffer[1] = 0; |
514 | 28 | } |
515 | 1.12M | } |