Skip to content

Commit

Permalink
feat: support short syntax for map functions
Browse files Browse the repository at this point in the history
fixes #344
  • Loading branch information
kantord committed Sep 15, 2019
1 parent 635fe95 commit 6a17c84
Show file tree
Hide file tree
Showing 7 changed files with 301 additions and 1 deletion.
16 changes: 16 additions & 0 deletions docs/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ For mapping objects, use a curried function:
```


### Shorthand for map

For simplifying map calls there is a syntactic sugar: instead of writing `map $ =>` you can write `~`.

For example instead of

```
["Hello", "World!"] | map $ => {"word": $}
```

you can write:

```
["Hello", "World!"] | ~ {"word": $}
```

## sortBy \

Takes an array as input and sorts it using the supplied function.
Expand Down
163 changes: 163 additions & 0 deletions src/__tests__/__snapshots__/interpreter.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ exports[`interpreter correct target code {'foo': ('bar' | 'baz')} 1`] = `"(funct
exports[`interpreter correct target code {each $: (length) in $} 1`] = `"(function(_) { return (function(input) { return (_.objectify(Array.from(((function (input) {return _.map((function(input) {return [input,(_.length(input))]}))(input)})(input)))))})})"`;
exports[`interpreter correct target code ~ " " 1`] = `"(function(_) { return (function(input) { return _.map((function(input) {return \\" \\"}))(input)})})"`;
exports[`interpreter correct target code ~{"original": $.foo} |~ {"new": $} 1`] = `"(function(_) { return (function(input) { return (function (input) {return _.map((function(input) {return (_.objectify(Array.from([[\\"new\\",input]])))}))(input)})(_.map((function(input) {return (_.objectify(Array.from([[\\"original\\",input.foo]])))}))(input))})})"`;
exports[`interpreter correct target code -(3 * 2) -1 > -1.34 * 3 && true 1`] = `"(function(_) { return (function(input) { return (-((3*2)))-1>(-(1.34))*3&&true})})"`;
exports[`interpreter correct target code 3 * 2 -1 != -1.34 * 3 1`] = `"(function(_) { return (function(input) { return 3*2-1!==(-(1.34))*3})})"`;
Expand Down Expand Up @@ -5503,6 +5507,165 @@ Object {
}
`;
exports[`interpreter correct target tree ~ " " 1`] = `
Object {
"status": true,
"value": Object {
"name": "functionCall",
"value": Object {
"left": Object {
"name": "identifier",
"value": "map",
},
"right": Object {
"name": "lambda",
"value": Object {
"definition": Object {
"name": "primitive",
"value": "\\" \\"",
},
"variable": "input",
},
},
},
},
}
`;
exports[`interpreter correct target tree ~{"original": $.foo} |~ {"new": $} 1`] = `
Object {
"status": true,
"value": Object {
"name": "pipe",
"value": Object {
"left": Object {
"name": "functionCall",
"value": Object {
"left": Object {
"name": "identifier",
"value": "map",
},
"right": Object {
"name": "lambda",
"value": Object {
"definition": Object {
"end": Object {
"column": 21,
"line": 1,
"offset": 20,
},
"name": "object",
"start": Object {
"column": 2,
"line": 1,
"offset": 1,
},
"value": Array [
Object {
"end": Object {
"column": 20,
"line": 1,
"offset": 19,
},
"name": "simpleList",
"start": Object {
"column": 3,
"line": 1,
"offset": 2,
},
"value": Array [
Object {
"name": "tuple",
"value": Array [
Object {
"name": "primitive",
"value": "\\"original\\"",
},
Object {
"name": "valueProp",
"value": Object {
"left": Object {
"name": "variable",
"value": "$",
},
"optional": false,
"right": ".foo",
},
},
],
},
],
},
],
},
"variable": "input",
},
},
},
},
"right": Object {
"name": "functionCall",
"value": Object {
"left": Object {
"name": "identifier",
"value": "map",
},
"right": Object {
"name": "lambda",
"value": Object {
"definition": Object {
"end": Object {
"column": 35,
"line": 1,
"offset": 34,
},
"name": "object",
"start": Object {
"column": 25,
"line": 1,
"offset": 24,
},
"value": Array [
Object {
"end": Object {
"column": 34,
"line": 1,
"offset": 33,
},
"name": "simpleList",
"start": Object {
"column": 26,
"line": 1,
"offset": 25,
},
"value": Array [
Object {
"name": "tuple",
"value": Array [
Object {
"name": "primitive",
"value": "\\"new\\"",
},
Object {
"name": "variable",
"value": "$",
},
],
},
],
},
],
},
"variable": "input",
},
},
},
},
},
},
}
`;
exports[`interpreter correct target tree -(3 * 2) -1 > -1.34 * 3 && true 1`] = `
Object {
"status": true,
Expand Down
1 change: 1 addition & 0 deletions src/__tests__/descriptions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const exclude = [
'collections',
'pipe.js',
'ternary.js',
'mapFunctionCall.js',
'math'
]
const files = fs
Expand Down
10 changes: 10 additions & 0 deletions src/__tests__/interpreter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ x`
input: ['Hello', 'World'],
output: [' ', ' ']
},
{
sourceCode: `~ " "`,
input: ['Hello', 'World'],
output: [' ', ' ']
},
{
sourceCode: `{"original": $.foo} | {"new": $}`,
input: { foo: 42 },
Expand All @@ -153,6 +158,11 @@ x`
input: [{ foo: 42 }, { foo: 'hello' }],
output: [{ new: { original: 42 } }, { new: { original: 'hello' } }]
},
{
sourceCode: `~{"original": $.foo} |~ {"new": $}`,
input: [{ foo: 42 }, { foo: 'hello' }],
output: [{ new: { original: 42 } }, { new: { original: 'hello' } }]
},
{
sourceCode: `map $ => {"original": $.foo} | "foo"`,
input: [{ foo: 42 }, { foo: 'hello' }],
Expand Down
78 changes: 78 additions & 0 deletions src/parsers/__tests__/mapFunctionCall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import parser from '../mapFunctionCall'

describe('functionCall parser', () => {
it('doesnt parse ~', () => {
expect(parser.parse('~').status).toBe(false)
})
it('parses ~ 4', () => {
expect(parser.parse('~ 4').status).toBe(true)
})

it('parses ~ $ + 3.1', () => {
expect(parser.parse('~ $ + 3.1').status).toBe(true)
})

it('returns correct value', () => {
expect(parser.parse('~ 4: "; "').value).toEqual({
name: 'functionCall',
value: {
left: {
name: 'identifier',
value: 'map'
},

right: {
name: 'lambda',
value: {
variable: 'input',
definition: {
name: 'tuple',
value: [
{
name: 'primitive',
value: '4'
},
{
name: 'primitive',
value: '"; "'
}
]
}
}
}
}
})
})

it('returns correct value', () => {
expect(parser.parse('~ ", ": "; "').value).toEqual({
name: 'functionCall',
value: {
left: {
name: 'identifier',
value: 'map'
},

right: {
name: 'lambda',
value: {
variable: 'input',
definition: {
name: 'tuple',
value: [
{
name: 'primitive',
value: '", "'
},
{
name: 'primitive',
value: '"; "'
}
]
}
}
}
}
})
})
})
31 changes: 31 additions & 0 deletions src/parsers/mapFunctionCall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// @flow

import P from 'parsimmon'
import crap from './crap'

import type { FunctionCallNodeType, NodeType } from '../types'

const FunctionCallParser = P.lazy((): mixed => {
const TupleParser = require('./collections/tuple').default
return P.string('~')
.then(crap)
.then(TupleParser)
.map((definition: NodeType): FunctionCallNodeType => ({
name: 'functionCall',
value: {
left: {
name: 'identifier',
value: 'map'
},
right: {
name: 'lambda',
value: {
variable: 'input',
definition
}
}
}
}))
})

export default FunctionCallParser
3 changes: 2 additions & 1 deletion src/parsers/section.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import P from 'parsimmon'
import FunctionCallParser from './functionCall'
import MapFunctionCallParser from './mapFunctionCall'
import MathParser from './math/math'

export default P.alt(MathParser, FunctionCallParser)
export default P.alt(MathParser, FunctionCallParser, MapFunctionCallParser)

0 comments on commit 6a17c84

Please sign in to comment.