From a8373e37c680eaa8e4117f8fab5c337a91ddd685 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Mon, 1 Nov 2021 10:35:14 +0100 Subject: [PATCH] Add Spry VM module http://sprylang.se/ --- src/preserves/sprypreserves.nim | 137 ++++++++++++++++++++++++++++ src/preserves/sprypreserves.nim.cfg | 2 + upstream | 2 +- 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 src/preserves/sprypreserves.nim create mode 100644 src/preserves/sprypreserves.nim.cfg diff --git a/src/preserves/sprypreserves.nim b/src/preserves/sprypreserves.nim new file mode 100644 index 0000000..f2e9cc0 --- /dev/null +++ b/src/preserves/sprypreserves.nim @@ -0,0 +1,137 @@ +# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway +# SPDX-License-Identifier: Unlicense + +import std/[sequtils, tables] + +import spryvm/spryvm + +import preserves, preserves/parse + +type + PreservesNode* = ref object of Value + preserve: Preserve[void] + EmbeddedNode* = ref object of PreservesNode + ByteStringNode* = ref object of StringVal + RecordNode* = ref object of Blok + SetNode = ref object of PreservesNode + +method eval*(self: PreservesNode; spry: Interpreter): Node = + self + +method `$`*(self: PreservesNode): string = + $self.preserve + +method typeName*(self: PreservesNode): string = + "preserves-value" + +method typeName*(self: EmbeddedNode): string = + "preserves-embedded-value" + +method typeName*(self: ByteStringNode): string = + "preserves-bytestring" + +method typeName*(self: RecordNode): string = + "preserves-record" + +method typeName*(self: SetNode): string = + "preserves-set" + +proc toSpry(pr: Preserve[void], spry: Interpreter): Node = + if pr.embedded: + result = EmbeddedNode(preserve: pr) + # TODO: need to be able to manipulate these + else: + case pr.kind + of pkBoolean: + result = boolVal(pr.bool, spry) + of pkFloat: + result = newValue(pr.float) + of pkDouble: + result = newValue(pr.double) + of pkSignedInteger: + result = newValue(int pr.int) + of pkBigInteger: discard + of pkString: + result = newValue(pr.string) + of pkByteString: + result = ByteStringNode(value: cast[string](pr.bytes)) + of pkSymbol: + result = + if pr.symbol == "null": newNilVal() + else: newLitWord(spry, pr.symbol) + of pkRecord: + var comp = RecordNode() + proc f(pr: Preserve[void]): Node = toSpry(pr, spry) + comp.nodes = map(pr.record, f) + result = comp + of pkSequence: + var blk = newBlok() + for e in pr.sequence: blk.add toSpry(e, spry) + result = blk + of pkSet: + result = SetNode(preserve: pr) + of pkDictionary: + var map = newMap() + for (key, val) in pr.dict.items: + map[toSpry(key, spry)] = toSpry(val, spry) + result = map + of pkEmbedded: + result = EmbeddedNode(preserve: pr) + +proc toPreserveHook*(node: Node; E: typedesc): Preserve[E] = + if node of PreservesNode: + result = PreservesNode(node).preserve + elif node of RecordNode: + result = Preserve[E](kind: pkRecord) + var comp = RecordNode(node) + proc f(child: Node): Preserve[void] = toPreserve(child, void) + result.record = map(comp.nodes, f) + elif node of ByteStringNode: + result = toPreserve(cast[seq[byte]](ByteStringNode(node).value), E) + elif node of Blok: + var blk = Blok(node) + result = initSequence[E](blk.nodes.len) + for i, child in blk.nodes: result.sequence[i] = toPreserve(child, E) + elif node of Map: + result = initDictionary[E]() + for key, val in Map(node).bindings: + result[toPreserve(key, E)] = toPreserve(val, E) + elif node of StringVal: + result = toPreserve(StringVal(node).value, E) + elif node of LitWord: + result = toSymbol(LitWord(node).word, E) + elif node of IntVal: + result = toPreserve(IntVal(node).value, E) + elif node of FloatVal: + result = toPreserve(FloatVal(node).value, E) + elif node of BoolVal: + result = toPreserve(BoolVal(node).value, E) + else: # node of NilVal: + result = toSymbol("null", E) + +when isMainModule: + var + node: Node + pr = toPreserveHook(node, void) + +proc addPreserves*(spry: Interpreter) = + nimFunc("parsePreserves"): + let str = StringVal(evalArg(spry)).value + PreservesNode(preserve: parsePreserves(str)) + nimFunc("fromPreserves"): + let node = evalArg(spry) + if node of PreservesNode: + let pr = PreservesNode(node).preserve + return toSpry(pr, spry) + nimMeth("toPreserves"): + let node = evalArgInfix(spry) + PreservesNode(preserve: node.toPreserve) + nimMeth("arity"): + let node = evalArgInfix(spry) + if node of RecordNode: + return newValue(pred SeqComposite(node).nodes.len) + nimMeth("label"): + let node = evalArgInfix(spry) + if node of RecordNode: + let rec = RecordNode(node) + return rec.nodes[rec.nodes.high] diff --git a/src/preserves/sprypreserves.nim.cfg b/src/preserves/sprypreserves.nim.cfg new file mode 100644 index 0000000..45b2143 --- /dev/null +++ b/src/preserves/sprypreserves.nim.cfg @@ -0,0 +1,2 @@ +multimethods:on +nilseqs:on diff --git a/upstream b/upstream index b2c3032..2ff489d 160000 --- a/upstream +++ b/upstream @@ -1 +1 @@ -Subproject commit b2c3032e7a9c5157aaea88a77be83438b7a23c58 +Subproject commit 2ff489d9753169ef57446d22cfd4722ca1264e2e