75 lines
1.9 KiB
TypeScript
75 lines
1.9 KiB
TypeScript
/**
|
|
* Lazy evaluation system for nix-js
|
|
* Implements thunks for lazy evaluation of Nix expressions
|
|
*/
|
|
|
|
import type { NixValue, NixThunkInterface, NixStrictValue } from "./types";
|
|
|
|
/**
|
|
* Symbol used to mark objects as thunks
|
|
* This is exported to Rust via Nix.IS_THUNK
|
|
*/
|
|
export const IS_THUNK = Symbol("is_thunk");
|
|
|
|
/**
|
|
* NixThunk class - represents a lazy, unevaluated expression
|
|
*
|
|
* A thunk wraps a function that produces a value when called.
|
|
* Once evaluated, the result is cached to avoid recomputation.
|
|
*/
|
|
export class NixThunk implements NixThunkInterface {
|
|
[key: symbol]: any;
|
|
readonly [IS_THUNK] = true as const;
|
|
func: (() => NixValue) | undefined;
|
|
result: NixStrictValue | undefined;
|
|
|
|
constructor(func: () => NixValue) {
|
|
this.func = func;
|
|
this.result = undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Type guard to check if a value is a thunk
|
|
* @param value - Value to check
|
|
* @returns true if value is a NixThunk
|
|
*/
|
|
export const isThunk = (value: unknown): value is NixThunkInterface => {
|
|
return value !== null && typeof value === "object" && IS_THUNK in value && value[IS_THUNK] === true;
|
|
};
|
|
|
|
/**
|
|
* Force evaluation of a value
|
|
* If the value is a thunk, evaluate it and cache the result
|
|
* If already evaluated or not a thunk, return as-is
|
|
*
|
|
* @param value - Value to force (may be a thunk)
|
|
* @returns The forced/evaluated value
|
|
*/
|
|
export const force = (value: NixValue): NixStrictValue => {
|
|
if (!isThunk(value)) {
|
|
return value;
|
|
}
|
|
|
|
// Already evaluated - return cached result
|
|
if (value.func === undefined) {
|
|
return value.result!;
|
|
}
|
|
|
|
// Evaluate and cache
|
|
const result = force(value.func());
|
|
value.result = result;
|
|
value.func = undefined;
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Create a new thunk from a function
|
|
* @param func - Function that produces a value when called
|
|
* @returns A new NixThunk wrapping the function
|
|
*/
|
|
export const createThunk = (func: () => NixValue): NixThunkInterface => {
|
|
return new NixThunk(func);
|
|
};
|