From 38d9df0367f782ae2aa5e27d40d7b35e96a9d833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20L=C3=B6vqvist?= Date: Sat, 4 Apr 2026 07:53:19 +0200 Subject: [PATCH] Work on experimental storage system --- experiments/os1.mjs | 84 ++++++++++++++++++++++++++++---------------- experiments/res1.mjs | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 30 deletions(-) create mode 100644 experiments/res1.mjs diff --git a/experiments/os1.mjs b/experiments/os1.mjs index de08e13..f5a028d 100644 --- a/experiments/os1.mjs +++ b/experiments/os1.mjs @@ -3,24 +3,31 @@ import { inspect } from 'node:util'; class Not_Storable_Error extends Error { - constructor({ storage, value, prop, id }) { + constructor(data) { + const { storage, value, property, id } = data; const type = value === null ? 'null' : typeof value; - const location = prop ? `property "${prop}" of record #${id}` : `record #${id}`; + const location = property ? `property "${property}" of record #${id}` : `record #${id}`; super(`Cannot store value of type "${type}" in ${location}: ${inspect(value)}`); - this.name = 'Not_Storable_Error'; - this.storage = storage; - this.value = value; + this.data = data; } } class Not_Mutable_Error extends Error { - constructor({ storage, value, prop, id }) { + constructor(data) { + const { storage, value, property, id } = data; const type = value === null ? 'null' : typeof value; - const location = prop ? `property "${prop}" of record #${id}` : `record #${id}`; + const location = property ? `property "${property}" of record #${id}` : `record #${id}`; super(`Cannot set ${location}: record is immutable (tried to store value of type "${type}": ${inspect(value)})`); - this.name = 'Not_Mutable_Error'; - this.storage = storage; - this.value = value; + this.data = data; + } +} + +class No_Such_Object_Index_Error extends Error { + constructor(data) { + const { storage, property, id } = data; + const location = property ? `property "${property}" of record #${id}` : `record #${id}`; + super(`Cannot get ${location}: no such record index`); + this.data = data; } } @@ -35,29 +42,19 @@ function load_descriptor({ type, value }, { storage, mutable }) { const Record_Handler = { - get(target, prop, receiver) { - const { storage, id, mutable } = target; - - const result_descriptor = storage.get_record_property(id, prop); - if (result_descriptor) { - return load_descriptor(result_descriptor, { storage, mutable }); - } else { - return undefined; - } + get(target, property, receiver) { + const { storage, id } = target; + return storage.get_record_property(id, property); }, - set(target, prop, value) { + set(target, property, value) { const { storage, id, mutable } = target; if (!mutable) { - throw new Not_Mutable_Error({ storage, id, prop, value }); + throw new Not_Mutable_Error({ storage, id, property, value }); } - if (!storage.can_be_stored(value)) { - throw new Not_Storable_Error({ storage, id, prop, value }); - } - - storage.set_record_property(id, prop, value); + storage.set_record_property(id, property, value); return true; } @@ -89,12 +86,36 @@ class Storage { } get_record_property(item_id, property) { - console.log("Should get record property", { item_id, property }); - return { type: 'primitive', value: 'Hello' }; + + const property_bag = this.#records.get(item_id); + if (property_bag === undefined) { + throw new No_Such_Object_Index_Error({storage: this, id: item_id, property}); + } + + return property_bag[property]; + } set_record_property(item_id, property, value) { - console.log("Should set record property", { item_id, property, value }); + + const descriptor = this.maybe_create_descriptor(value); + + if (!descriptor) { + throw new Not_Storable_Error({ storage: this, id: item_id, property, value }); + } + + const property_bag = this.#records.get(item_id); + if (property_bag === undefined) { + throw new No_Such_Object_Index_Error({storage: this, id: item_id, property}); + } + + property_bag[property] = descriptor; + } + + maybe_create_descriptor(value) { + if (typeof value === 'string') { + return { type: 'primitive', value }; + } } can_be_stored(value) { @@ -115,7 +136,10 @@ class Storage { const s1 = new Storage(); -const p1 = s1.create_record({stuff: 'hello'}, true); +const p1 = s1.create_record({stuff: 5n}, true); console.log(p1.blargh); +console.log(s1.get_record_property(1, 'stuff')) + + //p1.stuff = ['hello', 'world']; \ No newline at end of file diff --git a/experiments/res1.mjs b/experiments/res1.mjs new file mode 100644 index 0000000..06c045b --- /dev/null +++ b/experiments/res1.mjs @@ -0,0 +1,65 @@ +import { inspect } from 'node:util'; + +class Item_Unresolvable extends Error { + constructor(data) { + const { resolver, item } = data; + const type = item === null ? 'null' : typeof item; + super(`Cannot resolve item ${inspect(item)} of type "${type}" using resolver ${resolver}`); + this.data = data; + } +} + +class Abstract_Resolver { + resolve(item) { + const handler = this.resolve_handler(item); + if (!handler) { + throw new Item_Unresolvable({ resolver: this, item }); + } + return handler({ resolver: this, item }); + } +} + +class Chained_Resolver extends Abstract_Resolver { + constructor(chain_links) { + super(); + Object.assign(this, { chain_links }); + } + + resolve_handler(item) { + const { chain_links } = this; + for (const link of chain_links) { + const handler = link.resolve_handler(item); + if (handler) { + return handler; + } + } + } +} + + +class Mapping_Resolver { + constructor(rules=new Map(), key_function=null) { + Object.assign(this, { rules, key_function }); + } + + resolve_handler(item) { + const { key_function, rules } = this; + const key = key_function ? key_function(item) : item; + return rules.get(key); + } + +} + + + +const vr = new Mapping_Resolver(); +const tr = new Mapping_Resolver(new Map(), item => typeof item); + +const cr = new Chained_Resolver([vr, tr]); + + +vr.rules.set('HELLO', () => 'WORLD'); +tr.rules.set('string', () => 'World'); + +console.log(cr.resolve('HELLO')); +console.log(cr.resolve('hello'));