diff --git a/src/bytecode.ts b/src/bytecode.ts index 66b21ea..4e8ae75 100644 --- a/src/bytecode.ts +++ b/src/bytecode.ts @@ -495,7 +495,19 @@ function toBytecodeFromString(str: string): Bytecode /* throws */ { bytecode.constants.push(toValue(null)) operandValue = bytecode.constants.length - 1 - } else { + } else if (/^\/.*\/[a-z]*$/.test(operand)) { + // regex literal (/pattern/flags) + const lastSlash = operand.lastIndexOf('/') + const pattern = operand.slice(1, lastSlash) + const flags = operand.slice(lastSlash + 1) + try { + const regex = new RegExp(pattern, flags) + bytecode.constants.push(toValue(regex)) + operandValue = bytecode.constants.length - 1 + } catch (e) { + throw new Error(`Invalid regex literal: ${operand}`) + } + }else { // Assume it's a variable name if it doesn't match any other pattern // This allows emoji, Unicode, and other creative identifiers // (already checked that it doesn't start with . # or match other patterns) diff --git a/tests/basic.test.ts b/tests/basic.test.ts index 4d7d22b..288d3c1 100644 --- a/tests/basic.test.ts +++ b/tests/basic.test.ts @@ -102,6 +102,29 @@ test("EQ - equality comparison", async () => { expect(await run(toBytecode(str2))).toEqual({ type: 'boolean', value: false }) }) +test('EQ - equality with regexes', async () => { + const str = ` + PUSH /cool/i + PUSH /cool/i + EQ +` + expect(await run(toBytecode(str))).toEqual({ type: 'boolean', value: true }) + + const str2 = ` + PUSH /cool/ + PUSH /cool/i + EQ +` + expect(await run(toBytecode(str2))).toEqual({ type: 'boolean', value: false }) + + const str3 = ` + PUSH /not-cool/ + PUSH /cool/ + EQ +` + expect(await run(toBytecode(str3))).toEqual({ type: 'boolean', value: false }) +}) + test("NEQ - not equal comparison", async () => { const str = ` PUSH 5