chore: tidy
This commit is contained in:
7
.lazy.lua
Normal file
7
.lazy.lua
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
vim.lsp.config("biome", {
|
||||||
|
root_dir = function (bufnr, on_dir)
|
||||||
|
on_dir(vim.fn.getcwd())
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
return {}
|
||||||
@@ -17,6 +17,13 @@
|
|||||||
"lineWidth": 110,
|
"lineWidth": 110,
|
||||||
"lineEnding": "lf"
|
"lineEnding": "lf"
|
||||||
},
|
},
|
||||||
|
"linter": {
|
||||||
|
"rules": {
|
||||||
|
"style": {
|
||||||
|
"useNamingConvention": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"javascript": {
|
"javascript": {
|
||||||
"formatter": {
|
"formatter": {
|
||||||
"arrowParentheses": "always",
|
"arrowParentheses": "always",
|
||||||
|
|||||||
@@ -3,33 +3,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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 { forceNumeric, coerceNumeric, forceInt } from "../type-assert";
|
||||||
|
|
||||||
export const add =
|
export const add =
|
||||||
(a: NixValue) =>
|
(a: NixValue) =>
|
||||||
(b: NixValue): bigint | number => {
|
(b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) + (bv as any);
|
return (av as any) + (bv as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sub =
|
export const sub =
|
||||||
(a: NixValue) =>
|
(a: NixValue) =>
|
||||||
(b: NixValue): bigint | number => {
|
(b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) - (bv as any);
|
return (av as any) - (bv as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mul =
|
export const mul =
|
||||||
(a: NixValue) =>
|
(a: NixValue) =>
|
||||||
(b: NixValue): bigint | number => {
|
(b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) * (bv as any);
|
return (av as any) * (bv as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const div =
|
export const div =
|
||||||
(a: NixValue) =>
|
(a: NixValue) =>
|
||||||
(b: NixValue): NixNumber => {
|
(b: NixValue): NixNumber => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
|
|
||||||
if (bv === 0 || bv === 0n) {
|
if (bv === 0 || bv === 0n) {
|
||||||
throw new RangeError("Division by zero");
|
throw new RangeError("Division by zero");
|
||||||
@@ -42,28 +42,28 @@ export const div =
|
|||||||
export const bitAnd =
|
export const bitAnd =
|
||||||
(a: NixValue) =>
|
(a: NixValue) =>
|
||||||
(b: NixValue): NixInt => {
|
(b: NixValue): NixInt => {
|
||||||
const av = force_int(a);
|
const av = forceInt(a);
|
||||||
const bv = force_int(b);
|
const bv = forceInt(b);
|
||||||
return av & bv;
|
return av & bv;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const bitOr =
|
export const bitOr =
|
||||||
(a: NixValue) =>
|
(a: NixValue) =>
|
||||||
(b: NixValue): NixInt => {
|
(b: NixValue): NixInt => {
|
||||||
const av = force_int(a);
|
const av = forceInt(a);
|
||||||
const bv = force_int(b);
|
const bv = forceInt(b);
|
||||||
return av | bv;
|
return av | bv;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const bitXor =
|
export const bitXor =
|
||||||
(a: NixValue) =>
|
(a: NixValue) =>
|
||||||
(b: NixValue): NixInt => {
|
(b: NixValue): NixInt => {
|
||||||
const av = force_int(a);
|
const av = forceInt(a);
|
||||||
const bv = force_int(b);
|
const bv = forceInt(b);
|
||||||
return av ^ bv;
|
return av ^ bv;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const lessThan =
|
export const lessThan =
|
||||||
(a: NixValue) =>
|
(a: NixValue) =>
|
||||||
(b: NixValue): NixBool =>
|
(b: NixValue): NixBool =>
|
||||||
force_numeric(a) < force_numeric(b);
|
forceNumeric(a) < forceNumeric(b);
|
||||||
|
|||||||
@@ -3,30 +3,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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 { forceAttrs, forceString, forceFunction, forceList } from "../type-assert";
|
||||||
|
|
||||||
export const attrNames = (set: NixValue): string[] => Object.keys(force_attrs(set)).sort();
|
export const attrNames = (set: NixValue): string[] => Object.keys(forceAttrs(set)).sort();
|
||||||
|
|
||||||
export const attrValues = (set: NixValue): NixValue[] => Object.values(force_attrs(set));
|
export const attrValues = (set: NixValue): NixValue[] => Object.values(forceAttrs(set));
|
||||||
|
|
||||||
export const getAttr =
|
export const getAttr =
|
||||||
(s: NixValue) =>
|
(s: NixValue) =>
|
||||||
(set: NixValue): NixValue =>
|
(set: NixValue): NixValue =>
|
||||||
force_attrs(set)[force_string(s)];
|
forceAttrs(set)[forceString(s)];
|
||||||
|
|
||||||
export const hasAttr =
|
export const hasAttr =
|
||||||
(s: NixValue) =>
|
(s: NixValue) =>
|
||||||
(set: NixValue): boolean =>
|
(set: NixValue): boolean =>
|
||||||
Object.hasOwn(force_attrs(set), force_string(s));
|
Object.hasOwn(forceAttrs(set), forceString(s));
|
||||||
|
|
||||||
export const mapAttrs =
|
export const mapAttrs =
|
||||||
(f: NixValue) =>
|
(f: NixValue) =>
|
||||||
(attrs: NixValue): NixAttrs => {
|
(attrs: NixValue): NixAttrs => {
|
||||||
const new_attrs: NixAttrs = {};
|
const new_attrs: NixAttrs = {};
|
||||||
const forced_attrs = force_attrs(attrs);
|
const forced_attrs = forceAttrs(attrs);
|
||||||
const forced_f = force_function(f);
|
const forced_f = forceFunction(f);
|
||||||
for (const key in forced_attrs) {
|
for (const key in forced_attrs) {
|
||||||
new_attrs[key] = forced_f(key)(forced_attrs[key]);
|
new_attrs[key] = forceFunction(forced_f(key))(forced_attrs[key]);
|
||||||
}
|
}
|
||||||
return new_attrs;
|
return new_attrs;
|
||||||
};
|
};
|
||||||
@@ -35,8 +35,8 @@ export const removeAttrs =
|
|||||||
(attrs: NixValue) =>
|
(attrs: NixValue) =>
|
||||||
(list: NixValue): NixAttrs => {
|
(list: NixValue): NixAttrs => {
|
||||||
const new_attrs: NixAttrs = {};
|
const new_attrs: NixAttrs = {};
|
||||||
const forced_attrs = force_attrs(attrs);
|
const forced_attrs = forceAttrs(attrs);
|
||||||
const forced_list = force_list(list);
|
const forced_list = forceList(list);
|
||||||
|
|
||||||
for (const key in forced_attrs) {
|
for (const key in forced_attrs) {
|
||||||
if (!(key in forced_list)) {
|
if (!(key in forced_list)) {
|
||||||
@@ -48,10 +48,10 @@ export const removeAttrs =
|
|||||||
|
|
||||||
export const listToAttrs = (e: NixValue): NixAttrs => {
|
export const listToAttrs = (e: NixValue): NixAttrs => {
|
||||||
const attrs: NixAttrs = {};
|
const attrs: NixAttrs = {};
|
||||||
const forced_e = [...force_list(e)].reverse();
|
const forced_e = [...forceList(e)].reverse();
|
||||||
for (const obj of forced_e) {
|
for (const obj of forced_e) {
|
||||||
const item = force_attrs(obj);
|
const item = forceAttrs(obj);
|
||||||
attrs[force_string(item.name)] = item.value;
|
attrs[forceString(item.name)] = item.value;
|
||||||
}
|
}
|
||||||
return attrs;
|
return attrs;
|
||||||
};
|
};
|
||||||
@@ -59,8 +59,8 @@ export const listToAttrs = (e: NixValue): NixAttrs => {
|
|||||||
export const intersectAttrs =
|
export const intersectAttrs =
|
||||||
(e1: NixValue) =>
|
(e1: NixValue) =>
|
||||||
(e2: NixValue): NixAttrs => {
|
(e2: NixValue): NixAttrs => {
|
||||||
const f1 = force_attrs(e1);
|
const f1 = forceAttrs(e1);
|
||||||
const f2 = force_attrs(e2);
|
const f2 = forceAttrs(e2);
|
||||||
const attrs: NixAttrs = {};
|
const attrs: NixAttrs = {};
|
||||||
for (const key of Object.keys(f2)) {
|
for (const key of Object.keys(f2)) {
|
||||||
if (Object.hasOwn(f1, key)) {
|
if (Object.hasOwn(f1, key)) {
|
||||||
@@ -73,9 +73,9 @@ export const intersectAttrs =
|
|||||||
export const catAttrs =
|
export const catAttrs =
|
||||||
(attr: NixValue) =>
|
(attr: NixValue) =>
|
||||||
(list: NixValue): NixList => {
|
(list: NixValue): NixList => {
|
||||||
const key = force_string(attr);
|
const key = forceString(attr);
|
||||||
return force_list(list)
|
return forceList(list)
|
||||||
.map((set) => force_attrs(set)[key])
|
.map((set) => forceAttrs(set)[key])
|
||||||
.filter((val) => val !== undefined);
|
.filter((val) => val !== undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -83,10 +83,10 @@ export const groupBy =
|
|||||||
(f: NixValue) =>
|
(f: NixValue) =>
|
||||||
(list: NixValue): NixAttrs => {
|
(list: NixValue): NixAttrs => {
|
||||||
const attrs: NixAttrs = {};
|
const attrs: NixAttrs = {};
|
||||||
const forced_f = force_function(f);
|
const forced_f = forceFunction(f);
|
||||||
const forced_list = force_list(list);
|
const forced_list = forceList(list);
|
||||||
for (const elem of forced_list) {
|
for (const elem of forced_list) {
|
||||||
const key = force_string(forced_f(elem));
|
const key = forceString(forced_f(elem));
|
||||||
if (!attrs[key]) attrs[key] = [];
|
if (!attrs[key]) attrs[key] = [];
|
||||||
(attrs[key] as NixList).push(elem);
|
(attrs[key] as NixList).push(elem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,6 +191,6 @@ export const coerceToString = (
|
|||||||
* @param value - The value to convert to a string
|
* @param value - The value to convert to a string
|
||||||
* @returns The string representation
|
* @returns The string representation
|
||||||
*/
|
*/
|
||||||
export const toString = (value: NixValue): string => {
|
export const toStringFunc = (value: NixValue): string => {
|
||||||
return coerceToString(value, StringCoercionMode.ToString, false);
|
return coerceToString(value, StringCoercionMode.ToString, false);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import { CatchableError, type NixValue } from "../types";
|
import { CatchableError, type NixValue } from "../types";
|
||||||
import { force } from "../thunk";
|
import { force } from "../thunk";
|
||||||
import { force_string } from "../type-assert";
|
import { forceString } from "../type-assert";
|
||||||
|
|
||||||
export const seq =
|
export const seq =
|
||||||
(e1: NixValue) =>
|
(e1: NixValue) =>
|
||||||
@@ -24,7 +24,7 @@ export const abort = (s: NixValue): never => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const throwFunc = (s: NixValue): never => {
|
export const throwFunc = (s: NixValue): never => {
|
||||||
throw new CatchableError(force_string(s));
|
throw new CatchableError(forceString(s));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const trace = (e1: NixValue, e2: NixValue): NixValue => {
|
export const trace = (e1: NixValue, e2: NixValue): NixValue => {
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ export const builtins: any = {
|
|||||||
fromTOML: mkPrimop(conversion.fromTOML, "fromTOML", 1),
|
fromTOML: mkPrimop(conversion.fromTOML, "fromTOML", 1),
|
||||||
toJSON: mkPrimop(conversion.toJSON, "toJSON", 1),
|
toJSON: mkPrimop(conversion.toJSON, "toJSON", 1),
|
||||||
toXML: mkPrimop(conversion.toXML, "toXML", 1),
|
toXML: mkPrimop(conversion.toXML, "toXML", 1),
|
||||||
toString: mkPrimop(conversion.toString, "toString", 1),
|
toString: mkPrimop(conversion.toStringFunc, "toString", 1),
|
||||||
|
|
||||||
addErrorContext: mkPrimop(misc.addErrorContext, "addErrorContext", 1),
|
addErrorContext: mkPrimop(misc.addErrorContext, "addErrorContext", 1),
|
||||||
appendContext: mkPrimop(misc.appendContext, "appendContext", 1),
|
appendContext: mkPrimop(misc.appendContext, "appendContext", 1),
|
||||||
|
|||||||
@@ -3,23 +3,20 @@
|
|||||||
* Implemented via Rust ops exposed through deno_core
|
* Implemented via Rust ops exposed through deno_core
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { forceString } from "../type-assert";
|
||||||
import type { NixValue } from "../types";
|
import type { NixValue } from "../types";
|
||||||
import { force_string } from "../type-assert";
|
|
||||||
|
|
||||||
// Declare Deno.core.ops global (provided by deno_core runtime)
|
// Declare Deno.core.ops global (provided by deno_core runtime)
|
||||||
|
|
||||||
export const importFunc = (path: NixValue): NixValue => {
|
export const importFunc = (path: NixValue): NixValue => {
|
||||||
// For MVP: only support string paths
|
// For MVP: only support string paths
|
||||||
// TODO: After implementing path type, also accept path values
|
// TODO: After implementing path type, also accept path values
|
||||||
const pathStr = force_string(path);
|
const pathStr = forceString(path);
|
||||||
|
|
||||||
// Call Rust op - returns JS code string
|
// Call Rust op - returns JS code string
|
||||||
const code = Deno.core.ops.op_import(pathStr);
|
const code = Deno.core.ops.op_import(pathStr);
|
||||||
|
|
||||||
// Eval in current context - returns V8 value directly!
|
return Function(`return (${code})`)();
|
||||||
// (0, eval) = indirect eval = global scope
|
|
||||||
// Wrap in parentheses to ensure object literals are parsed correctly
|
|
||||||
return (0, eval)(`(${code})`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const scopedImport =
|
export const scopedImport =
|
||||||
@@ -61,7 +58,7 @@ export const readDir = (path: NixValue): never => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const readFile = (path: NixValue): string => {
|
export const readFile = (path: NixValue): string => {
|
||||||
const pathStr = force_string(path);
|
const pathStr = forceString(path);
|
||||||
return Deno.core.ops.op_read_file(pathStr);
|
return Deno.core.ops.op_read_file(pathStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,7 +67,7 @@ export const readFileType = (path: NixValue): never => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const pathExists = (path: NixValue): boolean => {
|
export const pathExists = (path: NixValue): boolean => {
|
||||||
const pathStr = force_string(path);
|
const pathStr = forceString(path);
|
||||||
return Deno.core.ops.op_path_exists(pathStr);
|
return Deno.core.ops.op_path_exists(pathStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,38 +5,38 @@
|
|||||||
|
|
||||||
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 { forceList, forceFunction, forceInt } from "../type-assert";
|
||||||
|
|
||||||
export const map =
|
export const map =
|
||||||
(f: NixValue) =>
|
(f: NixValue) =>
|
||||||
(list: NixValue): NixList =>
|
(list: NixValue): NixList =>
|
||||||
force_list(list).map(force_function(f));
|
forceList(list).map(forceFunction(f));
|
||||||
|
|
||||||
export const filter =
|
export const filter =
|
||||||
(f: NixValue) =>
|
(f: NixValue) =>
|
||||||
(list: NixValue): NixList =>
|
(list: NixValue): NixList =>
|
||||||
force_list(list).filter(force_function(f));
|
forceList(list).filter(forceFunction(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(forceList(forced).length);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const head = (list: NixValue): NixValue => force_list(list)[0];
|
export const head = (list: NixValue): NixValue => forceList(list)[0];
|
||||||
|
|
||||||
export const tail = (list: NixValue): NixList => force_list(list).slice(1);
|
export const tail = (list: NixValue): NixList => forceList(list).slice(1);
|
||||||
|
|
||||||
export const elem =
|
export const elem =
|
||||||
(x: NixValue) =>
|
(x: NixValue) =>
|
||||||
(xs: NixValue): boolean =>
|
(xs: NixValue): boolean =>
|
||||||
force_list(xs).includes(force(x));
|
forceList(xs).includes(force(x));
|
||||||
|
|
||||||
export const elemAt =
|
export const elemAt =
|
||||||
(xs: NixValue) =>
|
(xs: NixValue) =>
|
||||||
(n: NixValue): NixValue => {
|
(n: NixValue): NixValue => {
|
||||||
const list = force_list(xs);
|
const list = forceList(xs);
|
||||||
const idx = Number(force_int(n));
|
const idx = Number(forceInt(n));
|
||||||
|
|
||||||
if (idx < 0 || idx >= list.length) {
|
if (idx < 0 || idx >= list.length) {
|
||||||
throw new RangeError(`Index ${idx} out of bounds for list of length ${list.length}`);
|
throw new RangeError(`Index ${idx} out of bounds for list of length ${list.length}`);
|
||||||
@@ -46,16 +46,16 @@ export const elemAt =
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const concatLists = (lists: NixValue): NixList => {
|
export const concatLists = (lists: NixValue): NixList => {
|
||||||
return force_list(lists).reduce((acc: NixList, cur: NixValue) => {
|
return forceList(lists).reduce((acc: NixList, cur: NixValue) => {
|
||||||
return acc.concat(force_list(cur));
|
return acc.concat(forceList(cur));
|
||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const concatMap =
|
export const concatMap =
|
||||||
(f: NixValue) =>
|
(f: NixValue) =>
|
||||||
(lists: NixValue): NixList => {
|
(lists: NixValue): NixList => {
|
||||||
const fn = force_function(f);
|
const fn = forceFunction(f);
|
||||||
return force_list(lists).reduce((acc: NixList, cur: NixValue) => {
|
return forceList(lists).reduce((acc: NixList, cur: NixValue) => {
|
||||||
return acc.concat(force(fn(cur)) as NixList);
|
return acc.concat(force(fn(cur)) as NixList);
|
||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
@@ -64,20 +64,20 @@ export const foldlPrime =
|
|||||||
(op_fn: NixValue) =>
|
(op_fn: NixValue) =>
|
||||||
(nul: NixValue) =>
|
(nul: NixValue) =>
|
||||||
(list: NixValue): NixValue => {
|
(list: NixValue): NixValue => {
|
||||||
const forced_op = force_function(op_fn);
|
const forced_op = forceFunction(op_fn);
|
||||||
return force_list(list).reduce((acc: NixValue, cur: NixValue) => {
|
return forceList(list).reduce((acc: NixValue, cur: NixValue) => {
|
||||||
return forced_op(acc)(cur);
|
return forceFunction(forced_op(acc))(cur);
|
||||||
}, nul);
|
}, nul);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sort =
|
export const sort =
|
||||||
(cmp: NixValue) =>
|
(cmp: NixValue) =>
|
||||||
(list: NixValue): NixList => {
|
(list: NixValue): NixList => {
|
||||||
const forced_list = [...force_list(list)];
|
const forced_list = [...forceList(list)];
|
||||||
const forced_cmp = force_function(cmp);
|
const forced_cmp = forceFunction(cmp);
|
||||||
return forced_list.sort((a, b) => {
|
return forced_list.sort((a, b) => {
|
||||||
if (force(forced_cmp(a)(b))) return -1;
|
if (force(forceFunction(forced_cmp(a))(b))) return -1;
|
||||||
if (force(forced_cmp(b)(a))) return 1;
|
if (force(forceFunction(forced_cmp(b))(a))) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -85,8 +85,8 @@ export const sort =
|
|||||||
export const partition =
|
export const partition =
|
||||||
(pred: NixValue) =>
|
(pred: NixValue) =>
|
||||||
(list: NixValue): NixAttrs => {
|
(list: NixValue): NixAttrs => {
|
||||||
const forced_list = force_list(list);
|
const forced_list = forceList(list);
|
||||||
const forced_pred = force_function(pred);
|
const forced_pred = forceFunction(pred);
|
||||||
const attrs: NixAttrs = {
|
const attrs: NixAttrs = {
|
||||||
right: [],
|
right: [],
|
||||||
wrong: [],
|
wrong: [],
|
||||||
@@ -104,8 +104,8 @@ export const partition =
|
|||||||
export const genList =
|
export const genList =
|
||||||
(f: NixValue) =>
|
(f: NixValue) =>
|
||||||
(len: NixValue): NixList => {
|
(len: NixValue): NixList => {
|
||||||
const func = force_function(f);
|
const func = forceFunction(f);
|
||||||
const length = force_int(len);
|
const length = forceInt(len);
|
||||||
|
|
||||||
if (length < 0) {
|
if (length < 0) {
|
||||||
throw new TypeError(`genList length must be non-negative integer, got ${length}`);
|
throw new TypeError(`genList length must be non-negative integer, got ${length}`);
|
||||||
@@ -117,9 +117,9 @@ export const genList =
|
|||||||
export const all =
|
export const all =
|
||||||
(pred: NixValue) =>
|
(pred: NixValue) =>
|
||||||
(list: NixValue): boolean =>
|
(list: NixValue): boolean =>
|
||||||
force_list(list).every(force_function(pred));
|
forceList(list).every(forceFunction(pred));
|
||||||
|
|
||||||
export const any =
|
export const any =
|
||||||
(pred: NixValue) =>
|
(pred: NixValue) =>
|
||||||
(list: NixValue): boolean =>
|
(list: NixValue): boolean =>
|
||||||
force_list(list).some(force_function(pred));
|
forceList(list).some(forceFunction(pred));
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue } from "../types";
|
import type { NixValue } from "../types";
|
||||||
import { force_numeric } from "../type-assert";
|
import { forceNumeric } from "../type-assert";
|
||||||
|
|
||||||
export const ceil = (x: NixValue): bigint => {
|
export const ceil = (x: NixValue): bigint => {
|
||||||
const val = force_numeric(x);
|
const val = forceNumeric(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 = forceNumeric(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
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,27 +3,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue } from "../types";
|
import type { NixValue } from "../types";
|
||||||
import { force_string, force_list, force_int } from "../type-assert";
|
import { forceString, forceList, forceInt } from "../type-assert";
|
||||||
|
|
||||||
export const stringLength = (e: NixValue): number => force_string(e).length;
|
export const stringLength = (e: NixValue): number => forceString(e).length;
|
||||||
|
|
||||||
export const substring =
|
export const substring =
|
||||||
(start: NixValue) =>
|
(start: NixValue) =>
|
||||||
(len: NixValue) =>
|
(len: NixValue) =>
|
||||||
(s: NixValue): string => {
|
(s: NixValue): string => {
|
||||||
const str = force_string(s);
|
const str = forceString(s);
|
||||||
const startPos = Number(force_int(start));
|
const startPos = Number(forceInt(start));
|
||||||
const length = Number(force_int(len));
|
const length = Number(forceInt(len));
|
||||||
return str.substring(startPos, startPos + length);
|
return str.substring(startPos, startPos + length);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const concatStringsSep =
|
export const concatStringsSep =
|
||||||
(sep: NixValue) =>
|
(sep: NixValue) =>
|
||||||
(list: NixValue): string =>
|
(list: NixValue): string =>
|
||||||
force_list(list).join(force_string(sep));
|
forceList(list).join(forceString(sep));
|
||||||
|
|
||||||
export const baseNameOf = (x: NixValue): string => {
|
export const baseNameOf = (x: NixValue): string => {
|
||||||
const str = force_string(x);
|
const str = forceString(x);
|
||||||
if (str.length === 0) return "";
|
if (str.length === 0) return "";
|
||||||
|
|
||||||
let last = str.length - 1;
|
let last = str.length - 1;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { NixValue, NixAttrs, NixBool } from "./types";
|
import type { NixValue, NixAttrs, NixBool } from "./types";
|
||||||
import { force_attrs, force_string } from "./type-assert";
|
import { forceAttrs, forceString } from "./type-assert";
|
||||||
import { isAttrs } from "./builtins/type-check";
|
import { isAttrs } from "./builtins/type-check";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,7 +14,7 @@ import { isAttrs } from "./builtins/type-check";
|
|||||||
* @returns Absolute path string
|
* @returns Absolute path string
|
||||||
*/
|
*/
|
||||||
export const resolvePath = (path: NixValue): string => {
|
export const resolvePath = (path: NixValue): string => {
|
||||||
const path_str = force_string(path);
|
const path_str = forceString(path);
|
||||||
return Deno.core.ops.op_resolve_path(path_str);
|
return Deno.core.ops.op_resolve_path(path_str);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,8 +28,8 @@ export const resolvePath = (path: NixValue): string => {
|
|||||||
* @throws Error if obj is null/undefined or key not found
|
* @throws Error if obj is null/undefined or key not found
|
||||||
*/
|
*/
|
||||||
export const select = (obj: NixValue, key: NixValue): NixValue => {
|
export const select = (obj: NixValue, key: NixValue): NixValue => {
|
||||||
const forced_obj = force_attrs(obj);
|
const forced_obj = forceAttrs(obj);
|
||||||
const forced_key = force_string(key);
|
const forced_key = forceString(key);
|
||||||
|
|
||||||
if (!(forced_key in forced_obj)) {
|
if (!(forced_key in forced_obj)) {
|
||||||
throw new Error(`Attribute '${forced_key}' not found`);
|
throw new Error(`Attribute '${forced_key}' not found`);
|
||||||
@@ -48,8 +48,8 @@ export const select = (obj: NixValue, key: NixValue): NixValue => {
|
|||||||
* @returns obj[key] if exists, otherwise default_val
|
* @returns obj[key] if exists, otherwise default_val
|
||||||
*/
|
*/
|
||||||
export const selectWithDefault = (obj: NixValue, key: NixValue, default_val: NixValue): NixValue => {
|
export const selectWithDefault = (obj: NixValue, key: NixValue, default_val: NixValue): NixValue => {
|
||||||
const attrs = force_attrs(obj);
|
const attrs = forceAttrs(obj);
|
||||||
const forced_key = force_string(key);
|
const forced_key = forceString(key);
|
||||||
|
|
||||||
if (!(forced_key in attrs)) {
|
if (!(forced_key in attrs)) {
|
||||||
return default_val;
|
return default_val;
|
||||||
@@ -65,7 +65,7 @@ export const hasAttr = (obj: NixValue, attrpath: NixValue[]): NixBool => {
|
|||||||
let attrs = obj;
|
let attrs = obj;
|
||||||
|
|
||||||
for (const attr of attrpath.slice(0, -1)) {
|
for (const attr of attrpath.slice(0, -1)) {
|
||||||
const cur = attrs[force_string(attr)];
|
const cur = attrs[forceString(attr)];
|
||||||
if (!isAttrs(cur)) {
|
if (!isAttrs(cur)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ export const validateParams = (
|
|||||||
required: string[] | null,
|
required: string[] | null,
|
||||||
allowed: string[] | null,
|
allowed: string[] | null,
|
||||||
): NixAttrs => {
|
): NixAttrs => {
|
||||||
const forced_arg = force_attrs(arg);
|
const forced_arg = forceAttrs(arg);
|
||||||
|
|
||||||
// Check required parameters
|
// Check required parameters
|
||||||
if (required) {
|
if (required) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* All functionality is exported via the global `Nix` object
|
* All functionality is exported via the global `Nix` object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createThunk, force, is_thunk, IS_THUNK } from "./thunk";
|
import { createThunk, force, isThunk, IS_THUNK } from "./thunk";
|
||||||
import { select, selectWithDefault, validateParams, resolvePath, hasAttr } from "./helpers";
|
import { select, selectWithDefault, validateParams, resolvePath, hasAttr } from "./helpers";
|
||||||
import { op } from "./operators";
|
import { op } from "./operators";
|
||||||
import { builtins, PRIMOP_METADATA } from "./builtins";
|
import { builtins, PRIMOP_METADATA } from "./builtins";
|
||||||
@@ -18,7 +18,7 @@ export type NixRuntime = typeof Nix;
|
|||||||
export const Nix = {
|
export const Nix = {
|
||||||
createThunk,
|
createThunk,
|
||||||
force,
|
force,
|
||||||
is_thunk,
|
isThunk,
|
||||||
IS_THUNK,
|
IS_THUNK,
|
||||||
|
|
||||||
hasAttr,
|
hasAttr,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
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 { forceNumeric, forceList, forceAttrs, coerceNumeric } from "./type-assert";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operator object exported as Nix.op
|
* Operator object exported as Nix.op
|
||||||
@@ -15,22 +15,22 @@ export const op = {
|
|||||||
// Arithmetic operators - preserve int/float distinction
|
// Arithmetic operators - preserve int/float distinction
|
||||||
add: (a: NixValue, b: NixValue): bigint | number => {
|
add: (a: NixValue, b: NixValue): bigint | number => {
|
||||||
// FIXME: String & Path
|
// FIXME: String & Path
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) + (bv as any);
|
return (av as any) + (bv as any);
|
||||||
},
|
},
|
||||||
|
|
||||||
sub: (a: NixValue, b: NixValue): bigint | number => {
|
sub: (a: NixValue, b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) - (bv as any);
|
return (av as any) - (bv as any);
|
||||||
},
|
},
|
||||||
|
|
||||||
mul: (a: NixValue, b: NixValue): bigint | number => {
|
mul: (a: NixValue, b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) * (bv as any);
|
return (av as any) * (bv as any);
|
||||||
},
|
},
|
||||||
|
|
||||||
div: (a: NixValue, b: NixValue): bigint | number => {
|
div: (a: NixValue, b: NixValue): bigint | number => {
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
|
|
||||||
if (bv === 0 || bv === 0n) {
|
if (bv === 0 || bv === 0n) {
|
||||||
throw new RangeError("Division by zero");
|
throw new RangeError("Division by zero");
|
||||||
@@ -54,22 +54,22 @@ export const op = {
|
|||||||
},
|
},
|
||||||
lt: (a: NixValue, b: NixValue): boolean => {
|
lt: (a: NixValue, b: NixValue): boolean => {
|
||||||
// FIXME: Non-numeric
|
// FIXME: Non-numeric
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) < (bv as any);
|
return (av as any) < (bv as any);
|
||||||
},
|
},
|
||||||
lte: (a: NixValue, b: NixValue): boolean => {
|
lte: (a: NixValue, b: NixValue): boolean => {
|
||||||
// FIXME: Non-numeric
|
// FIXME: Non-numeric
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) <= (bv as any);
|
return (av as any) <= (bv as any);
|
||||||
},
|
},
|
||||||
gt: (a: NixValue, b: NixValue): boolean => {
|
gt: (a: NixValue, b: NixValue): boolean => {
|
||||||
// FIXME: Non-numeric
|
// FIXME: Non-numeric
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) > (bv as any);
|
return (av as any) > (bv as any);
|
||||||
},
|
},
|
||||||
gte: (a: NixValue, b: NixValue): boolean => {
|
gte: (a: NixValue, b: NixValue): boolean => {
|
||||||
// FIXME: Non-numeric
|
// FIXME: Non-numeric
|
||||||
const [av, bv] = coerce_numeric(force_numeric(a), force_numeric(b));
|
const [av, bv] = coerceNumeric(forceNumeric(a), forceNumeric(b));
|
||||||
return (av as any) >= (bv as any);
|
return (av as any) >= (bv as any);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -81,11 +81,11 @@ export const op = {
|
|||||||
|
|
||||||
// List concatenation
|
// List concatenation
|
||||||
concat: (a: NixValue, b: NixValue): NixList => {
|
concat: (a: NixValue, b: NixValue): NixList => {
|
||||||
return Array.prototype.concat.call(force_list(a), force_list(b));
|
return Array.prototype.concat.call(forceList(a), forceList(b));
|
||||||
},
|
},
|
||||||
|
|
||||||
// Attribute set update (merge)
|
// Attribute set update (merge)
|
||||||
update: (a: NixValue, b: NixValue): NixAttrs => {
|
update: (a: NixValue, b: NixValue): NixAttrs => {
|
||||||
return { ...force_attrs(a), ...force_attrs(b) };
|
return { ...forceAttrs(a), ...forceAttrs(b) };
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class NixThunk implements NixThunkInterface {
|
|||||||
* @param value - Value to check
|
* @param value - Value to check
|
||||||
* @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 isThunk = (value: unknown): value is NixThunkInterface => {
|
||||||
return value !== null && typeof value === "object" && IS_THUNK in value && value[IS_THUNK] === true;
|
return value !== null && typeof value === "object" && IS_THUNK in value && value[IS_THUNK] === true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ export const is_thunk = (value: unknown): value is NixThunkInterface => {
|
|||||||
* @returns The forced/evaluated value
|
* @returns The forced/evaluated value
|
||||||
*/
|
*/
|
||||||
export const force = (value: NixValue): NixStrictValue => {
|
export const force = (value: NixValue): NixStrictValue => {
|
||||||
if (!is_thunk(value)) {
|
if (!isThunk(value)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
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";
|
||||||
import { isAttrs } from "./builtins/type-check";
|
|
||||||
|
|
||||||
const typeName = (value: NixValue): string => {
|
const typeName = (value: NixValue): string => {
|
||||||
const val = force(value);
|
const val = force(value);
|
||||||
@@ -26,7 +25,7 @@ const typeName = (value: NixValue): string => {
|
|||||||
* Force a value and assert it's a list
|
* Force a value and assert it's a list
|
||||||
* @throws TypeError if value is not a list after forcing
|
* @throws TypeError if value is not a list after forcing
|
||||||
*/
|
*/
|
||||||
export const force_list = (value: NixValue): NixList => {
|
export const forceList = (value: NixValue): NixList => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (!Array.isArray(forced)) {
|
if (!Array.isArray(forced)) {
|
||||||
throw new TypeError(`Expected list, got ${typeName(forced)}`);
|
throw new TypeError(`Expected list, got ${typeName(forced)}`);
|
||||||
@@ -38,7 +37,7 @@ export const force_list = (value: NixValue): NixList => {
|
|||||||
* Force a value and assert it's a function
|
* Force a value and assert it's a function
|
||||||
* @throws TypeError if value is not a function after forcing
|
* @throws TypeError if value is not a function after forcing
|
||||||
*/
|
*/
|
||||||
export const force_function = (value: NixValue): NixFunction => {
|
export const forceFunction = (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 ${typeName(forced)}`);
|
throw new TypeError(`Expected function, got ${typeName(forced)}`);
|
||||||
@@ -50,7 +49,7 @@ export const force_function = (value: NixValue): NixFunction => {
|
|||||||
* Force a value and assert it's an attribute set
|
* Force a value and assert it's an attribute set
|
||||||
* @throws TypeError if value is not an attribute set after forcing
|
* @throws TypeError if value is not an attribute set after forcing
|
||||||
*/
|
*/
|
||||||
export const force_attrs = (value: NixValue): NixAttrs => {
|
export const forceAttrs = (value: NixValue): NixAttrs => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced !== "object" || Array.isArray(forced) || forced === null) {
|
if (typeof forced !== "object" || Array.isArray(forced) || forced === null) {
|
||||||
throw new TypeError(`Expected attribute set, got ${typeName(forced)}`);
|
throw new TypeError(`Expected attribute set, got ${typeName(forced)}`);
|
||||||
@@ -62,7 +61,7 @@ export const force_attrs = (value: NixValue): NixAttrs => {
|
|||||||
* Force a value and assert it's a string
|
* Force a value and assert it's a string
|
||||||
* @throws TypeError if value is not a string after forcing
|
* @throws TypeError if value is not a string after forcing
|
||||||
*/
|
*/
|
||||||
export const force_string = (value: NixValue): string => {
|
export const forceString = (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 ${typeName(forced)}`);
|
throw new TypeError(`Expected string, got ${typeName(forced)}`);
|
||||||
@@ -74,7 +73,7 @@ export const force_string = (value: NixValue): string => {
|
|||||||
* Force a value and assert it's a boolean
|
* Force a value and assert it's a boolean
|
||||||
* @throws TypeError if value is not a boolean after forcing
|
* @throws TypeError if value is not a boolean after forcing
|
||||||
*/
|
*/
|
||||||
export const force_bool = (value: NixValue): boolean => {
|
export const forceBool = (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 ${typeName(forced)}`);
|
throw new TypeError(`Expected boolean, got ${typeName(forced)}`);
|
||||||
@@ -86,7 +85,7 @@ export const force_bool = (value: NixValue): boolean => {
|
|||||||
* Force a value and extract int value
|
* Force a value and extract int value
|
||||||
* @throws TypeError if value is not an int
|
* @throws TypeError if value is not an int
|
||||||
*/
|
*/
|
||||||
export const force_int = (value: NixValue): NixInt => {
|
export const forceInt = (value: NixValue): NixInt => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced === "bigint") {
|
if (typeof forced === "bigint") {
|
||||||
return forced;
|
return forced;
|
||||||
@@ -98,7 +97,7 @@ export const force_int = (value: NixValue): NixInt => {
|
|||||||
* Force a value and extract float value
|
* Force a value and extract float value
|
||||||
* @throws TypeError if value is not a float
|
* @throws TypeError if value is not a float
|
||||||
*/
|
*/
|
||||||
export const force_float = (value: NixValue): NixFloat => {
|
export const forceFloat = (value: NixValue): NixFloat => {
|
||||||
const forced = force(value);
|
const forced = force(value);
|
||||||
if (typeof forced === "number") {
|
if (typeof forced === "number") {
|
||||||
return forced;
|
return forced;
|
||||||
@@ -110,7 +109,7 @@ export const force_float = (value: NixValue): NixFloat => {
|
|||||||
* Force a value and extract numeric value (int or float)
|
* Force a value and extract numeric value (int or float)
|
||||||
* @throws TypeError if value is not a numeric type
|
* @throws TypeError if value is not a numeric type
|
||||||
*/
|
*/
|
||||||
export const force_numeric = (value: NixValue): NixNumber => {
|
export const forceNumeric = (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;
|
||||||
@@ -123,7 +122,7 @@ 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 = (a: NixNumber, b: NixNumber): [NixFloat, NixFloat] | [NixInt, NixInt] => {
|
export const coerceNumeric = (a: NixNumber, b: NixNumber): [NixFloat, NixFloat] | [NixInt, NixInt] => {
|
||||||
const aIsInt = typeof a === "bigint";
|
const aIsInt = typeof a === "bigint";
|
||||||
const bIsInt = typeof b === "bigint";
|
const bIsInt = typeof b === "bigint";
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export type NixNull = null;
|
|||||||
// Nix composite types
|
// Nix composite types
|
||||||
export type NixList = NixValue[];
|
export type NixList = NixValue[];
|
||||||
export type NixAttrs = { [key: string]: NixValue };
|
export type NixAttrs = { [key: string]: NixValue };
|
||||||
export type NixFunction = (...args: any[]) => any;
|
export type NixFunction = (arg: NixValue) => NixValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for lazy thunk values
|
* Interface for lazy thunk values
|
||||||
@@ -42,11 +42,7 @@ export type NixStrictValue = Exclude<NixValue, NixThunkInterface>;
|
|||||||
* CatchableError: Error type thrown by `builtins.throw`
|
* CatchableError: Error type thrown by `builtins.throw`
|
||||||
* This can be caught by `builtins.tryEval`
|
* This can be caught by `builtins.tryEval`
|
||||||
*/
|
*/
|
||||||
export class CatchableError extends Error {
|
export class CatchableError extends Error {}
|
||||||
constructor(msg: string) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
||||||
|
|||||||
@@ -199,11 +199,7 @@ impl<Ctx: CodegenContext> Compile<Ctx> for Let {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let body = ctx.get_ir(self.body).compile(ctx);
|
let body = ctx.get_ir(self.body).compile(ctx);
|
||||||
format!(
|
format!("(()=>{{{}; return {}}})()", js_statements.join(";"), body)
|
||||||
"(()=>{{{}; return {}}})()",
|
|
||||||
js_statements.join(";"),
|
|
||||||
body
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +289,10 @@ impl<Ctx: CodegenContext> Compile<Ctx> for ConcatStrings {
|
|||||||
.map(|part| {
|
.map(|part| {
|
||||||
let compiled = ctx.get_ir(*part).compile(ctx);
|
let compiled = ctx.get_ir(*part).compile(ctx);
|
||||||
// TODO: copyToStore
|
// TODO: copyToStore
|
||||||
format!("Nix.coerceToString({}, Nix.StringCoercionMode.Interpolation, false)", compiled)
|
format!(
|
||||||
|
"Nix.coerceToString({}, Nix.StringCoercionMode.Interpolation, false)",
|
||||||
|
compiled
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::Path {
|
|||||||
path_str
|
path_str
|
||||||
} else {
|
} else {
|
||||||
let current_dir = ctx.get_current_dir();
|
let current_dir = ctx.get_current_dir();
|
||||||
dbg!(¤t_dir);
|
|
||||||
|
|
||||||
current_dir
|
current_dir
|
||||||
.join(&path_str)
|
.join(&path_str)
|
||||||
@@ -172,29 +171,22 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::AttrSet {
|
|||||||
|
|
||||||
// rec { a = 1; b = a; } => let a = 1; b = a; in { inherit a b; }
|
// rec { a = 1; b = a; } => let a = 1; b = a; in { inherit a b; }
|
||||||
let entries: Vec<_> = self.entries().collect();
|
let entries: Vec<_> = self.entries().collect();
|
||||||
let (binding_sccs, body) =
|
let (binding_sccs, body) = downgrade_let_bindings(entries, ctx, |ctx, binding_keys| {
|
||||||
downgrade_let_bindings(entries, ctx, |ctx, binding_keys| {
|
// Create plain attrset as body with inherit
|
||||||
// Create plain attrset as body with inherit
|
let mut attrs = AttrSet {
|
||||||
let mut attrs = AttrSet {
|
stcs: HashMap::new(),
|
||||||
stcs: HashMap::new(),
|
dyns: Vec::new(),
|
||||||
dyns: Vec::new(),
|
};
|
||||||
};
|
|
||||||
|
|
||||||
for sym in binding_keys {
|
for sym in binding_keys {
|
||||||
let expr = ctx.lookup(*sym)?;
|
let expr = ctx.lookup(*sym)?;
|
||||||
attrs.stcs.insert(*sym, expr);
|
attrs.stcs.insert(*sym, expr);
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ctx.new_expr(attrs.to_ir()))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(ctx.new_expr(
|
|
||||||
Let {
|
|
||||||
body,
|
|
||||||
binding_sccs,
|
|
||||||
}
|
}
|
||||||
.to_ir(),
|
|
||||||
))
|
Ok(ctx.new_expr(attrs.to_ir()))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(ctx.new_expr(Let { body, binding_sccs }.to_ir()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,13 +291,7 @@ impl<Ctx: DowngradeContext> Downgrade<Ctx> for ast::LetIn {
|
|||||||
let (binding_sccs, body) =
|
let (binding_sccs, body) =
|
||||||
downgrade_let_bindings(entries, ctx, |ctx, _binding_keys| body_expr.downgrade(ctx))?;
|
downgrade_let_bindings(entries, ctx, |ctx, _binding_keys| body_expr.downgrade(ctx))?;
|
||||||
|
|
||||||
Ok(ctx.new_expr(
|
Ok(ctx.new_expr(Let { body, binding_sccs }.to_ir()))
|
||||||
Let {
|
|
||||||
body,
|
|
||||||
binding_sccs,
|
|
||||||
}
|
|
||||||
.to_ir(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ where
|
|||||||
body,
|
body,
|
||||||
scc_info,
|
scc_info,
|
||||||
required_params: required,
|
required_params: required,
|
||||||
allowed_params: allowed
|
allowed_params: allowed,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +348,11 @@ where
|
|||||||
F: FnOnce(&mut Ctx, &[SymId]) -> Result<ExprId>,
|
F: FnOnce(&mut Ctx, &[SymId]) -> Result<ExprId>,
|
||||||
{
|
{
|
||||||
let slots: Vec<_> = ctx.reserve_slots(binding_keys.len()).collect();
|
let slots: Vec<_> = ctx.reserve_slots(binding_keys.len()).collect();
|
||||||
let let_bindings: HashMap<_, _> = binding_keys.iter().copied().zip(slots.iter().copied()).collect();
|
let let_bindings: HashMap<_, _> = binding_keys
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.zip(slots.iter().copied())
|
||||||
|
.collect();
|
||||||
|
|
||||||
ctx.push_dep_tracker(&slots);
|
ctx.push_dep_tracker(&slots);
|
||||||
|
|
||||||
|
|||||||
@@ -77,10 +77,7 @@ fn nested_function_parameters() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pattern_param_simple_reference_in_default() {
|
fn pattern_param_simple_reference_in_default() {
|
||||||
assert_eq!(
|
assert_eq!(eval("({ a, b ? a }: b) { a = 10; }"), Value::Int(10));
|
||||||
eval("({ a, b ? a }: b) { a = 10; }"),
|
|
||||||
Value::Int(10)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -90,8 +90,7 @@ fn import_with_complex_dependency_graph() {
|
|||||||
std::fs::write(&utils_path, "{ double = x: x * 2; }").unwrap();
|
std::fs::write(&utils_path, "{ double = x: x * 2; }").unwrap();
|
||||||
|
|
||||||
let math_path = temp_dir.path().join("math.nix");
|
let math_path = temp_dir.path().join("math.nix");
|
||||||
let math_content =
|
let math_content = r#"let utils = import ./utils.nix; in { triple = x: x + utils.double x; }"#;
|
||||||
r#"let utils = import ./utils.nix; in { triple = x: x + utils.double x; }"#;
|
|
||||||
std::fs::write(&math_path, math_content).unwrap();
|
std::fs::write(&math_path, math_content).unwrap();
|
||||||
|
|
||||||
let main_path = temp_dir.path().join("main.nix");
|
let main_path = temp_dir.path().join("main.nix");
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ use utils::eval;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_returns_as_is() {
|
fn string_returns_as_is() {
|
||||||
assert_eq!(eval(r#"toString "hello""#), Value::String("hello".to_string()));
|
assert_eq!(
|
||||||
|
eval(r#"toString "hello""#),
|
||||||
|
Value::String("hello".to_string())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -67,10 +70,7 @@ fn list_with_multiple_empty_lists() {
|
|||||||
eval("toString [1 [] [] 2]"),
|
eval("toString [1 [] [] 2]"),
|
||||||
Value::String("1 2".to_string())
|
Value::String("1 2".to_string())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(eval("toString [[] [] 1]"), Value::String("1".to_string()));
|
||||||
eval("toString [[] [] 1]"),
|
|
||||||
Value::String("1".to_string())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -112,7 +112,9 @@ fn attrs_with_to_string_method() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn attrs_to_string_self_reference() {
|
fn attrs_to_string_self_reference() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval(r#"let obj = { x = 42; __toString = self: "x is ${toString self.x}"; }; in toString obj"#),
|
eval(
|
||||||
|
r#"let obj = { x = 42; __toString = self: "x is ${toString self.x}"; }; in toString obj"#
|
||||||
|
),
|
||||||
Value::String("x is 42".to_string())
|
Value::String("x is 42".to_string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -120,9 +122,7 @@ fn attrs_to_string_self_reference() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn attrs_to_string_priority() {
|
fn attrs_to_string_priority() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval(
|
eval(r#"toString { __toString = self: "custom"; outPath = "/nix/store/foo"; }"#),
|
||||||
r#"toString { __toString = self: "custom"; outPath = "/nix/store/foo"; }"#
|
|
||||||
),
|
|
||||||
Value::String("custom".to_string())
|
Value::String("custom".to_string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user