Skip to content

Commit

Permalink
spreadLoop implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
wcjohnson committed Oct 7, 2017
1 parent 6e257e5 commit 26abf6e
Show file tree
Hide file tree
Showing 53 changed files with 5,605 additions and 4,706 deletions.
14 changes: 6 additions & 8 deletions src/parser/expression.js
Expand Up @@ -729,8 +729,8 @@ pp.parseExprAtom = function (refShorthandDefaultPos) {
if (this.state.inMatchAtom) {
this.unexpected(null, "Illegal expression in match atom.");
}
if (this.hasPlugin("splatComprehension")) {
return this.parseComprehensionArray(refShorthandDefaultPos);
if (this.hasPlugin("spreadLoop")) {
return this.parseArrayWithSpreadLoops(refShorthandDefaultPos);
}
node = this.startNode();
this.next();
Expand Down Expand Up @@ -1044,7 +1044,6 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
let decorators = [];
const propHash = Object.create(null);
let first = true;
let hasComprehension = false;
const node = this.startNode();

node.properties = [];
Expand All @@ -1064,12 +1063,11 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
if (this.eat(tt.braceR)) break;
}

if (this.hasPlugin("splatComprehension") && this.match(tt.splatComprehension)) {
if (this.hasPlugin("spreadLoop") && this.match(tt.spreadLoop)) {
if (isPattern) {
this.unexpected(null, "Comprehensions are illegal in patterns.");
this.unexpected(null, "Spread loops are illegal in patterns.");
}
node.properties.push(this.parseSomeComprehension());
hasComprehension = true;
node.properties.push(this.parseSpreadLoop("SpreadProperty"));
continue;
}

Expand Down Expand Up @@ -1154,7 +1152,7 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) {
this.raise(this.state.start, "You have trailing decorators with no property");
}

return this.finishNode(node, hasComprehension ? "ObjectComprehension" : (isPattern ? "ObjectPattern" : "ObjectExpression"));
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
};

pp.isGetterOrSetterMethod = function (prop, isPattern) {
Expand Down
77 changes: 0 additions & 77 deletions src/plugins/splatComprehension.js

This file was deleted.

55 changes: 55 additions & 0 deletions src/plugins/spreadLoop.js
@@ -0,0 +1,55 @@
import Parser from "../parser";
import { types as tt, TokenType } from "../tokenizer/types";
const pp = Parser.prototype;

export default function(parser) {
if (parser.__spreadLoopPluginInstalled) return;
parser.__spreadLoopPluginInstalled = true;

tt.spreadLoop = new TokenType("...for");

pp.parseArrayWithSpreadLoops = function(refShorthandDefaultPos) {
const node = this.startNode();
this.next();
this.parseArrayElementsWithSpreadLoops(node, refShorthandDefaultPos);
return this.finishNode(node, "ArrayExpression");
};

// c/p parseExprList
pp.parseArrayElementsWithSpreadLoops = function (node, refShorthandDefaultPos) {
const elts = [];
let first = true, hasSpreadLoop = false;

while (!this.eat(tt.bracketR)) {
if (first) {
first = false;
} else {
if (this.hasPlugin("lightscript")) {
this.expectCommaOrLineBreak();
} else {
this.expect(tt.comma);
}
if (this.eat(tt.bracketR)) break;
}

if (this.match(tt.spreadLoop) && this.state.value === "for") {
hasSpreadLoop = true;
elts.push(this.parseSpreadLoop("SpreadElement"));
} else {
elts.push(this.parseExprListItem(true, refShorthandDefaultPos));
}
}

node.elements = elts;
return hasSpreadLoop;
};

pp.parseSpreadLoop = function(spreadElementType) {
const spreadElement = this.startNode();
const spreadLoop = this.startNode();
const loop = this.startNode();
spreadLoop.loop = this.parseForStatement(loop);
spreadElement.argument = this.finishNode(spreadLoop, "SpreadLoop");
return this.finishNode(spreadElement, spreadElementType);
};
}
9 changes: 2 additions & 7 deletions src/registerPlugins.js
Expand Up @@ -6,7 +6,7 @@ import tildeCallPlugin from "./plugins/tildeCall";
import safeCallExistentialPlugin from "./plugins/safeCallExistential";
import bangCallPlugin from "./plugins/bangCall";
import significantWhitespacePlugin from "./plugins/significantWhitespace";
import splatComprehensionPlugin from "./plugins/splatComprehension";
import spreadLoopPlugin from "./plugins/spreadLoop";
import syntacticPlaceholderPlugin from "./plugins/syntacticPlaceholder";
import { matchCoreSyntax, match } from "./plugins/match";

Expand Down Expand Up @@ -76,12 +76,7 @@ export default function registerPlugins(plugins, metadata) {
dependencies: ["lightscript", "matchCoreSyntax"]
});

registerPlugin("splatComprehension", splatComprehensionPlugin, {
dependencies: [
"lightscript", // needed for `parseIf`
"seqExprRequiresParen"
]
});
registerPlugin("spreadLoop", spreadLoopPlugin);

// Parse identifiers beginning with `_` or another user-chosen symbol
// as PlaceholderExpressions.
Expand Down
11 changes: 4 additions & 7 deletions src/tokenizer/index.js
Expand Up @@ -282,23 +282,20 @@ export default class Tokenizer {
const next2 = this.input.charCodeAt(this.state.pos + 2);
if (next === 46 && next2 === 46) { // 46 = dot '.'
this.state.pos += 3;
// splatComprehension: parse ...for and ...if
if (this.hasPlugin("splatComprehension")) {
// spreadLoop: parse ...for
if (this.hasPlugin("spreadLoop")) {
const next3 = this.input.charCodeAt(this.state.pos);
const next4 = this.input.charCodeAt(this.state.pos + 1);
const next5 = this.input.charCodeAt(this.state.pos + 2);
// "...if"
if (next3 === 105 && next4 === 102 && !isIdentifierChar(next5)) {
this.state.pos += 2;
return this.finishToken(tt.splatComprehension, "if");
} else if ( // "...for"
if ( // "...for"
next3 === 102 &&
next4 === 111 &&
next5 === 114 &&
!isIdentifierChar(this.input.charCodeAt(this.state.pos + 3))
) {
this.state.pos += 3;
return this.finishToken(tt.splatComprehension, "for");
return this.finishToken(tt.spreadLoop, "for");
}
}
return this.finishToken(tt.ellipsis);
Expand Down

0 comments on commit 26abf6e

Please sign in to comment.