tefkah / thesis-writing

A thesis about representations in physics, an experiment in scholarship in the open.
https://thesis.tefkah.com
5 stars 0 forks source link

Consider not using a universal comparison function. #57

Closed github-actions[bot] closed 1 year ago

github-actions[bot] commented 2 years ago

https://github.com/tefkah/thesis-writing/blob/feb2b179fdba26c2122ff47145d31634631427f6/.obsidian/plugins/dataview/main.js#L15189


            type: link.type,
        });
    })
        .build();
})(DefaultFunctions || (DefaultFunctions = {}));
/** Default function implementations for the expression evaluator. */
const DEFAULT_FUNCTIONS = {
    // Constructors.
    list: DefaultFunctions.list,
    array: DefaultFunctions.list,
    link: DefaultFunctions.link,
    embed: DefaultFunctions.embed,
    elink: DefaultFunctions.elink,
    date: DefaultFunctions.date,
    dur: DefaultFunctions.dur,
    dateformat: DefaultFunctions.dateformat,
    localtime: DefaultFunctions.localtime,
    number: DefaultFunctions.number,
    string: DefaultFunctions.string,
    object: DefaultFunctions.object,
    typeof: DefaultFunctions.typeOf,
    // Math Operations.
    round: DefaultFunctions.round,
    min: DefaultFunctions.min,
    max: DefaultFunctions.max,
    minby: DefaultFunctions.minby,
    maxby: DefaultFunctions.maxby,
    // String operations.
    regexreplace: DefaultFunctions.regexreplace,
    regexmatch: DefaultFunctions.regexmatch,
    replace: DefaultFunctions.replace,
    lower: DefaultFunctions.lower,
    upper: DefaultFunctions.upper,
    split: DefaultFunctions.split,
    startswith: DefaultFunctions.startswith,
    endswith: DefaultFunctions.endswith,
    padleft: DefaultFunctions.padleft,
    padright: DefaultFunctions.padright,
    substring: DefaultFunctions.substring,
    truncate: DefaultFunctions.truncate,
    // Date Operations.
    striptime: DefaultFunctions.striptime,
    // List operations.
    length: DefaultFunctions.length,
    contains: DefaultFunctions.contains,
    icontains: DefaultFunctions.icontains,
    econtains: DefaultFunctions.econtains,
    containsword: DefaultFunctions.containsword,
    reverse: DefaultFunctions.reverse,
    sort: DefaultFunctions.sort,
    // Aggregation operations like reduce.
    reduce: DefaultFunctions.reduce,
    join: DefaultFunctions.join,
    sum: DefaultFunctions.sum,
    product: DefaultFunctions.product,
    all: DefaultFunctions.all,
    any: DefaultFunctions.any,
    none: DefaultFunctions.none,
    filter: DefaultFunctions.filter,
    map: DefaultFunctions.map,
    nonnull: DefaultFunctions.nonnull,
    // Object/Utility operations.
    extract: DefaultFunctions.extract,
    default: DefaultFunctions.fdefault,
    ldefault: DefaultFunctions.ldefault,
    choice: DefaultFunctions.choice,
    meta: DefaultFunctions.meta,
};

