Skip to content

Commit 8bbc409

Browse files
Simplify fidelity implementation of context flags.
1 parent 626e90e commit 8bbc409

File tree

3 files changed

+81
-91
lines changed

3 files changed

+81
-91
lines changed

src/services/syntax/constants.ts

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
11
///<reference path='references.ts' />
22

33
module TypeScript {
4+
export const enum ParserContextFlags {
5+
StrictMode = 1 << 0,
6+
DisallowIn = 1 << 1,
7+
Yield = 1 << 2,
8+
GeneratorParameter = 1 << 3,
9+
10+
Mask = 0xF
11+
}
12+
413
export enum SyntaxNodeConstants {
514
None = 0,
615

7-
// Masks that we use to place information about a node into a single int. The first bit tells
8-
// us if we've computed the data for a node.
9-
//
10-
// The second bit tells us if the node is incrementally reusable if it does not
11-
// containe any skipped tokens, zero width tokens, regex tokens in it ("/", "/=" or "/.../"),
12-
// and contains no tokens that were parser generated.
13-
//
14-
// The next bit lets us know if the nodes was parsed in a strict context or node. A node can
15-
// only be used by the incremental parser if it is parsed in the same strict context as before.
16-
// last masks off the part of the int
17-
//
16+
// The first four bit of the flags are used to store parser context flags.
1817
// The width of the node is stored in the remainder of the int. This allows us up to 128MB
1918
// for a node by using all 27 bits. However, in the common case, we'll use less than 27 bits
2019
// for the width. Thus, the info will be stored in a single int in chakra.
21-
DataComputed = 0x00000001, // 0000 0000 0000 0000 0000 0000 0000 0001
22-
IncrementallyUnusableMask = 0x00000002, // 0000 0000 0000 0000 0000 0000 0000 0010
23-
ParsedInStrictModeContext = 0x00000004, // 0000 0000 0000 0000 0000 0000 0000 0100
24-
ParsedInDisallowInContext = 0x00000008, // 0000 0000 0000 0000 0000 0000 0000 1000
25-
ParsedInYieldContext = 0x00000010, // 0000 0000 0000 0000 0000 0000 0001 0000
26-
ParsedInGeneratorParameterContext = 0x00000020, // 0000 0000 0000 0000 0000 0000 0010 0000
27-
FullWidthShift = 1 << 6, // 1111 1111 1111 1111 1111 1111 1100 0000
20+
DataComputed = 1 << 4, // 0000 0000 0000 0000 0000 0000 0001 0000
21+
IncrementallyUnusableMask = 1 << 5, // 0000 0000 0000 0000 0000 0000 0010 0000
22+
FullWidthShift = 1 << 6, // 1111 1111 1111 1111 1111 1111 1100 0000
2823
}
2924
}

