-
Notifications
You must be signed in to change notification settings - Fork 48
additions
Assigns to an existing variable without declaring a new one.
$ coco -bce 'a = 1; new -> a := 2; b = 3'
var a;
a = 1;
new function(){
var b;
a = 2;
b = 3;
};
$ coco -ce 'x := 0'
assignment to undeclared variable "x" on line 1
This is essential because (unlike CoffeeScript) our =
always declares the variable in current scope.
ref. https://github.com/jashkenas/coffee-script/issues/712
Any assignment operator can be conditional when prefixed with &&
, ||
, ?
or !?
.
$ coco -bce 'a.b |||= c.d ?= e'
var __ref;
a.b || (a.b |= (__ref = c.d) != null ? __ref : c.d = e);
$ coco -bce '[x, y] &&= z'
var x, y;
x && (x = z[0]), y && (y = z[1]);
Compound assignments for unary operators.
$ coco -bcs
# syntax: UnaryOp+ AssignOp LHSExpression
+ = x # numberize
!! = x # enbool
-~-~ = x # intcasting bicrement
var x;
x = +x;
x = !!x;
x = -~-~x;
You can specify a default value to each function parameter or destructuring target, using one of logical operators (||
&&
?
!?
).
$ coco -bce '(o || {}) -> [@a ? b] = c'
(function(o){
var __ref;
o || (o = {});
return this.a = (__ref = c[0]) != null ? __ref : b, c;
});
- For parameters,
=
can be used in place of?
.
Performs destructuring into an object's properties.
$ coco -bcs
x[a, b] = y
x{a, b} = y
x[a] = y[0], x[b] = y[1];
x.a = y.a, x.b = y.b;
You can provide a name to a destructuring pattern, which will be used for the intermediate variable instead of a temporary one.
$ coco -bcs
([p, q]:a) ->
{{x}:b, [y]:c} = o # short for {b: {x}:b, c: [y]:c}
var b, x, c, y;
(function(a){
var p, q;
p = a[0], q = a[1];
});
b = o.b, x = b.x, c = o.c, y = c[0];
Performs assignment only when the right-hand-side value exists.
$ coco -bcs
[, left, rite]? = /(\w+)\s*=\s*(\w+)/exec input
({when, where}?) -> go where, when
var left, rite, __ref;
if ((__ref = /(\w+)\s*=\s*(\w+)/.exec(input)) != null) {
left = __ref[1], rite = __ref[2];
}
(function(__arg){
var when, where;
if (__arg != null) {
when = __arg.when, where = __arg.where;
}
return go(where, when);
});
Performs assignments and flags the declared variables as read-only. Redeclaration/reassignment on them will be a compile error.
$ coco -s
const a = 0
a++
SyntaxError: increment of constant "a" on line 2
Plain ol' var
without initialization and redeclaration.
$ coco -ps
var a, b
a is b is undefined
true
$ coco -e '(x) -> var x'
SyntaxError: redeclaration of "x" on line 1
Creates the same name property of target expression(s) on exports
or top-level this
.
$ coco -bcs
export a, b.c
export
d: e
function f then g
export const h = 1
var h, __out = typeof exports != 'undefined' && exports || this;
__out.a = a;
__out.c = b.c;
__out.d = e;
__out.f = f;
function f(){
return g;
}
__out.h = h = 1;
- Named expressions (variable, dot-identifier access,
function
declaration,class
) are exported with those names. - All other expressions get all own properties exported.
In addition to identifiers, our dot operators accept many more things as their right operand. Numbers, strings, parentheses, brackets and braces.
$ coco -bce 'x.0."1".(2).[3]'
x[0]["1"][2][3];
Therefore we don't technically have the bracket notation for property access in {Java,Coffee}Script sense. o[x]
is just short for o.[x]
.
Compound assignments for .
.
$ coco -bce 'location.href.=replace /^http:/, \https:'
location.href = location.href.replace(/^http:/, 'https:');
$ coco -bce 'a.+=0'
a += a[0];
$ coco -bce '[b, c].=reverse()'
var b, c, __ref;
__ref = [b, c].reverse(), b = __ref[0], c = __ref[1];
- Is at same precedence as
.
. - Consumes all dot/call chains to the right.
Retrieves an object's method as bound to the object.
$ coco -bce o.p.~m
__bind(o.p, 'm');
function __bind(obj, key){
return function(){ return obj[key].apply(obj, arguments) };
}
$ coco -ps
[2 5 9]map 42~toString
# desugars to: [2, 5, 9].map -> 42.toString.apply 42, arguments
[ '101010', '132', '46' ]
In other words, o.~m
sort of emulates o.m.bind(o)
in ES5.
Postfix brackets can take multiple arguments, in which case they collect retrieved values into an array.
$ coco -bce 'x[a, b]'
[x[a], x[b]];
object slice x{a, b: c}
_
Postfix curly braces extract the selected properties into a new object.
$ coco -bce 'x{a: b, c}'
({
a: x.b,
c: x.c
});
An asterisk within an indexer represents the length of the indexee.
$ coco -bce 'a[*] = b'
a[a.length] = b;
$ coco -bce 'arr()[* - 1]'
var __ref;
(__ref = arr())[__ref.length - 1];
$ coco -bce '{(* >> 1): mid} = a'
var mid;
mid = a[a.length >> 1];
semiautovivification .@
.@@
Ensures that the property exists as an object or array. x.@y
desugars to (x.y ||= {})
.
$ coco -bcs
root.@obj.@@arr.push it
A@D@@I
var __ref;
((__ref = root.obj || (root.obj = {})).arr || (__ref.arr = [])).push(it);
(__ref = A.D || (A.D = {})).I || (__ref.I = []);
$ coco -se
setXYZ = (
point # target object to set the coordinates
point.x, point.y, point.z
) -> point
setXYZ {} 2 3 5
{ x: 2, y: 3, z: 5 }
Function parameters can be:
- written multi-line, using the same syntax as array items.
- any assignable expressions.
Declares or creates a named function, without touching the nasty JScript bug.
$ coco -bcs
# syntax: "function" Name? ParameterList? Block
function equal a, b
a is b
add = function (x, y)
x + y
~function bound then this
var add, __this = this;
function equal(a, b){
return a === b;
}
add = (function(){
function add(x, y){
return x + y;
}
return add;
}());
function bound(){
return __this;
}
$ coco -s
function f
f = ->
SyntaxError: redeclaration of function "f" on line 2
- Parentheses around parameter list can be omitted in the same way that
f(a)
can bef a
. - Prefix
~
to bind parentthis
. - The declared variable is read-only.
Represents the first argument of the current function, like in Groovy's closure. Available only when no parameters are declared.
$ coco -bce 'I = -> it'
var I;
I = function(it){
return it;
};
A unary operator that calls a function with no arguments, helping you write less parentheses.
$ coco -bce 'do f; do ->'
f();
(function(){})();
Sugar for ()
.
$ coco -bce 'f! g?!'
f()(typeof g == 'function' ? g() : void 8);
IIFE sugars
with arguments let a = b then ...
Short for the idiom (function(a){...}.call(this, b))
.
$ coco -bcs
# syntax: "let" Assignments? Block
let (a = b)
assert a is b
r = let # short for `let ()`
let c, @d # short for `let (c = c, d = @d)`
c + d
var r;
(function(a){
assert(a === b);
}.call(this, b));
r = (function(){
return (function(c, d){
return c + d;
}.call(this, c, this.d));
}.call(this));
with context with x then ...
Short for the idiom (function(){...}.call(x))
.
$ coco -bcs
# syntax: "with" Expression Block
xhr = with new XMLHttpRequest
@open \GET \data
@send null
this
var xhr;
xhr = (function(){
this.open('GET', 'data');
this.send(null);
return this;
}.call(new XMLHttpRequest));
with new context new then ...
Short for new ->
, saving precious two key strokes.
$ coco -bcs
point = new
@x = 9
@y = 6
var point;
point = new function(){
this.x = 9;
this.y = 6;
};
$ coco -se
# pseudo object comprehension
flip = (obj) -> new
@[v] = k for own k, v in obj
flip \flop
{ f: '0', l: '1', o: '2', p: '3' }
As in class
constructor, no implicit return is generated.
thisplat f(...)
_
Shorthand to delegate the current context to a function.
$ coco -bce 'f ...'
f.apply(this, arguments);
backcall <- f
_
Sugar for flattening nested callbacks.
$ coco -bcs
<~ f
e <- g this
return if e
( x
y
) <- h ..., z
var __this = this;
f(function(){
return g(__this, function(e){
if (e) {
return;
}
return h(function(x, y){}, z);
});
});
- Can only appear on the top level of a block.
- Consumes all consecutive lines of that block as the function body.
-
<-
for plain,<~
for bound. -
...
can be used to specify the callback position when there are other arguments after it.
Negating a function literal or the callee of a backcall suppresses the implicit return
.
$ coco -bcs
setTimeout !->
!function say
console.log it
<-! setTimeout
say \yes
setTimeout(function(){
function say(it){
console.log(it);
}
setTimeout(function(){
say('yes');
});
});
Implicit calls don't cross spaced dots, allowing you to chain methods without parentheses.
$ coco -bcs
obj.foo x, y .bar z
.baz!
obj.foo(x, y).bar(z).baz();
Function literals within loops are defined outside.
$ coco -bcs
sums = for a of as
a.reduce (x, y) -> x + y
var a, sums, __res, __i, __ref, __len;
__res = [];
for (__i = 0, __len = (__ref = as).length; __i < __len; ++__i) {
a = __ref[__i];
__res.push(a.reduce(__fn));
}
sums = __res;
function __fn(x, y){
return x + y;
}
do
with an indented block represents a pair of parenthesis (unless followed by while
/until
), either as grouping or calling.
$ coco -bcs
r = do
f do
a
b
g()
var r;
r = (f(a, b), g());
Our class
defines the constructor as a bare function and properties (prototype members) as bare objects, both on top level under the class block.
$ coco -bcs
class exports.C extends P
/* constructor */
-> super ...
/* properties */
member: 'U'
method: -> super @member, ..static()
/* any code */
$private = 42
@static = -> $private
var C;
exports.C = C = (function(superclass){
/* constructor */
C.displayName = 'C';
var $private, prototype = __extend(C, superclass).prototype, constructor = C;
function C(){
superclass.apply(this, arguments);
}
/* properties */
prototype.member = 'U';
prototype.method = function(){
return superclass.prototype.method.call(this, this.member, constructor['static']());
};
/* any code */;
$private = 42;
C['static'] = function(){
return $private;
};
return C;
}(P));
function __extend(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
In short,
class C extends P
-> /* constructor */
{'properties'}
...
desugars roughly to
C = do ->
function C
/* constructor */
C.displayName = 'C'
with {prototype} = constructor = C extends superclass = P
prototype import {'properties'}
...
C
The constructor:
- receives
displayName
property, useful for debugging, reflection etc. - is accessible as
constructor
(or..
).
Using the wavy arrow ~>
for constructor makes the class to be new
-free, like native Array
which works with or without new
.
$ coco -bce 'Bound = class then (@name) ~>'
var Bound;
Bound = (function(){
Bound.displayName = 'Bound';
var prototype = Bound.prototype, constructor = Bound;
function Bound(name){
var __this = this instanceof __ctor ? this : new __ctor;
__this.name = name;
return __this;
} function __ctor(){} __ctor.prototype = prototype;
return Bound;
}());
This form allows the constructor to return non-object values.
Make sure to return this
when you're returning the instance early.
super
is an alias to superclass
or the nearest method (a function defined via top-level object under class
).
When a super
starts an access/call chain, the next call auto-passes current this
.
$ coco -bce 'super.classMethod!'
superclass.classMethod.call(this);
You can specify mixin objects to be merged into prototype
at the tail of class
line.
$ coco -bce 'class implements M, N then O'
(function(){
var prototype = constructor.prototype;
__importAll(prototype, arguments[0]);
__importAll(prototype, arguments[1]);
O;
function constructor(){}
return constructor;
}(M, N));
function __importAll(obj, src){
for (var key in src) obj[key] = src[key];
return obj;
}
in range for
from
to
til
by
A generic way to loop within certain numeric ranges.
$ coco -bce 'for i from x to y then'
var i, __to;
for (i = x, __to = y; i <= __to; ++i) {}
$ coco -bce 'for i from x til y then'
var i, __to;
for (i = x, __to = y; i < __to; ++i) {}
$ coco -bce 'for i from x to y by -1 then'
var i, __to;
for (i = x, __to = y; i >= __to; --i) {}
$ coco -bce 'for i from x to y by z then'
var i, __step, __to;
for (i = x, __to = y, __step = z; __step < 0 ? i >= __to : i <= __to; i += __step) {}
$ coco -bce 'for i til x then'
var i, __to;
for (i = 0, __to = x; i < __to; ++i) {}
-
to
for inclusive,til
for exclusive. -
by
optionally specifies the step value. -
from
clause is optional, implyingfrom 0
.
scoped
IIFE sugars (let
/with
/new
) within for
body automatically capture the loop variables.
$ coco -s
fs = for i til 3
let then -> console.log i
fs.forEach -> do it
0
1
2
$ coco -bce 'for k in o then new -> say k'
var k;
for (k in o) {
new __fn(k);
}
function __fn(k){
say(k);
}
postconditional _
The traditional do
-while
(or until
) loop.
$ coco -bcs
# syntax: "do" Block "while"|"until" Condition
do
do then
while x
until y
do {
do {} while (x);
} while (!y);
with update clause while i < l, ++i
while
/until
accepts an update clause after test clause, enabling full emulation of JS for
wrt continue
.
$ coco -bcs
until ok(), step()
continue if hop()
jump()
for (; !ok(); step()) {
if (hop()) {
continue;
}
jump();
}
with else
clause while f() then g() else h()
Preconditional loops can have an else
clause, which runs when the loop body didn't run.
$ coco -bce 'while f() then g() else h()'
var __yet;
for (__yet = true; f();) {
__yet = false;
g();
} if (__yet) {
h();
}
forever for ever
Sugar for while true
.
$ coco -bce 'continue for ever'
for (;;) {}
switch
(as in JS) with multiple conditions and auto break
insertions.
$ coco -bcs
switch n
case 1 then 2
case 3 4 then 5
case [6 7] then 8; fallthrough
default 9
switch
case a
break
case c[d, e]
f
switch (n) {
case 1:
2;
break;
case 3:
case 4:
5;
break;
case 6:
case 7:
8;
// fallthrough
default:
9;
}
switch (false) {
case !a:
break;
case !(c[d] || c[e]):
f;
}
Basically the same as CoffeeScript's switch-when-else, except ours:
- requires less indentation.
-
case
/default
are placed at the same level asswitch
.
-
- supports falling through.
- If the last expression of
case
block isfallthrough
, it becomes a comment instead ofbreak
.
- If the last expression of
- expands arrays in
case
conditions.
Incidentally this is pretty similar to Go's switch
.
case
can be omitted. This form is handy for refactoring nested if
s, e.g.:
unless a()
b()
unless c()
d()
↓
switch
break if a()
b()
break if c()
d()
Each that
in those blocks implicitly refers to the condition value.
$ coco -bcs
that if a
that while b?
switch c case d then that
switch case e then that
var that;
if (that = a) {
that;
}
while ((that = b) != null) {
that;
}
switch (that = c) {
case d:
that;
}
switch (false) {
case !(that = e):
that;
}
$ coco -bce ':label block or expression'
label: {
block || expression;
}
$ coco -se
:pythagoras for a from 1 to 9
for b from a to 99
h = Math.sqrt a*a + b*b
if h % 1 == 0
console.log a, b, h
continue pythagoras
:plain
\end
break plain
\unreachable
3 4 5
5 12 13
6 8 10
7 24 25
8 15 17
9 12 15
end
The syntax is backward from JS to disambiguate from the implicit object literal.
Labeling a function (literal, IIFE sugar, or backcall) gives it a name instead of creating a useless block.
$ coco -bcs
:f ->
:g let
<-:h f
(function f(){
return (function g(){
return f(function h(){});
}.call(this));
});
Infix operators that copy enumerable properties from the right operand to left, and return the left value.
$ coco -bce 'x <<< y <<<< z'
__import(__importAll(x, y), z);
function __importAll(obj, src){
for (var key in src) obj[key] = src[key];
return obj;
}
function __import(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
$ coco -bce 'import {y, (z)}'
this.y = y;
this[z] = z;
-
<<<
is for own properties. It gets optimized to a series of assignments if the right operand is an object literal. -
import
andimport all
are available as aliases.
Copies properties from target object(s) into current this
.
$ coco -bcs
import a, b
import all c
import
f: g
h: i
__import(this, a);
__import(this, b);
__importAll(this, c);
this.f = g;
this.h = i;
function __import(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
function __importAll(obj, src){
for (var key in src) obj[key] = src[key];
return obj;
}
Unary ^
creates a prototypal child of the operand.
$ coco -pe '[c = ^(p = {0}); c.0; c.hasOwnProperty 0; p.isPrototypeOf c]'
[ {}, 0, false, true ]
$ coco -bce 'child = ^parent'
var child;
child = __clone(parent);
function __clone(it){
function fun(){} fun.prototype = it;
return new fun;
}
A bare array to the right of instanceof
is expanded into or
chains.
$ coco -bce 'o instanceof [C, K]'
o instanceof C || o instanceof K;
If used in an expression, delete
returns the original value as opposed to the useless
JS behavior.
$ coco -bce 'f delete @x; delete @y'
var __ref;
f((__ref = this.x, delete this.x, __ref));
delete this.y;
The counterpart of ?
.
$ coco -bce '@a !?= b !? c.d!?'
this.a != null && (this.a = typeof b == 'undefined' || b === null
? b
: c.d == null);
$ coco -bce '@x **= y ** z'
this.x = Math.pow(this.x, Math.pow(y, z));
The precedence and associativity are set to the same as *
//
, not to complicate the hierarchy further.
Binary operators that return the lesser/greater value of the two.
$ coco -bce 'r = a <? b; @c >?= d'
var r;
r = a < b ? a : b;
this.c >= d || (this.c = d);
$ coco -pe '4 >? 3 + 2'
5
- Precedence is same as
<<
.
Unary operators affect each item when applied to an array literal.
$ coco -bcs
@inverts = ~[a, b]
++player<[str def]>
this.inverts = [~a, ~b];
++player['str'], ++player['def'];
When the left operand of *
is a (syntactically obvious) string/array, it is repeated [right operand] times.
$ coco -bcs
[1] * 2
'x' * 3
'z' * y
[1, 1];
'xxx';
__repeatString('z', y);
function __repeatString(str, n){
for (var r = ''; n > 0; (n >>= 1) && (str += str)) if (n & 1) r += str;
return r;
}
The helper function (generated when the right operand is large or non-constant) uses O(logN) algorithm, making "#x" * y
more efficient than the idiom Array(-~y).join('x')
.
When the right operand of *
is a string literal, [].join
is called on the left.
$ coco -bce 'a * "-"'
var __join = [].join;
__join.call(a, "-");
When the right operand of -
//
is a string/regex literal, ''.replace
/''.split
is called on the left.
$ coco -bce 'x - /r/; y / "s"'
var __replace = ''.replace, __split = ''.split;
__replace.call(x, /r/, '');
__split.call(y, "s");
$ coco -pe '({} - /\w/g) / " "'
[ '[', ']' ]
A literal that compiles to an undefined
value.
$ coco -bcs
void
(void, a) -> void
[,,]
(function(__arg, a){});
[void 8, void 8];
- Simply ignored when on top-level or
return
ed. - Works as a placeholder within function parameters or destructuring assignment.
- Implied when
,
follows(
,[
, or another,
.
Simple strings without whitespace can be written by prefixing a backslash rather than enclosing with single quotes.
$ coco -bce '\\ + \" + \word + \"'
'\\' + '"' + 'word' + '"';
Note that closing symbols ()
]
}
,
;
) are disallowed after the first character, so that you can naturally write:
prompt(\?, \!)
Sugar for a bracketted list of strings, either as an array or indexer.
$ coco -bce 'f <[ array of strings ]>'
f(["array", "of", "strings"]);
$ coco -bce 'o<[ property names ]>'
[o['property'], o['names']];
Property names within object literals can be dynamically set using parentheses or interpolated strings.
$ coco -bce 'o = {(paren): 1, "str#ing": 2, (shorthand = 3)}'
var shorthand, o, __ref, __ref2;
o = (__ref = {}, __ref[paren] = 1, __ref["str" + ing] = 2, __ref[__ref2 = shorthand = 3] = __ref2, __ref);
Mixes an object's own properties into the created object.
$ coco -bcs
poq = {p, ...o, q}
abc =
a: true
...: b
...: c
var poq, abc, __ref;
poq = (__ref = {
p: p
}, __import(__ref, o), __ref.q = q, __ref);
abc = (__ref = {
a: true
}, __import(__ref, b), __import(__ref, c));
function __import(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
$ coco -bce '{+x, -y}'
({
x: true,
y: false
});
ref. https://github.com/jashkenas/coffee-script/issues/885
$ coco -bcs
a:~ (@a) -> # setter if the function has one argument
b:~ -> @b # getter if none
c:~ # indent and line them up to define both
-> @c
(@c) ->
# uses `Object.defineProperty` when imported
import x:~ ->
({
set a(a){
this.a = a;
},
get b(){
return this.b;
},
get c(){
return this.c;
},
set c(c){
this.c = c;
}
});
Object.defineProperty(this, 'x', {
get: function(){},
configurable: true,
enumerable: true
});
implicit array a = then b; c
_
Some operators (:
=
:=
<<<
<<<<
return
throw
!
~
delete
typeof
) can take a block on the right, which becomes an array when it contains multiple items.
$ coco -bcs
list =
1
2
atom =
3
var list, atom;
list = [1, 2];
atom = 3;
Leading asterisk denotes an expression or array of expressions (thanks to implicit array).
$ coco -bcs
points =
* x:0 y:1
* x:2 y:3
var points;
points = [
{
x: 0,
y: 1
}, {
x: 2,
y: 3
}
];
$ coco -se
* * 0 1
* 2
[ [ 0, 1 ], 2 ]
This is a sugar over an empty assignment taking an implicit block; the last example is same as writing:
[] =
[] =
0, 1
[] =
2
Borrowing from Smalltalk, numbers can have any base between 2 to 36 in the form RRrXXX.
$ coco -bce '[2r101010, 8r52, 36r16]'
[42, 42, 42];
Underscores within numbers, and alphabets after decimals are ignored.
$ coco -pe '[0xDead_Beef 7_heads]'
[ 3735928559, 7 ]
Expands to comma separated characters or numbers.
$ coco -bce
# syntax: CharOrNum ("to"|"til") CharOrNum ("by" Num)?
[\A to \C]
f 1 til 10 by 2
["A", "B", "C"];
f(1, 3, 5, 7, 9);
$ coco -bcs
//
heregex
#{ y } # normal interpolation
#{ z } # sets the flag part
//?
RegExp('heregex' + y, z);
Same as .source
, but on compile time. Useful for building large regexes piece by piece.
$ coco -bce '/\\/$; //\b#word\b//$'
'\\\\';
'\\b' + word + '\\b';
debugger
works as literal rather than statement, allowing you to suspend anywhere. The return value is undefined
.
$ coco -bce 'f() or debugger'
f() || (function(){
debugger;
}());
$ coco -bce '@@0 @@'
arguments[0](arguments);
Read: @rgument @rray
constructor shorthand ..
_
$ coco -bce '@..classMethod ..'
this.constructor.classMethod(constructor);
...
in an array desugars to ...[]
, which can be used to force implicit array or ignore intermediate items in destructuring.
$ coco -bcs
empty =
...
[first, ..., last] = array
var empty, first, last;
empty = [];
first = array[0], last = array[array.length - 1];
Variables can be interpolated brace-free.
$ coco -bce '"(#id)"'
"(" + id + ")";
Commas after non-callable literals can be omitted when spaced.
$ coco -bce '[null true 1 "2" [3] ->]'
[null, true, 1, "2", [3], function(){}];
automatic dot insertion @0\!
_
Dots before {number,string,identifier}s can be omitted unless spaced.
$ coco -bce '@1"!"l'
this[1]["!"].l;
Similarly:
-
?
becomes?.
if surrounded without space.-
a?b
=>a?.b
-
c?=b
=>c?.=d
-
-
~
,@
and@@
become.~
/.@
/.@@
when they follow previous token without space.
\
cancels subsequent whitespaces a la Perl6.
$ coco -bcs
o\ p # triggers ADI
f \
x # continues line and triggers implicit call
o.p;
f(x);
yada yada yada ...
Short for throw Error('unimplemented')
on top level.
$ coco -e ...
Error: unimplemented
Works just as JS with no propagation to compilation.
$ coco -bce 'f /* implicit call */ x'
f(x);
$ coco ast
Failed at: ast.co
ReferenceError: typo is not defined
at Object.<anonymous> (/usr/tmp/ast.co:248:1)
244| }
245| }
246| return fromJSON;
247| }());
248+ typo;
249| Negatable = {
250| show: function(){
251| return this.negated && '!';
252| },
at Module._compile (module.js:402:26)
at Object.run (/usr/local/lib/coco/lib/node.js:19:19)
at compileScript (/usr/local/lib/coco/lib/command.js:172:14)
at /usr/local/lib/coco/lib/command.js:130:18
at /usr/local/lib/coco/lib/command.js:103:12
at [object Object].<anonymous> (fs.js:107:5)
at [object Object].emit (events.js:61:17)
at afterRead (fs.js:878:12)
at wrapper (fs.js:245:17)
$ coco -icb
coco -cb> with document.body
......... @style.color = \purple
......... @textCentent = \rose
(function(){
this.style.color = 'purple';
this.textCentent = 'rose';
}.call(document.body));
coco -cb>
--json
modifies the behavior of --ast
and --compile
.
$ coco -aje 3
{
"type": "Block",
"lines": [
{
"type": "Literal",
"value": "3",
"line": 1
}
]
}
$ coco -cje '{6 9}'
{
"6": 6,
"9": 9
}
-
-aj
: Serializes the AST in JSON. -
-cj
: Evaluates input, then prints the result in JSON.