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