src/services/syntax/parser.ts

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,7 @@ module TypeScript.Parser {
195195
//
196196
// Getting this all correct is tricky and requires careful reading of the grammar to
197197
// understand when these values should be changed versus when they should be inherited.
198-
var strictModeContext: boolean = false;
199-
var disallowInContext: boolean = false;
200-
var yieldContext: boolean = false;
201-
var generatorParameterContext: boolean = false;
202-
var contextFlags: number = 0;
198+
var contextFlags: ParserContextFlags = 0;
203199

204200
// Current state of the parser. If we need to rewind we will store and reset these values as
205201
// appropriate.
@@ -223,7 +219,7 @@ module TypeScript.Parser {
223219

224220
// Now, clear out our state so that our singleton parser doesn't keep things alive.
225221
diagnostics = [];
226-
contextFlags = SyntaxNodeConstants.None;
222+
contextFlags = 0;
227223
fileName = undefined;
228224
source.release();
229225
source = undefined;
@@ -284,10 +280,7 @@ module TypeScript.Parser {
284280
// are unaffected by strict mode. It's just the parser will decide what to do with it
285281
// differently depending on what mode it is in.
286282
if (node &&
287-
parsedInStrictModeContext(node) === strictModeContext &&
288-
parsedInDisallowInContext(node) === disallowInContext &&
289-
parsedInYieldContext(node) === yieldContext &&
290-
parsedInGeneratorParameterContext(node) === generatorParameterContext) {
283+
parserContextFlags(node) === contextFlags) {
291284

292285
return node;
293286
}
@@ -421,7 +414,7 @@ module TypeScript.Parser {
421414

422415
// If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is
423416
// considered a keyword and is not an identifier.
424-
if (tokenKind === SyntaxKind.YieldKeyword && yieldContext) {
417+
if (tokenKind === SyntaxKind.YieldKeyword && inYieldContext()) {
425418
return false;
426419
}
427420

@@ -431,7 +424,7 @@ module TypeScript.Parser {
431424
if (tokenKind <= SyntaxKind.LastFutureReservedStrictKeyword) {
432425
// Could be a keyword or identifier. It's an identifier if we're not in strict
433426
// mode.
434-
return !strictModeContext;
427+
return !inStrictModeContext();
435428
}
436429

437430
// If it's typescript keyword, then it's actually a javascript identifier.
@@ -633,39 +626,52 @@ module TypeScript.Parser {
633626
throw Errors.invalidOperation();
634627
}
635628

636-
function updateContextFlags() {
637-
contextFlags =
638-
(strictModeContext ? SyntaxNodeConstants.ParsedInStrictModeContext : 0) |
639-
(disallowInContext ? SyntaxNodeConstants.ParsedInDisallowInContext : 0) |
640-
(yieldContext ? SyntaxNodeConstants.ParsedInYieldContext : 0) |
641-
(generatorParameterContext ? SyntaxNodeConstants.ParsedInGeneratorParameterContext : 0);
629+
function setContextFlag(val: boolean, flag: ParserContextFlags) {
630+
if (val) {
631+
contextFlags |= flag;
632+
}
633+
else {
634+
contextFlags &= ~flag;
635+
}
642636
}
643637

644638
function setStrictModeContext(val: boolean) {
645-
strictModeContext = val;
646-
updateContextFlags();
639+
setContextFlag(val, ParserContextFlags.StrictMode);
647640
}
648641

649642
function setDisallowInContext(val: boolean) {
650-
disallowInContext = val;
651-
updateContextFlags();
643+
setContextFlag(val, ParserContextFlags.DisallowIn);
652644
}
653645

654646
function setYieldContext(val: boolean) {
655-
yieldContext = val;
656-
updateContextFlags();
647+
setContextFlag(val, ParserContextFlags.Yield);
657648
}
658649

659650
function setGeneratorParameterContext(val: boolean) {
660-
generatorParameterContext = val;
661-
updateContextFlags();
651+
setContextFlag(val, ParserContextFlags.GeneratorParameter);
652+
}
653+
654+
function inStrictModeContext() {
655+
return (contextFlags & ParserContextFlags.StrictMode) !== 0;
656+
}
657+
658+
function inDisallowInContext() {
659+
return (contextFlags & ParserContextFlags.DisallowIn) !== 0;
660+
}
661+
662+
function inYieldContext() {
663+
return (contextFlags & ParserContextFlags.Yield) !== 0;
664+
}
665+
666+
function inGeneratorParameterContext() {
667+
return (contextFlags & ParserContextFlags.GeneratorParameter) !== 0;
662668
}
663669

664670
function parseSourceUnit(): SourceUnitSyntax {
665671
// Note: saving and restoring the 'isInStrictMode' state is not really necessary here
666672
// (as it will never be read afterwards). However, for symmetry with the rest of the
667673
// parsing code, we do the same here.
668-
var savedIsInStrictMode = strictModeContext
674+
var savedIsInStrictMode = inStrictModeContext()
669675

670676
// Note: any skipped tokens produced after the end of all the module elements will be
671677
// added as skipped trivia to the start of the EOF token.
@@ -692,7 +698,7 @@ module TypeScript.Parser {
692698
}
693699

694700
function updateStrictModeState(items: any[]): void {
695-
if (!strictModeContext) {
701+
if (!inStrictModeContext()) {
696702
// Check if all the items are directive prologue elements.
697703
for (var i = 0, n = items.length; i < n; i++) {
698704
if (!isDirectivePrologueElement(items[i])) {
@@ -972,7 +978,7 @@ module TypeScript.Parser {
972978
}
973979

974980
function allowInAnd<T>(func: () => T): T {
975-
if (disallowInContext) {
981+
if (inDisallowInContext()) {
976982
setDisallowInContext(false);
977983
var result = func();
978984
setDisallowInContext(true);
@@ -984,7 +990,7 @@ module TypeScript.Parser {
984990
}
985991

986992
function disallowInAnd<T>(func: () => T): T {
987-
if (disallowInContext) {
993+
if (inDisallowInContext()) {
988994
// no need to do anything special if 'in' is already disallowed.
989995
return func();
990996
}
@@ -996,7 +1002,7 @@ module TypeScript.Parser {
9961002
}
9971003

9981004
function enterYieldContextAnd<T>(func: () => T): T {
999-
if (yieldContext) {
1005+
if (inYieldContext()) {
10001006
// no need to do anything special if we're already in the [Yield] context.
10011007
return func();
10021008
}
@@ -1008,7 +1014,7 @@ module TypeScript.Parser {
10081014
}
10091015

10101016
function exitYieldContextAnd<T>(func: () => T): T {
1011-
if (yieldContext) {
1017+
if (inYieldContext()) {
10121018
setYieldContext(false);
10131019
var result = func();
10141020
setYieldContext(true);
@@ -1108,7 +1114,7 @@ module TypeScript.Parser {
11081114
// [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
11091115

11101116
if (isHeritageClause()) {
1111-
return isClassHeritageClause && generatorParameterContext
1117+
return isClassHeritageClause && inGeneratorParameterContext()
11121118
? exitYieldContextAnd(parseHeritageClausesWorker)
11131119
: parseHeritageClausesWorker();
11141120
}
@@ -1143,7 +1149,7 @@ module TypeScript.Parser {
11431149
// [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
11441150

11451151
if (openBraceToken.fullWidth() > 0) {
1146-
return generatorParameterContext
1152+
return inGeneratorParameterContext()
11471153
? exitYieldContextAnd(parseClassElements)
11481154
: parseClassElements();
11491155
}
@@ -2446,11 +2452,11 @@ module TypeScript.Parser {
24462452
if (_currentToken.kind === SyntaxKind.YieldKeyword) {
24472453
// If we have a 'yield' keyword, and htis is a context where yield expressions are
24482454
// allowed, then definitely parse out a yield expression.
2449-
if (yieldContext) {
2455+
if (inYieldContext()) {
24502456
return true;
24512457
}
24522458

2453-
if (strictModeContext) {
2459+
if (inStrictModeContext()) {
24542460
// If we're in strict mode, then 'yield' is a keyword, could only ever start
24552461
// a yield expression.
24562462
return true;
@@ -2583,7 +2589,7 @@ module TypeScript.Parser {
25832589
}
25842590

25852591
// also, if it's the 'in' operator, only allow if our caller allows it.
2586-
if (tokenKind === SyntaxKind.InKeyword && disallowInContext) {
2592+
if (tokenKind === SyntaxKind.InKeyword && inDisallowInContext()) {
25872593
break;
25882594
}
25892595

@@ -3140,7 +3146,7 @@ module TypeScript.Parser {
31403146
//
31413147
// [Yield], on the other hand, is available, and is passed through.
31423148

3143-
var callSignature = parseCallSignature(/*requireCompleteTypeParameterList:*/ true, /*yield:*/ yieldContext, /*generatorParameter:*/ false);
3149+
var callSignature = parseCallSignature(/*requireCompleteTypeParameterList:*/ true, /*yield:*/ inYieldContext(), /*generatorParameter:*/ false);
31443150

31453151
if (requireArrow && currentToken().kind !== SyntaxKind.EqualsGreaterThanToken) {
31463152
return undefined;
@@ -3502,7 +3508,7 @@ module TypeScript.Parser {
35023508

35033509
var _currentToken = currentToken();
35043510
if (_currentToken.kind === SyntaxKind.OpenBracketToken) {
3505-
return generatorParameterContext
3511+
return inGeneratorParameterContext()
35063512
? exitYieldContextAnd(parseComputedPropertyName)
35073513
: parseComputedPropertyName();
35083514
}
@@ -3585,17 +3591,17 @@ module TypeScript.Parser {
35853591
}
35863592

35873593
function parseFunctionBlockStatements() {
3588-
var savedIsInStrictMode = strictModeContext;
3594+
var savedIsInStrictMode = inStrictModeContext();
35893595
var statements = parseSyntaxList<IStatementSyntax>(ListParsingState.Block_Statements, updateStrictModeState);
35903596
setStrictModeContext(savedIsInStrictMode);
35913597

35923598
return statements;
35933599
}
35943600

3595-
function parseCallSignature(requireCompleteTypeParameterList: boolean, _yieldContext: boolean, _generatorParameterContext: boolean): CallSignatureSyntax {
3601+
function parseCallSignature(requireCompleteTypeParameterList: boolean, yieldContext: boolean, generatorParameterContext: boolean): CallSignatureSyntax {
35963602
return new CallSignatureSyntax(contextFlags,
35973603
tryParseTypeParameterList(requireCompleteTypeParameterList),
3598-
parseParameterList(_yieldContext, _generatorParameterContext),
3604+
parseParameterList(yieldContext, generatorParameterContext),
35993605
parseOptionalTypeAnnotation(/*allowStringLiteral:*/ false));
36003606
}
36013607

@@ -3645,7 +3651,7 @@ module TypeScript.Parser {
36453651
return new ConstraintSyntax(contextFlags, eatToken(SyntaxKind.ExtendsKeyword), parseTypeOrExpression());
36463652
}
36473653

3648-
function parseParameterList(_yieldContext: boolean, _generatorParameterContext: boolean): ParameterListSyntax {
3654+
function parseParameterList(yieldContext: boolean, generatorParameterContext: boolean): ParameterListSyntax {
36493655
// FormalParameters[Yield,GeneratorParameter] :
36503656
// ...
36513657
//
@@ -3661,11 +3667,11 @@ module TypeScript.Parser {
36613667
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
36623668
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
36633669

3664-
var savedYieldContext = yieldContext;
3665-
var savedGeneratorParameterContext = generatorParameterContext;
3670+
var savedYieldContext = inYieldContext();
3671+
var savedGeneratorParameterContext = inGeneratorParameterContext();
36663672

3667-
setYieldContext(_yieldContext);
3668-
setGeneratorParameterContext(_generatorParameterContext);
3673+
setYieldContext(yieldContext);
3674+
setGeneratorParameterContext(generatorParameterContext);
36693675

36703676
var openParenToken: ISyntaxToken;
36713677
var result = new ParameterListSyntax(contextFlags,
@@ -3747,8 +3753,8 @@ module TypeScript.Parser {
37473753
function tryParseType(): ITypeSyntax {
37483754
// The rules about 'yield' only apply to actual code/expression contexts. They don't
37493755
// apply to 'type' contexts. So we disable these parameters here before moving on.
3750-
var savedYieldContext = yieldContext;
3751-
var savedGeneratorParameterContext = generatorParameterContext;
3756+
var savedYieldContext = inYieldContext();
3757+
var savedGeneratorParameterContext = inGeneratorParameterContext();
37523758

37533759
setYieldContext(false);
37543760
setGeneratorParameterContext(false);
@@ -3997,7 +4003,7 @@ module TypeScript.Parser {
39974003
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
39984004
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
39994005

4000-
var identifier = generatorParameterContext
4006+
var identifier = inGeneratorParameterContext()
40014007
? enterYieldContextAnd(eatIdentifierToken)
40024008
: eatIdentifierToken();
40034009

@@ -4006,7 +4012,7 @@ module TypeScript.Parser {
40064012

40074013
var equalsValueClause: EqualsValueClauseSyntax = undefined;
40084014
if (isEqualsValueClause(/*inParameter*/ true)) {
4009-
equalsValueClause = generatorParameterContext
4015+
equalsValueClause = inGeneratorParameterContext()
40104016
? exitYieldContextAnd(parseEqualsValueClause)
40114017
: parseEqualsValueClause();
40124018
}
@@ -4388,7 +4394,7 @@ module TypeScript.Parser {
43884394
}
43894395

43904396
function isExpectedVariableDeclaration_VariableDeclaratorsTerminator(): boolean {
4391-
if (disallowInContext) {
4397+
if (inDisallowInContext()) {
43924398
// This is the case when we're parsing variable declarations in a for/for-in statement.
43934399
var tokenKind = currentToken().kind;
43944400

0 commit comments

Comments
 (0)