UNPKG

godprotocol

Version:

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

421 lines (385 loc) 12.8 kB
import Callable from "./Callable.js"; class Virtual_machine extends Callable { constructor(account) { super(); this.envs = new Object(); this.account = account; } nodelist = async (config, options = {}) => { let { call, list } = options; list = list || new Array(); const flatten = async (config, no_call) => { if (typeof config === "string") { config = await this.read_config(config); } switch (config.type) { case "module": for (let b = 0; b < config.body.length; b++) { let bdy = config.body[b]; config.body[b] = await flatten(bdy); } list.push(config); return list; break; case "function": if (call && !no_call) { for (let p = 0; p < config.parameters.length; p++) { let param = config.parameters[p]; param.location = `${config.address}/${param.identifier}`; config.parameters[p] = await flatten(param); } for (let b = 0; b < config.body.length; b++) { let bdy = config.body[b]; await flatten(bdy, true); } } else { list.push({ type: "function", _id: config._id, address: config.address, module: config.module, }); } return list.length - 1; case "class": if (call) { } else { list.push({ type: "class", _id: config._id, address: config.address, module: config.module, }); } return list.length - 1; case "return": config.output = await flatten(config.output); list.push(config); return list.length - 1; case "raise": return await flatten(config.object); case "assignment": let val = await flatten(config.value); config.value = val; list.push(config); return list.length - 1; break; case "nest": for (let n = 0; n < config.nests.length; n++) { let nst = config.nests[n]; let val = await flatten(nst); config.nests[n] = val; } if (config.assignment) { config.assignment = await flatten(config.assignment); } list.push(config); return list.length - 1; case "call": let id = await this.read_config(config.identifier); if (id && ["call", "nest"].includes(id.type)) { config.identifier = await flatten(id); } for (let a = 0; a < config.arguments.length; a++) { let arg = config.arguments[a]; config.arguments[a] = await flatten(arg); } list.push(config); return list.length - 1; case "trycatch": let try_index = list.length; let try_conf = { type: "try", alias: config.alias, location: config.location, }; list.push(try_conf); for (let i = 0; i < config.try_body.length; i++) { let bdy = config.try_body[i]; let b = await flatten(bdy); config.try_body[i] = b; } let catch_index = list.length; try_conf.catch_index = catch_index; list.push({ type: "catch", objects: config.objects, try_index }); for (let i = 0; i < config.catch_body.length; i++) { let bdy = config.catch_body[i]; config.catch_body[i] = await flatten(bdy); } try_conf.catch_offset = -1 + list.length - catch_index; return try_index; case "variable": list.push(config); return list.length - 1; case "reference": list.push(config); return list.length - 1; case "address": list.push(config); return list.length - 1; case "loop": let loop_config = { type: "loop", kind: config.loop_type || "while" }; let loop_index = list.length; list.push(loop_config); if (config.loop_type === "for") await flatten(config.iterator); loop_config.condition_index = list.length; let cond_index = await flatten(config.condition); for (let b = 0; b < config.body.length; b++) { let bdy = config.body[b]; await flatten(bdy); } if (loop_config.kind === "while") { loop_config.update_jmp = loop_config.condition_index; } else loop_config.update_jmp = list.length; if (config.loop_type === "for") { await flatten(config.update); } list.push({ jmp: loop_config.condition_index }); list[cond_index].conditional_jmp = list.length; list[cond_index].invert = true; loop_config.conditional_jmp = list.length; list.push({ type: "endloop", kind: "unloop" }); return loop_index; case "condition": let prior_index, bdys = new Array(), indexx, prior_bdy; for (let b = 0; b < config.blocks.length; b++) { let blk = config.blocks[b]; indexx = list.length; let index = await flatten(blk.predicate); if (prior_index) { list[prior_index].conditional_jmp = indexx; } prior_index = index; prior_bdy; for (let d = 0; d < blk.body.length; d++) { let bdy = blk.body[d]; prior_bdy = await flatten(bdy); } bdys.push(blk.body.length ? prior_bdy : index); list.push({}); } if (config.blocks.length === 1) { list[prior_index].conditional_jmp = prior_bdy + 1; } bdys.map((dy) => { list[dy + 1].jmp = list.length; }); return list.length - 1; case "twain": for (let key in config.value) { let [prop, val] = config.value[key]; prop = await flatten(prop); val = await flatten(val); config.value[key][0] = prop; config.value[key][1] = val; } list.push(config); return list.length - 1; case "array": for (let i = 0; i < config.value.length; i++) { config.value[i] = await flatten(config.value[i]); } list.push(config); return list.length - 1; default: if (["number", "string", "void", "boolean"].includes(config.type)) { list.push(config); return list.length - 1; } else if (["continue", "break"].includes(config.type)) { list.push(config); return list.length - 1; } } }; let result = await flatten(config); return list; }; read_config = async (addr, options = {}) => { if (typeof addr !== "string") { return addr; } addr = addr.split("/"); let folder = await this.account.ds.folder(addr.slice(0, -1).join("/")); let result = await folder.readone({ _id: addr.slice(-1)[0] }); return result; }; sync = async () => {}; throw_error = async (payload) => { return { __interrupt__: true, payload, }; }; execute_body = async (body, options) => { let res; for (let b = 0; b < body.length; b++) { let line = body[b]; res = await this.execute(line, options); if (res) { if (res.done || res.__interrupt__) break; } } return res; }; modules = new Array(); times = new Array(); curr_field = () => { let curr = this.modules.slice(-1)[0]; return curr && curr.address; }; spawns = new Array(); execute = async (config, options = {}) => { let { chain, cloth, thread } = options; config = await this.read_config(config, chain); this.running_thread = thread; // console.log(config, 'EXE') let result; if (!config) return config; switch (config.type) { case "module": let mod_chain = await chain.chain(config.location); // result = await this.execute_body(config.body, {chain: mod_chain, config}) result = config.body; break; case "class": let cls_chn = await chain.chain(config.address); result = await ( await cls_chn.folder() ).write(config, { replace: true }); result = { type: "function", address: config.address, value: config.address, _id: result._id, }; break; case "function": let fn_chn = await chain.chain(config.address); result = await (await fn_chn.folder()).write(config, { replace: true }); result = { type: "function", address: config.address, value: config.address, _id: result._id, }; break; case "return": result = { __interrupt__: true, type: "return", output: config.output, }; break; case "loop": break; case "condition": break; case "assignment": let ass_chain = await chain.chain(config.location); result = await ass_chain.write(config.value, { addr: true }); result = { ...config.value, identifier: config.identifier }; break; case "nest": let prev = await this.cloth(config.nests[0]); result = config.nests[0]; for ( let i = 1; i < config.nests.length - (config.assignment ? 1 : 0); i++ ) { let nst = await this.read_config(config.nests[i]), obj; if (nst.type === "call") { obj = await this.execute( { type: "string", value: nst.identifier, location: `${nst.location}_`, }, { chain, cloth: true } ); obj = await prev.get(nst.identifier, { chain, obj, config: nst }); if (obj.__interrupt__) { result = obj; break; } else { result = await this.execute( { ...nst, identifier: obj, }, { chain } ); prev = await this.cloth(result); } } else { obj = await this.cloth(nst); prev = await prev.get(await obj.literal(), { chain, obj, config: nst, }); if (prev.__interrupt__) { result = prev; break; } else { result = prev; prev = await this.cloth(prev); } } } if (config.assignment) { let bull = thread.bullets[thread.pointer]; if (result && result.__interrupt__) { } else { let last = await this.cloth(config.nests.slice(-1)[0], { just_content: true, }); if (this.datatypes.includes(last.type)) { let r = await prev.set( config.nests.slice(-1)[0], config.assignment, { chain } ); bull.assignment_location = r; result = config.assignment; } } } break; case "call": result = await this.execute_call(config, { chain, thread }); break; default: if (this.datatypes.includes(config.type)) { result = await this.instantiate(config, { chain }); } else if (config.type === "variable" || config.type === "reference") { if ( !!(await this.callable(config.value)) || this.datatypes.includes(config.value) ) { result = { type: "address", value: config.value, _id: config.value, config: true, }; } else result = await this.variable(config.location, { chain, config }); } else if (["continue", "break"].includes(config.type)) { config.__interrupt__ = config.type; result = config; } } if (result && cloth && !result.__interrupt__) { result = await this.cloth(result); } else if (result && config.conditional_jmp) { result = await this.cloth(result); } return result; }; } export default Virtual_machine;