"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.installStdlib = installStdlib;
const evaluator_1 = require("../language/evaluator");
const fs_1 = require("./fs");
const net_1 = require("./net");
const crypto_1 = require("./crypto");
const task_1 = require("./task");
const memory_1 = require("../runtime/memory");
const ffi_1 = require("../language/ffi");
/**
 * Register the zero-config universal standard library into a Nexus environment.
 */
function installStdlib(env, runtime) {
    (0, fs_1.installFs)(env);
    (0, net_1.installNet)(env);
    (0, crypto_1.installCrypto)(env);
    (0, task_1.installTask)(env, runtime);
    // Logical helpers used by syntax sugar
    env.set("__and", new evaluator_1.BuiltinObj((...args) => {
        if (args.length !== 2) {
            return new evaluator_1.ErrorObj("__and: want 2 args");
        }
        const a = args[0];
        const b = args[1];
        const aTruthy = !(a instanceof evaluator_1.BooleanObj && !a.value) && a.type !== "NULL";
        if (!aTruthy) {
            return new evaluator_1.BooleanObj(false);
        }
        const bTruthy = !(b instanceof evaluator_1.BooleanObj && !b.value) && b.type !== "NULL";
        return new evaluator_1.BooleanObj(bTruthy);
    }));
    env.set("__or", new evaluator_1.BuiltinObj((...args) => {
        if (args.length !== 2) {
            return new evaluator_1.ErrorObj("__or: want 2 args");
        }
        const a = args[0];
        const b = args[1];
        const aTruthy = !(a instanceof evaluator_1.BooleanObj && !a.value) && a.type !== "NULL";
        if (aTruthy) {
            return new evaluator_1.BooleanObj(true);
        }
        const bTruthy = !(b instanceof evaluator_1.BooleanObj && !b.value) && b.type !== "NULL";
        return new evaluator_1.BooleanObj(bTruthy);
    }));
    // Memory engine introspection
    env.set("mem_stats", new evaluator_1.BuiltinObj(() => {
        const s = (0, memory_1.getMemoryEngine)().stats();
        return new evaluator_1.StringObj(`allocated=${s.allocated} live=${s.live} freed=${s.freed} buffered=${s.buffered}`);
    }));
    env.set("mem_collect", new evaluator_1.BuiltinObj(() => {
        const n = (0, memory_1.getMemoryEngine)().collectCycles();
        return new evaluator_1.IntegerObj(n);
    }));
    // FFI
    env.set("ffi_load", new evaluator_1.BuiltinObj((...args) => {
        if (args.length !== 1) {
            return new evaluator_1.ErrorObj("ffi_load: want library path string");
        }
        return (0, ffi_1.ffiLoadBuiltin)(args[0]);
    }));
    env.set("ffi_symbol", new evaluator_1.BuiltinObj((...args) => {
        if (args.length < 3) {
            return new evaluator_1.ErrorObj("ffi_symbol: want lib, name, retType, ...argTypes");
        }
        return (0, ffi_1.ffiSymbolBuiltin)(args[0], args[1], args[2], ...args.slice(3));
    }));
    env.set("ffi_call", new evaluator_1.BuiltinObj((...args) => {
        if (args.length < 1) {
            return new evaluator_1.ErrorObj("ffi_call: want fn, ...args");
        }
        return (0, ffi_1.ffiCallBuiltin)(args[0], ...args.slice(1));
    }));
    env.set("ffi_available", new evaluator_1.BuiltinObj(() => new evaluator_1.BooleanObj((0, ffi_1.isFfiAvailable)())));
}
//# sourceMappingURL=index.js.map