286 lines
6.1 KiB
TypeScript
286 lines
6.1 KiB
TypeScript
import { expect, describe, test } from 'bun:test'
|
|
|
|
import '../shrimp.grammar' // Importing this so changes cause it to retest!
|
|
|
|
describe('calling functions', () => {
|
|
test('call with no args', () => {
|
|
expect('tail').toMatchTree(`
|
|
FunctionCallOrIdentifier
|
|
Identifier tail
|
|
`)
|
|
})
|
|
|
|
test('call with arg', () => {
|
|
expect('tail path').toMatchTree(`
|
|
FunctionCall
|
|
Identifier tail
|
|
PositionalArg
|
|
Identifier path
|
|
`)
|
|
})
|
|
|
|
test('call with arg and named arg', () => {
|
|
expect('tail path lines=30').toMatchTree(`
|
|
FunctionCall
|
|
Identifier tail
|
|
PositionalArg
|
|
Identifier path
|
|
NamedArg
|
|
NamedArgPrefix lines=
|
|
Number 30
|
|
`)
|
|
})
|
|
|
|
test('call with dashed named arg', () => {
|
|
expect('tail pre-lines=30 path').toMatchTree(`
|
|
FunctionCall
|
|
Identifier tail
|
|
NamedArg
|
|
NamedArgPrefix pre-lines=
|
|
Number 30
|
|
PositionalArg
|
|
Identifier path
|
|
`)
|
|
})
|
|
|
|
test('call with function', () => {
|
|
expect(`tail do x: x end`).toMatchTree(`
|
|
FunctionCall
|
|
Identifier tail
|
|
PositionalArg
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
colon :
|
|
FunctionCallOrIdentifier
|
|
Identifier x
|
|
keyword end
|
|
`)
|
|
})
|
|
|
|
test('call with arg and function', () => {
|
|
expect(`tail true do x: x end`).toMatchTree(`
|
|
FunctionCall
|
|
Identifier tail
|
|
PositionalArg
|
|
Boolean true
|
|
PositionalArg
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
colon :
|
|
FunctionCallOrIdentifier
|
|
Identifier x
|
|
keyword end
|
|
`)
|
|
})
|
|
|
|
test('call with function in named arg', () => {
|
|
expect(`tail callback=do x: x end`).toMatchTree(`
|
|
FunctionCall
|
|
Identifier tail
|
|
NamedArg
|
|
NamedArgPrefix callback=
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
colon :
|
|
FunctionCallOrIdentifier
|
|
Identifier x
|
|
keyword end
|
|
`)
|
|
})
|
|
|
|
|
|
test('command with arg that is also a command', () => {
|
|
expect('tail tail').toMatchTree(`
|
|
FunctionCall
|
|
Identifier tail
|
|
PositionalArg
|
|
Identifier tail
|
|
`)
|
|
|
|
expect('tai').toMatchTree(`
|
|
FunctionCallOrIdentifier
|
|
Identifier tai
|
|
`)
|
|
})
|
|
|
|
test.skip('Incomplete namedArg', () => {
|
|
expect('tail lines=').toMatchTree(`
|
|
FunctionCall
|
|
Identifier tail
|
|
NamedArg
|
|
NamedArgPrefix lines=
|
|
⚠
|
|
⚠ `)
|
|
})
|
|
})
|
|
|
|
describe('Do', () => {
|
|
test('parses function no parameters', () => {
|
|
expect('do: 1 end').toMatchTree(`
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
colon :
|
|
Number 1
|
|
keyword end`)
|
|
})
|
|
|
|
test('parses function with single parameter', () => {
|
|
expect('do x: x + 1 end').toMatchTree(`
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
colon :
|
|
BinOp
|
|
Identifier x
|
|
Plus +
|
|
Number 1
|
|
keyword end`)
|
|
})
|
|
|
|
test('parses function with multiple parameters', () => {
|
|
expect('do x y: x * y end').toMatchTree(`
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
Identifier y
|
|
colon :
|
|
BinOp
|
|
Identifier x
|
|
Star *
|
|
Identifier y
|
|
keyword end`)
|
|
})
|
|
|
|
test('parses multiline function with multiple statements', () => {
|
|
expect(`do x y:
|
|
x * y
|
|
x + 9
|
|
end`).toMatchTree(`
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
Identifier y
|
|
colon :
|
|
BinOp
|
|
Identifier x
|
|
Star *
|
|
Identifier y
|
|
BinOp
|
|
Identifier x
|
|
Plus +
|
|
Number 9
|
|
keyword end`)
|
|
})
|
|
|
|
test('does not parse identifiers that start with fn', () => {
|
|
expect('fnnn = do x: x end').toMatchTree(`
|
|
Assign
|
|
AssignableIdentifier fnnn
|
|
Eq =
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
colon :
|
|
FunctionCallOrIdentifier
|
|
Identifier x
|
|
keyword end`)
|
|
})
|
|
|
|
test('does not parse identifiers that start with end', () => {
|
|
expect('enddd = do x: x end').toMatchTree(`
|
|
Assign
|
|
AssignableIdentifier enddd
|
|
Eq =
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
colon :
|
|
FunctionCallOrIdentifier
|
|
Identifier x
|
|
keyword end`)
|
|
})
|
|
|
|
test('can call a function returned by a parens expression', () => {
|
|
expect('(do x: x end) 5').toMatchTree(`
|
|
FunctionCall
|
|
ParenExpr
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
colon :
|
|
FunctionCallOrIdentifier
|
|
Identifier x
|
|
keyword end
|
|
PositionalArg
|
|
Number 5
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('default params', () => {
|
|
test('parses function with single default parameter', () => {
|
|
expect('do x=1: x + 1 end').toMatchTree(`
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
NamedParam
|
|
NamedArgPrefix x=
|
|
Number 1
|
|
colon :
|
|
BinOp
|
|
Identifier x
|
|
Plus +
|
|
Number 1
|
|
keyword end`)
|
|
})
|
|
|
|
test('parses function with multiple default parameters', () => {
|
|
expect(`do x='something' y=true: x * y end`).toMatchTree(`
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
NamedParam
|
|
NamedArgPrefix x=
|
|
String
|
|
StringFragment something
|
|
NamedParam
|
|
NamedArgPrefix y=
|
|
Boolean true
|
|
colon :
|
|
BinOp
|
|
Identifier x
|
|
Star *
|
|
Identifier y
|
|
keyword end`)
|
|
})
|
|
|
|
test('parses function with mixed parameters', () => {
|
|
expect('do x y=true: x * y end').toMatchTree(`
|
|
FunctionDef
|
|
Do do
|
|
Params
|
|
Identifier x
|
|
NamedParam
|
|
NamedArgPrefix y=
|
|
Boolean true
|
|
colon :
|
|
BinOp
|
|
Identifier x
|
|
Star *
|
|
Identifier y
|
|
keyword end`)
|
|
})
|
|
}) |