Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

`accumulate` keyword for making an assignment, performing a block of …

…code, then returning the value of the assignable
  • Loading branch information...
commit 42ff65128d5b1ad021bd6c6897a444b68e3c5d7a 1 parent f3caa92
@sstephenson authored
View
11 lib/grammar.js
@@ -34,7 +34,7 @@
return new LiteralNode($1);
})
],
- Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment")],
+ Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("Accumulate"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment")],
Block: [
o("INDENT Body OUTDENT", function() {
return $2;
@@ -221,6 +221,13 @@
return $1.concat($4);
})
],
+ Accumulate: [
+ o("ACCUMULATE Assignable Block", function() {
+ return new AccumulateNode($2, new LiteralNode('null'), $3);
+ }), o("ACCUMULATE Assignable = Expression Block", function() {
+ return new AccumulateNode($2, $4, $5);
+ })
+ ],
Class: [
o("CLASS SimpleAssignable", function() {
return new ClassNode($2);
@@ -632,7 +639,7 @@
})
]
};
- operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||', 'OP?'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']];
+ operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||', 'OP?'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS'], ["right", 'ACCUMULATE'], ["left", 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']];
tokens = [];
_a = grammar;
for (name in _a) {
View
2  lib/lexer.js
@@ -584,7 +584,7 @@
})();
JS_KEYWORDS = ["if", "else", "true", "false", "new", "return", "try", "catch", "finally", "throw", "break", "continue", "for", "in", "while", "delete", "instanceof", "typeof", "switch", "super", "extends", "class", "this", "null"];
COFFEE_ALIASES = ["and", "or", "is", "isnt", "not"];
- COFFEE_KEYWORDS = COFFEE_ALIASES.concat(["then", "unless", "until", "loop", "yes", "no", "on", "off", "of", "by", "where", "when"]);
+ COFFEE_KEYWORDS = COFFEE_ALIASES.concat(["then", "unless", "until", "loop", "yes", "no", "on", "off", "of", "by", "where", "when", "accumulate"]);
RESERVED = ["case", "default", "do", "function", "var", "void", "with", "const", "let", "enum", "export", "import", "native", "__hasProp", "__extends", "__slice"];
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
IDENTIFIER = /^([a-zA-Z\$_](\w|\$)*)/;
View
25 lib/nodes.js
@@ -1,5 +1,5 @@
(function() {
- var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, DOUBLE_PARENS, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, InNode, IndexNode, LiteralNode, NUMBER, ObjectNode, OpNode, ParamNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SIMPLENUM, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, ends, flatten, helpers, include, indexOf, literal, merge, starts, utility;
+ var AccessorNode, AccumulateNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, DOUBLE_PARENS, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, InNode, IndexNode, LiteralNode, NUMBER, ObjectNode, OpNode, ParamNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SIMPLENUM, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, ends, flatten, helpers, include, indexOf, literal, merge, starts, utility;
var __extends = function(child, parent) {
var ctor = function(){};
ctor.prototype = parent.prototype;
@@ -753,6 +753,29 @@
};
return ArrayNode;
})();
+ exports.AccumulateNode = (function() {
+ AccumulateNode = function(_b, _c, _d) {
+ this.body = _d;
+ this.value = _c;
+ this.variable = _b;
+ return this;
+ };
+ __extends(AccumulateNode, BaseNode);
+ AccumulateNode.prototype["class"] = 'AccumulateNode';
+ AccumulateNode.prototype.children = ['variable', 'value', 'body'];
+ AccumulateNode.prototype.isStatement = function() {
+ return true;
+ };
+ AccumulateNode.prototype.makeReturn = function() {
+ return new Expressions([this, new ReturnNode(this.variable)]);
+ };
+ AccumulateNode.prototype.compileNode = function(o) {
+ var expressions;
+ expressions = Expressions.wrap([new AssignNode(this.variable, this.value), this.body]);
+ return "" + this.tab + (expressions.compile(o));
+ };
+ return AccumulateNode;
+ })();
exports.ClassNode = (function() {
ClassNode = function(_b, _c, _d) {
this.properties = _d;
View
400 lib/parser.js
203 additions, 197 deletions not shown
View
7 src/grammar.coffee
@@ -90,6 +90,7 @@ grammar =
o "Code"
o "Operation"
o "Assign"
+ o "Accumulate"
o "If"
o "Try"
o "While"
@@ -272,6 +273,11 @@ grammar =
o "AssignList OptComma INDENT AssignList OptComma OUTDENT", -> $1.concat $4
]
+ Accumulate: [
+ o "ACCUMULATE Assignable Block", -> new AccumulateNode $2, new LiteralNode('null'), $3
+ o "ACCUMULATE Assignable = Expression Block", -> new AccumulateNode $2, $4, $5
+ ]
+
# Class definitions have optional bodies of prototype property assignments,
# and optional references to the superclass.
Class: [
@@ -603,6 +609,7 @@ operators = [
["left", 'OUTDENT']
["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW']
["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS']
+ ["right", 'ACCUMULATE']
["left", 'EXTENDS']
["right", '=', ':', 'RETURN']
["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']
View
3  src/lexer.coffee
@@ -499,7 +499,8 @@ COFFEE_ALIASES = ["and", "or", "is", "isnt", "not"]
COFFEE_KEYWORDS = COFFEE_ALIASES.concat [
"then", "unless", "until", "loop",
"yes", "no", "on", "off",
- "of", "by", "where", "when"
+ "of", "by", "where", "when",
+ "accumulate"
]
# The list of keywords that are reserved by JavaScript, but not used, or are
View
18 src/nodes.coffee
@@ -659,6 +659,24 @@ exports.ArrayNode = class ArrayNode extends BaseNode
else
"[#objects]"
+
+#### AccumulateNode
+exports.AccumulateNode = class AccumulateNode extends BaseNode
+
+ class: 'AccumulateNode'
+ children: ['variable', 'value', 'body']
+ isStatement: -> yes
+
+ constructor: (@variable, @value, @body) ->
+
+ makeReturn: ->
+ new Expressions [this, new ReturnNode @variable]
+
+ compileNode: (o) ->
+ expressions = Expressions.wrap [new AssignNode(@variable, @value), @body]
+ "#@tab#{expressions.compile o}"
+
+
#### ClassNode
# The CoffeeScript class definition.
View
33 test/test_accumulate.coffee
@@ -0,0 +1,33 @@
+# Default value is null.
+accumulate x
+ ok x is null
+
+
+# Returns the assignable.
+sum = (range) ->
+ accumulate result = 0
+ result += value for value in range
+
+ok sum([1..10]) is 55
+
+
+# Assignable can be an array.
+partition = (collection, test) ->
+ accumulate [trues, falses] = [[], []]
+ for value in collection
+ if test value
+ trues.push value
+ else
+ falses.push value
+
+[odds, evens] = partition [1..10], (n) -> n % 2 is 1
+ok odds.join(' ') is '1 3 5 7 9'
+ok evens.join(' ') is '2 4 6 8 10'
+
+
+# Assignable can be reassigned in the body.
+accumulate x = "hello"
+ for value in [1..3]
+ x = "#value #x *"
+
+ok x is '3 2 1 hello * * *'
Please sign in to comment.
Something went wrong with that request. Please try again.