Skip to content

Commit

Permalink
feature: goldstein: add-array: add
Browse files Browse the repository at this point in the history
  • Loading branch information
coderaiser committed Oct 19, 2023
1 parent 6f342dc commit 924f182
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/nodejs-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
- 16.x
- 18.x
- 20.x
- 21.x
steps:
- uses: actions/checkout@v3
- uses: oven-sh/setup-bun@v1
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ jobs:
- 16.x
- 18.x
- 20.x
- 21.x
steps:
- uses: actions/checkout@v3
with:
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,22 @@ function hello() {
}
```


### `append array`

```swift
const a = [1];

a += [2, 3];
```

Is the same as:

```js
const a = [1];
a.push(...[2, 3]);
```

### `guard`

Applies not to `IfCondition`:
Expand Down
15 changes: 15 additions & 0 deletions packages/goldstein/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,21 @@ test('goldstein: parse: if', (t) => {
t.end();
});

test('goldstein: parse: append array', (t) => {
const result = compile(montag`
const a = [1];
a += [2, 3];
`);

const expected = montag`
const a = [1];
a.push(...[2, 3]);\n
`;

t.equal(result, expected);
t.end();
});

test('goldstein: parse: import', (t) => {
const result = compile(montag`
import hello from './hello.gs';
Expand Down
2 changes: 2 additions & 0 deletions packages/goldstein/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import keywordFreeze from '../keyword-freeze/index.js';
import keywordIf from '../keyword-if/index.js';
import keywordImport from '../keyword-import/index.js';
import keywordArrow from '../keyword-arrow/index.js';
import keywordAddArray from '../keyword-add-array/index.js';

const defaultKeywords = {
keywordFn,
Expand All @@ -23,6 +24,7 @@ const defaultKeywords = {
keywordIf,
keywordImport,
keywordArrow,
keywordAddArray,
stringInterpolation,
};

Expand Down
1 change: 1 addition & 0 deletions packages/keyword-add-array/fixture/add-array.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a += [1, 2, 3];
1 change: 1 addition & 0 deletions packages/keyword-add-array/fixture/add-array.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a.push(...[1, 2, 3]);
121 changes: 121 additions & 0 deletions packages/keyword-add-array/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import {types} from 'putout';
import {tokTypes as tt} from 'acorn';
import {DestructuringErrors} from '../operator/index.js';

const {assign} = Object;

const {
identifier,
isArrayExpression,
memberExpression,
spreadElement,
} = types;

export default function keywordAddArray(Parser) {
return class extends Parser {
parseMaybeAssign(forInit, refDestructuringErrors, afterLeftParse) {
if (this.isContextual('yield')) {
if (this.inGenerator) {
return this.parseYield(forInit);
}

// The tokenizer will assume an expression is allowed after
// `yield`, but this isn't that kind of yield
this.exprAllowed = false;
}

let ownDestructuringErrors = false;
let oldParenAssign = -1;
let oldTrailingComma = -1;
let oldDoubleProto = -1;

if (refDestructuringErrors) {
oldParenAssign = refDestructuringErrors.parenthesizedAssign;
oldTrailingComma = refDestructuringErrors.trailingComma;
oldDoubleProto = refDestructuringErrors.doubleProto;
refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
} else {
refDestructuringErrors = new DestructuringErrors();
ownDestructuringErrors = true;
}

const startPos = this.start;
const {startLoc} = this;

if (this.type === tt.parenL || this.type === tt.name) {
this.potentialArrowAt = this.start;
this.potentialArrowInForAwait = forInit === 'await';
}

let left = this.parseMaybeConditional(forInit, refDestructuringErrors);

if (afterLeftParse) {
left = afterLeftParse.call(this, left, startPos, startLoc);
}

if (this.type.isAssign) {
const node = this.startNodeAt(startPos, startLoc);

node.operator = this.value;

if (this.type === tt.eq) {
left = this.toAssignable(left, false, refDestructuringErrors);
}

if (!ownDestructuringErrors) {
refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
}

if (refDestructuringErrors.shorthandAssign >= left.start) {
refDestructuringErrors.shorthandAssign = -1;
}

// reset because shorthand default was used correctly
if (this.type === tt.eq) {
this.checkLValPattern(left);
} else {
this.checkLValSimple(left);
}

node.left = left;
this.next();
node.right = this.parseMaybeAssign(forInit);

if (oldDoubleProto > -1) {
refDestructuringErrors.doubleProto = oldDoubleProto;
}

if (node.operator === '+=' && isArrayExpression(node.right))
return createAppendNode(this, node);

return this.finishNode(node, 'AssignmentExpression');
}

if (ownDestructuringErrors) {
this.checkExpressionErrors(refDestructuringErrors, true);
}

if (oldParenAssign > -1) {
refDestructuringErrors.parenthesizedAssign = oldParenAssign;
}

if (oldTrailingComma > -1) {
refDestructuringErrors.trailingComma = oldTrailingComma;
}

return left;
}
};
}

function createAppendNode(context, node) {
const {left, right} = node;

assign(node, {
a: 'x',
callee: memberExpression(left, identifier('push')),
arguments: [spreadElement(right)],
});

return context.finishNode(node, 'CallExpression');
}
9 changes: 9 additions & 0 deletions packages/keyword-add-array/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {createTest} from '../test/index.js';
import keywordFn from './index.js';

const test = createTest(import.meta.url, keywordFn);

test('goldstein: keyword: add-array', (t) => {
t.compile('add-array');
t.end();
});
7 changes: 7 additions & 0 deletions packages/operator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@ export function addKeyword(keyword, keywords) {
return RegExp(str);
}

export class DestructuringErrors {
shorthandAssign = -1;
trailingComma = -1;
parenthesizedAssign = -1;
parenthesizedBind = -1;
doubleProto = -1;
}

0 comments on commit 924f182

Please sign in to comment.