UNPKG

ion

Version:

ion language ========================

1,351 lines (1,346 loc) 27.5 kB
ion = require '../' index = require '../compiler' tests = "let x = 10": """ 'use strict'; let x = 10; """ """ for name, value of foo console.log(name + value) """: """ 'use strict'; for (let name in foo) { let value = foo[name]; console.log(name + value); } """ """ for let name, value of {a:1,b:2,c:3} console.log(name + value) """: """ 'use strict'; { let _ref = { a: 1, b: 2, c: 3 }; for (let name in _ref) { let value = _ref[name]; console.log(name + value); } } """ """ for let name in ["a","b","c"] console.log(name) """: """ 'use strict'; { let _ref = [ 'a', 'b', 'c' ]; for (let _i = 0; _i < _ref.length; _i++) { let name = _ref[_i]; console.log(name); } } """ """ for name, index in ["a","b","c"] console.log(name) """: """ 'use strict'; { let _ref = [ 'a', 'b', 'c' ]; for (let _i = 0; _i < _ref.length; _i++) { let index = _i; let name = _ref[_i]; console.log(name); } } """ """ let object = x: 1 y: 2 foo: z: 3 """: """ 'use strict'; let object = { x: 1, y: 2, foo: { z: 3 } }; """ """ let array = [] 1 2 3 """: """ 'use strict'; let array = [ 1, 2, 3 ]; """ """ let kids = [] {} name: "Alpha" age: 10 {} name: "Beta" age: 8 """: """ 'use strict'; let kids = [ { name: 'Alpha', age: 10 }, { name: 'Beta', age: 8 } ]; """ """ try doSomething(1) catch e log(e) """: """ 'use strict'; try { doSomething(1); } catch (e) { log(e); } """ """ try doSomething(1) finally log(e) """: """ 'use strict'; try { doSomething(1); } finally { log(e); } """ """ try doSomething(1) catch e console.error(e) finally log(e) """: """ 'use strict'; try { doSomething(1); } catch (e) { console.error(e); } finally { log(e); } """ """ for key, name of foo if name is 'a' break else if name is 'b' continue else if name is 'c' return else if name is 'd' throw new Error("D") else return x: 1 y: 2 """: """ 'use strict'; for (let key in foo) { let name = foo[key]; if (name === 'a') { break; } else if (name === 'b') { continue; } else if (name === 'c') { return; } else if (name === 'd') { throw new Error('D'); } else { return { x: 1, y: 2 }; } } """ """ console.log("Hello {{name}}") """: """ 'use strict'; console.log('Hello ' + name); """ """ console.log("{{name}}") """: """ 'use strict'; console.log('' + name); """ """ console.log("{{ 1 }}{{ 2 }}") """: """ 'use strict'; console.log('' + 1 + 2); """ """ return "" <html> <head><title>{{ title }}</title></head> <body> {{ body }} </body> </html> """: """ 'use strict'; return '<html>\\n <head><title>' + title + '</title></head>\\n <body>\\n ' + body + '\\n </body>\\n</html>'; """ """ return '' <html> <head><title>{{ title }}</title></head> <body> {{ body }} </body> </html> """: """ 'use strict'; return '<html>\\n <head><title>{{ title }}</title></head>\\n <body>\\n {{ body }}\\n </body>\\n</html>'; """ """ do -> x """: """ 'use strict'; (function () { return x; }()); """ """ do (x, y) => x + y """: """ 'use strict'; const ion = require('ion'); ion.bind(function (x, y) { return x + y; }, this)(x, y); """ """ const ion = import "ion" """: """ 'use strict'; const ion = require('ion'); """ """ export secret: 97542 """: """ 'use strict'; module.exports = exports = { secret: 97542 }; """ """ export let x = 1, y = 2 """: """ 'use strict'; let x = exports.x = 1, y = exports.y = 2; """ """ export const x = 1 y = 2 z = 3 """: """ 'use strict'; const x = exports.x = 1, y = exports.y = 2, z = exports.z = 3; """ """ let {x,y} = {x:1,y:2} """: """ 'use strict'; let _ref = { x: 1, y: 2 }; let x = _ref.x; let y = _ref.y; """ """ for key, {x:[a,b],y:{c:d}} of points console.log(x, y) """: """ 'use strict'; for (let key in points) { let _ref = points[key]; let a = _ref.x[0]; let b = _ref.x[1]; let d = _ref.y.c; console.log(x, y); } """ """ for {x:[a,b],y:{c:d}}, index in points console.log(x, y) """: """ 'use strict'; for (let _i = 0; _i < points.length; _i++) { let index = _i; let _ref = points[_i]; let a = _ref.x[0]; let b = _ref.x[1]; let d = _ref.y.c; console.log(x, y); } """ """ foo ? bar """: """ 'use strict'; foo != null ? foo : bar; """ """ foo ?? bar """: """ 'use strict'; foo != void 0 ? foo : bar; """ """ let x x ?= y """: """ 'use strict'; let x; x = x != null ? x : y; """ """ let x x ??= y """: """ 'use strict'; let x; x = x != void 0 ? x : y; """ """ for const x, index in foo log(x) """: """ 'use strict'; for (let _i = 0; _i < foo.length; _i++) { const index = _i; const x = foo[_i]; log(x); } """ """ let x = 1, y = 2 [x,y] = [y,x] """: """ 'use strict'; let x = 1, y = 2; const _ref = [ y, x ]; x = _ref[0]; y = _ref[1]; """ """ a?.b """: """ 'use strict'; a != null ? a.b : void 0; """ """ a?.b.c?.d """: """ 'use strict'; a != null ? a.b.c != null ? a.b.c.d : void 0 : void 0; """ """ a?() """: """ 'use strict'; a != null ? a() : void 0; """ """ a?.b?.c?() """: """ 'use strict'; a != null ? a.b != null ? a.b.c != null ? a.b.c() : void 0 : void 0 : void 0; """ """ a?.b().c?() """: """ 'use strict'; a != null ? a.b().c != null ? a.b().c() : void 0 : void 0; """ """ let y = (x) -> 2 """: """ 'use strict'; let y = function (x) { return 2; }; """ """ s? """: """ 'use strict'; s != null; """ """ # also test comments let regex = /foo/ """: """ 'use strict'; let regex = /foo/; """ """ for let i = 0; i < 10; i++ console.log(i) """: """ 'use strict'; for (let i = 0; i < 10; i++) { console.log(i); } """ """ for key of object if key[0] isnt '_' for c in key console.log(c) """: """ 'use strict'; for (let key in object) { if (key[0] !== '_') { for (let _i = 0; _i < key.length; _i++) { let c = key[_i]; console.log(c); } } } """ """ console.log([key for key of object if key is cool]) """: """ 'use strict'; let _ref = []; for (let key in object) { if (key === cool) { _ref.push(key); } } console.log(_ref); """ """ console.log( 1 2 {} x: 1 y: 2 ) """: """ 'use strict'; console.log(1, 2, { x: 1, y: 2 }); """ """ let x = -> try foo() bar() catch e baz() """: """ 'use strict'; let x = function () { try { foo(); bar(); } catch (e) { baz(); } }; """ # empty comment block statement """ if foo # bar """: """ 'use strict'; if (foo) { } """ # function parameter default values """ let trim = (a = "") -> a.trim() """: """ 'use strict'; let trim = function (a) { if (a == null) a = ''; return a.trim(); }; """ # function call with single property names """ foo( 1 2 ) """: """ 'use strict'; foo(1, 2); """ """ compile( foo: 1 bar: 2 baz: a: 1 b: 2 ) """: """ 'use strict'; compile({ foo: 1, bar: 2, baz: { a: 1, b: 2 } }); """ """ let array = [1,2,3] 4 5 6 """: """ 'use strict'; let array = [ 1, 2, 3, 4, 5, 6 ]; """ """ let point = new Point(10, 20) z: 30 """: """ 'use strict'; const ion = require('ion'); let point = ion.patch.combine(new Point(10, 20), { z: 30 }); """ """ let object = {x:1, y:2} z: 3 """: """ 'use strict'; let object = { x: 1, y: 2, z: 3 }; """ """ let origin = new Point x: 1 y: 2 """: """ 'use strict'; const ion = require('ion'); let origin = ion.patch.combine(new Point(), { x: 1, y: 2 }); """ """ let origin = new Line a: new Point x: 0 y: 0 b: new Point x: 10 y: 20 """: """ 'use strict'; const ion = require('ion'); let origin = ion.patch.combine(new Line(), { a: ion.patch.combine(new Point(), { x: 0, y: 0 }), b: ion.patch.combine(new Point(), { x: 10, y: 20 }) }); """ """ input # ignore this comment x: 10 y: 20 z: # also ignore this one a: 1 b: 2 w: new Point x: 0 y: 0 """: """ 'use strict'; const ion = require('ion'); ion.patch.combine(input, { x: 10, y: 20, z: { a: 1, b: 2 }, w: ion.patch.combine(new Point(), { x: 0, y: 0 }) }); """ """ let point = new Point [x]: 1 [y]: 2 """: """ 'use strict'; let point = new Point(); { point[x] = 1; point[y] = 2; } """ """ let self = @ let x = @x let y = @.y let z = this.z """: """ 'use strict'; let self = this; let x = this.x; let y = this.y; let z = this.z; """ """ let x = {} [key]: value """: """ 'use strict'; let x = {}; x[key] = value; """ """ if foo return {} for key, value of object [key]: value """: """ 'use strict'; if (foo) { let _ref = {}; for (let key in object) { let value = object[key]; _ref[key] = value; } return _ref; } """ # test for syntax errors """ for x, y, z of foo log(foo) """: {line:1, column:11} """ export let x """: {line:1, column:12} """ export const x """: {line:1, column:14} """ export const x = 1 export {y:2} """: {line:2,column:1} """ const x = 1 x = 2 """: {line:2, column:1} """ const double = (x) -> x *= 2 return x """: """ 'use strict'; const double = function (x) { x *= 2; return x; }; """ """ x = 1 """: {line:1, column:1} """ let x = 1 let x = 2 """: {line:2, column:5} # make sure we allow variable shadowing """ let x = 1 const double = (x) -> return x """: """ 'use strict'; let x = 1; const double = function (x) { return x; }; """ """ console.log(x) if a let x = 1 """: {line:1, column:13} """ if typeof a is 'string' and void a and delete a.b log(a) """: """ 'use strict'; if (typeof a === 'string' && void a && delete a.b) { log(a); } """ # testing error correct location with comments and indents """ if 1 # 1 # 2 x = 12 """: {line:4, column:5} # testing parsing error correct location """ export const BlockStatement = isBlock: true newScope: tr ue """: {line:4, column:22} """ export class Foo extends import 'Bar' constructor: (x,y) -> @x = x @y = y properties: x: 1 y: 2 getXY: -> [@x,@y] isThisPropertyStatic: true """: """ 'use strict'; const ion = require('ion'); const Foo = ion.defineClass({ name: 'Foo', constructor: function Foo(x, y) { this.x = x; this.y = y; }, properties: { x: 1, y: 2, getXY: function () { return [ this.x, this.y ]; } }, isThisPropertyStatic: true }, require('Bar')); module.exports = exports = Foo; """ """ const double(a) -> a * 2 """: """ 'use strict'; function double(a) { return a * 2; } """ """ const double(a) -> a * 2 double = 12 """: {line:2, column: 1} """ let object = const double(a) -> a * 2 if a [key]: value else foo: double(2) """: """ 'use strict'; let object = {}; { function double(a) { return a * 2; } if (a) { object[key] = value; } else { object.foo = double(2); } } """ """ let items = [] for key, value of window value """: """ 'use strict'; let items = []; for (let key in window) { let value = window[key]; items.push(value); } """ """ let foo = div() span() 'Hello' """: """ 'use strict'; const ion = require('ion'); let foo = div(); let _ref = span(); ion.add(_ref, 'Hello'); ion.add(foo, _ref); """ # we don't auto import ion if the user already declares an ion variable """ const ion = import './' let foo = div() span() 'Hello' """: """ 'use strict'; const ion = require('./'); let foo = div(); let _ref = span(); ion.add(_ref, 'Hello'); ion.add(foo, _ref); """ """ const translate({x,y}) -> x++ y++ return {x,y} """: """ 'use strict'; function translate(_ref) { let x = _ref.x; let y = _ref.y; x++; y++; return { x: x, y: y }; } """ """ let x = foo( '' multiline string literal "" multiline string template ) """: """ 'use strict'; let x = foo('multiline string literal', 'multiline string template'); """ """ assert x is 2 """: """ 'use strict'; if (!(x === 2)) throw new Error('Assertion Failed: (x is 2)'); """ """ export class Point constructor: -> # call super with arguments object super # call super again with explicit arguments super(width, height) # calling twice is silly, but legal properties: x: 0 y: 0 superIdentifier: (x, y) -> super superExplicit: (a, b) -> super(a, b) """: """ 'use strict'; const ion = require('ion'); const Point = ion.defineClass({ name: 'Point', constructor: function Point() { Point.super.apply(this, arguments); Point.super.call(this, width, height); }, properties: { x: 0, y: 0, superIdentifier: function (x, y) { return Point.super.prototype.superIdentifier.apply(this, arguments); }, superExplicit: function (a, b) { return Point.super.prototype.superExplicit.call(this, a, b); } } }); module.exports = exports = Point; """ """ const spreadFunction1(a, b, ...c) -> log(1) const spreadFunction2(a, b, ...c, d, e) -> log(2) const spreadFunction3(a,b, ...c, {d,e}) -> log(3) """: """ 'use strict'; function spreadFunction1(a, b, ___c) { let c = Array.prototype.slice.call(arguments, 2); log(1); } function spreadFunction2(a, b, ___c, d, e) { let c = Array.prototype.slice.call(arguments, 2, arguments.length - 2); d = arguments[arguments.length - 2]; e = arguments[arguments.length - 1]; log(2); } function spreadFunction3(a, b, ___c, _ref) { let c = Array.prototype.slice.call(arguments, 2, arguments.length - 1); _ref = arguments[arguments.length - 1]; let d = _ref.d; let e = _ref.e; log(3); } """ """ # default value for a should be set before b const foo(a = 0, b = a) -> a + b """: """ 'use strict'; function foo(a, b) { if (a == null) a = 0; if (b == null) b = a; return a + b; } """ """ export template -> # cannot define classes in templates class Poo """: {line: 3, column: 5} """ export template -> # cannot for loop in templates for let i = 0; i < 10; i++ console.log(i) """: {line: 3, column: 5} """ export template -> # cannot export in templates export x """: {line: 3, column: 5} """ export template -> # cannot try/catch in templates try return 0 catch e return 1 """: {line: 3, column: 5} """ export template -> # cannot throw errors in templates throw new Error """: {line: 3, column: 5} # """ # # cannot use => syntax in templates # export template => 0 # """: {line: 2, column: 8} """ export template -> const x = 12 # cannot assign to const variables, make sure enforced within template x = 10 return x """: {line: 4, column: 5} """ export template -> let x = 12 # cannot assign to let variables either. x = 12 return x """: {line: 4, column: 5} """ export template -> let x = {y:10} # cannot assign to anything really. x.y = 12 return x.y """: {line: 4, column: 5} """ export template (a) -> # cannot assign to parameters either a = 10 return a """: {line: 3, column: 5} """ export class Foo constructor: -> # there was a problem with existential operators not processing within class definitions if properties? log(properties) """: """ 'use strict'; const ion = require('ion'); const Foo = ion.defineClass({ name: 'Foo', constructor: function Foo() { if (properties != null) { log(properties); } } }); module.exports = exports = Foo; """ """ const ctor = @@ const ctorName = @@name """: """ 'use strict'; const ctor = this.constructor; const ctorName = this.constructor.name; """ """ const inlineThrow() -> throw new Error('inline throw') """: """ 'use strict'; function inlineThrow() { throw new Error('inline throw'); } """ """ class DynamicExpression observe: -> let x = @x ?= [] """: """ 'use strict'; const ion = require('ion'); const DynamicExpression = ion.defineClass({ name: 'DynamicExpression', observe: function () { let x = this.x = this.x != null ? this.x : []; } }); DynamicExpression; """ """ let a = new Point( 1 2 ) """: """ 'use strict'; let a = new Point(1, 2); """ """ let x = [y for y in z] """: """ 'use strict'; let _ref = []; for (let _i = 0; _i < z.length; _i++) { let y = z[_i]; _ref.push(y); } let x = _ref; """ """ return z: [] let items = [3,2,1] for item in items item * 2 """: """ 'use strict'; let _ref = []; { let items = [ 3, 2, 1 ]; for (let _i = 0; _i < items.length; _i++) { let item = items[_i]; _ref.push(item * 2); } } return { z: _ref }; """ """ let x = `y == null` """: """ 'use strict'; let x = y == null; """ """ # should get accurate error locations even from inline javascript expressions let x = `y := null` """: {line: 2, column: 13} """ let x = 0 in Array let y = "foo" instanceof String """: """ 'use strict'; let x = 0 in Array; let y = 'foo' instanceof String; """ """ let output output := x: 1 y: 2 """: """ 'use strict'; const ion = require('ion'); let output; output = ion.patch.combine(output, { x: 1, y: 2 }); """ """ output for a in b [c]: d """: """ 'use strict'; let _ref = output; for (let _i = 0; _i < b.length; _i++) { let a = b[_i]; _ref[c] = d; } _ref; """ """ # # # """: """ 'use strict'; """ """ [a for a in b] [a for a in c] """: """ 'use strict'; let _ref = []; for (let _i = 0; _i < b.length; _i++) { let a = b[_i]; _ref.push(a); } _ref; let _ref2 = []; for (let _i2 = 0; _i2 < c.length; _i2++) { let a = c[_i2]; _ref2.push(a); } _ref2; """ # """ # let text = "" # foo # // #bar # #baz # """: null """ let array = [] 1, 0, 0 0, 1, 0 0, 0, 1 """: """ 'use strict'; let array = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; """ """ import(foo).bar """: """ 'use strict'; require(foo).bar; """ """ let x = [] -> """: """ 'use strict'; let x = [function () { }]; """ """ x delete: true """: """ 'use strict'; const ion = require('ion'); ion.patch.combine(x, { delete: true }); """ """ return style: fontSize: "0.7em" "delete" """: """ 'use strict'; const ion = require('ion'); let _ref = {}; { _ref.style = ion.patch.combine(_ref.style, { fontSize: '0.7em' }); ion.add(_ref, 'delete'); } return _ref; """ # """ # content: # name: 'foo' # 1 # 2 # """: """ # 'use strict'; # const ion = require('ion'); # { # content.name = 'foo'; # ion.add(content, 1); # ion.add(content, 2); # } # """ # """ # for name, file of directory # write(name, file) # else # delete(name) # """: """ # 'use strict'; # for (let name in directory) { # let file = directory[name]; # write(name, file); # } # """ # # """ # # Point # # x: 10 # # y: delete # # """: null # """ # foo( # bar() # baz( # 1 # 2 # ) # ) # """: """ # 'use strict'; # foo(bar(), baz(1, 2)); # """ # # the following is similar to input from a script tag. # "\n console.log('ion')": """ # 'use strict'; # console.log('ion'); # """ # # """ # # let a = template -> # # let b = template -> 1 # # return 2 # # """: null if global.window? return exports.test = -> for input, expected of tests options = {target:'es6'} if expected is null loc = false console.log '---------------------------------------------------' console.log JSON.stringify index.compile(input, ion.patch({postprocess:false,loc:loc}, options)), null, ' ' console.log '-Postprocessed-------------------------------------' console.log JSON.stringify index.compile(input, ion.patch({generate:false,loc:loc}, options)), null, ' ' console.log '---------------------------------------------------' console.log index.compile input, ion.patch({loc:loc}, options) else if typeof expected is 'object' # expected to throw an error error = null try index.compile input, options catch e error = e # check equivalent fields for key, value of expected if value isnt e[key] throw new Error "\n#{JSON.stringify e}\n!=\n#{JSON.stringify expected}" if not error? throw new Error "Expected an error: #{JSON.stringify expected}" else output = index.compile input, options if output.trim() isnt expected.trim() console.log '-Output---------------------------------------------' console.log output throw new Error "\n#{output}\n!=\n#{expected}" return