Add Tox-based Spry interpreter
This commit is contained in:
parent
358a7389a3
commit
fbf62c53ac
|
@ -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
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ description = "Sets of named blobs"
|
||||||
license = "AGPLv3"
|
license = "AGPLv3"
|
||||||
srcDir = "src"
|
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"]
|
bin = @["blobset", "blobserver"]
|
||||||
skipFiles = @["blobset.nim", "blobserver.nim"]
|
skipFiles = @["blobset.nim", "blobserver.nim"]
|
||||||
|
|
102
src/blobset.nim
102
src/blobset.nim
|
@ -6,13 +6,16 @@ import cbor
|
||||||
import ./blobsets, ./blobsets/filestores,
|
import ./blobsets, ./blobsets/filestores,
|
||||||
./blobsets/httpservers, ./blobsets/httpstores
|
./blobsets/httpservers, ./blobsets/httpstores
|
||||||
|
|
||||||
|
when defined(tox):
|
||||||
|
import toxcore
|
||||||
|
|
||||||
# Basic Spry
|
# Basic Spry
|
||||||
when defined(spry):
|
when defined(spry):
|
||||||
import spryvm/spryvm
|
import spryvm/spryvm
|
||||||
|
|
||||||
# Spry extra modules
|
# Spry extra modules
|
||||||
import spryvm/sprycore, spryvm/spryextend, spryvm/sprymath, spryvm/spryos, spryvm/spryio,
|
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,
|
spryvm/spryblock,
|
||||||
./blobsets/spryblobs
|
./blobsets/spryblobs
|
||||||
|
|
||||||
|
@ -20,18 +23,77 @@ import os, strutils
|
||||||
when defined(readLine):
|
when defined(readLine):
|
||||||
import rdstdin, linenoise
|
import rdstdin, linenoise
|
||||||
|
|
||||||
#when defined(genode):
|
|
||||||
# import dagfsclient
|
|
||||||
|
|
||||||
#else:
|
|
||||||
# import ./blobsets/tcp
|
|
||||||
|
|
||||||
proc openStore(): BlobStore =
|
proc openStore(): BlobStore =
|
||||||
const key = "BLOB_STORE_URL"
|
const key = "BLOB_STORE_URL"
|
||||||
let url = os.getEnv key
|
var url = os.getEnv key
|
||||||
if url == "":
|
if url == "":
|
||||||
quit(key & " not set in environment")
|
url = "/tmp/blobs"
|
||||||
newHttpStore(url)
|
#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] =
|
proc serverMain(): Future[void] =
|
||||||
let
|
let
|
||||||
|
@ -835,19 +897,7 @@ proc getLine(prompt: string): string =
|
||||||
|
|
||||||
when defined(spry):
|
when defined(spry):
|
||||||
proc spryMain() =
|
proc spryMain() =
|
||||||
let spry = newInterpreter()
|
let spry = newSpry(openStore())
|
||||||
spry.addCore()
|
|
||||||
spry.addExtend()
|
|
||||||
spry.addMath()
|
|
||||||
spry.addOS()
|
|
||||||
spry.addIO()
|
|
||||||
spry.addOO()
|
|
||||||
spry.addString()
|
|
||||||
spry.addModules()
|
|
||||||
spry.addReflect()
|
|
||||||
spry.addMemfile()
|
|
||||||
spry.addBlock()
|
|
||||||
spry.addBlobSets()
|
|
||||||
var
|
var
|
||||||
lines, stashed, fileLines = newSeq[string]()
|
lines, stashed, fileLines = newSeq[string]()
|
||||||
suspended: bool = true
|
suspended: bool = true
|
||||||
|
@ -926,4 +976,10 @@ when isMainModule:
|
||||||
quit "not compiled with Spry interpreter"
|
quit "not compiled with Spry interpreter"
|
||||||
of "check": waitFor checkMain()
|
of "check": waitFor checkMain()
|
||||||
of "replicate": waitFor replicateMain()
|
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)
|
else: quit("no such subcommand " & cmd)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
# Disable this to use only primitive stdin
|
# Disable this to use only primitive stdin
|
||||||
-d:readLine
|
-d:readLine
|
||||||
--nilseqs:on
|
--nilseqs:on
|
||||||
|
-d:spry
|
||||||
|
-d:tox
|
||||||
|
|
|
@ -10,10 +10,10 @@ type BlobIdSpryNode* = ref object of Value
|
||||||
type BlobSetSpryNode* = ref object of Value
|
type BlobSetSpryNode* = ref object of Value
|
||||||
set*: BlobSet
|
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: BlobIdSpryNode): string = $self.id
|
||||||
|
|
||||||
method `$`*(self: BlobSetSpryNode): string = "<BlobSet>"
|
method `$`*(self: BlobSetSpryNode): string = "<BlobSet>"
|
||||||
|
|
||||||
type BlobStoreNode* = ref object of Value
|
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 =
|
proc insertPath(store: BlobStore; bs: BlobSet; kind: PathComponent; path: string): BlobSet =
|
||||||
result = bs
|
result = bs
|
||||||
try:
|
case kind
|
||||||
case kind
|
of pcFile, pcLinkToFile:
|
||||||
of pcFile, pcLinkToFile:
|
var path = normalizedPath path
|
||||||
var path = normalizedPath path
|
let (id, size) = waitFor store.ingestFile(path)
|
||||||
let (id, size) = waitFor store.ingestFile(path)
|
path.removePrefix(getCurrentDir())
|
||||||
path.removePrefix(getCurrentDir())
|
path.removePrefix("/")
|
||||||
path.removePrefix("/")
|
result = waitFor insert(store, result, path, id, size)
|
||||||
result = waitFor insert(store, result, path, id, size)
|
of pcDir, pcLinkToDir:
|
||||||
writeLine(stdout, id, align($size, 11), " ", path)
|
for kind, subPath in path.walkDir:
|
||||||
of pcDir, pcLinkToDir:
|
result = store.insertPath(result, kind, subPath)
|
||||||
for kind, subPath in path.walkDir:
|
|
||||||
result = store.insertPath(result, kind, subPath)
|
|
||||||
except:
|
|
||||||
let e = getCurrentException()
|
|
||||||
writeLine(stderr, "failed to ingest '", path, "', ", e.msg)
|
|
||||||
|
|
||||||
proc getSet(env: BlobStoreNode; path: string): BlobSet =
|
proc getSet(env: BlobStoreNode; path: string): BlobSet =
|
||||||
result = env.sets.getOrDefault(path)
|
result = env.sets.getOrDefault(path)
|
||||||
|
@ -53,41 +48,48 @@ proc ingestBlobs(env: BlobStoreNode; path: string): BlobSetSpryNode =
|
||||||
BlobSetSpryNode(set: bs)
|
BlobSetSpryNode(set: bs)
|
||||||
|
|
||||||
# Spry Blobset module
|
# Spry Blobset module
|
||||||
proc addBlobSets*(spry: Interpreter) =
|
proc addBlobSets*(spry: Interpreter; store: BlobStore) =
|
||||||
|
|
||||||
nimMeth "ingestBlobs":
|
let env = BlobStoreNode(
|
||||||
var env = BlobStoreNode(evalArgInfix(spry))
|
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
|
let path = StringVal(evalArg(spry)).value
|
||||||
result = ingestBlobs(env, path)
|
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":
|
nimFunc "toBlobId":
|
||||||
let str = StringVal(evalArg(spry)).value
|
let str = StringVal(evalArg(spry)).value
|
||||||
BlobIdSpryNode(id: str.toBlobId)
|
BlobIdSpryNode(id: str.toBlobId)
|
||||||
|
|
||||||
nimFunc "cbor":
|
nimFunc "blobCbor":
|
||||||
let set = BlobSetSpryNode(evalArg(spry)).set
|
let set = BlobSetSpryNode(evalArg(spry)).set
|
||||||
newValue($toCbor(set))
|
newValue($toCbor(set))
|
||||||
|
|
||||||
nimFunc "commit":
|
nimFunc "blobCommit":
|
||||||
let
|
let
|
||||||
env = BlobStoreNode(evalArgInfix(spry))
|
setNode = BlobSetSpryNode(evalArg(spry))
|
||||||
set = BlobSetSpryNode(evalArg(spry)).set
|
coldSet = waitFor env.store.commit(setNode.set)
|
||||||
BlobSetSpryNode(set: waitFor env.store.commit(set))
|
BlobIdSpryNode(id: coldSet.setId)
|
||||||
|
|
||||||
nimFunc "hex":
|
nimFunc "blobHex":
|
||||||
let id = BlobIdSpryNode(evalArg(spry)).id
|
let id = BlobIdSpryNode(evalArg(spry)).id
|
||||||
newValue(id.toHex)
|
newValue(id.toHex)
|
||||||
|
|
||||||
#nimFunc "key":
|
nimFunc "key":
|
||||||
# let str = StringVal(evalArg(spry)).value
|
let str = StringVal(evalArg(spry)).value
|
||||||
# newValue(str.toKey)
|
newValue(str.toKey.int)
|
||||||
|
|
Loading…
Reference in New Issue