fmt: biome & editorconfig
This commit is contained in:
11
.editorconfig
Normal file
11
.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{rs,toml}]
|
||||||
|
indent_size = 4
|
||||||
36
biome.json
Normal file
36
biome.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/2.3.6/schema.json",
|
||||||
|
"vcs": {
|
||||||
|
"enabled": true,
|
||||||
|
"clientKind": "git",
|
||||||
|
"useIgnoreFile": true
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"includes": ["**", "!!**/dist"]
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": true,
|
||||||
|
"formatWithErrors": true,
|
||||||
|
"attributePosition": "auto",
|
||||||
|
"indentStyle": "space",
|
||||||
|
"indentWidth": 2,
|
||||||
|
"lineWidth": 110,
|
||||||
|
"lineEnding": "lf"
|
||||||
|
},
|
||||||
|
"javascript": {
|
||||||
|
"formatter": {
|
||||||
|
"arrowParentheses": "always",
|
||||||
|
"bracketSameLine": false,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"jsxQuoteStyle": "double",
|
||||||
|
"quoteProperties": "asNeeded",
|
||||||
|
"semicolons": "always",
|
||||||
|
"trailingCommas": "all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"json": {
|
||||||
|
"formatter": {
|
||||||
|
"trailingCommas": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
valgrind
|
valgrind
|
||||||
claude-code
|
claude-code
|
||||||
|
|
||||||
# Node.js tooling for TypeScript build
|
|
||||||
nodejs
|
nodejs
|
||||||
nodePackages.npm
|
nodePackages.npm
|
||||||
|
biome
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,52 +2,68 @@
|
|||||||
* Arithmetic builtin functions
|
* Arithmetic builtin functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixBool, NixInt, NixNumber, NixValue } from '../types';
|
import type { NixBool, NixInt, NixNumber, NixValue } from "../types";
|
||||||
import { force_numeric, coerce_numeric, force_int } from '../type-assert';
|
import { force_numeric, coerce_numeric, force_int } from "../type-assert";
|
||||||
|
|
||||||
export const add = (a: NixValue) => (b: NixValue): bigint | number => {
|
export const add =
|
||||||
|
(a: NixValue) =>
|
||||||
|
(b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
||||||
return (av as any) + (bv as any);
|
return (av as any) + (bv as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sub = (a: NixValue) => (b: NixValue): bigint | number => {
|
export const sub =
|
||||||
|
(a: NixValue) =>
|
||||||
|
(b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
||||||
return (av as any) - (bv as any);
|
return (av as any) - (bv as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mul = (a: NixValue) => (b: NixValue): bigint | number => {
|
export const mul =
|
||||||
|
(a: NixValue) =>
|
||||||
|
(b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
||||||
return (av as any) * (bv as any);
|
return (av as any) * (bv as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const div = (a: NixValue) => (b: NixValue): NixNumber => {
|
export const div =
|
||||||
|
(a: NixValue) =>
|
||||||
|
(b: NixValue): NixNumber => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
||||||
|
|
||||||
if (bv === 0 || bv === 0n) {
|
if (bv === 0 || bv === 0n) {
|
||||||
throw new RangeError('Division by zero');
|
throw new RangeError("Division by zero");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (av as any) / (bv as any)
|
return (av as any) / (bv as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bitwise operations - only for integers
|
// Bitwise operations - only for integers
|
||||||
export const bitAnd = (a: NixValue) => (b: NixValue): NixInt => {
|
export const bitAnd =
|
||||||
|
(a: NixValue) =>
|
||||||
|
(b: NixValue): NixInt => {
|
||||||
const av = force_int(a);
|
const av = force_int(a);
|
||||||
const bv = force_int(b);
|
const bv = force_int(b);
|
||||||
return av & bv;
|
return av & bv;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const bitOr = (a: NixValue) => (b: NixValue): NixInt => {
|
export const bitOr =
|
||||||
|
(a: NixValue) =>
|
||||||
|
(b: NixValue): NixInt => {
|
||||||
const av = force_int(a);
|
const av = force_int(a);
|
||||||
const bv = force_int(b);
|
const bv = force_int(b);
|
||||||
return av | bv;
|
return av | bv;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const bitXor = (a: NixValue) => (b: NixValue): NixInt => {
|
export const bitXor =
|
||||||
|
(a: NixValue) =>
|
||||||
|
(b: NixValue): NixInt => {
|
||||||
const av = force_int(a);
|
const av = force_int(a);
|
||||||
const bv = force_int(b);
|
const bv = force_int(b);
|
||||||
return av ^ bv;
|
return av ^ bv;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const lessThan = (a: NixValue) => (b: NixValue): NixBool =>
|
export const lessThan =
|
||||||
|
(a: NixValue) =>
|
||||||
|
(b: NixValue): NixBool =>
|
||||||
force_numeric(a) < force_numeric(b);
|
force_numeric(a) < force_numeric(b);
|
||||||
|
|||||||
@@ -2,20 +2,26 @@
|
|||||||
* Attribute set operation builtin functions
|
* Attribute set operation builtin functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue, NixAttrs, NixList } from '../types';
|
import type { NixValue, NixAttrs, NixList } from "../types";
|
||||||
import { force_attrs, force_string, force_function, force_list } from '../type-assert';
|
import { force_attrs, force_string, force_function, force_list } from "../type-assert";
|
||||||
|
|
||||||
export const attrNames = (set: NixValue): string[] => Object.keys(force_attrs(set));
|
export const attrNames = (set: NixValue): string[] => Object.keys(force_attrs(set));
|
||||||
|
|
||||||
export const attrValues = (set: NixValue): NixValue[] => Object.values(force_attrs(set));
|
export const attrValues = (set: NixValue): NixValue[] => Object.values(force_attrs(set));
|
||||||
|
|
||||||
export const getAttr = (s: NixValue) => (set: NixValue): NixValue =>
|
export const getAttr =
|
||||||
|
(s: NixValue) =>
|
||||||
|
(set: NixValue): NixValue =>
|
||||||
force_attrs(set)[force_string(s)];
|
force_attrs(set)[force_string(s)];
|
||||||
|
|
||||||
export const hasAttr = (s: NixValue) => (set: NixValue): boolean =>
|
export const hasAttr =
|
||||||
|
(s: NixValue) =>
|
||||||
|
(set: NixValue): boolean =>
|
||||||
Object.prototype.hasOwnProperty.call(force_attrs(set), force_string(s));
|
Object.prototype.hasOwnProperty.call(force_attrs(set), force_string(s));
|
||||||
|
|
||||||
export const mapAttrs = (f: NixValue) => (attrs: NixValue): NixAttrs => {
|
export const mapAttrs =
|
||||||
|
(f: NixValue) =>
|
||||||
|
(attrs: NixValue): NixAttrs => {
|
||||||
const new_attrs: NixAttrs = {};
|
const new_attrs: NixAttrs = {};
|
||||||
const forced_attrs = force_attrs(attrs);
|
const forced_attrs = force_attrs(attrs);
|
||||||
const forced_f = force_function(f);
|
const forced_f = force_function(f);
|
||||||
@@ -23,7 +29,7 @@ export const mapAttrs = (f: NixValue) => (attrs: NixValue): NixAttrs => {
|
|||||||
new_attrs[key] = forced_f(key)(forced_attrs[key]);
|
new_attrs[key] = forced_f(key)(forced_attrs[key]);
|
||||||
}
|
}
|
||||||
return new_attrs;
|
return new_attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const listToAttrs = (e: NixValue): NixAttrs => {
|
export const listToAttrs = (e: NixValue): NixAttrs => {
|
||||||
const attrs: NixAttrs = {};
|
const attrs: NixAttrs = {};
|
||||||
@@ -35,7 +41,9 @@ export const listToAttrs = (e: NixValue): NixAttrs => {
|
|||||||
return attrs;
|
return attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const intersectAttrs = (e1: NixValue) => (e2: NixValue): NixAttrs => {
|
export const intersectAttrs =
|
||||||
|
(e1: NixValue) =>
|
||||||
|
(e2: NixValue): NixAttrs => {
|
||||||
const f1 = force_attrs(e1);
|
const f1 = force_attrs(e1);
|
||||||
const f2 = force_attrs(e2);
|
const f2 = force_attrs(e2);
|
||||||
const attrs: NixAttrs = {};
|
const attrs: NixAttrs = {};
|
||||||
@@ -45,16 +53,20 @@ export const intersectAttrs = (e1: NixValue) => (e2: NixValue): NixAttrs => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return attrs;
|
return attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const catAttrs = (attr: NixValue) => (list: NixValue): NixList => {
|
export const catAttrs =
|
||||||
|
(attr: NixValue) =>
|
||||||
|
(list: NixValue): NixList => {
|
||||||
const key = force_string(attr);
|
const key = force_string(attr);
|
||||||
return force_list(list)
|
return force_list(list)
|
||||||
.map((set) => force_attrs(set)[key])
|
.map((set) => force_attrs(set)[key])
|
||||||
.filter((val) => val !== undefined);
|
.filter((val) => val !== undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const groupBy = (f: NixValue) => (list: NixValue): NixAttrs => {
|
export const groupBy =
|
||||||
|
(f: NixValue) =>
|
||||||
|
(list: NixValue): NixAttrs => {
|
||||||
const attrs: NixAttrs = {};
|
const attrs: NixAttrs = {};
|
||||||
const forced_f = force_function(f);
|
const forced_f = force_function(f);
|
||||||
const forced_list = force_list(list);
|
const forced_list = force_list(list);
|
||||||
@@ -64,4 +76,4 @@ export const groupBy = (f: NixValue) => (list: NixValue): NixAttrs => {
|
|||||||
(attrs[key] as NixList).push(elem);
|
(attrs[key] as NixList).push(elem);
|
||||||
}
|
}
|
||||||
return attrs;
|
return attrs;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,24 +2,24 @@
|
|||||||
* Conversion and serialization builtin functions (unimplemented)
|
* Conversion and serialization builtin functions (unimplemented)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue } from '../types';
|
import type { NixValue } from "../types";
|
||||||
|
|
||||||
export const fromJSON = (e: NixValue): never => {
|
export const fromJSON = (e: NixValue): never => {
|
||||||
throw 'Not implemented: fromJSON';
|
throw "Not implemented: fromJSON";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fromTOML = (e: NixValue): never => {
|
export const fromTOML = (e: NixValue): never => {
|
||||||
throw 'Not implemented: fromTOML';
|
throw "Not implemented: fromTOML";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const toJSON = (e: NixValue): never => {
|
export const toJSON = (e: NixValue): never => {
|
||||||
throw 'Not implemented: toJSON';
|
throw "Not implemented: toJSON";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const toXML = (e: NixValue): never => {
|
export const toXML = (e: NixValue): never => {
|
||||||
throw 'Not implemented: toXML';
|
throw "Not implemented: toXML";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const toString = (name: NixValue, s: NixValue): never => {
|
export const toString = (name: NixValue, s: NixValue): never => {
|
||||||
throw 'Not implemented: toString';
|
throw "Not implemented: toString";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,17 +2,21 @@
|
|||||||
* Functional programming builtin functions
|
* Functional programming builtin functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue } from '../types';
|
import type { NixValue } from "../types";
|
||||||
import { force } from '../thunk';
|
import { force } from "../thunk";
|
||||||
|
|
||||||
export const seq = (e1: NixValue) => (e2: NixValue): NixValue => {
|
export const seq =
|
||||||
|
(e1: NixValue) =>
|
||||||
|
(e2: NixValue): NixValue => {
|
||||||
force(e1); // Force evaluation of e1
|
force(e1); // Force evaluation of e1
|
||||||
return e2;
|
return e2;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deepSeq = (e1: NixValue) => (e2: NixValue): never => {
|
export const deepSeq =
|
||||||
throw 'Not implemented: deepSeq';
|
(e1: NixValue) =>
|
||||||
};
|
(e2: NixValue): never => {
|
||||||
|
throw "Not implemented: deepSeq";
|
||||||
|
};
|
||||||
|
|
||||||
export const abort = (s: NixValue): never => {
|
export const abort = (s: NixValue): never => {
|
||||||
throw `evaluation aborted with the following error message: '${force(s)}'`;
|
throw `evaluation aborted with the following error message: '${force(s)}'`;
|
||||||
@@ -27,9 +31,11 @@ export const trace = (e1: NixValue, e2: NixValue): NixValue => {
|
|||||||
return e2;
|
return e2;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const warn = (e1: NixValue) => (e2: NixValue): NixValue => {
|
export const warn =
|
||||||
|
(e1: NixValue) =>
|
||||||
|
(e2: NixValue): NixValue => {
|
||||||
console.log(`evaluation warning: ${force(e1)}`);
|
console.log(`evaluation warning: ${force(e1)}`);
|
||||||
return e2;
|
return e2;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const breakFunc = (v: NixValue): NixValue => v;
|
export const breakFunc = (v: NixValue): NixValue => v;
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
* Combines all builtin function categories into the global `builtins` object
|
* Combines all builtin function categories into the global `builtins` object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { create_thunk } from '../thunk';
|
import { create_thunk } from "../thunk";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbol used to mark functions as primops (primitive operations)
|
* Symbol used to mark functions as primops (primitive operations)
|
||||||
* This is similar to IS_THUNK but for builtin functions
|
* This is similar to IS_THUNK but for builtin functions
|
||||||
*/
|
*/
|
||||||
export const IS_PRIMOP = Symbol('is_primop');
|
export const IS_PRIMOP = Symbol("is_primop");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata interface for primop functions
|
* Metadata interface for primop functions
|
||||||
@@ -37,7 +37,7 @@ export const markPrimop = <T extends Function>(
|
|||||||
func: T,
|
func: T,
|
||||||
name: string,
|
name: string,
|
||||||
arity: number,
|
arity: number,
|
||||||
applied: number = 0
|
applied: number = 0,
|
||||||
): T => {
|
): T => {
|
||||||
// Mark this function as a primop
|
// Mark this function as a primop
|
||||||
(func as any)[IS_PRIMOP] = {
|
(func as any)[IS_PRIMOP] = {
|
||||||
@@ -52,7 +52,7 @@ export const markPrimop = <T extends Function>(
|
|||||||
const wrappedFunc = ((...args: any[]) => {
|
const wrappedFunc = ((...args: any[]) => {
|
||||||
const result = func(...args);
|
const result = func(...args);
|
||||||
// If result is a function, mark it as the next layer
|
// If result is a function, mark it as the next layer
|
||||||
if (typeof result === 'function') {
|
if (typeof result === "function") {
|
||||||
return markPrimop(result, name, arity, applied + args.length);
|
return markPrimop(result, name, arity, applied + args.length);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -78,9 +78,9 @@ export const markPrimop = <T extends Function>(
|
|||||||
*/
|
*/
|
||||||
export const is_primop = (value: unknown): value is Function & { [IS_PRIMOP]: PrimopMetadata } => {
|
export const is_primop = (value: unknown): value is Function & { [IS_PRIMOP]: PrimopMetadata } => {
|
||||||
return (
|
return (
|
||||||
typeof value === 'function' &&
|
typeof value === "function" &&
|
||||||
IS_PRIMOP in value &&
|
IS_PRIMOP in value &&
|
||||||
typeof value[IS_PRIMOP] === 'object' &&
|
typeof value[IS_PRIMOP] === "object" &&
|
||||||
value[IS_PRIMOP] !== null
|
value[IS_PRIMOP] !== null
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -98,16 +98,16 @@ export const get_primop_metadata = (func: unknown): PrimopMetadata | undefined =
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Import all builtin categories
|
// Import all builtin categories
|
||||||
import * as arithmetic from './arithmetic';
|
import * as arithmetic from "./arithmetic";
|
||||||
import * as math from './math';
|
import * as math from "./math";
|
||||||
import * as typeCheck from './type-check';
|
import * as typeCheck from "./type-check";
|
||||||
import * as list from './list';
|
import * as list from "./list";
|
||||||
import * as attrs from './attrs';
|
import * as attrs from "./attrs";
|
||||||
import * as string from './string';
|
import * as string from "./string";
|
||||||
import * as functional from './functional';
|
import * as functional from "./functional";
|
||||||
import * as io from './io';
|
import * as io from "./io";
|
||||||
import * as conversion from './conversion';
|
import * as conversion from "./conversion";
|
||||||
import * as misc from './misc';
|
import * as misc from "./misc";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The global builtins object
|
* The global builtins object
|
||||||
@@ -120,122 +120,126 @@ import * as misc from './misc';
|
|||||||
* All primop functions are marked with IS_PRIMOP symbol for runtime introspection
|
* All primop functions are marked with IS_PRIMOP symbol for runtime introspection
|
||||||
*/
|
*/
|
||||||
export const builtins: any = {
|
export const builtins: any = {
|
||||||
add: markPrimop(arithmetic.add, 'add', 2),
|
add: markPrimop(arithmetic.add, "add", 2),
|
||||||
sub: markPrimop(arithmetic.sub, 'sub', 2),
|
sub: markPrimop(arithmetic.sub, "sub", 2),
|
||||||
mul: markPrimop(arithmetic.mul, 'mul', 2),
|
mul: markPrimop(arithmetic.mul, "mul", 2),
|
||||||
div: markPrimop(arithmetic.div, 'div', 2),
|
div: markPrimop(arithmetic.div, "div", 2),
|
||||||
bitAnd: markPrimop(arithmetic.bitAnd, 'bitAnd', 2),
|
bitAnd: markPrimop(arithmetic.bitAnd, "bitAnd", 2),
|
||||||
bitOr: markPrimop(arithmetic.bitOr, 'bitOr', 2),
|
bitOr: markPrimop(arithmetic.bitOr, "bitOr", 2),
|
||||||
bitXor: markPrimop(arithmetic.bitXor, 'bitXor', 2),
|
bitXor: markPrimop(arithmetic.bitXor, "bitXor", 2),
|
||||||
lessThan: markPrimop(arithmetic.lessThan, 'lessThan', 2),
|
lessThan: markPrimop(arithmetic.lessThan, "lessThan", 2),
|
||||||
|
|
||||||
ceil: markPrimop(math.ceil, 'ceil', 1),
|
ceil: markPrimop(math.ceil, "ceil", 1),
|
||||||
floor: markPrimop(math.floor, 'floor', 1),
|
floor: markPrimop(math.floor, "floor", 1),
|
||||||
|
|
||||||
isAttrs: markPrimop(typeCheck.isAttrs, 'isAttrs', 1),
|
isAttrs: markPrimop(typeCheck.isAttrs, "isAttrs", 1),
|
||||||
isBool: markPrimop(typeCheck.isBool, 'isBool', 1),
|
isBool: markPrimop(typeCheck.isBool, "isBool", 1),
|
||||||
isFloat: markPrimop(typeCheck.isFloat, 'isFloat', 1),
|
isFloat: markPrimop(typeCheck.isFloat, "isFloat", 1),
|
||||||
isFunction: markPrimop(typeCheck.isFunction, 'isFunction', 1),
|
isFunction: markPrimop(typeCheck.isFunction, "isFunction", 1),
|
||||||
isInt: markPrimop(typeCheck.isInt, 'isInt', 1),
|
isInt: markPrimop(typeCheck.isInt, "isInt", 1),
|
||||||
isList: markPrimop(typeCheck.isList, 'isList', 1),
|
isList: markPrimop(typeCheck.isList, "isList", 1),
|
||||||
isNull: markPrimop(typeCheck.isNull, 'isNull', 1),
|
isNull: markPrimop(typeCheck.isNull, "isNull", 1),
|
||||||
isPath: markPrimop(typeCheck.isPath, 'isPath', 1),
|
isPath: markPrimop(typeCheck.isPath, "isPath", 1),
|
||||||
isString: markPrimop(typeCheck.isString, 'isString', 1),
|
isString: markPrimop(typeCheck.isString, "isString", 1),
|
||||||
typeOf: markPrimop(typeCheck.typeOf, 'typeOf', 1),
|
typeOf: markPrimop(typeCheck.typeOf, "typeOf", 1),
|
||||||
|
|
||||||
map: markPrimop(list.map, 'map', 2),
|
map: markPrimop(list.map, "map", 2),
|
||||||
filter: markPrimop(list.filter, 'filter', 2),
|
filter: markPrimop(list.filter, "filter", 2),
|
||||||
length: markPrimop(list.length, 'length', 1),
|
length: markPrimop(list.length, "length", 1),
|
||||||
head: markPrimop(list.head, 'head', 1),
|
head: markPrimop(list.head, "head", 1),
|
||||||
tail: markPrimop(list.tail, 'tail', 1),
|
tail: markPrimop(list.tail, "tail", 1),
|
||||||
elem: markPrimop(list.elem, 'elem', 2),
|
elem: markPrimop(list.elem, "elem", 2),
|
||||||
elemAt: markPrimop(list.elemAt, 'elemAt', 2),
|
elemAt: markPrimop(list.elemAt, "elemAt", 2),
|
||||||
concatLists: markPrimop(list.concatLists, 'concatLists', 1),
|
concatLists: markPrimop(list.concatLists, "concatLists", 1),
|
||||||
concatMap: markPrimop(list.concatMap, 'concatMap', 2),
|
concatMap: markPrimop(list.concatMap, "concatMap", 2),
|
||||||
'foldl\'': markPrimop(list.foldlPrime, 'foldl\'', 3),
|
"foldl'": markPrimop(list.foldlPrime, "foldl'", 3),
|
||||||
sort: markPrimop(list.sort, 'sort', 2),
|
sort: markPrimop(list.sort, "sort", 2),
|
||||||
partition: markPrimop(list.partition, 'partition', 2),
|
partition: markPrimop(list.partition, "partition", 2),
|
||||||
genList: markPrimop(list.genList, 'genList', 2),
|
genList: markPrimop(list.genList, "genList", 2),
|
||||||
all: markPrimop(list.all, 'all', 2),
|
all: markPrimop(list.all, "all", 2),
|
||||||
any: markPrimop(list.any, 'any', 2),
|
any: markPrimop(list.any, "any", 2),
|
||||||
|
|
||||||
attrNames: markPrimop(attrs.attrNames, 'attrNames', 1),
|
attrNames: markPrimop(attrs.attrNames, "attrNames", 1),
|
||||||
attrValues: markPrimop(attrs.attrValues, 'attrValues', 1),
|
attrValues: markPrimop(attrs.attrValues, "attrValues", 1),
|
||||||
getAttr: markPrimop(attrs.getAttr, 'getAttr', 2),
|
getAttr: markPrimop(attrs.getAttr, "getAttr", 2),
|
||||||
hasAttr: markPrimop(attrs.hasAttr, 'hasAttr', 2),
|
hasAttr: markPrimop(attrs.hasAttr, "hasAttr", 2),
|
||||||
mapAttrs: markPrimop(attrs.mapAttrs, 'mapAttrs', 2),
|
mapAttrs: markPrimop(attrs.mapAttrs, "mapAttrs", 2),
|
||||||
listToAttrs: markPrimop(attrs.listToAttrs, 'listToAttrs', 1),
|
listToAttrs: markPrimop(attrs.listToAttrs, "listToAttrs", 1),
|
||||||
intersectAttrs: markPrimop(attrs.intersectAttrs, 'intersectAttrs', 2),
|
intersectAttrs: markPrimop(attrs.intersectAttrs, "intersectAttrs", 2),
|
||||||
catAttrs: markPrimop(attrs.catAttrs, 'catAttrs', 2),
|
catAttrs: markPrimop(attrs.catAttrs, "catAttrs", 2),
|
||||||
groupBy: markPrimop(attrs.groupBy, 'groupBy', 2),
|
groupBy: markPrimop(attrs.groupBy, "groupBy", 2),
|
||||||
|
|
||||||
stringLength: markPrimop(string.stringLength, 'stringLength', 1),
|
stringLength: markPrimop(string.stringLength, "stringLength", 1),
|
||||||
substring: markPrimop(string.substring, 'substring', 3),
|
substring: markPrimop(string.substring, "substring", 3),
|
||||||
concatStringsSep: markPrimop(string.concatStringsSep, 'concatStringsSep', 2),
|
concatStringsSep: markPrimop(string.concatStringsSep, "concatStringsSep", 2),
|
||||||
baseNameOf: markPrimop(string.baseNameOf, 'baseNameOf', 1),
|
baseNameOf: markPrimop(string.baseNameOf, "baseNameOf", 1),
|
||||||
|
|
||||||
seq: markPrimop(functional.seq, 'seq', 2),
|
seq: markPrimop(functional.seq, "seq", 2),
|
||||||
deepSeq: markPrimop(functional.deepSeq, 'deepSeq', 2),
|
deepSeq: markPrimop(functional.deepSeq, "deepSeq", 2),
|
||||||
abort: markPrimop(functional.abort, 'abort', 1),
|
abort: markPrimop(functional.abort, "abort", 1),
|
||||||
throw: markPrimop(functional.throwFunc, 'throw', 1),
|
throw: markPrimop(functional.throwFunc, "throw", 1),
|
||||||
trace: markPrimop(functional.trace, 'trace', 2),
|
trace: markPrimop(functional.trace, "trace", 2),
|
||||||
warn: markPrimop(functional.warn, 'warn', 2),
|
warn: markPrimop(functional.warn, "warn", 2),
|
||||||
break: markPrimop(functional.breakFunc, 'break', 1),
|
break: markPrimop(functional.breakFunc, "break", 1),
|
||||||
|
|
||||||
import: markPrimop(io.importFunc, 'import', 1),
|
import: markPrimop(io.importFunc, "import", 1),
|
||||||
scopedImport: markPrimop(io.scopedImport, 'scopedImport', 2),
|
scopedImport: markPrimop(io.scopedImport, "scopedImport", 2),
|
||||||
fetchClosure: markPrimop(io.fetchClosure, 'fetchClosure', 1),
|
fetchClosure: markPrimop(io.fetchClosure, "fetchClosure", 1),
|
||||||
fetchGit: markPrimop(io.fetchGit, 'fetchGit', 1),
|
fetchGit: markPrimop(io.fetchGit, "fetchGit", 1),
|
||||||
fetchTarball: markPrimop(io.fetchTarball, 'fetchTarball', 1),
|
fetchTarball: markPrimop(io.fetchTarball, "fetchTarball", 1),
|
||||||
fetchTree: markPrimop(io.fetchTree, 'fetchTree', 1),
|
fetchTree: markPrimop(io.fetchTree, "fetchTree", 1),
|
||||||
fetchurl: markPrimop(io.fetchurl, 'fetchurl', 1),
|
fetchurl: markPrimop(io.fetchurl, "fetchurl", 1),
|
||||||
readDir: markPrimop(io.readDir, 'readDir', 1),
|
readDir: markPrimop(io.readDir, "readDir", 1),
|
||||||
readFile: markPrimop(io.readFile, 'readFile', 1),
|
readFile: markPrimop(io.readFile, "readFile", 1),
|
||||||
readFileType: markPrimop(io.readFileType, 'readFileType', 1),
|
readFileType: markPrimop(io.readFileType, "readFileType", 1),
|
||||||
pathExists: markPrimop(io.pathExists, 'pathExists', 1),
|
pathExists: markPrimop(io.pathExists, "pathExists", 1),
|
||||||
path: markPrimop(io.path, 'path', 1),
|
path: markPrimop(io.path, "path", 1),
|
||||||
toFile: markPrimop(io.toFile, 'toFile', 2),
|
toFile: markPrimop(io.toFile, "toFile", 2),
|
||||||
toPath: markPrimop(io.toPath, 'toPath', 1),
|
toPath: markPrimop(io.toPath, "toPath", 1),
|
||||||
filterSource: markPrimop(io.filterSource, 'filterSource', 2),
|
filterSource: markPrimop(io.filterSource, "filterSource", 2),
|
||||||
findFile: markPrimop(io.findFile, 'findFile', 2),
|
findFile: markPrimop(io.findFile, "findFile", 2),
|
||||||
getEnv: markPrimop(io.getEnv, 'getEnv', 1),
|
getEnv: markPrimop(io.getEnv, "getEnv", 1),
|
||||||
|
|
||||||
fromJSON: markPrimop(conversion.fromJSON, 'fromJSON', 1),
|
fromJSON: markPrimop(conversion.fromJSON, "fromJSON", 1),
|
||||||
fromTOML: markPrimop(conversion.fromTOML, 'fromTOML', 1),
|
fromTOML: markPrimop(conversion.fromTOML, "fromTOML", 1),
|
||||||
toJSON: markPrimop(conversion.toJSON, 'toJSON', 1),
|
toJSON: markPrimop(conversion.toJSON, "toJSON", 1),
|
||||||
toXML: markPrimop(conversion.toXML, 'toXML', 1),
|
toXML: markPrimop(conversion.toXML, "toXML", 1),
|
||||||
toString: markPrimop(conversion.toString, 'toString', 1),
|
toString: markPrimop(conversion.toString, "toString", 1),
|
||||||
|
|
||||||
getContext: markPrimop(misc.getContext, 'getContext', 1),
|
getContext: markPrimop(misc.getContext, "getContext", 1),
|
||||||
hasContext: markPrimop(misc.hasContext, 'hasContext', 1),
|
hasContext: markPrimop(misc.hasContext, "hasContext", 1),
|
||||||
hashFile: markPrimop(misc.hashFile, 'hashFile', 2),
|
hashFile: markPrimop(misc.hashFile, "hashFile", 2),
|
||||||
hashString: markPrimop(misc.hashString, 'hashString', 2),
|
hashString: markPrimop(misc.hashString, "hashString", 2),
|
||||||
convertHash: markPrimop(misc.convertHash, 'convertHash', 2),
|
convertHash: markPrimop(misc.convertHash, "convertHash", 2),
|
||||||
unsafeDiscardOutputDependency: markPrimop(misc.unsafeDiscardOutputDependency, 'unsafeDiscardOutputDependency', 1),
|
unsafeDiscardOutputDependency: markPrimop(
|
||||||
unsafeDiscardStringContext: markPrimop(misc.unsafeDiscardStringContext, 'unsafeDiscardStringContext', 1),
|
misc.unsafeDiscardOutputDependency,
|
||||||
unsafeGetAttrPos: markPrimop(misc.unsafeGetAttrPos, 'unsafeGetAttrPos', 2),
|
"unsafeDiscardOutputDependency",
|
||||||
addDrvOutputDependencies: markPrimop(misc.addDrvOutputDependencies, 'addDrvOutputDependencies', 2),
|
1,
|
||||||
compareVersions: markPrimop(misc.compareVersions, 'compareVersions', 2),
|
),
|
||||||
dirOf: markPrimop(misc.dirOf, 'dirOf', 1),
|
unsafeDiscardStringContext: markPrimop(misc.unsafeDiscardStringContext, "unsafeDiscardStringContext", 1),
|
||||||
flakeRefToString: markPrimop(misc.flakeRefToString, 'flakeRefToString', 1),
|
unsafeGetAttrPos: markPrimop(misc.unsafeGetAttrPos, "unsafeGetAttrPos", 2),
|
||||||
functionArgs: markPrimop(misc.functionArgs, 'functionArgs', 1),
|
addDrvOutputDependencies: markPrimop(misc.addDrvOutputDependencies, "addDrvOutputDependencies", 2),
|
||||||
genericClosure: markPrimop(misc.genericClosure, 'genericClosure', 1),
|
compareVersions: markPrimop(misc.compareVersions, "compareVersions", 2),
|
||||||
getFlake: markPrimop(misc.getFlake, 'getFlake', 1),
|
dirOf: markPrimop(misc.dirOf, "dirOf", 1),
|
||||||
match: markPrimop(misc.match, 'match', 2),
|
flakeRefToString: markPrimop(misc.flakeRefToString, "flakeRefToString", 1),
|
||||||
outputOf: markPrimop(misc.outputOf, 'outputOf', 2),
|
functionArgs: markPrimop(misc.functionArgs, "functionArgs", 1),
|
||||||
parseDrvName: markPrimop(misc.parseDrvName, 'parseDrvName', 1),
|
genericClosure: markPrimop(misc.genericClosure, "genericClosure", 1),
|
||||||
parseFlakeName: markPrimop(misc.parseFlakeName, 'parseFlakeName', 1),
|
getFlake: markPrimop(misc.getFlake, "getFlake", 1),
|
||||||
placeholder: markPrimop(misc.placeholder, 'placeholder', 1),
|
match: markPrimop(misc.match, "match", 2),
|
||||||
replaceStrings: markPrimop(misc.replaceStrings, 'replaceStrings', 3),
|
outputOf: markPrimop(misc.outputOf, "outputOf", 2),
|
||||||
split: markPrimop(misc.split, 'split', 2),
|
parseDrvName: markPrimop(misc.parseDrvName, "parseDrvName", 1),
|
||||||
splitVersion: markPrimop(misc.splitVersion, 'splitVersion', 1),
|
parseFlakeName: markPrimop(misc.parseFlakeName, "parseFlakeName", 1),
|
||||||
traceVerbose: markPrimop(misc.traceVerbose, 'traceVerbose', 2),
|
placeholder: markPrimop(misc.placeholder, "placeholder", 1),
|
||||||
tryEval: markPrimop(misc.tryEval, 'tryEval', 1),
|
replaceStrings: markPrimop(misc.replaceStrings, "replaceStrings", 3),
|
||||||
zipAttrsWith: markPrimop(misc.zipAttrsWith, 'zipAttrsWith', 2),
|
split: markPrimop(misc.split, "split", 2),
|
||||||
|
splitVersion: markPrimop(misc.splitVersion, "splitVersion", 1),
|
||||||
|
traceVerbose: markPrimop(misc.traceVerbose, "traceVerbose", 2),
|
||||||
|
tryEval: markPrimop(misc.tryEval, "tryEval", 1),
|
||||||
|
zipAttrsWith: markPrimop(misc.zipAttrsWith, "zipAttrsWith", 2),
|
||||||
|
|
||||||
builtins: create_thunk(() => builtins),
|
builtins: create_thunk(() => builtins),
|
||||||
currentSystem: create_thunk(() => {
|
currentSystem: create_thunk(() => {
|
||||||
throw 'Not implemented: currentSystem';
|
throw "Not implemented: currentSystem";
|
||||||
}),
|
}),
|
||||||
currentTime: create_thunk(() => Date.now()),
|
currentTime: create_thunk(() => Date.now()),
|
||||||
|
|
||||||
@@ -245,6 +249,6 @@ export const builtins: any = {
|
|||||||
|
|
||||||
langVersion: 6,
|
langVersion: 6,
|
||||||
nixPath: [],
|
nixPath: [],
|
||||||
nixVersion: 'NIX_JS_VERSION',
|
nixVersion: "NIX_JS_VERSION",
|
||||||
storeDir: '/nix/store',
|
storeDir: "/nix/store",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,72 +3,76 @@
|
|||||||
* These functions require Node.js/Deno APIs not available in V8
|
* These functions require Node.js/Deno APIs not available in V8
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue } from '../types';
|
import type { NixValue } from "../types";
|
||||||
|
|
||||||
export const importFunc = (path: NixValue): never => {
|
export const importFunc = (path: NixValue): never => {
|
||||||
throw 'Not implemented: import';
|
throw "Not implemented: import";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const scopedImport = (scope: NixValue) => (path: NixValue): never => {
|
export const scopedImport =
|
||||||
throw 'Not implemented: scopedImport';
|
(scope: NixValue) =>
|
||||||
};
|
(path: NixValue): never => {
|
||||||
|
throw "Not implemented: scopedImport";
|
||||||
|
};
|
||||||
|
|
||||||
export const fetchClosure = (args: NixValue): never => {
|
export const fetchClosure = (args: NixValue): never => {
|
||||||
throw 'Not implemented: fetchClosure';
|
throw "Not implemented: fetchClosure";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchGit = (args: NixValue): never => {
|
export const fetchGit = (args: NixValue): never => {
|
||||||
throw 'Not implemented: fetchGit';
|
throw "Not implemented: fetchGit";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchTarball = (args: NixValue): never => {
|
export const fetchTarball = (args: NixValue): never => {
|
||||||
throw 'Not implemented: fetchTarball';
|
throw "Not implemented: fetchTarball";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchTree = (args: NixValue): never => {
|
export const fetchTree = (args: NixValue): never => {
|
||||||
throw 'Not implemented: fetchTree';
|
throw "Not implemented: fetchTree";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchurl = (args: NixValue): never => {
|
export const fetchurl = (args: NixValue): never => {
|
||||||
throw 'Not implemented: fetchurl';
|
throw "Not implemented: fetchurl";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const readDir = (path: NixValue): never => {
|
export const readDir = (path: NixValue): never => {
|
||||||
throw 'Not implemented: readDir';
|
throw "Not implemented: readDir";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const readFile = (path: NixValue): never => {
|
export const readFile = (path: NixValue): never => {
|
||||||
throw 'Not implemented: readFile';
|
throw "Not implemented: readFile";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const readFileType = (path: NixValue): never => {
|
export const readFileType = (path: NixValue): never => {
|
||||||
throw 'Not implemented: readFileType';
|
throw "Not implemented: readFileType";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const pathExists = (path: NixValue): never => {
|
export const pathExists = (path: NixValue): never => {
|
||||||
throw 'Not implemented: pathExists';
|
throw "Not implemented: pathExists";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const path = (args: NixValue): never => {
|
export const path = (args: NixValue): never => {
|
||||||
throw 'Not implemented: path';
|
throw "Not implemented: path";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const toFile = (name: NixValue, s: NixValue): never => {
|
export const toFile = (name: NixValue, s: NixValue): never => {
|
||||||
throw 'Not implemented: toFile';
|
throw "Not implemented: toFile";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const toPath = (name: NixValue, s: NixValue): never => {
|
export const toPath = (name: NixValue, s: NixValue): never => {
|
||||||
throw 'Not implemented: toPath';
|
throw "Not implemented: toPath";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const filterSource = (args: NixValue): never => {
|
export const filterSource = (args: NixValue): never => {
|
||||||
throw 'Not implemented: filterSource';
|
throw "Not implemented: filterSource";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const findFile = (search: NixValue) => (lookup: NixValue): never => {
|
export const findFile =
|
||||||
throw 'Not implemented: findFile';
|
(search: NixValue) =>
|
||||||
};
|
(lookup: NixValue): never => {
|
||||||
|
throw "Not implemented: findFile";
|
||||||
|
};
|
||||||
|
|
||||||
export const getEnv = (s: NixValue): never => {
|
export const getEnv = (s: NixValue): never => {
|
||||||
throw 'Not implemented: getEnv';
|
throw "Not implemented: getEnv";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,19 +3,23 @@
|
|||||||
* All functions are properly curried
|
* All functions are properly curried
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue, NixList, NixAttrs } from '../types';
|
import type { NixValue, NixList, NixAttrs } from "../types";
|
||||||
import { force } from '../thunk';
|
import { force } from "../thunk";
|
||||||
import { force_list, force_function, force_numeric, force_int } from '../type-assert';
|
import { force_list, force_function, force_numeric, force_int } from "../type-assert";
|
||||||
|
|
||||||
export const map = (f: NixValue) => (list: NixValue): NixList =>
|
export const map =
|
||||||
|
(f: NixValue) =>
|
||||||
|
(list: NixValue): NixList =>
|
||||||
force_list(list).map(force_function(f));
|
force_list(list).map(force_function(f));
|
||||||
|
|
||||||
export const filter = (f: NixValue) => (list: NixValue): NixList =>
|
export const filter =
|
||||||
|
(f: NixValue) =>
|
||||||
|
(list: NixValue): NixList =>
|
||||||
force_list(list).filter(force_function(f));
|
force_list(list).filter(force_function(f));
|
||||||
|
|
||||||
export const length = (e: NixValue): bigint => {
|
export const length = (e: NixValue): bigint => {
|
||||||
const forced = force(e);
|
const forced = force(e);
|
||||||
if (typeof forced === 'string') return BigInt(forced.length);
|
if (typeof forced === "string") return BigInt(forced.length);
|
||||||
return BigInt(force_list(forced).length);
|
return BigInt(force_list(forced).length);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -23,10 +27,14 @@ export const head = (list: NixValue): NixValue => force_list(list)[0];
|
|||||||
|
|
||||||
export const tail = (list: NixValue): NixList => force_list(list).slice(1);
|
export const tail = (list: NixValue): NixList => force_list(list).slice(1);
|
||||||
|
|
||||||
export const elem = (x: NixValue) => (xs: NixValue): boolean =>
|
export const elem =
|
||||||
|
(x: NixValue) =>
|
||||||
|
(xs: NixValue): boolean =>
|
||||||
force_list(xs).includes(force(x));
|
force_list(xs).includes(force(x));
|
||||||
|
|
||||||
export const elemAt = (xs: NixValue) => (n: NixValue): NixValue => {
|
export const elemAt =
|
||||||
|
(xs: NixValue) =>
|
||||||
|
(n: NixValue): NixValue => {
|
||||||
const list = force_list(xs);
|
const list = force_list(xs);
|
||||||
const idx = Number(force_int(n));
|
const idx = Number(force_int(n));
|
||||||
|
|
||||||
@@ -35,7 +43,7 @@ export const elemAt = (xs: NixValue) => (n: NixValue): NixValue => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return list[idx];
|
return list[idx];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const concatLists = (lists: NixValue): NixList => {
|
export const concatLists = (lists: NixValue): NixList => {
|
||||||
return force_list(lists).reduce((acc: NixList, cur: NixValue) => {
|
return force_list(lists).reduce((acc: NixList, cur: NixValue) => {
|
||||||
@@ -43,21 +51,28 @@ export const concatLists = (lists: NixValue): NixList => {
|
|||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const concatMap = (f: NixValue) => (lists: NixValue): NixList => {
|
export const concatMap =
|
||||||
|
(f: NixValue) =>
|
||||||
|
(lists: NixValue): NixList => {
|
||||||
const fn = force_function(f);
|
const fn = force_function(f);
|
||||||
return force_list(lists).reduce((acc: NixList, cur: NixValue) => {
|
return force_list(lists).reduce((acc: NixList, cur: NixValue) => {
|
||||||
return acc.concat(force(fn(cur)) as NixList);
|
return acc.concat(force(fn(cur)) as NixList);
|
||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const foldlPrime = (op_fn: NixValue) => (nul: NixValue) => (list: NixValue): NixValue => {
|
export const foldlPrime =
|
||||||
|
(op_fn: NixValue) =>
|
||||||
|
(nul: NixValue) =>
|
||||||
|
(list: NixValue): NixValue => {
|
||||||
const forced_op = force_function(op_fn);
|
const forced_op = force_function(op_fn);
|
||||||
return force_list(list).reduce((acc: NixValue, cur: NixValue) => {
|
return force_list(list).reduce((acc: NixValue, cur: NixValue) => {
|
||||||
return forced_op(acc)(cur);
|
return forced_op(acc)(cur);
|
||||||
}, nul);
|
}, nul);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sort = (cmp: NixValue) => (list: NixValue): NixList => {
|
export const sort =
|
||||||
|
(cmp: NixValue) =>
|
||||||
|
(list: NixValue): NixList => {
|
||||||
const forced_list = [...force_list(list)];
|
const forced_list = [...force_list(list)];
|
||||||
const forced_cmp = force_function(cmp);
|
const forced_cmp = force_function(cmp);
|
||||||
return forced_list.sort((a, b) => {
|
return forced_list.sort((a, b) => {
|
||||||
@@ -65,9 +80,11 @@ export const sort = (cmp: NixValue) => (list: NixValue): NixList => {
|
|||||||
if (force(forced_cmp(b)(a))) return 1;
|
if (force(forced_cmp(b)(a))) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const partition = (pred: NixValue) => (list: NixValue): NixAttrs => {
|
export const partition =
|
||||||
|
(pred: NixValue) =>
|
||||||
|
(list: NixValue): NixAttrs => {
|
||||||
const forced_list = force_list(list);
|
const forced_list = force_list(list);
|
||||||
const forced_pred = force_function(pred);
|
const forced_pred = force_function(pred);
|
||||||
const attrs: NixAttrs = {
|
const attrs: NixAttrs = {
|
||||||
@@ -82,9 +99,11 @@ export const partition = (pred: NixValue) => (list: NixValue): NixAttrs => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return attrs;
|
return attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const genList = (f: NixValue) => (len: NixValue): NixList => {
|
export const genList =
|
||||||
|
(f: NixValue) =>
|
||||||
|
(len: NixValue): NixList => {
|
||||||
const func = force_function(f);
|
const func = force_function(f);
|
||||||
const length = force_int(len);
|
const length = force_int(len);
|
||||||
|
|
||||||
@@ -92,11 +111,15 @@ export const genList = (f: NixValue) => (len: NixValue): NixList => {
|
|||||||
throw new TypeError(`genList length must be non-negative integer, got ${length}`);
|
throw new TypeError(`genList length must be non-negative integer, got ${length}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...Array(Number(length)).keys()].map(i => func(BigInt(i)));
|
return [...Array(Number(length)).keys()].map((i) => func(BigInt(i)));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const all = (pred: NixValue) => (list: NixValue): boolean =>
|
export const all =
|
||||||
|
(pred: NixValue) =>
|
||||||
|
(list: NixValue): boolean =>
|
||||||
force_list(list).every(force_function(pred));
|
force_list(list).every(force_function(pred));
|
||||||
|
|
||||||
export const any = (pred: NixValue) => (list: NixValue): boolean =>
|
export const any =
|
||||||
|
(pred: NixValue) =>
|
||||||
|
(list: NixValue): boolean =>
|
||||||
force_list(list).some(force_function(pred));
|
force_list(list).some(force_function(pred));
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
* Math builtin functions
|
* Math builtin functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue } from '../types';
|
import type { NixValue } from "../types";
|
||||||
import { force_numeric } from '../type-assert';
|
import { force_numeric } from "../type-assert";
|
||||||
|
|
||||||
export const ceil = (x: NixValue): bigint => {
|
export const ceil = (x: NixValue): bigint => {
|
||||||
const val = force_numeric(x);
|
const val = force_numeric(x);
|
||||||
if (typeof val === 'bigint') return val; // Already an integer
|
if (typeof val === "bigint") return val; // Already an integer
|
||||||
return BigInt(Math.ceil(val)); // Convert to integer
|
return BigInt(Math.ceil(val)); // Convert to integer
|
||||||
};
|
};
|
||||||
|
|
||||||
export const floor = (x: NixValue): bigint => {
|
export const floor = (x: NixValue): bigint => {
|
||||||
const val = force_numeric(x);
|
const val = force_numeric(x);
|
||||||
if (typeof val === 'bigint') return val; // Already an integer
|
if (typeof val === "bigint") return val; // Already an integer
|
||||||
return BigInt(Math.floor(val)); // Convert to integer
|
return BigInt(Math.floor(val)); // Convert to integer
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,108 +2,125 @@
|
|||||||
* Miscellaneous unimplemented builtin functions
|
* Miscellaneous unimplemented builtin functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue } from '../types';
|
import type { NixValue } from "../types";
|
||||||
|
|
||||||
export const getContext = (s: NixValue): never => {
|
export const getContext = (s: NixValue): never => {
|
||||||
throw 'Not implemented: getContext';
|
throw "Not implemented: getContext";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hasContext = (s: NixValue): never => {
|
export const hasContext = (s: NixValue): never => {
|
||||||
throw 'Not implemented: hasContext';
|
throw "Not implemented: hasContext";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hashFile = (type: NixValue) => (p: NixValue): never => {
|
export const hashFile =
|
||||||
throw 'Not implemented: hashFile';
|
(type: NixValue) =>
|
||||||
};
|
(p: NixValue): never => {
|
||||||
|
throw "Not implemented: hashFile";
|
||||||
|
};
|
||||||
|
|
||||||
export const hashString = (type: NixValue) => (p: NixValue): never => {
|
export const hashString =
|
||||||
throw 'Not implemented: hashString';
|
(type: NixValue) =>
|
||||||
};
|
(p: NixValue): never => {
|
||||||
|
throw "Not implemented: hashString";
|
||||||
|
};
|
||||||
|
|
||||||
export const convertHash = (args: NixValue): never => {
|
export const convertHash = (args: NixValue): never => {
|
||||||
throw 'Not implemented: convertHash';
|
throw "Not implemented: convertHash";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const unsafeDiscardOutputDependency = (s: NixValue): never => {
|
export const unsafeDiscardOutputDependency = (s: NixValue): never => {
|
||||||
throw 'Not implemented: unsafeDiscardOutputDependency';
|
throw "Not implemented: unsafeDiscardOutputDependency";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const unsafeDiscardStringContext = (s: NixValue): never => {
|
export const unsafeDiscardStringContext = (s: NixValue): never => {
|
||||||
throw 'Not implemented: unsafeDiscardStringContext';
|
throw "Not implemented: unsafeDiscardStringContext";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const unsafeGetAttrPos = (s: NixValue): never => {
|
export const unsafeGetAttrPos = (s: NixValue): never => {
|
||||||
throw 'Not implemented: unsafeGetAttrPos';
|
throw "Not implemented: unsafeGetAttrPos";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addDrvOutputDependencies = (s: NixValue): never => {
|
export const addDrvOutputDependencies = (s: NixValue): never => {
|
||||||
throw 'Not implemented: addDrvOutputDependencies';
|
throw "Not implemented: addDrvOutputDependencies";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const compareVersions = (s1: NixValue) => (s2: NixValue): never => {
|
export const compareVersions =
|
||||||
throw 'Not implemented: compareVersions';
|
(s1: NixValue) =>
|
||||||
};
|
(s2: NixValue): never => {
|
||||||
|
throw "Not implemented: compareVersions";
|
||||||
|
};
|
||||||
|
|
||||||
export const dirOf = (s: NixValue): never => {
|
export const dirOf = (s: NixValue): never => {
|
||||||
throw 'Not implemented: dirOf';
|
throw "Not implemented: dirOf";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const flakeRefToString = (attrs: NixValue): never => {
|
export const flakeRefToString = (attrs: NixValue): never => {
|
||||||
throw 'Not implemented: flakeRefToString';
|
throw "Not implemented: flakeRefToString";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const functionArgs = (f: NixValue): never => {
|
export const functionArgs = (f: NixValue): never => {
|
||||||
throw 'Not implemented: functionArgs';
|
throw "Not implemented: functionArgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const genericClosure = (args: NixValue): never => {
|
export const genericClosure = (args: NixValue): never => {
|
||||||
throw 'Not implemented: genericClosure';
|
throw "Not implemented: genericClosure";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFlake = (attrs: NixValue): never => {
|
export const getFlake = (attrs: NixValue): never => {
|
||||||
throw 'Not implemented: getFlake';
|
throw "Not implemented: getFlake";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const match = (regex: NixValue) => (str: NixValue): never => {
|
export const match =
|
||||||
throw 'Not implemented: match';
|
(regex: NixValue) =>
|
||||||
};
|
(str: NixValue): never => {
|
||||||
|
throw "Not implemented: match";
|
||||||
|
};
|
||||||
|
|
||||||
export const outputOf = (drv: NixValue) => (out: NixValue): never => {
|
export const outputOf =
|
||||||
throw 'Not implemented: outputOf';
|
(drv: NixValue) =>
|
||||||
};
|
(out: NixValue): never => {
|
||||||
|
throw "Not implemented: outputOf";
|
||||||
|
};
|
||||||
|
|
||||||
export const parseDrvName = (s: NixValue): never => {
|
export const parseDrvName = (s: NixValue): never => {
|
||||||
throw 'Not implemented: parseDrvName';
|
throw "Not implemented: parseDrvName";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseFlakeName = (s: NixValue): never => {
|
export const parseFlakeName = (s: NixValue): never => {
|
||||||
throw 'Not implemented: parseFlakeName';
|
throw "Not implemented: parseFlakeName";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const placeholder = (output: NixValue): never => {
|
export const placeholder = (output: NixValue): never => {
|
||||||
throw 'Not implemented: placeholder';
|
throw "Not implemented: placeholder";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const replaceStrings = (from: NixValue) => (to: NixValue) => (s: NixValue): never => {
|
export const replaceStrings =
|
||||||
throw 'Not implemented: replaceStrings';
|
(from: NixValue) =>
|
||||||
};
|
(to: NixValue) =>
|
||||||
|
(s: NixValue): never => {
|
||||||
|
throw "Not implemented: replaceStrings";
|
||||||
|
};
|
||||||
|
|
||||||
export const split = (regex: NixValue, str: NixValue): never => {
|
export const split = (regex: NixValue, str: NixValue): never => {
|
||||||
throw 'Not implemented: split';
|
throw "Not implemented: split";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const splitVersion = (s: NixValue): never => {
|
export const splitVersion = (s: NixValue): never => {
|
||||||
throw 'Not implemented: splitVersion';
|
throw "Not implemented: splitVersion";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const traceVerbose = (e1: NixValue, e2: NixValue): never => {
|
export const traceVerbose = (e1: NixValue, e2: NixValue): never => {
|
||||||
throw 'Not implemented: traceVerbose';
|
throw "Not implemented: traceVerbose";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const tryEval = (e1: NixValue) => (e2: NixValue): never => {
|
export const tryEval =
|
||||||
throw 'Not implemented: tryEval';
|
(e1: NixValue) =>
|
||||||
};
|
(e2: NixValue): never => {
|
||||||
|
throw "Not implemented: tryEval";
|
||||||
|
};
|
||||||
|
|
||||||
export const zipAttrsWith = (f: NixValue) => (list: NixValue): never => {
|
export const zipAttrsWith =
|
||||||
throw 'Not implemented: zipAttrsWith';
|
(f: NixValue) =>
|
||||||
};
|
(list: NixValue): never => {
|
||||||
|
throw "Not implemented: zipAttrsWith";
|
||||||
|
};
|
||||||
|
|||||||
@@ -2,32 +2,37 @@
|
|||||||
* String operation builtin functions
|
* String operation builtin functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue } from '../types';
|
import type { NixValue } from "../types";
|
||||||
import { force_string, force_list, force_int } from '../type-assert';
|
import { force_string, force_list, force_int } from "../type-assert";
|
||||||
|
|
||||||
export const stringLength = (e: NixValue): number => force_string(e).length;
|
export const stringLength = (e: NixValue): number => force_string(e).length;
|
||||||
|
|
||||||
export const substring = (start: NixValue) => (len: NixValue) => (s: NixValue): string => {
|
export const substring =
|
||||||
|
(start: NixValue) =>
|
||||||
|
(len: NixValue) =>
|
||||||
|
(s: NixValue): string => {
|
||||||
const str = force_string(s);
|
const str = force_string(s);
|
||||||
const startPos = Number(force_int(start));
|
const startPos = Number(force_int(start));
|
||||||
const length = Number(force_int(len));
|
const length = Number(force_int(len));
|
||||||
return str.substring(startPos, startPos + length);
|
return str.substring(startPos, startPos + length);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const concatStringsSep = (sep: NixValue) => (list: NixValue): string =>
|
export const concatStringsSep =
|
||||||
|
(sep: NixValue) =>
|
||||||
|
(list: NixValue): string =>
|
||||||
force_list(list).join(force_string(sep));
|
force_list(list).join(force_string(sep));
|
||||||
|
|
||||||
export const baseNameOf = (x: NixValue): string => {
|
export const baseNameOf = (x: NixValue): string => {
|
||||||
const str = force_string(x);
|
const str = force_string(x);
|
||||||
if (str.length === 0) return '';
|
if (str.length === 0) return "";
|
||||||
|
|
||||||
let last = str.length - 1;
|
let last = str.length - 1;
|
||||||
if (str[last] === '/' && last > 0) last -= 1;
|
if (str[last] === "/" && last > 0) last -= 1;
|
||||||
|
|
||||||
let pos = last;
|
let pos = last;
|
||||||
while (pos >= 0 && str[pos] !== '/') pos -= 1;
|
while (pos >= 0 && str[pos] !== "/") pos -= 1;
|
||||||
|
|
||||||
if (pos !== 0 || (pos === 0 && str[pos] === '/')) {
|
if (pos !== 0 || (pos === 0 && str[pos] === "/")) {
|
||||||
pos += 1;
|
pos += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,26 +2,36 @@
|
|||||||
* Type checking builtin functions
|
* Type checking builtin functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixAttrs, NixBool, NixFloat, NixFunction, NixInt, NixList, NixNull, NixString, NixValue } from '../types';
|
import type {
|
||||||
import { force } from '../thunk';
|
NixAttrs,
|
||||||
|
NixBool,
|
||||||
|
NixFloat,
|
||||||
|
NixFunction,
|
||||||
|
NixInt,
|
||||||
|
NixList,
|
||||||
|
NixNull,
|
||||||
|
NixString,
|
||||||
|
NixValue,
|
||||||
|
} from "../types";
|
||||||
|
import { force } from "../thunk";
|
||||||
|
|
||||||
export const isAttrs = (e: NixValue): e is NixAttrs => {
|
export const isAttrs = (e: NixValue): e is NixAttrs => {
|
||||||
const val = force(e);
|
const val = force(e);
|
||||||
return typeof val === 'object' && !Array.isArray(val) && val !== null;
|
return typeof val === "object" && !Array.isArray(val) && val !== null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isBool = (e: NixValue): e is NixBool => typeof force(e) === 'boolean';
|
export const isBool = (e: NixValue): e is NixBool => typeof force(e) === "boolean";
|
||||||
|
|
||||||
export const isFloat = (e: NixValue): e is NixFloat => {
|
export const isFloat = (e: NixValue): e is NixFloat => {
|
||||||
const val = force(e);
|
const val = force(e);
|
||||||
return typeof val === 'number'; // Only number is float
|
return typeof val === "number"; // Only number is float
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isFunction = (e: NixValue): e is NixFunction => typeof force(e) === 'function';
|
export const isFunction = (e: NixValue): e is NixFunction => typeof force(e) === "function";
|
||||||
|
|
||||||
export const isInt = (e: NixValue): e is NixInt => {
|
export const isInt = (e: NixValue): e is NixInt => {
|
||||||
const val = force(e);
|
const val = force(e);
|
||||||
return typeof val === 'bigint'; // Only bigint is int
|
return typeof val === "bigint"; // Only bigint is int
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isList = (e: NixValue): e is NixList => Array.isArray(force(e));
|
export const isList = (e: NixValue): e is NixList => Array.isArray(force(e));
|
||||||
@@ -29,22 +39,22 @@ export const isList = (e: NixValue): e is NixList => Array.isArray(force(e));
|
|||||||
export const isNull = (e: NixValue): e is NixNull => force(e) === null;
|
export const isNull = (e: NixValue): e is NixNull => force(e) === null;
|
||||||
|
|
||||||
export const isPath = (e: NixValue): never => {
|
export const isPath = (e: NixValue): never => {
|
||||||
throw 'Not implemented: isPath';
|
throw "Not implemented: isPath";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isString = (e: NixValue): e is NixString => typeof force(e) === 'string';
|
export const isString = (e: NixValue): e is NixString => typeof force(e) === "string";
|
||||||
|
|
||||||
export const typeOf = (e: NixValue): string => {
|
export const typeOf = (e: NixValue): string => {
|
||||||
const val = force(e);
|
const val = force(e);
|
||||||
|
|
||||||
if (typeof val === 'bigint') return 'int';
|
if (typeof val === "bigint") return "int";
|
||||||
if (typeof val === 'number') return 'float';
|
if (typeof val === "number") return "float";
|
||||||
if (typeof val === 'boolean') return 'bool';
|
if (typeof val === "boolean") return "bool";
|
||||||
if (typeof val === 'string') return 'string';
|
if (typeof val === "string") return "string";
|
||||||
if (val === null) return 'null';
|
if (val === null) return "null";
|
||||||
if (Array.isArray(val)) return 'list';
|
if (Array.isArray(val)) return "list";
|
||||||
if (typeof val === 'function') return 'lambda';
|
if (typeof val === "function") return "lambda";
|
||||||
if (typeof val === 'object') return 'set';
|
if (typeof val === "object") return "set";
|
||||||
|
|
||||||
throw new TypeError(`Unknown Nix type: ${typeof val}`);
|
throw new TypeError(`Unknown Nix type: ${typeof val}`);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
* Implements attribute selection, parameter validation, and lazy sets
|
* Implements attribute selection, parameter validation, and lazy sets
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue, NixAttrs } from './types';
|
import type { NixValue, NixAttrs } from "./types";
|
||||||
import { force_attrs, force_string } from './type-assert';
|
import { force_attrs, force_string } from "./type-assert";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select an attribute from an attribute set
|
* Select an attribute from an attribute set
|
||||||
@@ -35,11 +35,7 @@ export const select = (obj: NixValue, key: NixValue): NixValue => {
|
|||||||
* @param default_val - Value to return if key not found
|
* @param default_val - Value to return if key not found
|
||||||
* @returns obj[key] if exists, otherwise default_val
|
* @returns obj[key] if exists, otherwise default_val
|
||||||
*/
|
*/
|
||||||
export const select_with_default = (
|
export const select_with_default = (obj: NixValue, key: NixValue, default_val: NixValue): NixValue => {
|
||||||
obj: NixValue,
|
|
||||||
key: NixValue,
|
|
||||||
default_val: NixValue
|
|
||||||
): NixValue => {
|
|
||||||
const forced_obj = force_attrs(obj);
|
const forced_obj = force_attrs(obj);
|
||||||
const forced_key = force_string(key);
|
const forced_key = force_string(key);
|
||||||
|
|
||||||
@@ -72,7 +68,7 @@ export const select_with_default = (
|
|||||||
export const validate_params = (
|
export const validate_params = (
|
||||||
arg: NixValue,
|
arg: NixValue,
|
||||||
required: string[] | null,
|
required: string[] | null,
|
||||||
allowed: string[] | null
|
allowed: string[] | null,
|
||||||
): NixAttrs => {
|
): NixAttrs => {
|
||||||
const forced_arg = force_attrs(arg);
|
const forced_arg = force_attrs(arg);
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
* All functionality is exported via the global `Nix` object
|
* All functionality is exported via the global `Nix` object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { create_thunk, force, is_thunk, IS_THUNK } from './thunk';
|
import { create_thunk, force, is_thunk, IS_THUNK } from "./thunk";
|
||||||
import { select, select_with_default, validate_params } from './helpers';
|
import { select, select_with_default, validate_params } from "./helpers";
|
||||||
import { op } from './operators';
|
import { op } from "./operators";
|
||||||
import { builtins, IS_PRIMOP } from './builtins';
|
import { builtins, IS_PRIMOP } from "./builtins";
|
||||||
|
|
||||||
export type NixRuntime = typeof Nix;
|
export type NixRuntime = typeof Nix;
|
||||||
|
|
||||||
@@ -31,5 +31,5 @@ export const Nix = {
|
|||||||
|
|
||||||
globalThis.Nix = Nix;
|
globalThis.Nix = Nix;
|
||||||
declare global {
|
declare global {
|
||||||
var Nix: NixRuntime
|
var Nix: NixRuntime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Implements all binary and unary operators used by codegen
|
* Implements all binary and unary operators used by codegen
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue, NixList, NixAttrs } from './types';
|
import type { NixValue, NixList, NixAttrs } from "./types";
|
||||||
import { force } from './thunk';
|
import { force } from "./thunk";
|
||||||
import { force_numeric, force_list, force_attrs, coerce_numeric } from './type-assert';
|
import { force_numeric, force_list, force_attrs, coerce_numeric } from "./type-assert";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operator object exported as Nix.op
|
* Operator object exported as Nix.op
|
||||||
@@ -33,10 +33,10 @@ export const op = {
|
|||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
||||||
|
|
||||||
if (bv === 0 || bv === 0n) {
|
if (bv === 0 || bv === 0n) {
|
||||||
throw new RangeError('Division by zero');
|
throw new RangeError("Division by zero");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (av as any) / (bv as any)
|
return (av as any) / (bv as any);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Comparison operators (JavaScript natively supports bigint/number mixed comparison)
|
// Comparison operators (JavaScript natively supports bigint/number mixed comparison)
|
||||||
@@ -44,13 +44,13 @@ export const op = {
|
|||||||
// FIXME: Int and Float
|
// FIXME: Int and Float
|
||||||
const av = force(a);
|
const av = force(a);
|
||||||
const bv = force(b);
|
const bv = force(b);
|
||||||
return av === bv
|
return av === bv;
|
||||||
},
|
},
|
||||||
neq: (a: NixValue, b: NixValue): boolean => {
|
neq: (a: NixValue, b: NixValue): boolean => {
|
||||||
// FIXME: Int and Float
|
// FIXME: Int and Float
|
||||||
const av = force(a);
|
const av = force(a);
|
||||||
const bv = force(b);
|
const bv = force(b);
|
||||||
return av !== bv
|
return av !== bv;
|
||||||
},
|
},
|
||||||
lt: (a: NixValue, b: NixValue): boolean => {
|
lt: (a: NixValue, b: NixValue): boolean => {
|
||||||
// FIXME: Non-numeric
|
// FIXME: Non-numeric
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
* Implements thunks for lazy evaluation of Nix expressions
|
* Implements thunks for lazy evaluation of Nix expressions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue, NixThunkInterface } from './types';
|
import type { NixValue, NixThunkInterface } from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbol used to mark objects as thunks
|
* Symbol used to mark objects as thunks
|
||||||
* This is exported to Rust via Nix.IS_THUNK
|
* This is exported to Rust via Nix.IS_THUNK
|
||||||
*/
|
*/
|
||||||
export const IS_THUNK = Symbol('is_thunk');
|
export const IS_THUNK = Symbol("is_thunk");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NixThunk class - represents a lazy, unevaluated expression
|
* NixThunk class - represents a lazy, unevaluated expression
|
||||||
@@ -35,12 +35,7 @@ export class NixThunk implements NixThunkInterface {
|
|||||||
* @returns true if value is a NixThunk
|
* @returns true if value is a NixThunk
|
||||||
*/
|
*/
|
||||||
export const is_thunk = (value: unknown): value is NixThunkInterface => {
|
export const is_thunk = (value: unknown): value is NixThunkInterface => {
|
||||||
return (
|
return value !== null && typeof value === "object" && IS_THUNK in value && value[IS_THUNK] === true;
|
||||||
value !== null &&
|
|
||||||
typeof value === 'object' &&
|
|
||||||
IS_THUNK in value &&
|
|
||||||
value[IS_THUNK] === true
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
* These functions force evaluation and verify the type, throwing errors on mismatch
|
* These functions force evaluation and verify the type, throwing errors on mismatch
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue, NixList, NixAttrs, NixFunction, NixInt, NixFloat, NixNumber } from './types';
|
import type { NixValue, NixList, NixAttrs, NixFunction, NixInt, NixFloat, NixNumber } from "./types";
|
||||||
import { force } from './thunk';
|
import { force } from "./thunk";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force a value and assert it's a list
|
* Force a value and assert it's a list
|
||||||
@@ -24,7 +24,7 @@ export const force_list = (value: NixValue): NixList => {
|
|||||||
*/
|
*/
|
||||||
export const force_function = (value: NixValue): NixFunction => {
|
export const force_function = (value: NixValue): NixFunction => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced !== 'function') {
|
if (typeof forced !== "function") {
|
||||||
throw new TypeError(`Expected function, got ${typeof forced}`);
|
throw new TypeError(`Expected function, got ${typeof forced}`);
|
||||||
}
|
}
|
||||||
return forced;
|
return forced;
|
||||||
@@ -36,7 +36,7 @@ export const force_function = (value: NixValue): NixFunction => {
|
|||||||
*/
|
*/
|
||||||
export const force_attrs = (value: NixValue): NixAttrs => {
|
export const force_attrs = (value: NixValue): NixAttrs => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced !== 'object' || forced === null || Array.isArray(forced)) {
|
if (typeof forced !== "object" || forced === null || Array.isArray(forced)) {
|
||||||
throw new TypeError(`Expected attribute set, got ${typeof forced}`);
|
throw new TypeError(`Expected attribute set, got ${typeof forced}`);
|
||||||
}
|
}
|
||||||
return forced as NixAttrs;
|
return forced as NixAttrs;
|
||||||
@@ -48,7 +48,7 @@ export const force_attrs = (value: NixValue): NixAttrs => {
|
|||||||
*/
|
*/
|
||||||
export const force_string = (value: NixValue): string => {
|
export const force_string = (value: NixValue): string => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced !== 'string') {
|
if (typeof forced !== "string") {
|
||||||
throw new TypeError(`Expected string, got ${typeof forced}`);
|
throw new TypeError(`Expected string, got ${typeof forced}`);
|
||||||
}
|
}
|
||||||
return forced;
|
return forced;
|
||||||
@@ -60,7 +60,7 @@ export const force_string = (value: NixValue): string => {
|
|||||||
*/
|
*/
|
||||||
export const force_bool = (value: NixValue): boolean => {
|
export const force_bool = (value: NixValue): boolean => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced !== 'boolean') {
|
if (typeof forced !== "boolean") {
|
||||||
throw new TypeError(`Expected boolean, got ${typeof forced}`);
|
throw new TypeError(`Expected boolean, got ${typeof forced}`);
|
||||||
}
|
}
|
||||||
return forced;
|
return forced;
|
||||||
@@ -72,7 +72,7 @@ export const force_bool = (value: NixValue): boolean => {
|
|||||||
*/
|
*/
|
||||||
export const force_int = (value: NixValue): NixInt => {
|
export const force_int = (value: NixValue): NixInt => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced === 'bigint') {
|
if (typeof forced === "bigint") {
|
||||||
return forced;
|
return forced;
|
||||||
}
|
}
|
||||||
throw new TypeError(`Expected int, got ${typeof forced}`);
|
throw new TypeError(`Expected int, got ${typeof forced}`);
|
||||||
@@ -84,7 +84,7 @@ export const force_int = (value: NixValue): NixInt => {
|
|||||||
*/
|
*/
|
||||||
export const force_float = (value: NixValue): NixFloat => {
|
export const force_float = (value: NixValue): NixFloat => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced === 'number') {
|
if (typeof forced === "number") {
|
||||||
return forced;
|
return forced;
|
||||||
}
|
}
|
||||||
throw new TypeError(`Expected float, got ${typeof forced}`);
|
throw new TypeError(`Expected float, got ${typeof forced}`);
|
||||||
@@ -96,7 +96,7 @@ export const force_float = (value: NixValue): NixFloat => {
|
|||||||
*/
|
*/
|
||||||
export const force_numeric = (value: NixValue): NixNumber => {
|
export const force_numeric = (value: NixValue): NixNumber => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced === 'bigint' || typeof forced === 'number') {
|
if (typeof forced === "bigint" || typeof forced === "number") {
|
||||||
return forced;
|
return forced;
|
||||||
}
|
}
|
||||||
throw new TypeError(`Expected numeric type, got ${typeof forced}`);
|
throw new TypeError(`Expected numeric type, got ${typeof forced}`);
|
||||||
@@ -107,19 +107,13 @@ export const force_numeric = (value: NixValue): NixNumber => {
|
|||||||
* Rule: If either is float, convert both to float; otherwise keep as bigint
|
* Rule: If either is float, convert both to float; otherwise keep as bigint
|
||||||
* @returns [a, b] tuple of coerced values
|
* @returns [a, b] tuple of coerced values
|
||||||
*/
|
*/
|
||||||
export const coerce_numeric = (
|
export const coerce_numeric = (a: NixNumber, b: NixNumber): [NixFloat, NixFloat] | [NixInt, NixInt] => {
|
||||||
a: NixNumber,
|
const aIsInt = typeof a === "bigint";
|
||||||
b: NixNumber
|
const bIsInt = typeof b === "bigint";
|
||||||
): [NixFloat, NixFloat] | [NixInt, NixInt] => {
|
|
||||||
const aIsInt = typeof a === 'bigint';
|
|
||||||
const bIsInt = typeof b === 'bigint';
|
|
||||||
|
|
||||||
// If either is float, convert both to float
|
// If either is float, convert both to float
|
||||||
if (!aIsInt || !bIsInt) {
|
if (!aIsInt || !bIsInt) {
|
||||||
return [
|
return [aIsInt ? Number(a) : a, bIsInt ? Number(b) : b];
|
||||||
aIsInt ? Number(a) : a,
|
|
||||||
bIsInt ? Number(b) : b
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both are integers
|
// Both are integers
|
||||||
|
|||||||
@@ -32,12 +32,7 @@ export type NixPrimitive = NixNull | NixBool | NixInt | NixFloat | NixString;
|
|||||||
* NixValue: Union type representing any possible Nix value
|
* NixValue: Union type representing any possible Nix value
|
||||||
* This is the core type used throughout the runtime
|
* This is the core type used throughout the runtime
|
||||||
*/
|
*/
|
||||||
export type NixValue =
|
export type NixValue = NixPrimitive | NixList | NixAttrs | NixFunction | NixThunkInterface;
|
||||||
| NixPrimitive
|
|
||||||
| NixList
|
|
||||||
| NixAttrs
|
|
||||||
| NixFunction
|
|
||||||
| NixThunkInterface;
|
|
||||||
|
|
||||||
// Operator function signatures
|
// Operator function signatures
|
||||||
export type BinaryOp<T = NixValue, U = NixValue, R = NixValue> = (a: T, b: U) => R;
|
export type BinaryOp<T = NixValue, U = NixValue, R = NixValue> = (a: T, b: U) => R;
|
||||||
|
|||||||
Reference in New Issue
Block a user