godprotocol
Version:
A distributed computing environment for Web 4.0 — integrating AI, decentralisation, and virtual computation.
421 lines (385 loc) • 12.8 kB
JavaScript
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;