Implement group command + fallback error handling for invalid tables in output

This commit is contained in:
2026-04-14 17:59:54 -05:00
parent 042f21a9c6
commit fa851b680e
4 changed files with 77 additions and 8 deletions

56
src/vm/commands/group.ts Normal file
View File

@@ -0,0 +1,56 @@
import {LexInput} from "../lexer.js";
import {Command, hashStrRVal, ParseContext, StrRVal, StrTerm, wrapDestructured} from "./command.js";
import {StrVM} from "../vm.js";
import {Call} from "./call.js";
type GroupData = {
callable: StrTerm,
}
export class Group extends Command<GroupData> {
async attemptParse(context: ParseContext): Promise<GroupData> {
return {
callable: await context.popTerm(),
}
}
isParseCandidate(token: LexInput): boolean {
return this.isKeyword(token, 'group')
}
getDisplayName(): string {
return 'group'
}
async execute(vm: StrVM, data: GroupData): Promise<StrVM> {
return vm.replaceContextMatchingTerm(ctx => ({
destructured: async sub => {
const callable = ctx.resolveLambda(data.callable)
const groups: Record<string, StrRVal[]> = {}
for ( const part of sub ) {
// Run the exec in a child VM and group on the hashed result:
await vm.runInChild(async (childVM, childCtx) => {
await childCtx.replaceSubjectMatchingTerm({ override: part.value })
await (new Call).execute(childVM, {
callable,
params: [],
})
const groupVal = hashStrRVal(childCtx.getSubject())
groups[groupVal] ??= []
groups[groupVal].push(part.value)
})
}
const groupValues = Object.values(groups)
.map(group =>
wrapDestructured(
group.map(value => ({ value }))))
return groupValues.map(value => ({ value }))
},
}))
}
}

View File

@@ -52,6 +52,7 @@ import {Call} from "./call.js";
import {Chunk} from "./chunk.js";
import {Script} from "./script.js";
import {Take} from "./take.js";
import {Group} from "./group.js";
export type Commands = Command<CommandData>[]
export const commands: Commands = [
@@ -68,6 +69,7 @@ export const commands: Commands = [
new Enclose,
new Exit,
new From,
new Group,
new Help,
new History,
new Indent,