/** Provides a global dispatch table for evaluating binary operators, including comparison. */
/** Provides implementations for binary operators on two types using a registry. */
class BinaryOpHandler {
    constructor() {
        this.map = new Map();
    }
    static create() {
        return new BinaryOpHandler();
    }
    register(left, op, right, func) {
        this.map.set(BinaryOpHandler.repr(op, left, right), func);
        return this;
    }
    registerComm(left, op, right, func) {
        return this.register(left, op, right, func).register(right, op, left, (a, b, ctx) => func(b, a, ctx));
    }
    /** Implement a comparison function. */
    compare(type, compare) {
        return this.register(type, "<", type, (a, b, ctx) => compare(a, b, ctx) < 0)
            .register(type, "<=", type, (a, b, ctx) => compare(a, b, ctx) <= 0)
            .register(type, ">", type, (a, b, ctx) => compare(a, b, ctx) > 0)
            .register(type, ">=", type, (a, b, ctx) => compare(a, b, ctx) >= 0)
            .register(type, "=", type, (a, b, ctx) => compare(a, b, ctx) == 0)
            .register(type, "!=", type, (a, b, ctx) => compare(a, b, ctx) != 0);
    }
    /** Attempt to evaluate the given binary operator on the two literal fields. */
    evaluate(op, left, right, ctx) {
        let leftType = Values.typeOf(left);
        let rightType = Values.typeOf(right);
        if (!leftType)
            return Result.failure(`Unrecognized value '${left}'`);
        else if (!rightType)
            return Result.failure(`Unrecognized value '${right}'`);
        let handler = this.map.get(BinaryOpHandler.repr(op, leftType, rightType));
        if (handler)
            return Result.success(handler(left, right, ctx));
        // Right-'*' fallback:
        let handler2 = this.map.get(BinaryOpHandler.repr(op, leftType, "*"));
        if (handler2)
            return Result.success(handler2(left, right, ctx));
        // Left-'*' fallback:
        let handler3 = this.map.get(BinaryOpHandler.repr(op, "*", rightType));
        if (handler3)
            return Result.success(handler3(left, right, ctx));
        // Double '*' fallback.
        let handler4 = this.map.get(BinaryOpHandler.repr(op, "*", "*"));
        if (handler4)
            return Result.success(handler4(left, right, ctx));
        return Result.failure(`No implementation found for '${leftType} ${op} ${rightType}'`);
    }
    /** Create a string representation of the given triplet for unique lookup in the map. */
    static repr(op, left, right) {
        return `${left},${op},${right}`;
    }
}
/** Configure and create a binary OP handler with the given parameters. */
function createBinaryOps(linkNormalizer) {
    return (BinaryOpHandler.create()
        // TODO: Consider not using a universal comparison function.
        .compare("*", (a, b) => Values.compareValue(a, b, linkNormalizer))
        // Global boolean operations.
        .register("*", "&", "*", (a, b) => Values.isTruthy(a) && Values.isTruthy(b))
        .register("*", "|", "*", (a, b) => Values.isTruthy(a) || Values.isTruthy(b))
        // Number implementations.
        .register("number", "+", "number", (a, b) => a + b)
        .register("number", "-", "number", (a, b) => a - b)
        .register("number", "*", "number", (a, b) => a * b)
        .register("number", "/", "number", (a, b) => a / b)
        .register("number", "%", "number", (a, b) => a % b)
        // String implementations.
        .register("string", "+", "*", (a, b, ctx) => a + Values.toString(b, ctx.settings))
        .register("*", "+", "string", (a, b, ctx) => Values.toString(a, ctx.settings) + b)
        .registerComm("string", "*", "number", (a, b) => (b < 0 ? "" : a.repeat(b)))
        // Date Operations.
        .register("date", "-", "date", (a, b) => {
        return normalizeDuration(a.diff(b, ["years", "months", "days", "hours", "minutes", "seconds", "milliseconds"]));
    })
        .register("date", "-", "duration", (a, b) => a.minus(b))
        .registerComm("date", "+", "duration", (a, b) => a.plus(b))
        // Duration Operations.
        .register("duration", "+", "duration", (a, b) => normalizeDuration(a.plus(b)))
        .register("duration", "-", "duration", (a, b) => normalizeDuration(a.minus(b)))
        .register("duration", "/", "number", (a, b) => normalizeDuration(a.mapUnits(x => x / b)))
        .registerComm("duration", "*", "number", (a, b) => normalizeDuration(a.mapUnits(x => x * b)))
        // Array operations.
        .register("array", "+", "array", (a, b) => [].concat(a).concat(b))
        // Object operations.
        .register("object", "+", "object", (a, b) => Object.assign({}, a, b))
        // Null handling operators.
        .register("null", "+", "null", (_a, _b) => null)
        .register("null", "-", "null", (_a, _b) => null)
        .register("null", "*", "null", (_a, _b) => null)
        .register("null", "/", "null", (_a, _b) => null)
        .register("null", "%", "null", (_a, _b) => null));
}

/** Core implementation of the query language evaluation engine. */
/**
github-actions[bot] commented 1 year ago

Closed in dacf5a1d3976e242f2b23557258e96fa65d904e7