shrimp/src/compiler/tests/literals.test.ts

261 lines
6.3 KiB
TypeScript

import { describe } from 'bun:test'
import { expect, test } from 'bun:test'
describe('number literals', () => {
test('binary literals', () => {
expect('0b110').toEvaluateTo(6)
expect('0b1010').toEvaluateTo(10)
expect('0b11111111').toEvaluateTo(255)
expect('0b0').toEvaluateTo(0)
expect('0b1').toEvaluateTo(1)
})
test('hex literals', () => {
expect('0xdeadbeef').toEvaluateTo(0xdeadbeef)
expect('0xdeadbeef').toEvaluateTo(3735928559)
expect('0xFF').toEvaluateTo(255)
expect('0xff').toEvaluateTo(255)
expect('0x10').toEvaluateTo(16)
expect('0x0').toEvaluateTo(0)
expect('0xABCDEF').toEvaluateTo(0xabcdef)
})
test('decimal literals still work', () => {
expect('42').toEvaluateTo(42)
expect('3.14').toEvaluateTo(3.14)
expect('0').toEvaluateTo(0)
expect('999999').toEvaluateTo(999999)
})
test('negative hex and binary', () => {
expect('-0xFF').toEvaluateTo(-255)
expect('-0b1010').toEvaluateTo(-10)
})
test('positive prefix', () => {
expect('+0xFF').toEvaluateTo(255)
expect('+0b110').toEvaluateTo(6)
expect('+42').toEvaluateTo(42)
})
})
describe('array literals', () => {
test('work with numbers', () => {
expect('[1 2 3]').toEvaluateTo([1, 2, 3])
})
test('work with strings', () => {
expect("['one' 'two' 'three']").toEvaluateTo(['one', 'two', 'three'])
})
test('work with identifiers', () => {
expect('[one two three]').toEvaluateTo(['one', 'two', 'three'])
})
test('can be nested', () => {
expect('[one [two [three]]]').toEvaluateTo(['one', ['two', ['three']]])
})
test('can span multiple lines', () => {
expect(`[
1
2
3
]`).toEvaluateTo([1, 2, 3])
})
test('can span multiple w/o calling functions', () => {
expect(`[
one
two
three
]`).toEvaluateTo(['one', 'two', 'three'])
})
test('empty arrays', () => {
expect('[]').toEvaluateTo([])
})
test('mixed types', () => {
expect("[1 'two' three true null]").toEvaluateTo([1, 'two', 'three', true, null])
})
test('semicolons as separators', () => {
expect('[1; 2; 3]').toEvaluateTo([1, 2, 3])
})
test('expressions in arrays', () => {
expect('[(1 + 2) (3 * 4)]').toEvaluateTo([3, 12])
})
test('mixed separators - spaces and newlines', () => {
expect(`[1 2
3 4]`).toEvaluateTo([1, 2, 3, 4])
})
test('mixed separators - spaces and semicolons', () => {
expect('[1 2; 3 4]').toEvaluateTo([1, 2, 3, 4])
})
test('empty lines within arrays', () => {
expect(`[1
2]`).toEvaluateTo([1, 2])
})
test('comments within arrays', () => {
expect(`[1
2
]`).toEvaluateTo([1, 2])
})
test('complex nested multiline', () => {
expect(`[
[1 2]
[3 4]
[5 6]
]`).toEvaluateTo([
[1, 2],
[3, 4],
[5, 6],
])
})
test('boolean and null literals', () => {
expect('[true false null]').toEvaluateTo([true, false, null])
})
test('regex literals', () => {
expect('[//[0-9]+//]').toEvaluateTo([/[0-9]+/])
})
test('trailing newlines', () => {
expect(`[
1
2
]`).toEvaluateTo([1, 2])
})
})
describe('dict literals', () => {
test('work with numbers', () => {
expect('[a=1 b=2 c=3]').toEvaluateTo({ a: 1, b: 2, c: 3 })
})
test('work with strings', () => {
expect("[a='one' b='two' c='three']").toEvaluateTo({ a: 'one', b: 'two', c: 'three' })
})
test('work with identifiers', () => {
expect('[a=one b=two c=three]').toEvaluateTo({ a: 'one', b: 'two', c: 'three' })
})
test('can be nested', () => {
expect('[a=one b=[two [c=three]]]').toEvaluateTo({ a: 'one', b: ['two', { c: 'three' }] })
})
test('can span multiple lines', () => {
expect(`[
a=1
b=2
c=3
]`).toEvaluateTo({ a: 1, b: 2, c: 3 })
})
test('empty dict', () => {
expect('[=]').toEvaluateTo({})
expect('[ = ]').toEvaluateTo({})
})
test('mixed types', () => {
expect("[a=1 b='two' c=three d=true e=null]").toEvaluateTo({
a: 1,
b: 'two',
c: 'three',
d: true,
e: null,
})
})
test('semicolons as separators', () => {
expect('[a=1; b=2; c=3]').toEvaluateTo({ a: 1, b: 2, c: 3 })
})
test('expressions in dicts', () => {
expect('[a=(1 + 2) b=(3 * 4)]').toEvaluateTo({ a: 3, b: 12 })
})
test('empty lines within dicts', () => {
expect(`[a=1
b=2
c=3]`).toEvaluateTo({ a: 1, b: 2, c: 3 })
})
})
describe('curly strings', () => {
test('work on one line', () => {
expect('{ one two three }').toEvaluateTo(" one two three ")
})
test('work on multiple lines', () => {
expect(`{
one
two
three
}`).toEvaluateTo("\n one\n two\n three\n ")
})
test('can contain other curlies', () => {
expect(`{
{ one }
two
{ three }
}`).toEvaluateTo("\n { one }\n two\n { three }\n ")
})
test('interpolates variables', () => {
expect(`name = Bob; { Hello $name! }`).toEvaluateTo(` Hello Bob! `)
})
test("doesn't interpolate escaped variables ", () => {
expect(`name = Bob; { Hello \\$name }`).toEvaluateTo(` Hello $name `)
expect(`a = 1; b = 2; { sum is \\$(a + b)! }`).toEvaluateTo(` sum is $(a + b)! `)
})
test('interpolates expressions', () => {
expect(`a = 1; b = 2; { sum is $(a + b)! }`).toEvaluateTo(` sum is 3! `)
expect(`a = 1; b = 2; { sum is { $(a + b) }! }`).toEvaluateTo(` sum is { 3 }! `)
expect(`a = 1; b = 2; { sum is $(a + (b * b))! }`).toEvaluateTo(` sum is 5! `)
expect(`{ This is $({twisted}). }`).toEvaluateTo(` This is twisted. `)
expect(`{ This is $({{twisted}}). }`).toEvaluateTo(` This is {twisted}. `)
})
test('interpolation edge cases', () => {
expect(`{[a=1 b=2 c={wild}]}`).toEvaluateTo(`[a=1 b=2 c={wild}]`)
expect(`a = 1;b = 2;c = 3;{$a $b $c}`).toEvaluateTo(`1 2 3`)
expect(`a = 1;b = 2;c = 3;{$a$b$c}`).toEvaluateTo(`123`)
})
})
describe('double quoted strings', () => {
test("work", () => {
expect(`"hello world"`).toEvaluateTo('hello world')
})
test("don't interpolate", () => {
expect(`"hello $world"`).toEvaluateTo('hello $world')
expect(`"hello $(1 + 2)"`).toEvaluateTo('hello $(1 + 2)')
})
test("equal regular strings", () => {
expect(`"hello world" == 'hello world'`).toEvaluateTo(true)
})
test("can contain newlines", () => {
expect(`
"hello
world"`).toEvaluateTo('hello\n world')
})
})