From e572357dcbe252688342d344e46339e97cae0472 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Tue, 23 Apr 2024 14:41:00 +0200 Subject: [PATCH] Impement Preserves decoding and encoding in Nim --- min_syndicate.nimble | 9 +++ pkg/min_preserves.nim | 124 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 min_syndicate.nimble create mode 100644 pkg/min_preserves.nim diff --git a/min_syndicate.nimble b/min_syndicate.nimble new file mode 100644 index 0000000..0c77cec --- /dev/null +++ b/min_syndicate.nimble @@ -0,0 +1,9 @@ +# Package +version = "20240423" +author = "Emery Hemingway" +description = "Syndicate bindings for the Min language" +license = "unlicense" +bin = @["mindicate"] +srcDir = "pkg" + +requires "min >= 0.40.0", "http://git.syndicate-lang.org/ehmry/syndicate-nim.git >= 20240422" diff --git a/pkg/min_preserves.nim b/pkg/min_preserves.nim new file mode 100644 index 0000000..816c2ea --- /dev/null +++ b/pkg/min_preserves.nim @@ -0,0 +1,124 @@ +# 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")