Add Tox-based Spry interpreter

This commit is contained in:
Ehmry - 2019-06-05 19:41:36 +02:00
parent 358a7389a3
commit fbf62c53ac
5 changed files with 139 additions and 63 deletions

16
blobs.sy Normal file
View File

@ -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
}

View File

@ -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"]

View File

@ -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)

View File

@ -1,3 +1,5 @@
# Disable this to use only primitive stdin
-d:readLine
--nilseqs:on
-d:spry
-d:tox

View File

@ -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 = "<BlobSet>"
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)