godprotocol
Version:
A distributed computing environment
266 lines (224 loc) • 7.76 kB
JavaScript
import Vm_utils from "../utils/vm_utils";
class Callable extends Vm_utils {
constructor() {
super();
this.objects = new Object();
}
parse_aircode = async (result, { config, chain }) => {
if (result == null) result = "void";
let res = await this.account.compiler.to_sequence(
JSON.stringify(result),
config.location.split("/").slice(2).join("/")
)[0].body[0];
await chain.add_config(res);
result = await this.execute(res, { chain });
return result;
};
resolve_address = async (path, chain) => {
let oracle = this.account.manager.oracle,
fs = oracle.fs;
if (typeof path !== "string") {
return path;
}
if (path == "g") throw new Error();
let conf = await fs.read(`${path}/.config`),
value;
if (!conf.current) {
value = await fs.read(`${path}/${conf.index - 1}`);
value = JSON.parse(value.content);
} else value = await fs.read(`${path}/${conf.current}`);
value.path = path;
return value;
};
instantiate = async (config, { chain, hash, pure }) => {
let instance_chain = await chain.chain(
config.type === "void" ? config.value : config.location
);
let uid = this.gen_uid();
if (config.type === "twain") {
if (!pure) {
for (let p in config.value) {
let pair = config.value[p];
pair[0] = (await this.execute(pair[0], { chain })).value;
pair[1] = (await this.execute(pair[1], { chain })).value;
}
}
config.value = JSON.stringify(config.value);
} else if (config.type === "array") {
if (!pure) {
for (let i = 0; i < config.value.length; i++) {
let item = config.value[i];
config.value[i] = (await this.execute(item, { chain })).value;
}
}
config.value = JSON.stringify(config.value);
}
let res = await instance_chain.write(
{ content: config.value, __classifier__: config.type, uid },
{ hash, is_instance: true }
);
return res;
};
operate_result = async (value, call_config, chain) => {
let result;
if (value && value.error) {
result = value;
} else if (value && value.type === "address") {
result = value;
} else
result = await this.parse_aircode(value, { config: call_config, chain });
return result;
};
object_identifier = async (call_config, chain) => {
let { identifier } = call_config,
result,
oracle = this.account.manager.oracle;
let conf = await oracle.fs.read(`${identifier.object}/.config`);
let obj = await oracle.fs.read(`${identifier.object}/${conf.current}`);
let res = await this.cloth_content({ ...obj, path: identifier.object });
let classifier = await res.get("__classifier__");
if (this.datatypes.includes(classifier)) {
for (let a = 0; a < call_config.arguments.length; a++)
call_config.arguments[a] = await this.execute(
call_config.arguments[a],
{ chain, cloth: true }
);
let value = await res.operate(identifier.value, call_config.arguments, {
classifier,
config: call_config,
chain,
});
result = await this.operate_result(value, call_config, chain);
} else {
let conf = await oracle.fs.read(`${identifier.value}/.config`);
conf = await oracle.fs.read(`${identifier.value}/${conf.index - 1}`);
let content = JSON.parse(conf.content);
let val = await this.execute(content, {
chain,
call_config: {
...call_config,
object: { type: "address", value: identifier.object },
},
});
result = val;
}
return result;
};
execute_call = async (call_config, { chain, obj }) => {
let { identifier, arguments: args } = call_config,
result;
if (typeof identifier !== "string") {
if (identifier.object) {
result = await this.object_identifier(call_config, chain);
} else {
let conf = await this.read_config(identifier.value);
if (!["function", "class"].includes(conf.type)) {
conf = await obj.get(identifier.prev_name, {
obj: identifier.prev_name,
});
conf = await this.resolve_address(conf.value);
}
result = await this.execute(conf, { call_config, chain });
}
} else if (identifier.includes("/")) {
let oracle = this.account.manager.oracle;
let i_chain = identifier.startsWith(this.account.manager.path)
? { path: identifier }
: await chain.chain(identifier);
let conf = await oracle.fs.read(`${i_chain.path}/.config`);
if (conf.sibling) {
let config = await oracle.fs.read(conf.sibling);
if (config.content.type === "address") {
if (config.content.object) {
result = await this.object_identifier(
{ ...call_config, identifier: config.content },
chain
);
} else {
let iconf = await oracle.fs.read(`${config.content.value}/.config`);
let configg = await oracle.fs.read(
`${config.content.value}/${iconf.index - 1}`
);
result = await this.execute(JSON.parse(configg.content), {
call_config,
chain,
});
}
}
} else if (conf.current) {
let iconf = await oracle.fs.read(`${conf.current}/.config`);
let config = await oracle.fs.read(`${conf.current}/${iconf.index - 1}`);
result = await this.execute(JSON.parse(config.content), {
call_config,
chain,
});
} else {
let config = await oracle.fs.read(
`${call_config.identifier}/${conf.index - 1}`
);
result = await this.execute(JSON.parse(config.content), {
call_config,
chain,
});
}
} else {
if (this.datatypes.includes(identifier)) {
} else {
let { callable, config } = await this.callable(identifier);
let data = {};
for (let a = 0; a < args.length; a++) {
let param;
let arg = args[a];
if (arg.identifier) {
} else {
param = config.parameters[arg.position];
if (!param) {
let lst_param = config.parameters.slice(-1)[0];
if (lst_param.spread) param = lst_param;
}
}
let res = await this.execute(arg, { chain, cloth: true });
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, config, chain });
if (["Twain", "exit", "render"].includes(identifier)) {
} else
result = await this.parse_aircode(result, {
config: call_config,
chain,
});
}
}
return result;
};
callable = async (name) => {
let object = this.objects[name];
return object;
};
set = (name, config) => {
this.objects[name] = config;
};
native_components = async (config, chain) => {
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 });
children.push(await res.literal());
}
let obj = {
name: config.name,
props: await props.literal(),
children,
};
return obj;
};
}
export default Callable;