125 lines
3.3 KiB
Nim
125 lines
3.3 KiB
Nim
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
|
# SPDX-License-Identifier: Unlicense
|
|
|
|
import
|
|
std/critbits,
|
|
min,
|
|
preserves
|
|
|
|
proc toMin(i: In; pr: sink Value): MinValue =
|
|
case pr.kind
|
|
of pkBoolean:
|
|
result = pr.bool.newVal
|
|
of pkFloat:
|
|
result = pr.float.newVal
|
|
of pkRegister:
|
|
result = pr.register.newVal
|
|
of pkBigInt:
|
|
raiseAssert "big integers not supported by Min bindings"
|
|
of pkString:
|
|
result = pr.string.newVal
|
|
of pkByteString:
|
|
result = newDict(i.scope)
|
|
result.objType = "preserves-bytestring"
|
|
i.dset(result, "bytes", cast[string](pr.bytes).newVal)
|
|
of pkSymbol:
|
|
result = pr.symbol.string.newSym
|
|
|
|
of pkRecord:
|
|
result = newDict(i.scope)
|
|
result.objType = "preserves-record"
|
|
var fields = newSeq[MinValue](pr.record.len.pred)
|
|
for j, _ in fields:
|
|
fields[j] = i.toMin pr.record[j].move
|
|
i.dset(result, "fields", fields.newVal)
|
|
i.dset(result, "label", i.toMin pr.record[pr.record.high].move)
|
|
of pkSequence:
|
|
var entries = newSeq[MinValue](pr.sequence.len)
|
|
for j, _ in pr.sequence:
|
|
entries[j] = i.toMin pr.sequence[j].move
|
|
result = entries.newVal
|
|
of pkSet:
|
|
result = newDict(i.scope)
|
|
result.objType = "preserves-set"
|
|
var set = newSeq[MinValue](pr.set.len)
|
|
for j, _ in pr.set:
|
|
set[j] = i.toMin pr.set[j].move
|
|
i.dset(result, "set", set.newVal)
|
|
of pkDictionary:
|
|
result = newDict(i.scope)
|
|
result.objType = "preserves-dictionary"
|
|
for (k, v) in pr.dict.mitems:
|
|
i.dset(result, i.toMin k.move, i.toMin v.move)
|
|
|
|
of pkEmbedded:
|
|
result = newDict(i.scope)
|
|
result.objType = "preserves-embedded"
|
|
result.obj = pr.embeddedRef[].addr
|
|
|
|
proc toPreserves(i: In; val: MinValue): Value =
|
|
case val.kind
|
|
of minInt:
|
|
result = val.intVal.toPreserves
|
|
of minFloat:
|
|
result = val.floatVal.toPreserves
|
|
of minQuotation:
|
|
result = initSequence val.qVal.len
|
|
for j, v in val.qVal:
|
|
result.sequence[j] = i.toPreserves v
|
|
of minCommand:
|
|
discard
|
|
of minDictionary:
|
|
case val.objType
|
|
of "preserves-record":
|
|
let fields = i.dget(val, "fields")
|
|
result = initRecord(
|
|
i.toPreserves i.dget(val, "label"),
|
|
fields.qVal.len,
|
|
)
|
|
for j, f in fields.qVal:
|
|
result.record[j] = i.toPreserves f
|
|
of "preserves-set":
|
|
result = initSet()
|
|
for e in i.dget(val, "set").qVal:
|
|
result.incl i.toPreserves e
|
|
else:
|
|
result = initDictionary()
|
|
for k, v in val.dVal.pairs:
|
|
result[toSymbol k] = i.toPreserves v.val
|
|
of minString:
|
|
result = val.strVal.toPreserves
|
|
of minSymbol:
|
|
result = val.symVal.Symbol.toPreserves
|
|
of minNull:
|
|
result = initRecord"null"
|
|
of minBool:
|
|
result = val.boolVal.toPreserves
|
|
|
|
proc preserves_module*(i: In) =
|
|
let def = i.define()
|
|
|
|
def.symbol("from-preserves") do (i: In):
|
|
let vals = i.expect("str")
|
|
let s = vals[0].getString()
|
|
try:
|
|
var pr: Value
|
|
if s[0].ord < 0x20:
|
|
pr = decodePreserves s
|
|
else:
|
|
pr = parsePreserves s
|
|
i.push(i.toMin pr)
|
|
except CatchableError as err:
|
|
raiseInvalid(err.msg)
|
|
|
|
def.symbol("to-text") do (i: In):
|
|
let vals = i.expect("a")
|
|
var pr = i.toPreserves vals[0]
|
|
i.push ($pr).newVal
|
|
|
|
def.symbol("to-binary") do (i: In):
|
|
let vals = i.expect("a")
|
|
var pr = i.toPreserves vals[0]
|
|
i.push cast[string](pr.encode).newVal
|
|
|
|
def.finalize("preserves")
|