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`) }) })