bobe 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bobe.cjs.js +271 -88
- package/dist/bobe.cjs.js.map +1 -1
- package/dist/bobe.esm.js +272 -89
- package/dist/bobe.esm.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.umd.js +271 -88
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/bobe.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getPulling, setPulling, Keys, Computed, Effect, toRaw,
|
|
1
|
+
import { getPulling, setPulling, Keys, Computed, Effect, toRaw, runWithPulling, Scope, deepSignal, Store, shareSignal, effect } from 'aoye';
|
|
2
2
|
export * from 'aoye';
|
|
3
3
|
import { jsVarRegexp, Queue, isNum, matchIdStart2 } from 'bobe-shared';
|
|
4
4
|
|
|
@@ -156,6 +156,47 @@ class MultiTypeStack {
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
function macInc(arr) {
|
|
160
|
+
const len = arr.length;
|
|
161
|
+
let candyLast = [],
|
|
162
|
+
i = 0;
|
|
163
|
+
while (i < len) {
|
|
164
|
+
const it = arr[i];
|
|
165
|
+
if (it !== -1) {
|
|
166
|
+
candyLast = [i];
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
i++;
|
|
170
|
+
}
|
|
171
|
+
if (i + 1 >= len) return candyLast;
|
|
172
|
+
const toPrev = new Int32Array(len);
|
|
173
|
+
while (i < len) {
|
|
174
|
+
const target = arr[i];
|
|
175
|
+
if (target === -1) continue;
|
|
176
|
+
let start = -1,
|
|
177
|
+
end = candyLast.length;
|
|
178
|
+
while (start + 1 < end) {
|
|
179
|
+
const mid = start + end >> 1;
|
|
180
|
+
if (arr[candyLast[mid]] < target) {
|
|
181
|
+
start = mid;
|
|
182
|
+
} else {
|
|
183
|
+
end = mid;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
candyLast[end] = i;
|
|
187
|
+
toPrev[i] = candyLast[start];
|
|
188
|
+
i++;
|
|
189
|
+
}
|
|
190
|
+
let length = candyLast.length;
|
|
191
|
+
for (let j = length - 1; j > 0; j--) {
|
|
192
|
+
const prev = toPrev[candyLast[j]];
|
|
193
|
+
candyLast[j - 1] = prev;
|
|
194
|
+
}
|
|
195
|
+
return candyLast;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const KEY_INDEX = '__BOBE_KEY_INDEX';
|
|
199
|
+
|
|
159
200
|
const _excluded = ["dentStack", "isFirstToken"];
|
|
160
201
|
class Interpreter {
|
|
161
202
|
constructor(tokenizer) {
|
|
@@ -208,6 +249,9 @@ class Interpreter {
|
|
|
208
249
|
if (ctx.current.__logicType) {
|
|
209
250
|
if (isLogicNode) {
|
|
210
251
|
setPulling(ctx.current.effect);
|
|
252
|
+
if (ctx.current.__logicType & FakeType.ForItem) {
|
|
253
|
+
ctx.prevSibling = ctx.current.realBefore;
|
|
254
|
+
}
|
|
211
255
|
}
|
|
212
256
|
} else {
|
|
213
257
|
if (ctx.current) {
|
|
@@ -258,8 +302,8 @@ class Interpreter {
|
|
|
258
302
|
this.tokenizer.resume(snapshot);
|
|
259
303
|
this.tokenizer.nextToken();
|
|
260
304
|
this.tokenizer.nextToken();
|
|
261
|
-
ctx.prevSibling = parent;
|
|
262
305
|
ctx.current = forNode.children[++forNode.i];
|
|
306
|
+
ctx.prevSibling = ctx.current.realBefore;
|
|
263
307
|
continue;
|
|
264
308
|
}
|
|
265
309
|
ctx.prevSibling = forNode.prevSibling;
|
|
@@ -363,21 +407,25 @@ class Interpreter {
|
|
|
363
407
|
this.tokenizer.nextToken();
|
|
364
408
|
const itemToken = this.tokenizer.nextToken();
|
|
365
409
|
const isDestruct = itemToken.type === TokenType.InsertionExp;
|
|
366
|
-
let itemExp = itemToken.value
|
|
410
|
+
let itemExp = itemToken.value,
|
|
411
|
+
vars;
|
|
367
412
|
if (isDestruct) {
|
|
368
413
|
itemExp = '{' + itemExp + '}';
|
|
369
|
-
|
|
370
|
-
|
|
414
|
+
vars = itemExp.match(jsVarRegexp);
|
|
415
|
+
const varStr = vars.join(',');
|
|
416
|
+
itemExp = new Function(itemExp, `return {${varStr}};`);
|
|
371
417
|
}
|
|
372
|
-
let indexName,
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
418
|
+
let indexName,
|
|
419
|
+
keyExp,
|
|
420
|
+
char = this.tokenizer.peekChar();
|
|
421
|
+
if (char === ';') {
|
|
422
|
+
this.tokenizer.nextToken();
|
|
423
|
+
if (this.tokenizer.peekChar() !== '\n') keyExp = this.tokenizer.jsExp().value;
|
|
424
|
+
} else if (char === '\n') ; else {
|
|
425
|
+
indexName = this.tokenizer.nextToken().value;
|
|
426
|
+
if (this.tokenizer.peekChar() === ';') {
|
|
427
|
+
this.tokenizer.nextToken();
|
|
428
|
+
if (this.tokenizer.peekChar() !== '\n') keyExp = this.tokenizer.jsExp().value;
|
|
381
429
|
}
|
|
382
430
|
}
|
|
383
431
|
const owner = this.ctx.stack.peekByType(NodeSort.TokenizerSwitcher)?.node;
|
|
@@ -390,12 +438,14 @@ class Interpreter {
|
|
|
390
438
|
realBefore: prevSibling?.realAfter || prevSibling,
|
|
391
439
|
realAfter: null,
|
|
392
440
|
arr: null,
|
|
441
|
+
arrSignal: null,
|
|
393
442
|
itemExp,
|
|
394
443
|
indexName,
|
|
395
444
|
getKey: null,
|
|
396
445
|
children: [],
|
|
397
446
|
effect: null,
|
|
398
447
|
owner,
|
|
448
|
+
vars,
|
|
399
449
|
i: 0
|
|
400
450
|
};
|
|
401
451
|
if (keyExp) {
|
|
@@ -406,6 +456,7 @@ class Interpreter {
|
|
|
406
456
|
const cells = data[Keys.Meta].cells;
|
|
407
457
|
const hasArrExpKey = Reflect.has(data[Keys.Raw], arrExp);
|
|
408
458
|
const arrSignal = hasArrExpKey ? (data[arrExp], cells.get(arrExp)) : new Computed(this.getFn(data, arrExp));
|
|
459
|
+
forNode.arrSignal = arrSignal;
|
|
409
460
|
forNode.realAfter = this.insertAfterAnchor('for-after');
|
|
410
461
|
const _forNode$snapshot = forNode.snapshot;
|
|
411
462
|
_forNode$snapshot.dentStack;
|
|
@@ -413,26 +464,23 @@ class Interpreter {
|
|
|
413
464
|
const snapshotForUpdate = _objectWithoutProperties(_forNode$snapshot, _excluded);
|
|
414
465
|
let isFirstRender = true;
|
|
415
466
|
forNode.effect = new Effect(() => {
|
|
416
|
-
let arr =
|
|
467
|
+
let arr = arrSignal.get();
|
|
417
468
|
arr[Keys.Iterator];
|
|
418
|
-
|
|
469
|
+
const prevCtx = getPulling();
|
|
470
|
+
setPulling(null);
|
|
471
|
+
forNode.arr = arr = toRaw(arr);
|
|
419
472
|
const children = forNode.children;
|
|
420
473
|
if (isFirstRender) {
|
|
421
474
|
const len = arr.length;
|
|
422
475
|
for (let i = len; i--;) {
|
|
423
|
-
const nextItem = children[i + 1];
|
|
424
476
|
const item = this.createForItem(forNode, i, data);
|
|
425
|
-
|
|
426
|
-
item.
|
|
427
|
-
if (nextItem) {
|
|
428
|
-
nextItem.realBefore = anchor;
|
|
429
|
-
}
|
|
477
|
+
item.realAfter = this.insertAfterAnchor('for-item-after');
|
|
478
|
+
item.realBefore = this.insertAfterAnchor('for-item-before');
|
|
430
479
|
item.realParent = forNode.realParent;
|
|
431
480
|
children[i] = item;
|
|
432
481
|
}
|
|
433
482
|
const firstInsert = children[0];
|
|
434
483
|
if (firstInsert) {
|
|
435
|
-
firstInsert.realBefore = forNode.realBefore;
|
|
436
484
|
this.tokenizer.nextToken();
|
|
437
485
|
this.tokenizer.nextToken();
|
|
438
486
|
} else {
|
|
@@ -446,65 +494,214 @@ class Interpreter {
|
|
|
446
494
|
if (!forNode.getKey) {
|
|
447
495
|
if (newLen < oldLen) {
|
|
448
496
|
for (let i = oldLen - 1; i >= newLen; i--) {
|
|
449
|
-
|
|
450
|
-
this.removeLogicNode(child);
|
|
451
|
-
this.remove(child.realAfter);
|
|
452
|
-
child.effect.dispose();
|
|
497
|
+
this.removeForItem(children, i);
|
|
453
498
|
}
|
|
454
499
|
}
|
|
455
500
|
if (oldLen < newLen) {
|
|
456
501
|
const lastAfter = children.at(-1)?.realAfter || forNode.realBefore;
|
|
457
502
|
for (let i = newLen - 1; i >= oldLen; i--) {
|
|
458
|
-
|
|
459
|
-
newChildren[i] = item;
|
|
460
|
-
const nextItem = newChildren[i + 1];
|
|
461
|
-
const anchor = this.createAnchor('for-item-after');
|
|
462
|
-
this.insertAfter(forNode.realParent, anchor, lastAfter);
|
|
463
|
-
item.realAfter = anchor;
|
|
464
|
-
if (nextItem) {
|
|
465
|
-
nextItem.realBefore = anchor;
|
|
466
|
-
}
|
|
467
|
-
item.realParent = forNode.realParent;
|
|
468
|
-
this.tokenizer = owner.tokenizer;
|
|
469
|
-
this.tokenizer.resume(snapshotForUpdate);
|
|
470
|
-
this.tokenizer.useDedentAsEof = false;
|
|
471
|
-
runWithPulling(() => {
|
|
472
|
-
this.program(forNode.realParent, forNode.owner, lastAfter, item);
|
|
473
|
-
}, item.effect);
|
|
474
|
-
}
|
|
475
|
-
const firstInsert = newChildren[oldLen];
|
|
476
|
-
if (firstInsert) {
|
|
477
|
-
firstInsert.realBefore = lastAfter;
|
|
503
|
+
this.insertForItem(forNode, i, data, newChildren, lastAfter, snapshotForUpdate);
|
|
478
504
|
}
|
|
479
505
|
}
|
|
480
506
|
for (let i = minLen; i--;) {
|
|
481
507
|
const child = children[i];
|
|
482
508
|
newChildren[i] = child;
|
|
483
|
-
|
|
484
|
-
|
|
509
|
+
this.reuseForItem(child, arr[i], itemExp, i, indexName);
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
let s = 0,
|
|
513
|
+
e1 = oldLen - 1,
|
|
514
|
+
e2 = newLen - 1;
|
|
515
|
+
while (s <= e1 && s <= e2) {
|
|
516
|
+
const child = children[s];
|
|
517
|
+
const old = child.key;
|
|
518
|
+
const itemData = this.getItemData(forNode, s, data);
|
|
519
|
+
const key = forNode.getKey(itemData);
|
|
520
|
+
if (old === key) {
|
|
521
|
+
newChildren[s] = child;
|
|
522
|
+
this.reuseForItem(child, arr[s], itemExp, s, indexName);
|
|
523
|
+
s++;
|
|
524
|
+
} else {
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
while (s <= e1 && s <= e2) {
|
|
529
|
+
const child = children[e1];
|
|
530
|
+
const old = child.key;
|
|
531
|
+
const itemData = this.getItemData(forNode, e2, data);
|
|
532
|
+
const key = forNode.getKey(itemData);
|
|
533
|
+
if (old === key) {
|
|
534
|
+
newChildren[e2] = child;
|
|
535
|
+
this.reuseForItem(child, arr[e2], itemExp, e2, indexName);
|
|
536
|
+
e1--;
|
|
537
|
+
e2--;
|
|
485
538
|
} else {
|
|
486
|
-
|
|
539
|
+
break;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (s > e1) {
|
|
543
|
+
if (s <= e2) {
|
|
544
|
+
const firstBefore = s > 0 ? children.at(-1)?.realAfter || forNode.realBefore : forNode.realBefore;
|
|
545
|
+
for (let i = e2; i >= s; i--) {
|
|
546
|
+
this.insertForItem(forNode, i, data, newChildren, firstBefore, snapshotForUpdate);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
} else if (s > e2) {
|
|
550
|
+
if (s <= e1) {
|
|
551
|
+
for (let i = e1; i >= s; i--) {
|
|
552
|
+
this.removeForItem(children, i);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
} else {
|
|
556
|
+
let s1 = s,
|
|
557
|
+
s2 = s;
|
|
558
|
+
const mixLen = e2 - s2 + 1;
|
|
559
|
+
const key2new = new Map();
|
|
560
|
+
for (let i = s2; i <= e2; i++) {
|
|
561
|
+
const itemData = this.getItemData(forNode, i, data);
|
|
562
|
+
const key = forNode.getKey(itemData);
|
|
563
|
+
key2new.set(key, i);
|
|
564
|
+
}
|
|
565
|
+
let maxIncNewI = -1;
|
|
566
|
+
let hasMove = false;
|
|
567
|
+
const new2oldI = new Array(mixLen).fill(-1);
|
|
568
|
+
for (let i = s1; i <= e1; i++) {
|
|
569
|
+
const key = children[i].key;
|
|
570
|
+
const newI = key2new.get(key);
|
|
571
|
+
if (newI == null) {
|
|
572
|
+
this.removeForItem(children, i);
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
const child = children[i];
|
|
576
|
+
newChildren[newI] = child;
|
|
577
|
+
this.reuseForItem(child, arr[newI], itemExp, newI, indexName);
|
|
578
|
+
new2oldI[newI - s2] = i;
|
|
579
|
+
key2new.delete(key);
|
|
580
|
+
if (newI < maxIncNewI) {
|
|
581
|
+
hasMove = true;
|
|
582
|
+
} else {
|
|
583
|
+
maxIncNewI = newI;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
if (!hasMove) {
|
|
587
|
+
key2new.forEach((i, key) => {
|
|
588
|
+
const before = i === 0 ? forNode.realBefore : newChildren[i - 1].realAfter;
|
|
589
|
+
this.insertForItem(forNode, i, data, newChildren, before, snapshotForUpdate);
|
|
590
|
+
});
|
|
591
|
+
} else {
|
|
592
|
+
const incI = macInc(new2oldI),
|
|
593
|
+
incLen = incI.length;
|
|
594
|
+
let p1, p2;
|
|
595
|
+
for (p1 = s2, p2 = 0; p1 <= e2; p1++) {
|
|
596
|
+
const oldI = new2oldI[p1];
|
|
597
|
+
if (oldI === -1) {
|
|
598
|
+
const before = p1 === 0 ? forNode.realBefore : newChildren[p1 - 1].realAfter;
|
|
599
|
+
this.insertForItem(forNode, p1, data, newChildren, before, snapshotForUpdate);
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
const staticIdx = incI[p2] + s2;
|
|
603
|
+
if (p1 === staticIdx) {
|
|
604
|
+
p2 <= incLen && p2++;
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
let before = p1 === 0 ? forNode.realBefore : newChildren[p1 - 1].realAfter;
|
|
608
|
+
const child = newChildren[p1];
|
|
609
|
+
const realBefore = child.realBefore,
|
|
610
|
+
realAfter = child.realAfter,
|
|
611
|
+
realParent = child.realParent;
|
|
612
|
+
let point = realBefore,
|
|
613
|
+
next;
|
|
614
|
+
do {
|
|
615
|
+
next = this.nextSib(point);
|
|
616
|
+
this.insertAfter(realParent, point, before);
|
|
617
|
+
before = point;
|
|
618
|
+
if (point === realAfter) break;
|
|
619
|
+
point = next;
|
|
620
|
+
} while (true);
|
|
621
|
+
}
|
|
487
622
|
}
|
|
488
623
|
}
|
|
489
|
-
forNode.children = newChildren;
|
|
490
624
|
}
|
|
625
|
+
forNode.children = newChildren;
|
|
491
626
|
}
|
|
492
627
|
isFirstRender = false;
|
|
628
|
+
setPulling(prevCtx);
|
|
629
|
+
return isDestroy => {
|
|
630
|
+
if (isDestroy) {
|
|
631
|
+
for (let i = 0; i < forNode.children.length; i++) {
|
|
632
|
+
const item = forNode.children[i];
|
|
633
|
+
item.effect.dispose();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
};
|
|
493
637
|
});
|
|
494
638
|
return forNode.children[0] || forNode;
|
|
495
639
|
}
|
|
640
|
+
insertForItem(forNode, i, parentData, newChildren, before, snapshotForUpdate) {
|
|
641
|
+
const item = this.createForItem(forNode, i, parentData);
|
|
642
|
+
newChildren[i] = item;
|
|
643
|
+
let realAfter = this.createAnchor('for-item-after');
|
|
644
|
+
this.handleInsert(forNode.realParent, realAfter, before);
|
|
645
|
+
let realBefore = this.createAnchor('for-item-before');
|
|
646
|
+
this.handleInsert(forNode.realParent, realBefore, before);
|
|
647
|
+
item.realBefore = realBefore;
|
|
648
|
+
item.realAfter = realAfter;
|
|
649
|
+
this.tokenizer = forNode.owner.tokenizer;
|
|
650
|
+
this.tokenizer.resume(snapshotForUpdate);
|
|
651
|
+
this.tokenizer.useDedentAsEof = false;
|
|
652
|
+
runWithPulling(() => {
|
|
653
|
+
this.program(forNode.realParent, forNode.owner, realBefore, item);
|
|
654
|
+
}, item.effect);
|
|
655
|
+
}
|
|
656
|
+
removeForItem(children, i) {
|
|
657
|
+
const child = children[i];
|
|
658
|
+
this.removeLogicNode(child);
|
|
659
|
+
this.remove(child.realBefore);
|
|
660
|
+
this.remove(child.realAfter);
|
|
661
|
+
child.effect.dispose();
|
|
662
|
+
}
|
|
663
|
+
reuseForItem(child, data, itemExp, i, indexName) {
|
|
664
|
+
if (typeof itemExp === 'string') {
|
|
665
|
+
child.data[itemExp] = data;
|
|
666
|
+
if (indexName) {
|
|
667
|
+
child.data[indexName] = i;
|
|
668
|
+
}
|
|
669
|
+
} else {
|
|
670
|
+
indexName = indexName || KEY_INDEX;
|
|
671
|
+
child.data[indexName] = i;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
496
674
|
forItemId = 0;
|
|
497
675
|
createForItem(forNode, i, parentData) {
|
|
498
676
|
let forItemNode;
|
|
677
|
+
let data;
|
|
499
678
|
const scope = new Scope(() => {});
|
|
500
679
|
scope.scope = null;
|
|
501
680
|
runWithPulling(() => {
|
|
502
681
|
scope.get();
|
|
503
682
|
}, null);
|
|
683
|
+
data = this.getItemData(forNode, i, parentData);
|
|
684
|
+
forItemNode = {
|
|
685
|
+
id: this.forItemId++,
|
|
686
|
+
__logicType: FakeType.ForItem,
|
|
687
|
+
realParent: null,
|
|
688
|
+
realBefore: null,
|
|
689
|
+
realAfter: null,
|
|
690
|
+
forNode,
|
|
691
|
+
key: forNode.getKey?.(data),
|
|
692
|
+
effect: null,
|
|
693
|
+
data
|
|
694
|
+
};
|
|
695
|
+
forItemNode.effect = scope;
|
|
696
|
+
return forItemNode;
|
|
697
|
+
}
|
|
698
|
+
getItemData(forNode, i, parentData) {
|
|
504
699
|
const arr = forNode.arr,
|
|
505
700
|
itemExp = forNode.itemExp,
|
|
506
|
-
|
|
701
|
+
vars = forNode.vars,
|
|
702
|
+
arrSignal = forNode.arrSignal,
|
|
507
703
|
getKey = forNode.getKey;
|
|
704
|
+
let indexName = forNode.indexName;
|
|
508
705
|
let data;
|
|
509
706
|
if (typeof itemExp === 'string') {
|
|
510
707
|
data = deepSignal(indexName ? {
|
|
@@ -514,26 +711,21 @@ class Interpreter {
|
|
|
514
711
|
[itemExp]: arr[i]
|
|
515
712
|
}, getPulling());
|
|
516
713
|
} else {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
}
|
|
714
|
+
indexName = indexName ?? KEY_INDEX;
|
|
715
|
+
const rawData = {
|
|
716
|
+
[indexName]: i
|
|
717
|
+
};
|
|
521
718
|
data = deepSignal(rawData, getPulling());
|
|
719
|
+
const computedData = new Computed(() => itemExp(arrSignal.get()[getKey ? data[indexName] : i]));
|
|
720
|
+
const cells = data[Keys.Meta].cells;
|
|
721
|
+
for (let i = 0; i < vars.length; i++) {
|
|
722
|
+
const name = vars[i];
|
|
723
|
+
rawData[name] = undefined;
|
|
724
|
+
cells.set(name, new Computed(() => computedData.get()[name]));
|
|
725
|
+
}
|
|
522
726
|
}
|
|
523
727
|
Object.setPrototypeOf(data, parentData);
|
|
524
|
-
|
|
525
|
-
id: this.forItemId++,
|
|
526
|
-
__logicType: FakeType.ForItem,
|
|
527
|
-
realParent: null,
|
|
528
|
-
realBefore: null,
|
|
529
|
-
realAfter: null,
|
|
530
|
-
forNode,
|
|
531
|
-
key: getKey?.(data),
|
|
532
|
-
effect: null,
|
|
533
|
-
data
|
|
534
|
-
};
|
|
535
|
-
forItemNode.effect = scope;
|
|
536
|
-
return forItemNode;
|
|
728
|
+
return data;
|
|
537
729
|
}
|
|
538
730
|
getData() {
|
|
539
731
|
const _this$ctx$stack$peekB = this.ctx.stack.peekByType(NodeSort.CtxProvider),
|
|
@@ -1032,36 +1224,27 @@ class Tokenizer {
|
|
|
1032
1224
|
this.setToken(TokenType.Identifier, value || true);
|
|
1033
1225
|
return this.token;
|
|
1034
1226
|
}
|
|
1035
|
-
|
|
1227
|
+
jsExp() {
|
|
1036
1228
|
this.token = null;
|
|
1037
1229
|
let value = '';
|
|
1038
|
-
let count = 0;
|
|
1039
1230
|
while (1) {
|
|
1040
1231
|
const char = this.code[this.i];
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
if (!this.token) {
|
|
1045
|
-
this.setToken(TokenType.Identifier, value);
|
|
1046
|
-
} else {
|
|
1047
|
-
this.waitingTokens.push({
|
|
1048
|
-
type: TokenType.Identifier,
|
|
1049
|
-
typeName: TokenType[TokenType.Identifier],
|
|
1050
|
-
value
|
|
1051
|
-
});
|
|
1052
|
-
}
|
|
1053
|
-
value = '';
|
|
1054
|
-
count++;
|
|
1055
|
-
if (count > 3) {
|
|
1056
|
-
throw SyntaxError(`for 循环最多可包含三个表达式, 分别为 arr ; item index [; key]`);
|
|
1057
|
-
}
|
|
1058
|
-
if (!isSemicolon) return count === 3;
|
|
1232
|
+
if (char === ';' || char === '\n') {
|
|
1233
|
+
this.setToken(TokenType.Identifier, value.trim());
|
|
1234
|
+
return this.token;
|
|
1059
1235
|
} else {
|
|
1060
1236
|
value += char;
|
|
1061
1237
|
}
|
|
1062
1238
|
this.i++;
|
|
1063
1239
|
}
|
|
1064
1240
|
}
|
|
1241
|
+
peekChar() {
|
|
1242
|
+
let i = this.i;
|
|
1243
|
+
while (this.code[i] === ' ' || this.code[i] === '\t') {
|
|
1244
|
+
i++;
|
|
1245
|
+
}
|
|
1246
|
+
return this.code[i];
|
|
1247
|
+
}
|
|
1065
1248
|
assignment() {
|
|
1066
1249
|
this.setToken(TokenType.Assign, '=');
|
|
1067
1250
|
}
|