import {Command, ParseContext, processPath, StrLVal, StrTerm, wrapInt} from "./command.js"; import {LexInput} from "../lexer.js"; import {ExecutionError, StrVM} from "../vm.js"; import {Awaitable} from "../../util/types.js"; import * as fs from 'node:fs'; import {log} from "../../log.js"; export type ExistsData = { check: 'fs'|'var', lexical: StrTerm, } export class Exists extends Command { async attemptParse(context: ParseContext): Promise { return { check: context.popKeywordInSet(['fs', 'var']).value, lexical: await context.popTerm(), } } getDisplayName(): string { return 'exists' } isParseCandidate(token: LexInput): boolean { return this.isKeyword(token, 'exists') } execute(vm: StrVM, data: ExistsData): Awaitable { const logger = log.getStreamLogger('cmd-exists') return vm.replaceContextMatchingTerm(ctx => ({ override: async () => { if ( data.check === 'fs' ) { const path = processPath(ctx.resolveString(data.lexical)) logger.debug({ checkPath: path }) return wrapInt(fs.existsSync(path) ? 1 : 0) } else if ( data.check === 'var' ) { const lval: StrLVal = { term: 'variable', name: '$' + ctx.resolveString(data.lexical) } const val = ctx.resolve(lval) logger.debug({ checkVar: lval, val }) return wrapInt(val ? 1 : 0) } throw new ExecutionError(`Existence operator not implemented: ${data.check}`) }, })) } }