336 lines
7.3 KiB
TypeScript
336 lines
7.3 KiB
TypeScript
import { expect, describe, test } from 'bun:test'
|
|
import { parser } from '../shrimp'
|
|
|
|
import '../shrimp.grammar' // Importing this so changes cause it to retest!
|
|
|
|
describe('pipe expressions', () => {
|
|
test('simple pipe expression', () => {
|
|
expect('echo hello | grep h').toMatchTree(`
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier echo
|
|
PositionalArg
|
|
Identifier hello
|
|
operator |
|
|
FunctionCall
|
|
Identifier grep
|
|
PositionalArg
|
|
Identifier h
|
|
`)
|
|
})
|
|
|
|
test('multi-stage pipe chain', () => {
|
|
expect('find files | filter active | sort').toMatchTree(`
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier find
|
|
PositionalArg
|
|
Identifier files
|
|
operator |
|
|
FunctionCall
|
|
Identifier filter
|
|
PositionalArg
|
|
Identifier active
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier sort
|
|
`)
|
|
})
|
|
|
|
test('pipe with identifier', () => {
|
|
expect('get-value | process').toMatchTree(`
|
|
PipeExpr
|
|
FunctionCallOrIdentifier
|
|
Identifier get-value
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier process
|
|
`)
|
|
})
|
|
|
|
test('pipe expression in assignment', () => {
|
|
expect('result = echo hello | grep h').toMatchTree(`
|
|
Assign
|
|
AssignableIdentifier result
|
|
Eq =
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier echo
|
|
PositionalArg
|
|
Identifier hello
|
|
operator |
|
|
FunctionCall
|
|
Identifier grep
|
|
PositionalArg
|
|
Identifier h
|
|
`)
|
|
})
|
|
|
|
test('pipe with inline function', () => {
|
|
expect('items | each do x: x end').toMatchTree(`
|
|
PipeExpr
|
|
FunctionCallOrIdentifier
|
|
Identifier items
|
|
operator |
|
|
FunctionCall
|
|
Identifier each
|
|
PositionalArg
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
colon :
|
|
FunctionCallOrIdentifier
|
|
Identifier x
|
|
keyword end
|
|
`)
|
|
})
|
|
|
|
test(`double trouble (do keyword isn't over eager)`, () => {
|
|
expect(`
|
|
double 2 | double`).toMatchTree(`
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier double
|
|
PositionalArg
|
|
Number 2
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier double
|
|
`)
|
|
})
|
|
|
|
test('string literals can be piped', () => {
|
|
expect(`'hey there' | echo`).toMatchTree(`
|
|
PipeExpr
|
|
String
|
|
StringFragment hey there
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo
|
|
`)
|
|
})
|
|
|
|
test('number literals can be piped', () => {
|
|
expect(`42 | echo`).toMatchTree(`
|
|
PipeExpr
|
|
Number 42
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo`)
|
|
|
|
expect(`4.22 | echo`).toMatchTree(`
|
|
PipeExpr
|
|
Number 4.22
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo`)
|
|
})
|
|
|
|
test('null literals can be piped', () => {
|
|
expect(`null | echo`).toMatchTree(`
|
|
PipeExpr
|
|
Null null
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo`)
|
|
})
|
|
|
|
test('boolean literals can be piped', () => {
|
|
expect(`true | echo`).toMatchTree(`
|
|
PipeExpr
|
|
Boolean true
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo`)
|
|
})
|
|
|
|
test('array literals can be piped', () => {
|
|
expect(`[1 2 3] | echo`).toMatchTree(`
|
|
PipeExpr
|
|
Array
|
|
Number 1
|
|
Number 2
|
|
Number 3
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo
|
|
`)
|
|
})
|
|
|
|
test('dict literals can be piped', () => {
|
|
expect(`[a=1 b=2 c=3] | echo`).toMatchTree(`
|
|
PipeExpr
|
|
Dict
|
|
NamedArg
|
|
NamedArgPrefix a=
|
|
Number 1
|
|
NamedArg
|
|
NamedArgPrefix b=
|
|
Number 2
|
|
NamedArg
|
|
NamedArgPrefix c=
|
|
Number 3
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('pipe continuation', () => {
|
|
test('pipe on next line', () => {
|
|
expect(`hello
|
|
| echo`).toMatchTree(`
|
|
PipeExpr
|
|
FunctionCallOrIdentifier
|
|
Identifier hello
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo
|
|
`)
|
|
|
|
expect(`echo hello
|
|
| grep h`).toMatchTree(`
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier echo
|
|
PositionalArg
|
|
Identifier hello
|
|
operator |
|
|
FunctionCall
|
|
Identifier grep
|
|
PositionalArg
|
|
Identifier h
|
|
`)
|
|
})
|
|
|
|
test('pipe on next non-empty line', () => {
|
|
expect(`hello
|
|
|
|
|
|
| echo`).toMatchTree(`
|
|
PipeExpr
|
|
FunctionCallOrIdentifier
|
|
Identifier hello
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo
|
|
`)
|
|
})
|
|
|
|
test('multi-line pipe chain', () => {
|
|
expect(`echo hello
|
|
| grep h
|
|
| sort`).toMatchTree(`
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier echo
|
|
PositionalArg
|
|
Identifier hello
|
|
operator |
|
|
FunctionCall
|
|
Identifier grep
|
|
PositionalArg
|
|
Identifier h
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier sort
|
|
`)
|
|
})
|
|
|
|
test('pipe with indentation', () => {
|
|
expect(`echo hello
|
|
| grep h
|
|
| sort`).toMatchTree(`
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier echo
|
|
PositionalArg
|
|
Identifier hello
|
|
operator |
|
|
FunctionCall
|
|
Identifier grep
|
|
PositionalArg
|
|
Identifier h
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier sort
|
|
`)
|
|
})
|
|
|
|
test('pipe after operand on next line (trailing pipe style)', () => {
|
|
expect(`echo hello |
|
|
grep h`).toMatchTree(`
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier echo
|
|
PositionalArg
|
|
Identifier hello
|
|
operator |
|
|
FunctionCall
|
|
Identifier grep
|
|
PositionalArg
|
|
Identifier h
|
|
`)
|
|
})
|
|
|
|
test('same-line pipes still work', () => {
|
|
expect('echo hello | grep h | sort').toMatchTree(`
|
|
PipeExpr
|
|
FunctionCall
|
|
Identifier echo
|
|
PositionalArg
|
|
Identifier hello
|
|
operator |
|
|
FunctionCall
|
|
Identifier grep
|
|
PositionalArg
|
|
Identifier h
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier sort
|
|
`)
|
|
})
|
|
|
|
test('lots of pipes', () => {
|
|
expect(`
|
|
'this should help readability in long chains'
|
|
| split ' '
|
|
| map (ref str.to-upper)
|
|
| join '-'
|
|
| echo
|
|
`).toMatchTree(`
|
|
PipeExpr
|
|
String
|
|
StringFragment this should help readability in long chains
|
|
operator |
|
|
FunctionCall
|
|
Identifier split
|
|
PositionalArg
|
|
String
|
|
StringFragment
|
|
operator |
|
|
FunctionCall
|
|
Identifier map
|
|
PositionalArg
|
|
ParenExpr
|
|
FunctionCall
|
|
Identifier ref
|
|
PositionalArg
|
|
DotGet
|
|
IdentifierBeforeDot str
|
|
Identifier to-upper
|
|
operator |
|
|
FunctionCall
|
|
Identifier join
|
|
PositionalArg
|
|
String
|
|
StringFragment -
|
|
operator |
|
|
FunctionCallOrIdentifier
|
|
Identifier echo
|
|
`)
|
|
})
|
|
})
|