"use strict";
/**
 * Shared runtime value types for the Nexus interpreter.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.FALSE_OBJ = exports.TRUE_OBJ = exports.NULL_OBJ = exports.ClosureObj = exports.CompiledFunctionObj = exports.HashObj = exports.ArrayObj = exports.ErrorObj = exports.CONTINUE_SIGNAL = exports.BREAK_SIGNAL = exports.ContinueSignal = exports.BreakSignal = exports.ReturnValue = exports.NullObj = exports.BooleanObj = exports.StringObj = exports.IntegerObj = void 0;
exports.hashKey = hashKey;
exports.nativeBool = nativeBool;
exports.newError = newError;
exports.isError = isError;
exports.isTruthy = isTruthy;
class IntegerObj {
    value;
    type = "INTEGER";
    constructor(value) {
        this.value = value;
    }
    inspect() {
        return String(this.value);
    }
}
exports.IntegerObj = IntegerObj;
class StringObj {
    value;
    type = "STRING";
    constructor(value) {
        this.value = value;
    }
    inspect() {
        return this.value;
    }
}
exports.StringObj = StringObj;
class BooleanObj {
    value;
    type = "BOOLEAN";
    constructor(value) {
        this.value = value;
    }
    inspect() {
        return String(this.value);
    }
}
exports.BooleanObj = BooleanObj;
class NullObj {
    type = "NULL";
    inspect() {
        return "null";
    }
}
exports.NullObj = NullObj;
class ReturnValue {
    value;
    type = "RETURN_VALUE";
    constructor(value) {
        this.value = value;
    }
    inspect() {
        return this.value.inspect();
    }
}
exports.ReturnValue = ReturnValue;
class BreakSignal {
    type = "BREAK";
    inspect() {
        return "break";
    }
}
exports.BreakSignal = BreakSignal;
class ContinueSignal {
    type = "CONTINUE";
    inspect() {
        return "continue";
    }
}
exports.ContinueSignal = ContinueSignal;
exports.BREAK_SIGNAL = new BreakSignal();
exports.CONTINUE_SIGNAL = new ContinueSignal();
class ErrorObj {
    message;
    type = "ERROR";
    constructor(message) {
        this.message = message;
    }
    inspect() {
        return `ERROR: ${this.message}`;
    }
}
exports.ErrorObj = ErrorObj;
class ArrayObj {
    elements;
    type = "ARRAY";
    constructor(elements) {
        this.elements = elements;
    }
    inspect() {
        return `[${this.elements.map((e) => e.inspect()).join(", ")}]`;
    }
}
exports.ArrayObj = ArrayObj;
class HashObj {
    type = "HASH";
    pairs = new Map();
    set(key, value) {
        this.pairs.set(hashKey(key), { key, value });
    }
    get(key) {
        const pair = this.pairs.get(hashKey(key));
        return pair ? pair.value : exports.NULL_OBJ;
    }
    getString(field) {
        return this.get(new StringObj(field));
    }
    setString(field, value) {
        this.set(new StringObj(field), value);
    }
    inspect() {
        const parts = [];
        for (const { key, value } of this.pairs.values()) {
            parts.push(`${key.inspect()}: ${value.inspect()}`);
        }
        return `{${parts.join(", ")}}`;
    }
}
exports.HashObj = HashObj;
class CompiledFunctionObj {
    instructions;
    numLocals;
    numParameters;
    type = "COMPILED_FUNCTION";
    constructor(instructions, numLocals, numParameters) {
        this.instructions = instructions;
        this.numLocals = numLocals;
        this.numParameters = numParameters;
    }
    inspect() {
        return "compiled function";
    }
}
exports.CompiledFunctionObj = CompiledFunctionObj;
class ClosureObj {
    fn;
    free;
    type = "CLOSURE";
    constructor(fn, free = []) {
        this.fn = fn;
        this.free = free;
    }
    inspect() {
        return "closure";
    }
}
exports.ClosureObj = ClosureObj;
exports.NULL_OBJ = new NullObj();
exports.TRUE_OBJ = new BooleanObj(true);
exports.FALSE_OBJ = new BooleanObj(false);
function hashKey(key) {
    if (key instanceof IntegerObj) {
        return `i:${key.value}`;
    }
    if (key instanceof StringObj) {
        return `s:${key.value}`;
    }
    if (key instanceof BooleanObj) {
        return `b:${key.value}`;
    }
    return `o:${key.type}:${key.inspect()}`;
}
function nativeBool(value) {
    return value ? exports.TRUE_OBJ : exports.FALSE_OBJ;
}
function newError(message) {
    return new ErrorObj(message);
}
function isError(obj) {
    return obj instanceof ErrorObj || obj.type === "ERROR";
}
function isTruthy(obj) {
    if (obj === exports.NULL_OBJ || obj instanceof NullObj) {
        return false;
    }
    if (obj === exports.FALSE_OBJ) {
        return false;
    }
    if (obj instanceof BooleanObj && !obj.value) {
        return false;
    }
    return true;
}
//# sourceMappingURL=values.js.map