Implement group command + fallback error handling for invalid tables in output
This commit is contained in:
56
src/vm/commands/group.ts
Normal file
56
src/vm/commands/group.ts
Normal 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 }))
|
||||
},
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user