From fbf62c53accf74b086530d5754af8d45dc8ecd32 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Wed, 5 Jun 2019 19:41:36 +0200 Subject: [PATCH] Add Tox-based Spry interpreter --- blobs.sy | 16 ++++++ blobsets.nimble | 2 +- src/blobset.nim | 102 ++++++++++++++++++++++++++++--------- src/blobset.nim.cfg | 2 + src/blobsets/spryblobs.nim | 80 +++++++++++++++-------------- 5 files changed, 139 insertions(+), 63 deletions(-) create mode 100644 blobs.sy diff --git a/blobs.sy b/blobs.sy new file mode 100644 index 0000000..6edf83e --- /dev/null +++ b/blobs.sy @@ -0,0 +1,16 @@ +{ + _meta = { + name = 'Blobs + version = "1.0" + description = "Blobs module" + } + + cbor = $..blobCbor + commit = $..blobCommit + hex = $..blobHex + ingest = $..blobIngest + key = $..key + load = $..blobLoad + merge = $..blobMerge + toBlobId = $..toBlobId +} diff --git a/blobsets.nimble b/blobsets.nimble index a229ea0..ba31766 100644 --- a/blobsets.nimble +++ b/blobsets.nimble @@ -6,7 +6,7 @@ description = "Sets of named blobs" license = "AGPLv3" srcDir = "src" -requires "nim >= 0.18.0", "cbor >= 0.5.2", "siphash", "spryvm" +requires "nim >= 0.18.0", "cbor >= 0.5.2", "siphash", "spryvm", "toxcore" bin = @["blobset", "blobserver"] skipFiles = @["blobset.nim", "blobserver.nim"] diff --git a/src/blobset.nim b/src/blobset.nim index 8ad04ae..1c832a7 100644 --- a/src/blobset.nim +++ b/src/blobset.nim @@ -6,13 +6,16 @@ import cbor import ./blobsets, ./blobsets/filestores, ./blobsets/httpservers, ./blobsets/httpstores +when defined(tox): + import toxcore + # Basic Spry when defined(spry): import spryvm/spryvm # Spry extra modules import spryvm/sprycore, spryvm/spryextend, spryvm/sprymath, spryvm/spryos, spryvm/spryio, - spryvm/spryoo, spryvm/sprystring, spryvm/sprymodules, spryvm/spryreflect, spryvm /sprymemfile, + spryvm/spryoo, spryvm/sprystring, spryvm/sprymodules, spryvm/spryreflect, spryvm/sprymemfile, spryvm/spryblock, ./blobsets/spryblobs @@ -20,18 +23,77 @@ import os, strutils when defined(readLine): import rdstdin, linenoise -#when defined(genode): -# import dagfsclient - -#else: -# import ./blobsets/tcp - proc openStore(): BlobStore = const key = "BLOB_STORE_URL" - let url = os.getEnv key + var url = os.getEnv key if url == "": - quit(key & " not set in environment") - newHttpStore(url) + url = "/tmp/blobs" + #quit(key & " not set in environment") + if url.startsWith "http://": + newHttpStore(url) + else: + newFileStore(url) + +when defined(spry): + proc newSpry(store: BlobStore): Interpreter = + result = newInterpreter() + result.addCore() + result.addExtend() + result.addMath() + result.addOS() + result.addIO() + result.addOO() + result.addString() + result.addModules() + result.addReflect() + result.addMemfile() + result.addBlock() + result.addBlobSets(store) + discard result.evalRoot("""[loadFile: "blobs.sy"]""") + +when defined(tox) and defined(spry): + proc setupCallbacks(tox: Tox) = + tox.onSelfConnectionStatus do (status: TOX_CONNECTION): + echo "self status is ", status + let + store = openStore() + spry = newSpry(store) + proc eval(code: string): string {.gcsafe.} = + $(spry.evalRoot(code)) + tox.onFriendMessage do (friend: Friend; msg: string; kind: TOX_MESSAGE_TYPE): + try: + if kind == TOX_MESSAGE_TYPE_NORMAL: + tox.typing(friend, true) + let res = eval("[" & msg & "]") + tox.typing(friend, false) + discard tox.send(friend, $res, TOX_MESSAGE_TYPE_ACTION) + except: + discard tox.send(friend, getCurrentExceptionMsg()) + + tox.onFriendRequest do (key: PublicKey; msg: string): + echo "friend request from ", key, ", ", msg + discard tox.addFriendNoRequest(key) + tox.name = "blobbot" + echo "callbacks set" + echo "Tox address: ", tox.address + echo "Tox DHT: ", tox.udpPort, " ", tox.dhtId + + proc toxMain() {.async.} = + let tox = newTox do (o: Options): + o.ipv6Enabled = false + o.localDiscoveryEnabled = true + o.holePunchingEnabled = false + var saveData = "" + try: saveData = readFile "tox.save" + except: discard + if saveData != "": + o.saveData = saveData + o.saveDataType = TOX_SAVEDATA_TYPE_TOX_SAVE + writeFile "tox.save", tox.saveData + setupCallbacks(tox) + while not tox.isClosed: + iterate tox + await sleepAsync(tox.iterationInterval) proc serverMain(): Future[void] = let @@ -835,19 +897,7 @@ proc getLine(prompt: string): string = when defined(spry): proc spryMain() = - let spry = newInterpreter() - spry.addCore() - spry.addExtend() - spry.addMath() - spry.addOS() - spry.addIO() - spry.addOO() - spry.addString() - spry.addModules() - spry.addReflect() - spry.addMemfile() - spry.addBlock() - spry.addBlobSets() + let spry = newSpry(openStore()) var lines, stashed, fileLines = newSeq[string]() suspended: bool = true @@ -926,4 +976,10 @@ when isMainModule: quit "not compiled with Spry interpreter" of "check": waitFor checkMain() of "replicate": waitFor replicateMain() + of "tox": + when defined(tox) and defined(spry): + #waitFor toxReplicateMain() + waitFor toxMain() + else: + quit "not compiled with Tox node" else: quit("no such subcommand " & cmd) diff --git a/src/blobset.nim.cfg b/src/blobset.nim.cfg index 9d3df17..06ab0dd 100644 --- a/src/blobset.nim.cfg +++ b/src/blobset.nim.cfg @@ -1,3 +1,5 @@ # Disable this to use only primitive stdin -d:readLine --nilseqs:on +-d:spry +-d:tox diff --git a/src/blobsets/spryblobs.nim b/src/blobsets/spryblobs.nim index 5c2bd96..81f4c1d 100644 --- a/src/blobsets/spryblobs.nim +++ b/src/blobsets/spryblobs.nim @@ -10,10 +10,10 @@ type BlobIdSpryNode* = ref object of Value type BlobSetSpryNode* = ref object of Value set*: BlobSet -method eval*(self: BlobIdSpryNode|BlobSetSpryNode; spry: Interpreter): Node = self +method eval*(self: BlobIdSpryNode; spry: Interpreter): Node = self +method eval*(self: BlobSetSpryNode; spry: Interpreter): Node = self method `$`*(self: BlobIdSpryNode): string = $self.id - method `$`*(self: BlobSetSpryNode): string = "" type BlobStoreNode* = ref object of Value @@ -24,21 +24,16 @@ type BlobStoreNode* = ref object of Value proc insertPath(store: BlobStore; bs: BlobSet; kind: PathComponent; path: string): BlobSet = result = bs - try: - case kind - of pcFile, pcLinkToFile: - var path = normalizedPath path - let (id, size) = waitFor store.ingestFile(path) - path.removePrefix(getCurrentDir()) - path.removePrefix("/") - result = waitFor insert(store, result, path, id, size) - writeLine(stdout, id, align($size, 11), " ", path) - of pcDir, pcLinkToDir: - for kind, subPath in path.walkDir: - result = store.insertPath(result, kind, subPath) - except: - let e = getCurrentException() - writeLine(stderr, "failed to ingest '", path, "', ", e.msg) + case kind + of pcFile, pcLinkToFile: + var path = normalizedPath path + let (id, size) = waitFor store.ingestFile(path) + path.removePrefix(getCurrentDir()) + path.removePrefix("/") + result = waitFor insert(store, result, path, id, size) + of pcDir, pcLinkToDir: + for kind, subPath in path.walkDir: + result = store.insertPath(result, kind, subPath) proc getSet(env: BlobStoreNode; path: string): BlobSet = result = env.sets.getOrDefault(path) @@ -53,41 +48,48 @@ proc ingestBlobs(env: BlobStoreNode; path: string): BlobSetSpryNode = BlobSetSpryNode(set: bs) # Spry Blobset module -proc addBlobSets*(spry: Interpreter) = +proc addBlobSets*(spry: Interpreter; store: BlobStore) = - nimMeth "ingestBlobs": - var env = BlobStoreNode(evalArgInfix(spry)) + let env = BlobStoreNode( + store: store, + blobs: initTable[string, tuple[id: BlobId, size: BiggestInt]](), + sets: initTable[string, BlobSet]()) + + nimMeth "blobMerge": + let + a = BlobSetSpryNode(evalArgInfix(spry)) + b = BlobSetSpryNode(evalArg(spry)) + c = env.store.union(a.set, b.set) + BlobSetSpryNode(set: c) + + nimFunc "blobLoad": + let + node = BlobIdSpryNode(evalArg(spry)) + set = waitFor env.store.load(node.id) + BlobSetSpryNode(set: set) + + nimFunc "blobIngest": let path = StringVal(evalArg(spry)).value result = ingestBlobs(env, path) - nimFunc "newBlobStore": - proc newStore(s: string): BlobStore = - if s.startsWith "http://": newHttpStore(s) - else: newFileStore(s) - let arg = StringVal(evalArg(spry)).value - BlobStoreNode( - store: newStore(arg), - blobs: initTable[string, tuple[id: BlobId, size: BiggestInt]](), - sets: initTable[string, BlobSet]()) - nimFunc "toBlobId": let str = StringVal(evalArg(spry)).value BlobIdSpryNode(id: str.toBlobId) - nimFunc "cbor": + nimFunc "blobCbor": let set = BlobSetSpryNode(evalArg(spry)).set newValue($toCbor(set)) - nimFunc "commit": + nimFunc "blobCommit": let - env = BlobStoreNode(evalArgInfix(spry)) - set = BlobSetSpryNode(evalArg(spry)).set - BlobSetSpryNode(set: waitFor env.store.commit(set)) + setNode = BlobSetSpryNode(evalArg(spry)) + coldSet = waitFor env.store.commit(setNode.set) + BlobIdSpryNode(id: coldSet.setId) - nimFunc "hex": + nimFunc "blobHex": let id = BlobIdSpryNode(evalArg(spry)).id newValue(id.toHex) - #nimFunc "key": - # let str = StringVal(evalArg(spry)).value - # newValue(str.toKey) + nimFunc "key": + let str = StringVal(evalArg(spry)).value + newValue(str.toKey.int)