Add if command

This commit is contained in:
2026-04-20 22:14:55 -05:00
parent c7c605665c
commit 82510fea2f
3 changed files with 66 additions and 0 deletions

View File

@@ -381,6 +381,14 @@ str %> call $myFooReplacer bar
```
### Control Structures
#### `if <cond> <lambda>`
Execute the given lambda if `cond` is truthy. Cond may be a lambda, in which case it is executed.
A value is truthy UNLESS it is the literal empty string (`''`) or the integer `0`.
Example: `foo` -> `if (contains foo) (suffix bar)` -> `foobar`
### Misc
#### `lipsum <num> <word|line|para>`

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

@@ -0,0 +1,56 @@
import {LexInput} from "../lexer.js";
import {Command, ParseContext, StrTerm} from "./command.js";
import {StrVM} from "../vm.js";
import {Call} from "./call.js";
export type IfData = {
cond: StrTerm,
callable: StrTerm,
}
export class If extends Command<IfData> {
async attemptParse(context: ParseContext): Promise<IfData> {
return {
cond: await context.popTerm(),
callable: await context.popTerm(),
}
}
isParseCandidate(token: LexInput): boolean {
return this.isKeyword(token, 'if')
}
getDisplayName(): string {
return 'if'
}
async execute(vm: StrVM, data: IfData): Promise<StrVM> {
return vm.replaceContextFromChild(async (childVM, ctx) => {
let cond = ctx.resolveRequired(data.cond)
// If `cond` is a lambda, then call it before evaluating its truthiness.
if ( cond.term === 'lambda' ) {
await childVM.runInChild(async (lambdaVM, lambdaCtx) => {
await (new Call).execute(lambdaVM, {
callable: cond,
params: [],
})
cond = lambdaCtx.getSubject()
})
}
if ( (cond.term === 'string' || cond.term === 'int') && !cond.value ) {
// The string was empty/falsy, so do not execute the body.
return
}
const callable = ctx.resolveLambda(data.callable)
await (new Call).execute(childVM, {
callable,
params: [],
})
})
}
}

View File

@@ -54,6 +54,7 @@ import {Script} from "./script.js";
import {Take} from "./take.js";
import {Group} from "./group.js";
import {Flatten} from "./flatten.js";
import {If} from "./if.js";
export type Commands = Command<CommandData>[]
export const commands: Commands = [
@@ -74,6 +75,7 @@ export const commands: Commands = [
new Group,
new Help,
new History,
new If,
new Indent,
new InFile,
new Join,