Implement take command and comments (--) + misc cleanup

This commit is contained in:
2026-04-10 10:48:21 -05:00
parent 4dec54893c
commit 525f4bd065
8 changed files with 118 additions and 4 deletions

View File

@@ -382,7 +382,6 @@ export class ParseContext {
// Now, the remainder of the subcontext inputs should be a series of executables
// separated by `terminator` tokens -- e.g. (split _; join |), so parse executables
// from the subcontext until it is empty:
console.log(sc.inputs)
while ( sc.inputs.length > 0 ) {
const [exec, remainingInputs] = await this.childParser(sc.inputs)
lambda.body.push(exec)

View File

@@ -51,6 +51,7 @@ import {Concat} from "./concat.js";
import {Call} from "./call.js";
import {Chunk} from "./chunk.js";
import {Script} from "./script.js";
import {Take} from "./take.js";
export type Commands = Command<CommandData>[]
export const commands: Commands = [
@@ -97,6 +98,7 @@ export const commands: Commands = [
new Sort,
new Split,
new Suffix,
new Take,
new To,
new Trim,
new Undo,

76
src/vm/commands/take.ts Normal file
View File

@@ -0,0 +1,76 @@
import {Command, ParseContext, StrTerm, TypeError} from "./command.js";
import {LexInput} from "../lexer.js";
import {StrVM} from "../vm.js";
import {Lines} from "./lines.js";
import {Words} from "./words.js";
export type TakeData = {
type: 'line'|'word'|'index',
specific: StrTerm,
}
/**
* This command has a few forms:
*
* take line 3
* Assume the subject is a string and keep only line 3
*
* take word 3
* Assume the subject is a string and keep only word 3
*
* take index 3
* take 3
* Assume the subject is a destructured and keep only the item at index 3.
*/
export class Take extends Command<TakeData> {
async attemptParse(context: ParseContext): Promise<TakeData> {
// Check if the next term we received is an int or a variable.
// If so, we got the "on 3 <exec>" form of the command.
const next = await context.peekTerm()
if ( next?.term === 'int' || next?.term === 'variable' ) {
return {
type: 'index',
specific: await context.popTerm(),
}
}
// Otherwise, assume we got the "on <type> <index> <exec>" form:
return {
type: context.popKeywordInSet(['line', 'word', 'index']).value,
specific: await context.popTerm(),
}
}
getDisplayName(): string {
return 'take'
}
isParseCandidate(token: LexInput): boolean {
return this.isKeyword(token, 'take')
}
async execute(vm: StrVM, data: TakeData): Promise<StrVM> {
// If the type is line|word, first destructure the subject accordingly:
if ( data.type === 'line' ) {
vm = await (new Lines).execute(vm)
} else if ( data.type === 'word' ) {
vm = await (new Words).execute(vm)
}
return vm.replaceContextMatchingTerm(ctx => ({
override: async sub => {
if ( sub.term !== 'destructured' ) {
throw new TypeError('Cannot `take`: invalid type')
}
// Retrieve the specific item in the destructured we're operating over:
const idx = ctx.resolveInt(data.specific)
const operand = sub.value[idx]
if ( !operand ) {
throw new Error(`Invalid ${data.type} ${idx}`)
}
return operand.value
},
}))
}
}