import { expect, describe, test } from 'bun:test' import '../shrimp.grammar' // Importing this so changes cause it to retest! describe('try/catch/finally/throw', () => { test('parses try with catch', () => { expect(`try: risky-operation catch err: handle-error err end`).toMatchTree(` TryExpr keyword try colon : Block FunctionCallOrIdentifier Identifier risky-operation CatchExpr keyword catch Identifier err colon : Block FunctionCall Identifier handle-error PositionalArg Identifier err keyword end `) }) test('parses try with finally', () => { expect(`try: do-work finally: cleanup end`).toMatchTree(` TryExpr keyword try colon : Block FunctionCallOrIdentifier Identifier do-work FinallyExpr keyword finally colon : Block FunctionCallOrIdentifier Identifier cleanup keyword end `) }) test('parses try with catch and finally', () => { expect(`try: risky-operation catch err: handle-error err finally: cleanup end`).toMatchTree(` TryExpr keyword try colon : Block FunctionCallOrIdentifier Identifier risky-operation CatchExpr keyword catch Identifier err colon : Block FunctionCall Identifier handle-error PositionalArg Identifier err FinallyExpr keyword finally colon : Block FunctionCallOrIdentifier Identifier cleanup keyword end `) }) test('parses single-line try with catch', () => { expect('result = try: parse-number input catch err: 0 end').toMatchTree(` Assign AssignableIdentifier result Eq = TryExpr keyword try colon : Block FunctionCall Identifier parse-number PositionalArg Identifier input CatchExpr keyword catch Identifier err colon : Block Number 0 keyword end `) }) test('parses single-line try with finally', () => { expect('try: work catch err: 0 finally: cleanup end').toMatchTree(` TryExpr keyword try colon : Block FunctionCallOrIdentifier Identifier work CatchExpr keyword catch Identifier err colon : Block Number 0 FinallyExpr keyword finally colon : Block FunctionCallOrIdentifier Identifier cleanup keyword end `) }) test('parses throw statement with string', () => { expect("throw 'error message'").toMatchTree(` Throw keyword throw String StringFragment error message `) }) test('parses throw statement with identifier', () => { expect('throw error-object').toMatchTree(` Throw keyword throw Identifier error-object `) }) test('parses throw statement with dict', () => { expect('throw [type=validation-error message=failed]').toMatchTree(` Throw keyword throw Dict NamedArg NamedArgPrefix type= Identifier validation-error NamedArg NamedArgPrefix message= Identifier failed `) }) test('does not parse identifiers that start with try', () => { expect('trying = try: work catch err: 0 end').toMatchTree(` Assign AssignableIdentifier trying Eq = TryExpr keyword try colon : Block FunctionCallOrIdentifier Identifier work CatchExpr keyword catch Identifier err colon : Block Number 0 keyword end `) }) }) describe('function-level exception handling', () => { test('parses function with catch', () => { expect(`read-file = do path: read-data path catch e: empty-string end`).toMatchTree(` Assign AssignableIdentifier read-file Eq = FunctionDef Do do Params Identifier path colon : FunctionCall Identifier read-data PositionalArg Identifier path CatchExpr keyword catch Identifier e colon : Block FunctionCallOrIdentifier Identifier empty-string keyword end `) }) test('parses function with finally', () => { expect(`cleanup-task = do x: do-work x finally: close-resources end`).toMatchTree(` Assign AssignableIdentifier cleanup-task Eq = FunctionDef Do do Params Identifier x colon : FunctionCall Identifier do-work PositionalArg Identifier x FinallyExpr keyword finally colon : Block FunctionCallOrIdentifier Identifier close-resources keyword end `) }) test('parses function with catch and finally', () => { expect(`safe-operation = do x: risky-work x catch err: log err default-value finally: cleanup end`).toMatchTree(` Assign AssignableIdentifier safe-operation Eq = FunctionDef Do do Params Identifier x colon : FunctionCall Identifier risky-work PositionalArg Identifier x CatchExpr keyword catch Identifier err colon : Block FunctionCall Identifier log PositionalArg Identifier err FunctionCallOrIdentifier Identifier default-value FinallyExpr keyword finally colon : Block FunctionCallOrIdentifier Identifier cleanup keyword end `) }) })