UNPKG

godprotocol

Version:

A distributed computing environment for Web 4.0 — integrating AI, decentralisation, and virtual computation.

590 lines (483 loc) 15.9 kB
import Storage from "./functions/storage.js"; /* An Array is constructed by a parent config which holds properties such as length, and a value which is basically the last item in the array. The array stores its entries by using a parent address with a subfolder of item index so for a array address at /places/things First entry would be at > places/things/0 and second at >places/things/1 The native routines of an array are index, insert and pop. Which those 3 are all its super methods constructed. Now lets explain the `pop` native method and interface. It takes in the arr config, and the index. The index should always be less than the arr.length Unless its an empty array, because the index also would not be less than zero. It would access the index value by subfoldering. Then it would read the next */ class Arr extends Storage { constructor(config, account) { super(account); this.config = config; this.type = "array"; this.methods = { ...this.methods, 'replace': {args: [['index', 'number'], ['item', 'object']], ret: ['empty', 'void']}, 'pop': {args: [['name', 'number']], ret: ['item', 'object']}, 'insert': {args: [['item', 'object'], ['index', 'number']], ret: ['arr.length', 'number']}, 'push': {args: [['item', 'object']], ret: ['arr.length', 'number']}, call: {args: [['handler', 'function'], ['callback', 'function']], ret: ['results', 'array']}, // 'map': {args: [['handler', 'function']], ret: ['items', 'array']}, // 'filter': {args: [['handler', 'function']], ret: ['pass_items', 'array']}, // 'find': {args: [['handler', 'function']], ret: ['item', 'object']}, 'clear': {args: [], ret: ['empty', 'array']}, 'len': {args: [], ret: ['length', 'number']}, 'extend': {args: [['other', 'array']], ret: ['concatenated', 'array']}, 'padstart': {args: [['filler', 'object'], ['length', 'number']], ret: ['items', 'array']}, 'padend': {args: [['filler', 'object'], ['length', 'number']], ret: ['items', 'array']}, 'index': {args: [['index', 'number']], ret: ['item', 'object']}, 'to_string': {args: [['glue|ascii', 'object|string']], ret: ['chars', 'string']}, 'is_empty': {args: [[]], ret: ['isit', 'boolean']}, 'reverse': {args: [[]], ret: ['items', 'array']}, 'join': {args: [['other', 'object']], ret: ['concatenated_items', 'string']}, 'slice': {args: [['start', 'number'], ['stop', 'number']], ret: ['sub_arr', 'array']}, 'splice': {args: [['start', 'number'], ['stop', 'number']], ret: ['deleted_items', 'array']}, 'includes': {args: [['item', 'object']], ret: ['yes', 'boolean']}, 'repeat': {args: [['count', 'number']], ret: ['items', 'array']} } } swap_ = async (item, position) => { let chain = await this.chain(); await chain.pop({ arr: this.config, index: position }); await chain.insert({ arr: this.config, item, index: position }); }; replace = async (index, args) => { index = await index.literal(); if (index >= this.config.length) return; let item = args[1]; item = await item.to_address(); await this.swap_(item, index); return index >=0 && index < this.config.length }; retrieve =async (items)=>{ let ds = this.account.manager.ds delete this.config.items await (await ds.folder(this.config.location)).write(this.config, {replace: true}) for (let i=0; i< this.config.length; i++){ let addr = `${this.config.location}/${i}`; let item_ref = this.account.vm._split_datapath(items[i]) let item_folder = await ds.folder(item_ref[0], {account: this.account.physical_address}) let item = await item_folder.readone({_id: item_ref[1]}) if(!item && item_ref[0].endsWith('/instances')){ let adr = item_ref[0].split('/').slice(0,-1).join('/') item = await (await ds.folder(adr, {account: this.account.physical_address})).readone({_id: item_ref[1]}) } await (await ds.folder(addr)).write({ type: 'address', value: item.location, _id: item._id }, {replace: true}) if (['array', 'twain'].includes(item.type)){ await (await this.account.vm.cloth_content(item)).retrieve(item.items || item.entries) } else if (item.type === 'instance'){ await this.account.vm.retrieve(item) } else { await (await ds.folder(item.location)).write(item, {replace: true}) } } } store = async ({store, addresses, thread})=>{ let chain = await this.chain(); let data = {...this.config, items:[]} for (let i=0; i < this.config.length; i++){ let item = await chain.index({arr: this.config, i}) await store({object: await this.account.vm.cloth(item)}, {vm: this.account.vm, addresses, thread}) data.items.push(`${item.value}/${item._id}`) } return data; } find = async (func) => { let chain = await this.chain(), result = new Array(); for (let i = 0; i < this.config.length; i++) { let item = await chain.index({ arr: this.config, i }); let res = await func.invoke( [ item, await this.account.vm.instantiate( { type: "number", value: i.toString(), location: this.spawn_address(), }, { chain } ), ], { chain, cloth: true } ); let res_lit = await res.literal(); if (!!res_lit) { result = i; break; } } return result; }; filter = async (func, pure) => { let chain = await this.chain(), result = new Array(); for (let i = 0; i < this.config.length; i++) { let item = await chain.index({ arr: this.config, i }); let res = await func.invoke( [ item, await this.account.vm.instantiate( { type: "number", value: i.toString(), location: this.spawn_address(), }, { chain } ), ], { chain, cloth: true } ); let res_lit = await res.literal(); if (res_lit) { if (pure) { result.push(i); } else result.push(item); } } if (pure) return result; result = await this.account.vm.instantiate( { type: "array", value: result, location: this.spawn_address(), }, { chain } ); return result; }; __or__ = async (other) => { if (!this.config.length) { return await other.to_address(); } return await this.to_address(); }; __and__ = async (other) => { if (!this.config.length) { return await this.to_address(); } return await other.to_address(); }; call_ = async (func, args) => { let chain = await this.chain(), result = new Array(); for (let i = 0; i < this.config.length; i++) { let item = await chain.index({arr: this.config, i}) let index = await this.account.vm.instantiate({ type:'number', value: i.toString(), location: this.spawn_address() }, {chain}) await func.invoke([item, index], {no_wait: true, callback: async (res)=>{ if (res.__interrupt__){ res = await this.account.vm.instantiate({ type:'error', payload: res.payload, location: this.spawn_address() }, {chain}) } result[i] = res if (result.filter(r=>!!r).length === this.config.length){ await args[1].invoke([ await this.account.vm.instantiate({ type: 'array', value: result, location: this.spawn_address() }, {chain}) ], {no_wait: true}) } }}) } return result; }; extend = async (other) => { let other_chain = await other.chain(); let chain = await this.chain(); for (let i = 0; i < other.config.length; i++) { let obj = await other_chain.index({ arr: other.config, i }); await chain.insert({ arr: this.config, item: obj, index: this.config.length, }); } return this.config.length; }; len = () => { return this.config.length; }; padstart = async (filler, args) => { let index = args[1], chain = await this.chain(); while (this.config.length < await index.literal()) { await chain.insert({ arr: this.config, index: 0, item: await filler.to_address(), }); } return this.config.length; }; padend = async (filler, args) => { let index = await args[1].literal() let chain = await this.chain(); while (this.config.length < index) { await chain.insert({ arr: this.config, index: this.config.length, item: await filler.to_address(), }); } return this.config.length; }; to_string = async (other) => { other = other && (await other.literal()); let length = this.config.length, result = "", chain = await this.chain(); for (let k = 0; k < length; k++) { let item = await chain.index({ arr: this.config, i: k }); item = await this.account.vm.cloth(item); item = await item.literal(); if (other === "ascii") { result = `${result}${String.fromCharCode(item)}`; } else { result = k ? `${result},${item.toString()}` : item.toString(); } } return result; }; copy = async () => { let result = new Array(), chain = await this.chain(), length = this.config.length; for (let i = 0; i < length; i++) result.push(await chain.index({ arr: this.config, i })); return await this.account.vm.instantiate( { type: "array", value: result, location: this.spawn_address(), }, { chain } ); }; reverse = async () => { let chain = await this.chain(), result = new Array(), length = this.config.length, i = 0; while (i < this.config.length) { let pop = await chain.pop({ arr: this.config, index: i, }); result.unshift(pop); } for (let i = 0; i < length; i++) { await chain.insert({ arr: this.config, item: result[i], index: this.config.length, }); } return await this.to_address() }; join = async (other) => { other = other ? await other.literal() : ""; let chain = await this.chain(), result; for (let i = 0; i < this.config.length; i++) { let item = await chain.index({ arr: this.config, i }); let obj = await this.account.vm.cloth(item); result = result ? `${result}${other}${await obj.literal()}` : `${await obj.literal()}`; } return result; }; slice = async (other, args) => { let i = await other.literal(); let stop = args[1] ? await args[1].literal() : this.config.length; let skip = args[2] ? await args[2].literal() : 1; let res = new Array(), chain = await this.chain(); while (i < stop) { let obj = await chain.index({ arr: this.config, i }); if (!obj) break; res.push(obj); i += skip; } return await this.account.vm.instantiate( { value: res, location: this.spawn_address(), type: "array", }, { chain } ); }; splice = async (other, args) => { let i = await other.literal(); let count = args[1] ? await args[1].literal() : this.config.length - i; let replacement = args[2]; let res = new Array(), chain = await this.chain(); if (i < 0) { i = this.config.length + i; } while (this.config.length > i && count) { let obj = await chain.pop({ arr: this.config, index: i }); if (!obj) break; res.push(obj); count--; } if (replacement) { await chain.insert({ arr: this.config, index: i, item: await replacement.to_address(), }); } return await this.account.vm.instantiate( { value: res, location: this.spawn_address(), type: "array", }, { chain } ); }; is_empty = () => { return !this.config.length; }; includes = async (other) => { other = await other.literal(); let result = false, chain = await this.chain(); for (let i = 0; i < this.config.length; i++) { let item = await chain.index({ arr: this.config, i }); let obj = await this.account.vm.cloth(item); if ((await obj.literal()) === other) { result = true; break; } } return result; }; repeat = async (other) => { other = await other.literal(); let chain = await this.chain(); let length = this.config.length; for (let i = 1; i < other; i++) { for (let k = 0; k < length; k++) { let item = await chain.index({ arr: this.config, i: k }); await chain.insert({ arr: this.config, item, index: this.config.length, }); } } return this.config.length; }; clear = async () => { let chain = await this.chain(); while (this.config.length) { await chain.pop({ arr: this.config, index: this.config.length - 1 }); } }; index = async (other) => { if (other == null) return; let chain = await this.chain(); let i = other.literal ? await other.literal() : other; i = await this.normalise_index_(i) if (i.__interrupt__) return i return await chain.index({ arr: this.config, i }); }; normalise_index_ = async(i)=>{ if (i < 0) { i = this.config.length + i; } if (i >= this.config.length || i < 0){ return await this.account.vm.throw_error({type:"IndexError", message: `Index value out of range 0-${this.config.length-1}`}) } return i } pop = async (other) => { let chain = await this.chain(); if (other.type !== 'number'){ return await this.account.vm.throw_error({type:"TypeError", message: 'Array.pop method expects a numeric index'}) } let index = await other.literal() index = await this.normalise_index_(index) if (index.__interrupt__) return index let res = await chain.pop({ arr: this.config, index }); return res; }; insert = async (other, args) => { let item = await other.to_address(); if (other.object) item.object = other.object; let chain = await this.chain(); let index = await args[1].literal(); if (index === -1) { index = this.config.length - 1; } else { if (index < 0) { index = this.config.length + index; } } if (index >= this.config.length){ index = this.config.length } await chain.insert({ arr: this.config, item, index }); return this.config.length; }; push = async (other) => { let chain = await this.chain(); let item = await other.to_address(); if (other.object) item.object = other.object; await chain.insert({ arr: this.config, item, index: this.config.length }); return this.config.length; }; literal = async () => { if (this.value) return this.value; let value = new Array(); let folder = await this._folder(); for (let i = 0; i < this.config.length; i++) { let item_folder = await folder.folder(i.toString()); let item = (await item_folder.readone()); let obj = await this.account.vm.cloth(item); value.push(await obj.literal()); } this.value = value; return value; }; configs = (name) => { let conf = { push: { parameters: [{ name: "item", position: 0 }], }, }; return conf[name]; }; } export default Arr;