From d296646d4f96da9efde6ed0c1bf1c3a29c0f27ac Mon Sep 17 00:00:00 2001 From: garrettmills Date: Tue, 3 Mar 2026 09:15:21 -0600 Subject: [PATCH] Add zip command --- src/vm/commands/index.ts | 2 ++ src/vm/commands/zip.ts | 38 ++++++++++++++++++++++++++++++++++++++ src/vm/vm.ts | 4 ++++ 3 files changed, 44 insertions(+) create mode 100644 src/vm/commands/zip.ts diff --git a/src/vm/commands/index.ts b/src/vm/commands/index.ts index 8cdfea7..70ce909 100644 --- a/src/vm/commands/index.ts +++ b/src/vm/commands/index.ts @@ -45,6 +45,7 @@ import {Drop} from "./drop.js"; import {Sort} from "./sort.js"; import {Set} from "./set.js"; import {Assign} from "./assign.js"; +import {Zip} from "./zip.js"; export type Commands = Command[] export const commands: Commands = [ @@ -94,4 +95,5 @@ export const commands: Commands = [ new Upper, new Word, new Words, + new Zip, ] diff --git a/src/vm/commands/zip.ts b/src/vm/commands/zip.ts new file mode 100644 index 0000000..4e66848 --- /dev/null +++ b/src/vm/commands/zip.ts @@ -0,0 +1,38 @@ +import {Command, ParseContext, StrDestructured, StrTerm} from "./command.js"; +import {Awaitable} from "../../util/types.js"; +import {LexInput} from "../lexer.js"; +import {StrVM} from "../vm.js"; + +export type ZipData = { + with: StrTerm, +} + +export class Zip extends Command { + attemptParse(context: ParseContext): Awaitable { + return { + with: context.popTerm(), + } + } + + getDisplayName(): string { + return 'zip' + } + + isParseCandidate(token: LexInput): boolean { + return this.isKeyword(token, 'zip') + } + + execute(vm: StrVM, data: ZipData): Awaitable { + return vm.replaceContextMatchingTerm(ctx => ({ + destructured: lhs => { + const rhs = ctx.resolveDestructured(data.with) + const zipped: StrDestructured['value'] = [] + for ( let i = 0; i < Math.max(lhs.length, rhs.length); i += 1 ) { + if ( lhs[i] ) zipped.push(lhs[i]) + if ( rhs[i] ) zipped.push(rhs[i]) + } + return zipped + }, + })) + } +} diff --git a/src/vm/vm.ts b/src/vm/vm.ts index 07b0c2e..2540c72 100644 --- a/src/vm/vm.ts +++ b/src/vm/vm.ts @@ -266,6 +266,10 @@ export class ExecutionContext { return unwrapString(this.resolveRequired(term)) } + resolveDestructured(term: StrTerm) { + return unwrapDestructured(this.resolveRequired(term)) + } + resolveInt(term: StrTerm): number { return unwrapInt(this.resolveRequired(term)) }