godprotocol
Version:
A distributed computing environment for Web 4.0 — integrating AI, decentralisation, and virtual computation.
585 lines (501 loc) • 16.2 kB
JavaScript
import { generate_random_string } from "generalised-datastore/utils/functions.js";
class Storage {
constructor(account) {
this.account = account
this.methods = {
'get_id': {args:[], ret: ['_id', 'string']},
'folder': {args:[['address', 'string'], ['options', 'twain']], ret: ['folder', 'folder']},
'__and__': {args: [['other', 'object']], ret: ['result', 'object']},
'__sub__': {args: [['other', 'object']], ret: ['result', 'object']},
'__or__': {args: [['other', 'object']], ret: ['result', 'object']},
'__add__': {args: [['other', 'object']], ret: ['result', 'object']},
'__mul__': {args: [['other', 'object']], ret: ['result', 'object']},
'__div__': {args: [['other', 'object']], ret: ['result', 'object']},
'__gt__': {args: [['other', 'object']], ret: ['result', 'object']},
'__lt__': {args: [['other', 'object']], ret: ['result', 'object']},
'__gte__': {args: [['other', 'object']], ret: ['result', 'object']},
'__lte__': {args: [['other', 'object']], ret: ['result', 'object']},
'__ne__': {args: [['other', 'object']], ret: ['result', 'object']},
'__eq__': {args: [['other', 'object']], ret: ['result', 'object']},
}
}
__or__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value || other
break
case 'string':
result = this.value || other
break
case 'void':
result = await other.to_address()
break
case 'function':
result = await this.to_address()
break
case 'instance':
result = await this.run('__or__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__and__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value && other
break
case 'instance':
result = await this.run('__and__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__gt__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value > other
break
case 'instance':
result = await this.run('__gt__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__gte__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value >= other
break
case 'instance':
result = await this.run('__gte__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__lt__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value < other
break
case 'instance':
result = await this.run('__lt__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__lte__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value <= other
break
case 'instance':
result = await this.run('__lte__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__eq__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value == other
break
case 'string':
result = this.value == other
break
case 'class':
result = this.ref() === other.ref()
break
case 'function':
result = this.ref() === other.ref()
break
case 'instance':
await this.run('__eq__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (result == null) result = await this.account.vm.voided()
return result
}
__ne__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value != other
break
case 'void':
result = other.type === 'void'
break
case 'class':
result = this.ref() !== other.ref()
break
case 'function':
result = this.ref() !== other.ref()
break
case 'instance':
result = await this.run('__ne__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (result==null) result = await this.account.vm.voided()
return result
}
__div__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value / other
break
case 'instance':
result = await this.run('__div__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__mul__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value * other
break
case 'string':
if (typeof other === 'string')
result = await this.repeat(other)
break;
case 'instance':
result = await this.run('__mul__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__sub__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value - other
break
case 'instance':
result = await this.run('__sub__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
__add__ = async(other)=>{
let result;
switch(this.type){
case 'number':
if (typeof other === 'number')
result = this.value + other
break
case 'string':
if (typeof other === 'string')
result = await this.concat(other)
break;
case 'instance':
result = await this.run('__add__', {config: {arguments: [other], location: this.spawn_address()}, chain: this.account.chain})
break;
}
if (!result) result = await this.account.vm.voided()
return result
}
_folder = async(options={})=>{
let addr = this.type === 'folder'? this.config.value: this.address
let folder = await this.account.manager.ds.folder(addr, {...options})
return folder;
}
emit = async(name, args)=>{
name = await name.literal()
if(this.type === 'instance'){
name = `${name}:${this.config._id}`
}
let fold = await this._folder()
let res = await fold.emit(name, args[1]? [await args[1].to_address()]: [], {account: this.account})
let {vm, chain} = this.account
return await vm.instantiate({
type: 'array',
value: res,
location: vm.gen_location()
}, {chain})
}
listen = async(name, args)=>{
name = await name.literal()
let func = await args[1].to_address()
if (this.type === 'instance'){
name = `${name}:${this.config._id}`
}
let fold = await this._folder()
await fold.listen(name, func, {account: this.account})
}
folder = async(address, args, {call_config, chain})=>{
let parent = this.config.location
if (this.type === 'instance'){
parent = `${this.config.cls}/${this.config._id}`
}
let fold = await this.account.manager.ds.folder(parent, {account: this.account.physical_address})
address = await address.literal()
let subfolder = await fold.folder(address, {account: this.account.physical_address})
let obj = {
type: 'folder',
value: subfolder.address,
location: call_config.location
}
let folder = await chain.folder(call_config.location)
let res = await folder.write(obj)
return {
type: 'address',
value: folder.address,
_id: res._id
}
}
get_id = async()=>{
return this.config._id
}
call = async(method, options)=>{
let {chain, call_config, pure, thread} = options
let {arguments: args} = call_config, other, result;
let method_name = method;
let args_ = new Array()
for(let a=0; a < args.length; a++){
args_[a] = await this.account.vm.cloth(args[a])
}
args = args_
switch(this.type){
case 'number':
this.value = await this.literal()
other = args[0] && await args[0].literal()
method = this[method]
if (typeof method === 'function'){
result = await method(other, args, {call_config, thread, chain})
}
break;
case 'string':
this.value = await this.literal()
other = args[0] && await args[0].literal()
method = this[method]
if (typeof method === 'function'){
result = await method(other, args, {call_config})
}else {
result = await this.overloads(method_name, other, args, {call_config, thread, chain})
}
break;
case 'array':
if (method === 'call') method = 'call_'
method = this[method]
if(typeof method === 'function'){
result = await method(args[0], args, {call_config, thread, chain})
}
break;
case 'twain':
if(['set', 'get'].includes(method)){
method = `${method}_`
}
method = this[method]
if (typeof method === 'function'){
result = await method(args[0], args, {call_config, thread, chain})
}
break;
case 'function':
method = this[method]
if (typeof method === 'function'){
result = await method(args[0], args, {call_config, thread, chain})
}
break;
case 'instance':
method = this[method]
if(typeof method === 'function'){
result = await method(args[0], args, {call_config, chain})
}
break;
case 'class':
method = this[method]
if (typeof method === 'function'){
result = await method(args[0], args, {call_config, thread, chain})
}
break;
default:
method = this[method]
if (typeof method === 'function'){
result = await method(args[0], args, {call_config, thread, chain})
}
;
}
if(pure){
return result;
}
if (result && result.__interrupt__){}
else if (result && ['address', 'folder'].includes(result.type)){
}else result = await this.account.vm.parse_aircode(result, {
config: call_config,
chain
})
return result
}
overloads = async (name, other, args)=>{
let lit = await this.literal(), result;
switch(this.type){
case "string":
switch(name){
case '__eq__':
result = lit === other
break;
case '__ne__':
result = lit !== other
break;
case '__lt__':
result = lit < other;
break;
case '__lte__':
result = lit <= other;
break;
case '__gt__':
result = lit > other;
break;
case '__or__':
result = lit || other;
break;
case '__and__':
result = lit && other;
break;
case '__gte__':
result = lit >= other;
break;
case '__mul__':
result = await this.repeat(other, args)
break;
case '__add__':
result = await this.concat(other, args)
break
}
break;
}
return result
}
ref = ()=>{
return `${this.address || this.config.address}/${this.config._id}`
}
get_ =async(prop)=>{
if (!this.methods[prop] && !this[prop]) return;
return {
type: 'address',
object: this.ref(),
value: prop
}
}
get = async(prop, options={})=>{
let {obj, raw} = options
let result;
if (this.type === 'twain' && this.is_literal){
if (Object.keys(this.methods).includes(prop)){
return {
type: 'address',
value: prop,
object: this.ref()
}
}
}
if (this.account.vm.datatypes.includes(this.type) || this.type === 'error' || ['function', 'class'].includes(this.type)){
if(this.type === 'void' && !Object.keys(this.methods).includes(prop)){
result = await this.account.vm.throw_error({type: "ValueError", message: "Cannot subset a void value"})
} else if(this.type === 'function'){
result = await this.get_(prop)
} else if (this.type === 'twain'){
result = await this.get_(prop)
}else if (options.obj && options.obj.type === 'number' && ['array', 'string'].includes(this.type)){
if (this.type === 'array')
result = await this.index(prop)
else {
result = await this.call('index', {
chain: this.account.chain,
call_config: {arguments: [options.config], location: this.spawn_address()}
})
}
} else if (!prop.includes('/')){
if (this.methods[prop])
result = {
type: 'address',
value: prop,
object: this.ref()
}
if (['function', 'class'].includes(this.type)){
result.config = true;
}
}
}else if(this.type === 'instance'){
result = await this.get_(obj? await obj.literal() :prop)
} else if(this.type === 'folder'){
result = await this.get_(obj? await obj.literal() : prop)
}
if (!result && !raw){
result = await this.account.vm.statics({type:'void'})
}
return result
}
set = async(prop, value, options)=>{
let {chain} = options;
if (this.type === 'twain'){
await this.call('set', {call_config: {arguments: [prop, value], location: this.spawn_address()}, chain})
}else if(this.type === 'instance' || this.type === 'function'){
return await this.set_(prop, value)
}
}
chain =async ()=>{
if (this.chn || !this.address)return this.chn;
this.chn = await this.account.chain.chain(this.address)
return this.chn
}
sync = async()=>{
return this
}
spawn_address = (spw)=>{
return `${this.address}_${spw || Math.random().toString().slice(3)}`
}
_split_datapath = (datapath)=>{
datapath = datapath.split('/')
return [datapath.slice(0,-1).join('/'), datapath.slice(-1)[0]]
}
to_address = async()=>{
let o = {
type: 'address',
value: this.address || this.config.location,
_id: this.config._id,
}
if (this.value && this.value.object) o.object = this.value.object
if (['function', 'class'].includes(this.type)){
o.config = true
o.value = this.config.address
}
o.module = this.config.module
if (this.is_literal) {
o.is_literal = true
}
return o
}
sync = async()=>{
return this
}
}
export default Storage;