UNPKG

godprotocol

Version:

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

322 lines (273 loc) 9.39 kB
import Vm_utils from "../utils/vm_utils.js"; class Callable extends Vm_utils { constructor() { super(); this.objects = new Object(); } parse_aircode = async (result, { config, chain, id }) => { if (result == null) result = "void"; let loc = config && config.location.split("/").slice(2).join("/"); result = result === "void" ? result : JSON.stringify(result); if (result === "void") return await this.voided(); let res = await this.account.compiler.to_sequence( result, !loc ? "CONSTANTS" : loc ); res = res[0].body[0]; await chain.add_config(res); result = await this.execute(res, { chain, id }); return result; }; instantiate = async (config, { chain, value, _id }) => { let chn = await chain.chain(config.location); let folder = await chn.folder(); if (["void", "boolean"].includes(config.type)) { let res = await this.statics(config); return res; } let obj = { _id, type: config.type, created: Date.now(), location: folder.address, }, res; if (config.type === "error") { obj.value = config.payload; res = await folder.write(obj); obj._id = res._id; } else if (config.type === "twain") { res = await folder.write(obj); obj._id = res._id; obj.created = res.created; if (value) { let val_obj = await this.cloth(value); let obj_obj = await this.cloth_content(obj); obj_obj.address = folder.address; await obj_obj.extend(val_obj); } else { for (let key in config.value) { let [prop, value] = config.value[key]; if (typeof prop === "string") { prop = await this.execute(await this.read_config(prop), { chain }); } if (typeof value === "string") { value = await this.execute(await this.read_config(value), { chain, }); } await chn.set({ twa: obj, key, prop, value }); } } res = await folder.write(obj, { replace: true }); } else if (config.type === "array") { obj.length = 0; res = await folder.write(obj); obj._id = res._id; obj.created = res.created; if (value) { let val_obj = await this.cloth(value); let obj_obj = await this.cloth_content(obj); obj_obj.address = folder.address; await obj_obj.extend(val_obj); } else { for (let i = 0; i < config.value.length; i++) { let item = config.value[i]; if (typeof item === "string") { item = await this.execute(await this.read_config(item), { chain }); } await chn.insert({ arr: obj, item, index: obj.length }); } } res = await folder.write(obj, { replace: true }); } else if (["string", "number", "void", "boolean"].includes(config.type)) { if (value) { folder = await this.account.manager.ds.folder(value.value); obj._id = value._id; } else { obj.value = config.value; res = await folder.write(obj); obj._id = res._id; obj.created = res.created; obj.address = folder.address; } } res = { value: folder.address, type: "address", _id: obj._id, }; return res; }; callable_address = async (config, o) => { let obj = await this.cloth_content(config); obj.address = config.address; return o ? obj : await obj.to_address(); }; execute_call = async (call_config, { chain, thread }) => { let result; let { identifier, arguments: args, location } = call_config; if (location) { location = await chain.chain(location); } if (identifier.type === "address") { // If call is a reference, such as to a class method let { object, value, config: is_config } = identifier; if (object) { let spl = this._split_datapath(object); let obj = { value: spl[0], _id: spl[1], type: "address", config: is_config, }; obj = await this.cloth(obj); if (value.includes("/")) { await obj.run(call_config, { thread, chain }); } else { result = await obj.call(value, { chain, call_config, thread }); } } else { let obj = await this.cloth(identifier); if (["class", "function", "instance"].includes(obj.type)) { } else result = await this.throw_error({ type: "TypeError", message: `type ${obj.type} is not callable.`, }); } } else if (["function", "class"].includes(identifier.type)) { let call = await this.cloth(identifier); await call.invoke(args, { chain, call_config, thread }); } else if (identifier.includes("/")) { // If call is a user-defined address let folder = await this.account.manager.ds.folder(identifier); let payload = await folder.readone(); if (payload.object) { result = await this.execute_call( { ...call_config, identifier: payload }, { chain, thread } ); } else { if (payload.config && payload._id === payload.value) { result = await this.execute_call( { ...call_config, identifier: payload._id }, { chain, thread } ); } else { let call = await this.cloth(payload); await call.invoke(args, { chain, call_config, thread }); } } } else if (this.datatypes.includes(identifier)) { // If call is Datatype instantiation let _id = call_config.arguments.find((p) => p.identifier === "_id"); if (_id) { delete _id.identifier; _id = await this.cloth({ ..._id }); if (_id.type === "string") _id = await this.hash(await _id.literal()); else _id = null; } else _id = null; let val = call_config.arguments.find((p) => p.identifier === "value"); val = (val && val.value) || call_config.arguments[0]; result = await this.instantiate( { type: identifier, location: call_config.location }, { chain, _id, value: val } ); } else if (this.err_objects.includes(identifier)) { let message = await (await this.cloth(args[0])).literal(); result = await this.throw_error({ message, type: identifier }); } else { // If call is a reserved word. let call = await this.callable(identifier); let { callable, config } = call; let data = {}; for (let a = 0; a < args.length; a++) { let param; let arg = args[a]; if (arg.identifier) param = config.parameters.find((p) => p.name === arg.identifier); if (!param) { param = config.parameters[arg.position || a]; if (!param) { let lst_param = config.parameters.slice(-1)[0]; if (lst_param.spread) param = lst_param; } } let res = await this.cloth(arg); if (param) { if (param.spread) { let arr = data[param.name]; if (!arr) { arr = new Array(); data[param.name] = arr; } arr.push(res); } else data[param.name] = res; } } result = await callable(data, { vm: this, call_config, chain, thread }); if (["store", "net"].includes(identifier)) { result = await this.voided(); } else if (identifier === "parse" && result) { } else if (["Twain", "folder"].includes(identifier)) { result = await result.to_address(); } else if (result && ["address", "function"].includes(result.type)) { } else { result = await this.parse_aircode(result, { config: call_config, chain, }); } } return result; }; resolve_import = async (config, chain) => { let addr = this.resolve_addr(config.address), oracle = this.account.manager.oracle; for (let i = 0; i < config.identifiers.length; i++) { let id = config.identifiers[i]; let conf = await oracle.read(`${oracle.manager.path}/${addr}/${id}`, { config: true, }); await this.execute( { type: "assignment", identifier: id, value: { type: "address", value: conf.path, }, }, { chain } ); } }; callable = async (name) => { let object = this.objects[name]; return object; }; set = (name, config) => { this.objects[name] = config; }; native_components = async (config, { chain, object }) => { let props = await this.execute(config.props, { chain, cloth: true }); let children = new Array(); for (let c = 0; c < config.children.length; c++) { let child = config.children[c]; let res = await this.execute(child, { chain, cloth: true, object }); children.push(await res.literal({ adm: true })); } let obj = { name: config.name, props: await props.literal({ adm: true }), children, _id: props.config._id, path: props.path, }; let result = await this.parse_aircode(obj, { config, chain }); return result; }; rerender = async (object) => {}; } export default Callable;