jashkenas--coffeescript/lib/coffeescript/grammar.js

862 lines
28 KiB
JavaScript
Raw Normal View History

2.0.0-beta3 (#4594) * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * Correct comment * object destructuring * Allow custom position of the rest element. * Output simple array destructuring assignments to ES2015 * Output simple object destructured assignments to ES2015 * Compile shorthand object properties to ES2015 shorthand properties This dramatically improves the appearance of destructured imports. * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * object destructuring * Allow custom position of the rest element. * rest element in object destructuring * rest element in object destructuring * fix string interpolation * merging * fixing splats in object literal * Rest element in parameter destructuring * merging with CS2 * merged with CS2 * Add support for the object spread initializer. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md * Fix misspellings, trailing whitespace, other minor details * merging with beta2 * refactor object spread properties * small fix * - Fixed object spread function parameters. - Clean up "Assign" and moved all logic for object rest properties in single method (compileObjectDestruct). - Add helper function "objectWithoutKeys" to the "UTILITIES" for use with object rest properties, e.g. {a, b, r...} = obj => {a, b} = obj, r = objectWithoutKeys(...) - Clean up "Obj" and moved all logic for object spread properties in single method (compileSpread). - Clean up "Code". - Add method "hasSplat" to "Obj" and "Value" for checking if Obj contains the splat. - Enable placing spread syntax triple dots on either right or left, per #85 (https://github.com/coffeescript6/discuss/issues/85) * Fixed typos * Remove unused code * Removed dots (e.g. splat) on the left side from the grammar * Initial release for deep spread properties, e.g. obj2 = {obj.b..., a: 1} or {obj[b][c]..., d: 7} Tests need to be prepared! * 1. Object literal spread properties Object literals: - obj = { {b:{c:{d:1}}}..., a:1 } Parenthetical: - obj = { ( body ), a:1 } - obj = { ( body )..., a:1 } Invocation: - obj = { ( (args) -> ... )(params), a:1 } - obj = { ( (args) -> ... )(params)..., a:1 } - obj = { foo(), a:1 } - obj = { foo()..., a:1 } 2. Refactor, cleanup & other optimizations. * Merged with 2.0 * Cleanup * Some more cleanup. * Fixed error with freeVariable and object destructuring. * Fixed errors with object spread properties. * Improvements, fixed errors. * Minor improvement. * Minor improvements. * Typo. * Remove unnecessary whitespace. * Remove unnecessary whitespace. * Changed few "assertErrorFormat" tests since parentheses are now allowed in the Obj. * Whitespace cleanup * Comments cleanup * fix destructured obj param declarations * refine fix; add test * Refactor function args ({a, b...}) * Additional tests for object destructuring in function argument. * Minor improvement for object destructuring variable declaration. * refactor function args ({a, b...}) and ({a, b...} = {}); Obj And Param cleanup * fix comment * Fix object destructuring variable declaration. * more tests with default values * fix typo * Fixed default values in object destructuring. * small fix * Babel’s tests for object rest spread * Style: spaces after colons in object declarations * Cleanup comments * Simplify Babel tests * Fix comments * Fix destructuring with splats in multiple objects * Add test for default values in detsructuring assignment with splats * Handle default values when assigning to object splats * Rewrite traverseRest to fix handling of dynamic keys * Fix double parens around destructuring with splats * Update compileObjectDestruct comments * Improve formatting of top-level destructures with splats and tidy parens * Added a bigger destructuring-with-defaults test and fixed a bug * Refactor destructuring grammar to allow additional forms * Add a missing case to ObjSpreadExpr * These tests shouldn’t run in the browser * Fix test.html * Fix docs scroll position getting screwed up by CodeMirror initialization * Breaking change documentation about => (fixes #4593) * Spread/rest syntax documentation * Documentation about bound class methods * 2.0.0-beta3 changelog * Add note about ‘lib’ * Fix accidentally converting this to tabs * Bump version to 2.0.0-beta3 * Update annotated source and test.html
2017-06-30 16:58:05 +00:00
// Generated by CoffeeScript 2.0.0-beta3
2010-07-25 07:15:12 +00:00
(function() {
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
[CS2] Destructuring (#4478) * Output simple array destructuring assignments to ES2015 * Output simple object destructured assignments to ES2015 * Compile shorthand object properties to ES2015 shorthand properties This dramatically improves the appearance of destructured imports. * Compile default values in destructured assignment to ES2015 * Rename `wrapInBraces` to `wrapInParentheses`, and `compilePatternMatch` to `compileDestructuring`, for clarity; style improvements (no `==` or `!=`, etc.) * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Optional check for existence that only checks `!== undefined`, not `!= null`, to follow ES convention that default values only apply when a variable is undefined, not falsy * Add comments; remove unnecessary array splats in function tests * The fallback destructuring code should apply default values only if `undefined`, not falsy, to follow ES spec * Support destructuring in function parameters (first pass); catch destructured reserved words * Destructured variables in function parameter lists shouldn’t be added to the function body with `var` declarations; treat splat array function parameters the legacy way to avoid rethinking #4005 * Remove redundancy in undefined-only check for existence; fix passing option to check * Fix undefined redundancy * Simplify getting the variable name * Reimplement “check for existence if not undefined” without creating a new operator * `Obj::isAssignable` should not mutate; pass `lhs` property in from `Assign` or `Code` to child arrays and objects so that those child nodes are set as allowable for destructuring * Revert changes to tests * Restore revised test for empty destructuring assignment
2017-04-06 17:06:45 +00:00
({Parser} = require('jison'));
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
o = function(patternString, action, options) {
var addLocationDataFn, match, patternCount;
patternString = patternString.replace(/\s{2,}/g, ' ');
patternCount = patternString.split(' ').length;
2012-04-10 18:57:45 +00:00
if (!action) {
return [patternString, '$$ = $1;', options];
}
action = (match = unwrap.exec(action)) ? match[1] : `(${action}())`;
action = action.replace(/\bnew /g, '$&yy.');
2011-01-15 19:19:35 +00:00
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
addLocationDataFn = function(first, last) {
if (!last) {
return `yy.addLocationDataFn(@${first})`;
} else {
return `yy.addLocationDataFn(@${first}, @${last})`;
}
};
action = action.replace(/LOC\(([0-9]*)\)/g, addLocationDataFn('$1'));
action = action.replace(/LOC\(([0-9]*),\s*([0-9]*)\)/g, addLocationDataFn('$1', '$2'));
return [patternString, `$$ = ${addLocationDataFn(1, patternCount)}(${action});`, options];
2010-02-11 04:24:05 +00:00
};
2010-02-11 04:24:05 +00:00
grammar = {
Root: [
o('', function() {
2011-01-15 19:19:35 +00:00
return new Block;
}), o('Body')
2010-02-11 04:24:05 +00:00
],
Body: [
o('Line', function() {
2011-01-15 19:19:35 +00:00
return Block.wrap([$1]);
}), o('Body TERMINATOR Line', function() {
2010-02-11 04:24:05 +00:00
return $1.push($3);
}), o('Body TERMINATOR')
2010-04-05 14:26:23 +00:00
],
Line: [o('Expression'), o('Statement'), o('FuncDirective')],
FuncDirective: [o('YieldReturn'), o('AwaitReturn')],
Statement: [
o('Return'), o('Comment'), o('STATEMENT', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new StatementLiteral($1);
Support import and export of ES2015 modules (#4300) This pull request adds support for ES2015 modules, by recognizing `import` and `export` statements. The following syntaxes are supported, based on the MDN [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) pages: ```js import "module-name" import defaultMember from "module-name" import * as name from "module-name" import { } from "module-name" import { member } from "module-name" import { member as alias } from "module-name" import { member1, member2 as alias2, … } from "module-name" import defaultMember, * as name from "module-name" import defaultMember, { … } from "module-name" export default expression export class name export { } export { name } export { name as exportedName } export { name as default } export { name1, name2 as exportedName2, name3 as default, … } export * from "module-name" export { … } from "module-name" ``` As a subsitute for ECMAScript’s `export var name = …` and `export function name {}`, CoffeeScript also supports: ```js export name = … ``` CoffeeScript also supports optional commas within `{ … }`. This PR converts the supported `import` and `export` statements into ES2015 `import` and `export` statements; it **does not resolve the modules**. So any CoffeeScript with `import` or `export` statements will be output as ES2015, and will need to be transpiled by another tool such as Babel before it can be used in a browser. We will need to add a warning to the documentation explaining this. This should be fully backwards-compatible, as `import` and `export` were previously reserved keywords. No flags are used. There are extensive tests included, though because no current JavaScript runtime supports `import` or `export`, the tests compare strings of what the compiled CoffeeScript output is against what the expected ES2015 should be. I also conducted two more elaborate tests: * I forked the [ember-piqu](https://github.com/pauc/piqu-ember) project, which was an Ember CLI app that used ember-cli-coffeescript and [ember-cli-coffees6](https://github.com/alexspeller/ember-cli-coffees6) (which adds “support” for `import`/`export` by wrapping such statements in backticks before passing the result to the CoffeeScript compiler). I removed `ember-cli-coffees6` and replaced the CoffeeScript compiler used in the build chain with this code, and the app built without errors. [Demo here.](https://github.com/GeoffreyBooth/coffeescript-modules-test-piqu) * I also forked the [CoffeeScript version of Meteor’s Todos example app](https://github.com/meteor/todos/tree/coffeescript), and replaced all of its `require` statements with the `import` and `export` statements from the original ES2015 version of the app on its `master` branch. I then updated the `coffeescript` Meteor package in the app to use this new code, and again the app builds without errors. [Demo here.](https://github.com/GeoffreyBooth/coffeescript-modules-test-meteor-todos) The discussion history for this work started [here](https://github.com/jashkenas/coffeescript/pull/4160) and continued [here](https://github.com/GeoffreyBooth/coffeescript/pull/2). @lydell provided guidance, and @JimPanic and @rattrayalex contributed essential code.
2016-09-14 18:46:05 +00:00
}), o('Import'), o('Export')
2010-02-11 04:24:05 +00:00
],
Expression: [o('Value'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw'), o('Yield')],
Yield: [
o('YIELD', function() {
return new Op($1, new Value(new Literal('')));
}), o('YIELD Expression', function() {
return new Op($1, $2);
}), o('YIELD FROM Expression', function() {
return new Op($1.concat($2), $3);
})
],
Block: [
o('INDENT OUTDENT', function() {
2011-01-15 19:19:35 +00:00
return new Block;
}), o('INDENT Body OUTDENT', function() {
2010-02-11 04:24:05 +00:00
return $2;
})
],
Identifier: [
o('IDENTIFIER', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new IdentifierLiteral($1);
}), o('CSX_TAG', function() {
return new CSXTag($1);
2010-02-11 04:24:05 +00:00
})
],
Property: [
o('PROPERTY', function() {
return new PropertyName($1);
})
],
AlphaNumeric: [
o('NUMBER', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new NumberLiteral($1);
2015-02-07 19:16:59 +00:00
}), o('String')
],
String: [
o('STRING', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new StringLiteral($1);
2015-02-07 19:16:59 +00:00
}), o('STRING_START Body STRING_END', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new StringWithInterpolations($2);
2015-02-07 19:16:59 +00:00
})
],
Regex: [
o('REGEX', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new RegexLiteral($1);
2015-02-07 19:16:59 +00:00
}), o('REGEX_START Invocation REGEX_END', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new RegexWithInterpolations($2.args);
2010-02-11 04:24:05 +00:00
})
],
Literal: [
o('AlphaNumeric'), o('JS', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new PassthroughLiteral($1);
}), o('Regex'), o('UNDEFINED', function() {
return new UndefinedLiteral;
}), o('NULL', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new NullLiteral;
}), o('BOOL', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new BooleanLiteral($1);
}), o('INFINITY', function() {
return new InfinityLiteral($1);
}), o('NAN', function() {
return new NaNLiteral;
2010-02-11 04:24:05 +00:00
})
],
Assign: [
o('Assignable = Expression', function() {
return new Assign($1, $3);
2011-12-14 23:31:20 +00:00
}), o('Assignable = TERMINATOR Expression', function() {
return new Assign($1, $4);
}), o('Assignable = INDENT Expression OUTDENT', function() {
return new Assign($1, $4);
2010-02-11 04:24:05 +00:00
})
],
AssignObj: [
2010-10-24 05:05:31 +00:00
o('ObjAssignable', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
[CS2] Destructuring object spreads (#4493) * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * Correct comment * object destructuring * Allow custom position of the rest element. * Output simple array destructuring assignments to ES2015 * Output simple object destructured assignments to ES2015 * Compile shorthand object properties to ES2015 shorthand properties This dramatically improves the appearance of destructured imports. * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * object destructuring * Allow custom position of the rest element. * rest element in object destructuring * rest element in object destructuring * fix string interpolation * merging * fixing splats in object literal * Rest element in parameter destructuring * merging with CS2 * merged with CS2 * Add support for the object spread initializer. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md * Fix misspellings, trailing whitespace, other minor details * merging with beta2 * refactor object spread properties * small fix * - Fixed object spread function parameters. - Clean up "Assign" and moved all logic for object rest properties in single method (compileObjectDestruct). - Add helper function "objectWithoutKeys" to the "UTILITIES" for use with object rest properties, e.g. {a, b, r...} = obj => {a, b} = obj, r = objectWithoutKeys(...) - Clean up "Obj" and moved all logic for object spread properties in single method (compileSpread). - Clean up "Code". - Add method "hasSplat" to "Obj" and "Value" for checking if Obj contains the splat. - Enable placing spread syntax triple dots on either right or left, per #85 (https://github.com/coffeescript6/discuss/issues/85) * Fixed typos * Remove unused code * Removed dots (e.g. splat) on the left side from the grammar * Initial release for deep spread properties, e.g. obj2 = {obj.b..., a: 1} or {obj[b][c]..., d: 7} Tests need to be prepared! * 1. Object literal spread properties Object literals: - obj = { {b:{c:{d:1}}}..., a:1 } Parenthetical: - obj = { ( body ), a:1 } - obj = { ( body )..., a:1 } Invocation: - obj = { ( (args) -> ... )(params), a:1 } - obj = { ( (args) -> ... )(params)..., a:1 } - obj = { foo(), a:1 } - obj = { foo()..., a:1 } 2. Refactor, cleanup & other optimizations. * Merged with 2.0 * Cleanup * Some more cleanup. * Fixed error with freeVariable and object destructuring. * Fixed errors with object spread properties. * Improvements, fixed errors. * Minor improvement. * Minor improvements. * Typo. * Remove unnecessary whitespace. * Remove unnecessary whitespace. * Changed few "assertErrorFormat" tests since parentheses are now allowed in the Obj. * Whitespace cleanup * Comments cleanup * fix destructured obj param declarations * refine fix; add test * Refactor function args ({a, b...}) * Additional tests for object destructuring in function argument. * Minor improvement for object destructuring variable declaration. * refactor function args ({a, b...}) and ({a, b...} = {}); Obj And Param cleanup * fix comment * Fix object destructuring variable declaration. * more tests with default values * fix typo * Fixed default values in object destructuring. * small fix * Babel’s tests for object rest spread * Style: spaces after colons in object declarations * Cleanup comments * Simplify Babel tests * Fix comments * Fix destructuring with splats in multiple objects * Add test for default values in detsructuring assignment with splats * Handle default values when assigning to object splats * Rewrite traverseRest to fix handling of dynamic keys * Fix double parens around destructuring with splats * Update compileObjectDestruct comments * Improve formatting of top-level destructures with splats and tidy parens * Added a bigger destructuring-with-defaults test and fixed a bug * Refactor destructuring grammar to allow additional forms * Add a missing case to ObjSpreadExpr * These tests shouldn’t run in the browser * Fix test.html
2017-06-30 05:57:42 +00:00
}), o('ObjRestValue'), o('ObjAssignable : Expression', function() {
return new Assign(LOC(1)(new Value($1)), $3, 'object', {
operatorToken: LOC(2)(new Literal($2))
});
2013-11-18 04:32:15 +00:00
}), o('ObjAssignable : INDENT Expression OUTDENT', function() {
return new Assign(LOC(1)(new Value($1)), $4, 'object', {
operatorToken: LOC(2)(new Literal($2))
});
}), o('SimpleObjAssignable = Expression', function() {
return new Assign(LOC(1)(new Value($1)), $3, null, {
operatorToken: LOC(2)(new Literal($2))
});
}), o('SimpleObjAssignable = INDENT Expression OUTDENT', function() {
return new Assign(LOC(1)(new Value($1)), $4, null, {
operatorToken: LOC(2)(new Literal($2))
});
}), o('Comment')
2010-02-11 04:24:05 +00:00
],
SimpleObjAssignable: [o('Identifier'), o('Property'), o('ThisProperty')],
ObjAssignable: [o('SimpleObjAssignable'), o('AlphaNumeric')],
[CS2] Destructuring object spreads (#4493) * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * Correct comment * object destructuring * Allow custom position of the rest element. * Output simple array destructuring assignments to ES2015 * Output simple object destructured assignments to ES2015 * Compile shorthand object properties to ES2015 shorthand properties This dramatically improves the appearance of destructured imports. * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * object destructuring * Allow custom position of the rest element. * rest element in object destructuring * rest element in object destructuring * fix string interpolation * merging * fixing splats in object literal * Rest element in parameter destructuring * merging with CS2 * merged with CS2 * Add support for the object spread initializer. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md * Fix misspellings, trailing whitespace, other minor details * merging with beta2 * refactor object spread properties * small fix * - Fixed object spread function parameters. - Clean up "Assign" and moved all logic for object rest properties in single method (compileObjectDestruct). - Add helper function "objectWithoutKeys" to the "UTILITIES" for use with object rest properties, e.g. {a, b, r...} = obj => {a, b} = obj, r = objectWithoutKeys(...) - Clean up "Obj" and moved all logic for object spread properties in single method (compileSpread). - Clean up "Code". - Add method "hasSplat" to "Obj" and "Value" for checking if Obj contains the splat. - Enable placing spread syntax triple dots on either right or left, per #85 (https://github.com/coffeescript6/discuss/issues/85) * Fixed typos * Remove unused code * Removed dots (e.g. splat) on the left side from the grammar * Initial release for deep spread properties, e.g. obj2 = {obj.b..., a: 1} or {obj[b][c]..., d: 7} Tests need to be prepared! * 1. Object literal spread properties Object literals: - obj = { {b:{c:{d:1}}}..., a:1 } Parenthetical: - obj = { ( body ), a:1 } - obj = { ( body )..., a:1 } Invocation: - obj = { ( (args) -> ... )(params), a:1 } - obj = { ( (args) -> ... )(params)..., a:1 } - obj = { foo(), a:1 } - obj = { foo()..., a:1 } 2. Refactor, cleanup & other optimizations. * Merged with 2.0 * Cleanup * Some more cleanup. * Fixed error with freeVariable and object destructuring. * Fixed errors with object spread properties. * Improvements, fixed errors. * Minor improvement. * Minor improvements. * Typo. * Remove unnecessary whitespace. * Remove unnecessary whitespace. * Changed few "assertErrorFormat" tests since parentheses are now allowed in the Obj. * Whitespace cleanup * Comments cleanup * fix destructured obj param declarations * refine fix; add test * Refactor function args ({a, b...}) * Additional tests for object destructuring in function argument. * Minor improvement for object destructuring variable declaration. * refactor function args ({a, b...}) and ({a, b...} = {}); Obj And Param cleanup * fix comment * Fix object destructuring variable declaration. * more tests with default values * fix typo * Fixed default values in object destructuring. * small fix * Babel’s tests for object rest spread * Style: spaces after colons in object declarations * Cleanup comments * Simplify Babel tests * Fix comments * Fix destructuring with splats in multiple objects * Add test for default values in detsructuring assignment with splats * Handle default values when assigning to object splats * Rewrite traverseRest to fix handling of dynamic keys * Fix double parens around destructuring with splats * Update compileObjectDestruct comments * Improve formatting of top-level destructures with splats and tidy parens * Added a bigger destructuring-with-defaults test and fixed a bug * Refactor destructuring grammar to allow additional forms * Add a missing case to ObjSpreadExpr * These tests shouldn’t run in the browser * Fix test.html
2017-06-30 05:57:42 +00:00
ObjRestValue: [
o('SimpleObjAssignable ...', function() {
return new Splat(new Value($1));
}), o('... SimpleObjAssignable', function() {
return new Splat(new Value($2));
[CS2] Destructuring object spreads (#4493) * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * Correct comment * object destructuring * Allow custom position of the rest element. * Output simple array destructuring assignments to ES2015 * Output simple object destructured assignments to ES2015 * Compile shorthand object properties to ES2015 shorthand properties This dramatically improves the appearance of destructured imports. * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * object destructuring * Allow custom position of the rest element. * rest element in object destructuring * rest element in object destructuring * fix string interpolation * merging * fixing splats in object literal * Rest element in parameter destructuring * merging with CS2 * merged with CS2 * Add support for the object spread initializer. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md * Fix misspellings, trailing whitespace, other minor details * merging with beta2 * refactor object spread properties * small fix * - Fixed object spread function parameters. - Clean up "Assign" and moved all logic for object rest properties in single method (compileObjectDestruct). - Add helper function "objectWithoutKeys" to the "UTILITIES" for use with object rest properties, e.g. {a, b, r...} = obj => {a, b} = obj, r = objectWithoutKeys(...) - Clean up "Obj" and moved all logic for object spread properties in single method (compileSpread). - Clean up "Code". - Add method "hasSplat" to "Obj" and "Value" for checking if Obj contains the splat. - Enable placing spread syntax triple dots on either right or left, per #85 (https://github.com/coffeescript6/discuss/issues/85) * Fixed typos * Remove unused code * Removed dots (e.g. splat) on the left side from the grammar * Initial release for deep spread properties, e.g. obj2 = {obj.b..., a: 1} or {obj[b][c]..., d: 7} Tests need to be prepared! * 1. Object literal spread properties Object literals: - obj = { {b:{c:{d:1}}}..., a:1 } Parenthetical: - obj = { ( body ), a:1 } - obj = { ( body )..., a:1 } Invocation: - obj = { ( (args) -> ... )(params), a:1 } - obj = { ( (args) -> ... )(params)..., a:1 } - obj = { foo(), a:1 } - obj = { foo()..., a:1 } 2. Refactor, cleanup & other optimizations. * Merged with 2.0 * Cleanup * Some more cleanup. * Fixed error with freeVariable and object destructuring. * Fixed errors with object spread properties. * Improvements, fixed errors. * Minor improvement. * Minor improvements. * Typo. * Remove unnecessary whitespace. * Remove unnecessary whitespace. * Changed few "assertErrorFormat" tests since parentheses are now allowed in the Obj. * Whitespace cleanup * Comments cleanup * fix destructured obj param declarations * refine fix; add test * Refactor function args ({a, b...}) * Additional tests for object destructuring in function argument. * Minor improvement for object destructuring variable declaration. * refactor function args ({a, b...}) and ({a, b...} = {}); Obj And Param cleanup * fix comment * Fix object destructuring variable declaration. * more tests with default values * fix typo * Fixed default values in object destructuring. * small fix * Babel’s tests for object rest spread * Style: spaces after colons in object declarations * Cleanup comments * Simplify Babel tests * Fix comments * Fix destructuring with splats in multiple objects * Add test for default values in detsructuring assignment with splats * Handle default values when assigning to object splats * Rewrite traverseRest to fix handling of dynamic keys * Fix double parens around destructuring with splats * Update compileObjectDestruct comments * Improve formatting of top-level destructures with splats and tidy parens * Added a bigger destructuring-with-defaults test and fixed a bug * Refactor destructuring grammar to allow additional forms * Add a missing case to ObjSpreadExpr * These tests shouldn’t run in the browser * Fix test.html
2017-06-30 05:57:42 +00:00
}), o('ObjSpreadExpr ...', function() {
return new Splat($1);
}), o('... ObjSpreadExpr', function() {
return new Splat($2);
[CS2] Destructuring object spreads (#4493) * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * Correct comment * object destructuring * Allow custom position of the rest element. * Output simple array destructuring assignments to ES2015 * Output simple object destructured assignments to ES2015 * Compile shorthand object properties to ES2015 shorthand properties This dramatically improves the appearance of destructured imports. * Don’t confuse the syntax highlighter * Comment Assign::compilePatternMatch a bit * Assignment expressions in conditionals are a bad practice * Rename `wrapInBraces` to `wrapInParentheses`, to set the stage for future `wrapInBraces` that uses `{` and `wrapInBrackets` that uses `[` * object destructuring * Allow custom position of the rest element. * rest element in object destructuring * rest element in object destructuring * fix string interpolation * merging * fixing splats in object literal * Rest element in parameter destructuring * merging with CS2 * merged with CS2 * Add support for the object spread initializer. https://github.com/tc39/proposal-object-rest-spread/blob/master/Spread.md * Fix misspellings, trailing whitespace, other minor details * merging with beta2 * refactor object spread properties * small fix * - Fixed object spread function parameters. - Clean up "Assign" and moved all logic for object rest properties in single method (compileObjectDestruct). - Add helper function "objectWithoutKeys" to the "UTILITIES" for use with object rest properties, e.g. {a, b, r...} = obj => {a, b} = obj, r = objectWithoutKeys(...) - Clean up "Obj" and moved all logic for object spread properties in single method (compileSpread). - Clean up "Code". - Add method "hasSplat" to "Obj" and "Value" for checking if Obj contains the splat. - Enable placing spread syntax triple dots on either right or left, per #85 (https://github.com/coffeescript6/discuss/issues/85) * Fixed typos * Remove unused code * Removed dots (e.g. splat) on the left side from the grammar * Initial release for deep spread properties, e.g. obj2 = {obj.b..., a: 1} or {obj[b][c]..., d: 7} Tests need to be prepared! * 1. Object literal spread properties Object literals: - obj = { {b:{c:{d:1}}}..., a:1 } Parenthetical: - obj = { ( body ), a:1 } - obj = { ( body )..., a:1 } Invocation: - obj = { ( (args) -> ... )(params), a:1 } - obj = { ( (args) -> ... )(params)..., a:1 } - obj = { foo(), a:1 } - obj = { foo()..., a:1 } 2. Refactor, cleanup & other optimizations. * Merged with 2.0 * Cleanup * Some more cleanup. * Fixed error with freeVariable and object destructuring. * Fixed errors with object spread properties. * Improvements, fixed errors. * Minor improvement. * Minor improvements. * Typo. * Remove unnecessary whitespace. * Remove unnecessary whitespace. * Changed few "assertErrorFormat" tests since parentheses are now allowed in the Obj. * Whitespace cleanup * Comments cleanup * fix destructured obj param declarations * refine fix; add test * Refactor function args ({a, b...}) * Additional tests for object destructuring in function argument. * Minor improvement for object destructuring variable declaration. * refactor function args ({a, b...}) and ({a, b...} = {}); Obj And Param cleanup * fix comment * Fix object destructuring variable declaration. * more tests with default values * fix typo * Fixed default values in object destructuring. * small fix * Babel’s tests for object rest spread * Style: spaces after colons in object declarations * Cleanup comments * Simplify Babel tests * Fix comments * Fix destructuring with splats in multiple objects * Add test for default values in detsructuring assignment with splats * Handle default values when assigning to object splats * Rewrite traverseRest to fix handling of dynamic keys * Fix double parens around destructuring with splats * Update compileObjectDestruct comments * Improve formatting of top-level destructures with splats and tidy parens * Added a bigger destructuring-with-defaults test and fixed a bug * Refactor destructuring grammar to allow additional forms * Add a missing case to ObjSpreadExpr * These tests shouldn’t run in the browser * Fix test.html
2017-06-30 05:57:42 +00:00
})
],
ObjSpreadExpr: [
o('ObjSpreadIdentifier'), o('Object'), o('Parenthetical'), o('Super'), o('This'), o('SUPER Arguments', function() {
return new SuperCall(LOC(1)(new Super), $2);
}), o('SimpleObjAssignable Arguments', function() {
return new Call(new Value($1), $2);
}), o('ObjSpreadExpr Arguments', function() {
return new Call($1, $2);
})
],
ObjSpreadIdentifier: [
o('SimpleObjAssignable . Property', function() {
return (new Value($1)).add(new Access($3));
}), o('SimpleObjAssignable INDEX_START IndexValue INDEX_END', function() {
return (new Value($1)).add($3);
})
],
Return: [
o('RETURN Expression', function() {
return new Return($2);
}), o('RETURN INDENT Object OUTDENT', function() {
return new Return(new Value($3));
}), o('RETURN', function() {
return new Return;
2010-02-11 04:24:05 +00:00
})
],
YieldReturn: [
o('YIELD RETURN Expression', function() {
return new YieldReturn($3);
}), o('YIELD RETURN', function() {
return new YieldReturn;
})
],
AwaitReturn: [
o('AWAIT RETURN Expression', function() {
return new AwaitReturn($3);
}), o('AWAIT RETURN', function() {
return new AwaitReturn;
})
],
Comment: [
o('HERECOMMENT', function() {
return new Comment($1);
})
],
Code: [
o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() {
return new Code($2, $5, $4);
}), o('FuncGlyph Block', function() {
return new Code([], $2, $1);
2010-02-11 04:24:05 +00:00
})
],
FuncGlyph: [
o('->', function() {
2010-02-11 04:24:05 +00:00
return 'func';
}), o('=>', function() {
2010-02-11 04:24:05 +00:00
return 'boundfunc';
})
],
OptComma: [o(''), o(',')],
ParamList: [
o('', function() {
return [];
}), o('Param', function() {
2010-02-11 04:24:05 +00:00
return [$1];
}), o('ParamList , Param', function() {
2010-10-11 07:06:29 +00:00
return $1.concat($3);
}), o('ParamList OptComma TERMINATOR Param', function() {
return $1.concat($4);
}), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() {
return $1.concat($4);
2010-02-11 04:24:05 +00:00
})
],
Param: [
2010-10-26 10:08:01 +00:00
o('ParamVar', function() {
2010-10-26 04:09:46 +00:00
return new Param($1);
2010-10-26 10:08:01 +00:00
}), o('ParamVar ...', function() {
2010-10-26 04:09:46 +00:00
return new Param($1, null, true);
}), o('... ParamVar', function() {
return new Param($2, null, true);
}), o('ParamVar = Expression', function() {
2010-10-26 04:09:46 +00:00
return new Param($1, $3);
2014-01-24 16:00:34 +00:00
}), o('...', function() {
return new Expansion;
2010-02-11 04:24:05 +00:00
})
],
ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')],
Splat: [
o('Expression ...', function() {
return new Splat($1);
}), o('... Expression', function() {
return new Splat($2);
2010-02-11 04:24:05 +00:00
})
],
SimpleAssignable: [
o('Identifier', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
}), o('Value Accessor', function() {
return $1.add($2);
}), o('ThisProperty')
2010-03-28 17:06:16 +00:00
],
Assignable: [
2010-10-24 05:05:31 +00:00
o('SimpleAssignable'), o('Array', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
2010-10-24 05:05:31 +00:00
}), o('Object', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
})
],
Value: [
o('Assignable'), o('Literal', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
}), o('Parenthetical', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
2010-11-20 21:25:22 +00:00
}), o('Range', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
}), o('Invocation', function() {
return new Value($1);
}), o('This'), o('Super', function() {
return new Value($1);
})
[CS2] Compile all super calls to ES2015 super (#4424) * Compile all super calls to ES2015 super This breaks using `super` in non-methods, meaning several tests are failing. Self-compilation still works. * Use bound functions for IIFEs containing `super` `super` can only be called directly in a method, or in an arrow function. * Fix handling of `class @A extends A` This behaviour worked 'for free' when the parent reference was being cached by the executable class body wrapper. There now needs to be special handling in place to check if the parent name matches the class name, and if so to cache the parent reference. * Fix tests broken by compiling ES2015 `super` * Disallow bare super This removes syntax support for 'bare' super calls, e.g.: class B extends A constructor: -> super `super` must now always be followed with arguments like a regular function call. This also removes the capability of implicitly forwarding arguments. The above can be equivalently be written as: class B extends A constructor: -> super arguments... * Support super with accessors `super` with following accessor(s) is now compiled to ES2015 equivalents. In particular, expressions such as `super.name`, `super[name]`, and also `super.name.prop` are all now valid, and can be used as expected as calls (i.e. `super.name()`) or in expressions (i.e. `if super.name? ...`). `super` without accessors is compiled to a constructor super call in a constructor, and otherwise, as before, to a super call to the method of the same name, i.e. speak: -> super() ...is equivalent to speak: -> super.speak() A neat side-effect of the changes is that existential calls now work properly with super, meaning `super?()` will only call if the super property exists (and is a function). This is not valid for super in constructors. * Prevent calling `super` methods with `new` This fixes a bug in the previous super handling whereby using the `new` operator with a `super` call would silently drop the `new`. This is now an explicit compiler error, as it is invalid JS at runtime. * Clean up some old super handling code This was mostly code for tracking the source classes and variables for methods, which were needed to build the old lookups on `__super__`. * Add TODO to improve bare super parse error * Add some TODOs to improve some of the class tests
2017-02-04 20:03:17 +00:00
],
Super: [
o('SUPER . Property', function() {
return new Super(LOC(3)(new Access($3)));
}), o('SUPER INDEX_START Expression INDEX_END', function() {
return new Super(LOC(3)(new Index($3)));
})
2010-02-11 04:24:05 +00:00
],
Accessor: [
o('. Property', function() {
2010-11-21 01:09:36 +00:00
return new Access($2);
}), o('?. Property', function() {
2010-11-21 01:09:36 +00:00
return new Access($2, 'soak');
}), o(':: Property', function() {
return [LOC(1)(new Access(new PropertyName('prototype'))), LOC(2)(new Access($2))];
}), o('?:: Property', function() {
return [LOC(1)(new Access(new PropertyName('prototype'), 'soak')), LOC(2)(new Access($2))];
}), o('::', function() {
return new Access(new PropertyName('prototype'));
}), o('Index')
2010-02-11 04:24:05 +00:00
],
Index: [
o('INDEX_START IndexValue INDEX_END', function() {
return $2;
}), o('INDEX_SOAK Index', function() {
return extend($2, {
2010-10-25 13:31:52 +00:00
soak: true
});
2010-02-11 04:24:05 +00:00
})
],
IndexValue: [
o('Expression', function() {
return new Index($1);
}), o('Slice', function() {
return new Slice($1);
})
],
Object: [
o('{ AssignList OptComma }', function() {
return new Obj($2, $1.generated);
})
],
AssignList: [
o('', function() {
2010-02-11 04:24:05 +00:00
return [];
}), o('AssignObj', function() {
2010-02-11 04:24:05 +00:00
return [$1];
}), o('AssignList , AssignObj', function() {
2010-10-11 07:06:29 +00:00
return $1.concat($3);
}), o('AssignList OptComma TERMINATOR AssignObj', function() {
2010-10-11 07:06:29 +00:00
return $1.concat($4);
}), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() {
return $1.concat($4);
2010-02-11 04:24:05 +00:00
})
],
Class: [
o('CLASS', function() {
return new Class;
}), o('CLASS Block', function() {
return new Class(null, null, $2);
}), o('CLASS EXTENDS Expression', function() {
return new Class(null, $3);
}), o('CLASS EXTENDS Expression Block', function() {
return new Class(null, $3, $4);
}), o('CLASS SimpleAssignable', function() {
return new Class($2);
}), o('CLASS SimpleAssignable Block', function() {
return new Class($2, null, $3);
}), o('CLASS SimpleAssignable EXTENDS Expression', function() {
return new Class($2, $4);
}), o('CLASS SimpleAssignable EXTENDS Expression Block', function() {
return new Class($2, $4, $5);
})
2010-02-11 04:24:05 +00:00
],
Support import and export of ES2015 modules (#4300) This pull request adds support for ES2015 modules, by recognizing `import` and `export` statements. The following syntaxes are supported, based on the MDN [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) pages: ```js import "module-name" import defaultMember from "module-name" import * as name from "module-name" import { } from "module-name" import { member } from "module-name" import { member as alias } from "module-name" import { member1, member2 as alias2, … } from "module-name" import defaultMember, * as name from "module-name" import defaultMember, { … } from "module-name" export default expression export class name export { } export { name } export { name as exportedName } export { name as default } export { name1, name2 as exportedName2, name3 as default, … } export * from "module-name" export { … } from "module-name" ``` As a subsitute for ECMAScript’s `export var name = …` and `export function name {}`, CoffeeScript also supports: ```js export name = … ``` CoffeeScript also supports optional commas within `{ … }`. This PR converts the supported `import` and `export` statements into ES2015 `import` and `export` statements; it **does not resolve the modules**. So any CoffeeScript with `import` or `export` statements will be output as ES2015, and will need to be transpiled by another tool such as Babel before it can be used in a browser. We will need to add a warning to the documentation explaining this. This should be fully backwards-compatible, as `import` and `export` were previously reserved keywords. No flags are used. There are extensive tests included, though because no current JavaScript runtime supports `import` or `export`, the tests compare strings of what the compiled CoffeeScript output is against what the expected ES2015 should be. I also conducted two more elaborate tests: * I forked the [ember-piqu](https://github.com/pauc/piqu-ember) project, which was an Ember CLI app that used ember-cli-coffeescript and [ember-cli-coffees6](https://github.com/alexspeller/ember-cli-coffees6) (which adds “support” for `import`/`export` by wrapping such statements in backticks before passing the result to the CoffeeScript compiler). I removed `ember-cli-coffees6` and replaced the CoffeeScript compiler used in the build chain with this code, and the app built without errors. [Demo here.](https://github.com/GeoffreyBooth/coffeescript-modules-test-piqu) * I also forked the [CoffeeScript version of Meteor’s Todos example app](https://github.com/meteor/todos/tree/coffeescript), and replaced all of its `require` statements with the `import` and `export` statements from the original ES2015 version of the app on its `master` branch. I then updated the `coffeescript` Meteor package in the app to use this new code, and again the app builds without errors. [Demo here.](https://github.com/GeoffreyBooth/coffeescript-modules-test-meteor-todos) The discussion history for this work started [here](https://github.com/jashkenas/coffeescript/pull/4160) and continued [here](https://github.com/GeoffreyBooth/coffeescript/pull/2). @lydell provided guidance, and @JimPanic and @rattrayalex contributed essential code.
2016-09-14 18:46:05 +00:00
Import: [
o('IMPORT String', function() {
return new ImportDeclaration(null, $2);
}), o('IMPORT ImportDefaultSpecifier FROM String', function() {
return new ImportDeclaration(new ImportClause($2, null), $4);
}), o('IMPORT ImportNamespaceSpecifier FROM String', function() {
return new ImportDeclaration(new ImportClause(null, $2), $4);
}), o('IMPORT { } FROM String', function() {
return new ImportDeclaration(new ImportClause(null, new ImportSpecifierList([])), $5);
}), o('IMPORT { ImportSpecifierList OptComma } FROM String', function() {
return new ImportDeclaration(new ImportClause(null, new ImportSpecifierList($3)), $7);
}), o('IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String', function() {
return new ImportDeclaration(new ImportClause($2, $4), $6);
}), o('IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String', function() {
return new ImportDeclaration(new ImportClause($2, new ImportSpecifierList($5)), $9);
})
],
ImportSpecifierList: [
o('ImportSpecifier', function() {
return [$1];
}), o('ImportSpecifierList , ImportSpecifier', function() {
return $1.concat($3);
}), o('ImportSpecifierList OptComma TERMINATOR ImportSpecifier', function() {
return $1.concat($4);
}), o('INDENT ImportSpecifierList OptComma OUTDENT', function() {
return $2;
}), o('ImportSpecifierList OptComma INDENT ImportSpecifierList OptComma OUTDENT', function() {
return $1.concat($4);
})
],
ImportSpecifier: [
o('Identifier', function() {
return new ImportSpecifier($1);
}), o('Identifier AS Identifier', function() {
return new ImportSpecifier($1, $3);
}), o('DEFAULT', function() {
return new ImportSpecifier(new Literal($1));
}), o('DEFAULT AS Identifier', function() {
return new ImportSpecifier(new Literal($1), $3);
Support import and export of ES2015 modules (#4300) This pull request adds support for ES2015 modules, by recognizing `import` and `export` statements. The following syntaxes are supported, based on the MDN [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) pages: ```js import "module-name" import defaultMember from "module-name" import * as name from "module-name" import { } from "module-name" import { member } from "module-name" import { member as alias } from "module-name" import { member1, member2 as alias2, … } from "module-name" import defaultMember, * as name from "module-name" import defaultMember, { … } from "module-name" export default expression export class name export { } export { name } export { name as exportedName } export { name as default } export { name1, name2 as exportedName2, name3 as default, … } export * from "module-name" export { … } from "module-name" ``` As a subsitute for ECMAScript’s `export var name = …` and `export function name {}`, CoffeeScript also supports: ```js export name = … ``` CoffeeScript also supports optional commas within `{ … }`. This PR converts the supported `import` and `export` statements into ES2015 `import` and `export` statements; it **does not resolve the modules**. So any CoffeeScript with `import` or `export` statements will be output as ES2015, and will need to be transpiled by another tool such as Babel before it can be used in a browser. We will need to add a warning to the documentation explaining this. This should be fully backwards-compatible, as `import` and `export` were previously reserved keywords. No flags are used. There are extensive tests included, though because no current JavaScript runtime supports `import` or `export`, the tests compare strings of what the compiled CoffeeScript output is against what the expected ES2015 should be. I also conducted two more elaborate tests: * I forked the [ember-piqu](https://github.com/pauc/piqu-ember) project, which was an Ember CLI app that used ember-cli-coffeescript and [ember-cli-coffees6](https://github.com/alexspeller/ember-cli-coffees6) (which adds “support” for `import`/`export` by wrapping such statements in backticks before passing the result to the CoffeeScript compiler). I removed `ember-cli-coffees6` and replaced the CoffeeScript compiler used in the build chain with this code, and the app built without errors. [Demo here.](https://github.com/GeoffreyBooth/coffeescript-modules-test-piqu) * I also forked the [CoffeeScript version of Meteor’s Todos example app](https://github.com/meteor/todos/tree/coffeescript), and replaced all of its `require` statements with the `import` and `export` statements from the original ES2015 version of the app on its `master` branch. I then updated the `coffeescript` Meteor package in the app to use this new code, and again the app builds without errors. [Demo here.](https://github.com/GeoffreyBooth/coffeescript-modules-test-meteor-todos) The discussion history for this work started [here](https://github.com/jashkenas/coffeescript/pull/4160) and continued [here](https://github.com/GeoffreyBooth/coffeescript/pull/2). @lydell provided guidance, and @JimPanic and @rattrayalex contributed essential code.
2016-09-14 18:46:05 +00:00
})
],
ImportDefaultSpecifier: [
o('Identifier', function() {
return new ImportDefaultSpecifier($1);
})
],
ImportNamespaceSpecifier: [
o('IMPORT_ALL AS Identifier', function() {
return new ImportNamespaceSpecifier(new Literal($1), $3);
})
],
Export: [
o('EXPORT { }', function() {
return new ExportNamedDeclaration(new ExportSpecifierList([]));
}), o('EXPORT { ExportSpecifierList OptComma }', function() {
return new ExportNamedDeclaration(new ExportSpecifierList($3));
}), o('EXPORT Class', function() {
return new ExportNamedDeclaration($2);
}), o('EXPORT Identifier = Expression', function() {
return new ExportNamedDeclaration(new Assign($2, $4, null, {
moduleDeclaration: 'export'
}));
}), o('EXPORT Identifier = TERMINATOR Expression', function() {
return new ExportNamedDeclaration(new Assign($2, $5, null, {
moduleDeclaration: 'export'
}));
}), o('EXPORT Identifier = INDENT Expression OUTDENT', function() {
return new ExportNamedDeclaration(new Assign($2, $5, null, {
moduleDeclaration: 'export'
}));
}), o('EXPORT DEFAULT Expression', function() {
return new ExportDefaultDeclaration($3);
}), o('EXPORT EXPORT_ALL FROM String', function() {
return new ExportAllDeclaration(new Literal($2), $4);
}), o('EXPORT { ExportSpecifierList OptComma } FROM String', function() {
return new ExportNamedDeclaration(new ExportSpecifierList($3), $7);
})
],
ExportSpecifierList: [
o('ExportSpecifier', function() {
return [$1];
}), o('ExportSpecifierList , ExportSpecifier', function() {
return $1.concat($3);
}), o('ExportSpecifierList OptComma TERMINATOR ExportSpecifier', function() {
return $1.concat($4);
}), o('INDENT ExportSpecifierList OptComma OUTDENT', function() {
return $2;
}), o('ExportSpecifierList OptComma INDENT ExportSpecifierList OptComma OUTDENT', function() {
return $1.concat($4);
})
],
ExportSpecifier: [
o('Identifier', function() {
return new ExportSpecifier($1);
}), o('Identifier AS Identifier', function() {
return new ExportSpecifier($1, $3);
}), o('Identifier AS DEFAULT', function() {
return new ExportSpecifier($1, new Literal($3));
}), o('DEFAULT', function() {
return new ExportSpecifier(new Literal($1));
}), o('DEFAULT AS Identifier', function() {
return new ExportSpecifier(new Literal($1), $3);
Support import and export of ES2015 modules (#4300) This pull request adds support for ES2015 modules, by recognizing `import` and `export` statements. The following syntaxes are supported, based on the MDN [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) pages: ```js import "module-name" import defaultMember from "module-name" import * as name from "module-name" import { } from "module-name" import { member } from "module-name" import { member as alias } from "module-name" import { member1, member2 as alias2, … } from "module-name" import defaultMember, * as name from "module-name" import defaultMember, { … } from "module-name" export default expression export class name export { } export { name } export { name as exportedName } export { name as default } export { name1, name2 as exportedName2, name3 as default, … } export * from "module-name" export { … } from "module-name" ``` As a subsitute for ECMAScript’s `export var name = …` and `export function name {}`, CoffeeScript also supports: ```js export name = … ``` CoffeeScript also supports optional commas within `{ … }`. This PR converts the supported `import` and `export` statements into ES2015 `import` and `export` statements; it **does not resolve the modules**. So any CoffeeScript with `import` or `export` statements will be output as ES2015, and will need to be transpiled by another tool such as Babel before it can be used in a browser. We will need to add a warning to the documentation explaining this. This should be fully backwards-compatible, as `import` and `export` were previously reserved keywords. No flags are used. There are extensive tests included, though because no current JavaScript runtime supports `import` or `export`, the tests compare strings of what the compiled CoffeeScript output is against what the expected ES2015 should be. I also conducted two more elaborate tests: * I forked the [ember-piqu](https://github.com/pauc/piqu-ember) project, which was an Ember CLI app that used ember-cli-coffeescript and [ember-cli-coffees6](https://github.com/alexspeller/ember-cli-coffees6) (which adds “support” for `import`/`export` by wrapping such statements in backticks before passing the result to the CoffeeScript compiler). I removed `ember-cli-coffees6` and replaced the CoffeeScript compiler used in the build chain with this code, and the app built without errors. [Demo here.](https://github.com/GeoffreyBooth/coffeescript-modules-test-piqu) * I also forked the [CoffeeScript version of Meteor’s Todos example app](https://github.com/meteor/todos/tree/coffeescript), and replaced all of its `require` statements with the `import` and `export` statements from the original ES2015 version of the app on its `master` branch. I then updated the `coffeescript` Meteor package in the app to use this new code, and again the app builds without errors. [Demo here.](https://github.com/GeoffreyBooth/coffeescript-modules-test-meteor-todos) The discussion history for this work started [here](https://github.com/jashkenas/coffeescript/pull/4160) and continued [here](https://github.com/GeoffreyBooth/coffeescript/pull/2). @lydell provided guidance, and @JimPanic and @rattrayalex contributed essential code.
2016-09-14 18:46:05 +00:00
})
],
Invocation: [
CS1 tagged template literals (and CS2 interpolated strings as template literals) (#4352) * Add initial support for template literals with no interpolation * Change ‘unexpected string’ error message tests to use number not identifier prefix. Identifer prefixes are now valid as tagged template literals * Test tagged template literals for non-interpolated strings and tag function. * Tagged template literals work for pure Strings. Pull tagged template definition up to Invocation level in grammar, enabling chained invocation calls. We can view a tagged template is a special form of function call. * Readying for StringWithInterpolations work. * Tweaks. * Fix style * Pass StringWithInterpolations parameter straight into Call constructor. StringWithInterpolations will be output as template literal, so already in correct form for outputting tagged template literal. * Strip down compileNode for StringWithInterpolations * Done StringLiteral case for interpolated Strings * Remove need for TemplateLiteral * Simplify code. * Small code tidy * Interpolated strings now outputting as template literals. Still needs comprehensive testing. * Move error message tests into error_messages.coffee; remove test that is testing for a Node runtime error * Split up tests that were testing multiple things per test, so that each test tests only one thing * Edge cases: tagged template literals containing interpolated strings or even internal tagged template literals * Make more concise, more idiomatic style * Pull back extreme indentation * Restore and fix commented-out tests * Edge case: tagged template literal with empty string * Only use new ES2015 interpolated string syntax if we’re inside a tagged template literal; this keeps this PR safe to merge into CoffeeScript 1.x. Remove the code from this commit to make all interpolated strings use ES2015 syntax, for CoffeeScript 2. * Compiler now _doesn’t_ use template literals. * Expand tagged template literal tests * Move ‘Unexpected string’ error message tests into tagged template literal section. ‘Unexpected string’ is not reported in these test scenarios anymore. Instead, we error that the prefixing literal is not a function. * Don’t unwrap StringWithInterpolations. Saw bug with program consisting of “#{2}” not compiling with template literals. Root cause was that Block.compileNode was unwrapping interpolated string and so didn’t use compileNode logic at StringWithInterpolations level. * No need to bracket interpolated strings any more. When interpolated string looks like `hello ${2}`, no extract brackets are needed, as the `s mark the beginning and end. * Show html templating with tagged template literals * Multiline should match multiline * Comment out unnecessary `unwrap`, which is only needed for CoffeeScript 2 all-ES2015 syntax output
2016-11-18 18:25:03 +00:00
o('Value OptFuncExist String', function() {
return new TaggedTemplateCall($1, $3, $2);
}), o('Value OptFuncExist Arguments', function() {
return new Call($1, $3, $2);
[CS2] Compile all super calls to ES2015 super (#4424) * Compile all super calls to ES2015 super This breaks using `super` in non-methods, meaning several tests are failing. Self-compilation still works. * Use bound functions for IIFEs containing `super` `super` can only be called directly in a method, or in an arrow function. * Fix handling of `class @A extends A` This behaviour worked 'for free' when the parent reference was being cached by the executable class body wrapper. There now needs to be special handling in place to check if the parent name matches the class name, and if so to cache the parent reference. * Fix tests broken by compiling ES2015 `super` * Disallow bare super This removes syntax support for 'bare' super calls, e.g.: class B extends A constructor: -> super `super` must now always be followed with arguments like a regular function call. This also removes the capability of implicitly forwarding arguments. The above can be equivalently be written as: class B extends A constructor: -> super arguments... * Support super with accessors `super` with following accessor(s) is now compiled to ES2015 equivalents. In particular, expressions such as `super.name`, `super[name]`, and also `super.name.prop` are all now valid, and can be used as expected as calls (i.e. `super.name()`) or in expressions (i.e. `if super.name? ...`). `super` without accessors is compiled to a constructor super call in a constructor, and otherwise, as before, to a super call to the method of the same name, i.e. speak: -> super() ...is equivalent to speak: -> super.speak() A neat side-effect of the changes is that existential calls now work properly with super, meaning `super?()` will only call if the super property exists (and is a function). This is not valid for super in constructors. * Prevent calling `super` methods with `new` This fixes a bug in the previous super handling whereby using the `new` operator with a `super` call would silently drop the `new`. This is now an explicit compiler error, as it is invalid JS at runtime. * Clean up some old super handling code This was mostly code for tracking the source classes and variables for methods, which were needed to build the old lookups on `__super__`. * Add TODO to improve bare super parse error * Add some TODOs to improve some of the class tests
2017-02-04 20:03:17 +00:00
}), o('SUPER OptFuncExist Arguments', function() {
return new SuperCall(LOC(1)(new Super), $3, $2);
})
],
OptFuncExist: [
o('', function() {
return false;
}), o('FUNC_EXIST', function() {
return true;
2010-02-11 04:24:05 +00:00
})
],
Arguments: [
o('CALL_START CALL_END', function() {
return [];
}), o('CALL_START ArgList OptComma CALL_END', function() {
return $2;
2010-02-11 04:24:05 +00:00
})
],
This: [
o('THIS', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new Value(new ThisLiteral);
}), o('@', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new Value(new ThisLiteral);
2010-03-28 17:06:16 +00:00
})
],
ThisProperty: [
o('@ Property', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new Value(LOC(1)(new ThisLiteral), [LOC(2)(new Access($2))], 'this');
2010-02-11 04:24:05 +00:00
})
],
Array: [
o('[ ]', function() {
return new Arr([]);
}), o('[ ArgList OptComma ]', function() {
return new Arr($2);
2010-02-11 04:24:05 +00:00
})
],
2010-11-20 21:25:22 +00:00
RangeDots: [
o('..', function() {
return 'inclusive';
}), o('...', function() {
return 'exclusive';
})
],
Range: [
o('[ Expression RangeDots Expression ]', function() {
return new Range($2, $4, $3);
})
],
Slice: [
o('Expression RangeDots Expression', function() {
return new Range($1, $3, $2);
}), o('Expression RangeDots', function() {
return new Range($1, null, $2);
}), o('RangeDots Expression', function() {
return new Range(null, $2, $1);
}), o('RangeDots', function() {
return new Range(null, null, $1);
2010-11-20 21:25:22 +00:00
})
],
ArgList: [
o('Arg', function() {
2010-02-11 04:24:05 +00:00
return [$1];
}), o('ArgList , Arg', function() {
2010-10-11 07:06:29 +00:00
return $1.concat($3);
}), o('ArgList OptComma TERMINATOR Arg', function() {
2010-10-11 07:06:29 +00:00
return $1.concat($4);
}), o('INDENT ArgList OptComma OUTDENT', function() {
return $2;
}), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() {
return $1.concat($4);
})
2010-02-11 04:24:05 +00:00
],
2014-01-24 16:00:34 +00:00
Arg: [
o('Expression'), o('Splat'), o('...', function() {
return new Expansion;
})
],
SimpleArgs: [
o('Expression'), o('SimpleArgs , Expression', function() {
2010-10-11 07:06:29 +00:00
return [].concat($1, $3);
2010-02-11 04:24:05 +00:00
})
],
Try: [
o('TRY Block', function() {
return new Try($2);
}), o('TRY Block Catch', function() {
return new Try($2, $3[0], $3[1]);
}), o('TRY Block FINALLY Block', function() {
return new Try($2, null, null, $4);
}), o('TRY Block Catch FINALLY Block', function() {
return new Try($2, $3[0], $3[1], $5);
2010-02-11 04:24:05 +00:00
})
],
Catch: [
o('CATCH Identifier Block', function() {
2010-02-11 04:24:05 +00:00
return [$2, $3];
}), o('CATCH Object Block', function() {
2013-02-28 13:37:30 +00:00
return [LOC(2)(new Value($2)), $3];
}), o('CATCH Block', function() {
return [null, $2];
2010-02-11 04:24:05 +00:00
})
],
Throw: [
o('THROW Expression', function() {
return new Throw($2);
}), o('THROW INDENT Object OUTDENT', function() {
return new Throw(new Value($3));
2010-02-11 04:24:05 +00:00
})
],
Parenthetical: [
o('( Body )', function() {
2010-10-07 03:53:26 +00:00
return new Parens($2);
}), o('( INDENT Body OUTDENT )', function() {
return new Parens($3);
2010-02-11 04:24:05 +00:00
})
],
WhileSource: [
o('WHILE Expression', function() {
return new While($2);
}), o('WHILE Expression WHEN Expression', function() {
return new While($2, {
guard: $4
});
}), o('UNTIL Expression', function() {
return new While($2, {
invert: true
});
}), o('UNTIL Expression WHEN Expression', function() {
return new While($2, {
invert: true,
guard: $4
});
})
],
While: [
o('WhileSource Block', function() {
return $1.addBody($2);
}), o('Statement WhileSource', function() {
return $2.addBody(LOC(1)(Block.wrap([$1])));
}), o('Expression WhileSource', function() {
return $2.addBody(LOC(1)(Block.wrap([$1])));
}), o('Loop', function() {
return $1;
})
],
Loop: [
o('LOOP Block', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new While(LOC(1)(new BooleanLiteral('true'))).addBody($2);
}), o('LOOP Expression', function() {
Refactor `Literal` into several subtypes Previously, the parser created `Literal` nodes for many things. This resulted in information loss. Instead of being able to check the node type, we had to use regexes to tell the different types of `Literal`s apart. That was a bit like parsing literals twice: Once in the lexer, and once (or more) in the compiler. It also caused problems, such as `` `this` `` and `this` being indistinguishable (fixes #2009). Instead returning `new Literal` in the grammar, subtypes of it are now returned instead, such as `NumberLiteral`, `StringLiteral` and `IdentifierLiteral`. `new Literal` by itself is only used to represent code chunks that fit no category. (While mentioning `NumberLiteral`, there's also `InfinityLiteral` now, which is a subtype of `NumberLiteral`.) `StringWithInterpolations` has been added as a subtype of `Parens`, and `RegexWithInterpolations` as a subtype of `Call`. This makes it easier for other programs to make use of CoffeeScript's "AST" (nodes). For example, it is now possible to distinguish between `"a #{b} c"` and `"a " + b + " c"`. Fixes #4192. `SuperCall` has been added as a subtype of `Call`. Note, though, that some information is still lost, especially in the lexer. For example, there is no way to distinguish a heredoc from a regular string, or a heregex without interpolations from a regular regex. Binary and octal number literals are indistinguishable from hexadecimal literals. After the new subtypes were added, they were taken advantage of, removing most regexes in nodes.coffee. `SIMPLENUM` (which matches non-hex integers) had to be kept, though, because such numbers need special handling in JavaScript (for example in `1..toString()`). An especially nice hack to get rid of was using `new String()` for the token value for reserved identifiers (to be able to set a property on them which could survive through the parser). Now it's a good old regular string. In range literals, slices, splices and for loop steps when number literals are involved, CoffeeScript can do some optimizations, such as precomputing the value of, say, `5 - 3` (outputting `2` instead of `5 - 3` literally). As a side bonus, this now also works with hexadecimal number literals, such as `0x02`. Finally, this also improves the output of `coffee --nodes`: # Before: $ bin/coffee -ne 'while true "#{a}" break' Block While Value Bool Block Value Parens Block Op + Value """" Value Parens Block Value "a" "break" # After: $ bin/coffee -ne 'while true "#{a}" break' Block While Value BooleanLiteral: true Block Value StringWithInterpolations Block Op + Value StringLiteral: "" Value Parens Block Value IdentifierLiteral: a StatementLiteral: break
2016-01-31 19:24:31 +00:00
return new While(LOC(1)(new BooleanLiteral('true'))).addBody(LOC(2)(Block.wrap([$2])));
2010-02-11 04:24:05 +00:00
})
],
For: [
o('Statement ForBody', function() {
return new For($1, $2);
}), o('Expression ForBody', function() {
return new For($1, $2);
}), o('ForBody Block', function() {
return new For($2, $1);
2010-11-20 21:25:22 +00:00
})
],
ForBody: [
o('FOR Range', function() {
return {
2013-02-28 13:37:30 +00:00
source: LOC(2)(new Value($2))
2010-11-20 21:25:22 +00:00
};
}), o('FOR Range BY Expression', function() {
return {
source: LOC(2)(new Value($2)),
step: $4
};
2010-11-20 21:25:22 +00:00
}), o('ForStart ForSource', function() {
2010-11-28 23:33:43 +00:00
$2.own = $1.own;
$2.ownTag = $1.ownTag;
$2.name = $1[0];
$2.index = $1[1];
2010-11-20 21:25:22 +00:00
return $2;
})
],
ForStart: [
o('FOR ForVariables', function() {
return $2;
2010-11-28 23:33:43 +00:00
}), o('FOR OWN ForVariables', function() {
$3.own = true;
$3.ownTag = LOC(2)(new Literal($2));
2010-11-20 21:25:22 +00:00
return $3;
2010-02-11 04:24:05 +00:00
})
],
ForValue: [
o('Identifier'), o('ThisProperty'), o('Array', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
}), o('Object', function() {
2013-02-28 13:37:30 +00:00
return new Value($1);
})
],
2010-11-20 21:25:22 +00:00
ForVariables: [
o('ForValue', function() {
return [$1];
}), o('ForValue , ForValue', function() {
return [$1, $3];
})
],
ForSource: [
o('FORIN Expression', function() {
2010-02-11 04:24:05 +00:00
return {
source: $2
};
2010-11-20 21:25:22 +00:00
}), o('FOROF Expression', function() {
2010-02-11 04:24:05 +00:00
return {
source: $2,
2010-11-20 21:25:22 +00:00
object: true
2010-02-11 04:24:05 +00:00
};
2010-11-20 21:25:22 +00:00
}), o('FORIN Expression WHEN Expression', function() {
return {
source: $2,
2010-11-20 21:25:22 +00:00
guard: $4
};
}), o('FOROF Expression WHEN Expression', function() {
return {
source: $2,
2010-11-20 21:25:22 +00:00
guard: $4,
object: true
};
2010-11-20 21:25:22 +00:00
}), o('FORIN Expression BY Expression', function() {
return {
2010-11-20 21:25:22 +00:00
source: $2,
step: $4
};
2010-11-20 21:25:22 +00:00
}), o('FORIN Expression WHEN Expression BY Expression', function() {
return {
2010-11-20 21:25:22 +00:00
source: $2,
guard: $4,
step: $6
};
2010-11-20 21:25:22 +00:00
}), o('FORIN Expression BY Expression WHEN Expression', function() {
return {
2010-11-20 21:25:22 +00:00
source: $2,
step: $4,
guard: $6
};
}), o('FORFROM Expression', function() {
return {
source: $2,
from: true
};
}), o('FORFROM Expression WHEN Expression', function() {
return {
source: $2,
guard: $4,
from: true
};
2010-02-11 04:24:05 +00:00
})
],
Switch: [
o('SWITCH Expression INDENT Whens OUTDENT', function() {
return new Switch($2, $4);
}), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() {
return new Switch($2, $4, $6);
}), o('SWITCH INDENT Whens OUTDENT', function() {
return new Switch(null, $3);
}), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() {
return new Switch(null, $3, $5);
2010-02-11 04:24:05 +00:00
})
],
Whens: [
o('When'), o('Whens When', function() {
return $1.concat($2);
2010-02-11 04:24:05 +00:00
})
],
When: [
o('LEADING_WHEN SimpleArgs Block', function() {
return [[$2, $3]];
}), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() {
return [[$2, $3]];
2010-02-11 04:24:05 +00:00
})
],
IfBlock: [
o('IF Expression Block', function() {
return new If($2, $3, {
type: $1
2010-04-27 23:35:15 +00:00
});
}), o('IfBlock ELSE IF Expression Block', function() {
return $1.addElse(LOC(3, 5)(new If($4, $5, {
type: $3
})));
})
],
If: [
2011-01-11 04:19:31 +00:00
o('IfBlock'), o('IfBlock ELSE Block', function() {
return $1.addElse($3);
}), o('Statement POST_IF Expression', function() {
return new If($3, LOC(1)(Block.wrap([$1])), {
type: $2,
2010-04-05 14:26:23 +00:00
statement: true
});
}), o('Expression POST_IF Expression', function() {
return new If($3, LOC(1)(Block.wrap([$1])), {
type: $2,
2010-02-11 04:24:05 +00:00
statement: true
});
})
],
Operation: [
2010-10-21 00:16:17 +00:00
o('UNARY Expression', function() {
2013-02-28 13:37:30 +00:00
return new Op($1, $2);
}), o('UNARY_MATH Expression', function() {
return new Op($1, $2);
}), o('- Expression', (function() {
2013-02-28 13:37:30 +00:00
return new Op('-', $2);
}), {
prec: 'UNARY_MATH'
}), o('+ Expression', (function() {
2013-02-28 13:37:30 +00:00
return new Op('+', $2);
}), {
prec: 'UNARY_MATH'
}), o('AWAIT Expression', function() {
return new Op($1, $2);
2010-10-21 00:16:17 +00:00
}), o('-- SimpleAssignable', function() {
2013-02-28 13:37:30 +00:00
return new Op('--', $2);
2010-10-21 00:16:17 +00:00
}), o('++ SimpleAssignable', function() {
2013-02-28 13:37:30 +00:00
return new Op('++', $2);
2010-10-21 00:16:17 +00:00
}), o('SimpleAssignable --', function() {
2013-02-28 13:37:30 +00:00
return new Op('--', $1, null, true);
2010-10-21 00:16:17 +00:00
}), o('SimpleAssignable ++', function() {
2013-02-28 13:37:30 +00:00
return new Op('++', $1, null, true);
}), o('Expression ?', function() {
return new Existence($1);
2010-10-21 00:16:17 +00:00
}), o('Expression + Expression', function() {
2013-02-28 13:37:30 +00:00
return new Op('+', $1, $3);
2010-10-21 00:16:17 +00:00
}), o('Expression - Expression', function() {
2013-02-28 13:37:30 +00:00
return new Op('-', $1, $3);
2010-10-21 00:16:17 +00:00
}), o('Expression MATH Expression', function() {
2013-02-28 13:37:30 +00:00
return new Op($2, $1, $3);
}), o('Expression ** Expression', function() {
return new Op($2, $1, $3);
2010-10-21 00:16:17 +00:00
}), o('Expression SHIFT Expression', function() {
2013-02-28 13:37:30 +00:00
return new Op($2, $1, $3);
2010-10-21 00:16:17 +00:00
}), o('Expression COMPARE Expression', function() {
2013-02-28 13:37:30 +00:00
return new Op($2, $1, $3);
}), o('Expression & Expression', function() {
return new Op($2, $1, $3);
}), o('Expression ^ Expression', function() {
return new Op($2, $1, $3);
}), o('Expression | Expression', function() {
return new Op($2, $1, $3);
}), o('Expression && Expression', function() {
return new Op($2, $1, $3);
}), o('Expression || Expression', function() {
return new Op($2, $1, $3);
}), o('Expression BIN? Expression', function() {
2013-02-28 13:37:30 +00:00
return new Op($2, $1, $3);
2010-10-21 00:16:17 +00:00
}), o('Expression RELATION Expression', function() {
if ($2.charAt(0) === '!') {
2013-02-28 13:37:30 +00:00
return new Op($2.slice(1), $1, $3).invert();
} else {
2013-02-28 13:37:30 +00:00
return new Op($2, $1, $3);
}
2013-11-18 04:32:15 +00:00
}), o('SimpleAssignable COMPOUND_ASSIGN Expression', function() {
return new Assign($1, $3, $2);
2013-11-18 04:32:15 +00:00
}), o('SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT', function() {
return new Assign($1, $4, $2);
2013-11-18 04:32:15 +00:00
}), o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR Expression', function() {
return new Assign($1, $4, $2);
})
2010-02-11 04:24:05 +00:00
]
};
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', 'AWAIT'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', '&'], ['left', '^'], ['left', '|'], ['left', '&&'], ['left', '||'], ['left', 'BIN?'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT'], ['left', 'POST_IF']];
2010-02-11 04:24:05 +00:00
tokens = [];
2010-10-01 22:26:37 +00:00
for (name in grammar) {
alternatives = grammar[name];
2010-12-23 18:50:52 +00:00
grammar[name] = (function() {
var i, j, len, len1, ref, results;
results = [];
for (i = 0, len = alternatives.length; i < len; i++) {
alt = alternatives[i];
ref = alt[0].split(' ');
for (j = 0, len1 = ref.length; j < len1; j++) {
token = ref[j];
2012-04-10 18:57:45 +00:00
if (!grammar[token]) {
tokens.push(token);
}
}
if (name === 'Root') {
alt[1] = `return ${alt[1]}`;
}
results.push(alt);
}
return results;
2010-12-23 18:50:52 +00:00
})();
}
2010-02-16 06:04:48 +00:00
exports.parser = new Parser({
tokens: tokens.join(' '),
bnf: grammar,
operators: operators.reverse(),
2010-02-11 04:24:05 +00:00
startSymbol: 'Root'
});
2011-12-14 15:39:20 +00:00
}).call(this);