From 0d815a8b79ea3eb02025999f9f83d5aaa72850f1 Mon Sep 17 00:00:00 2001 From: mikera Date: Mon, 2 Dec 2024 23:15:07 +0000 Subject: [PATCH] Refactor Do op as dense record --- .../src/main/java/convex/core/cvm/CVMTag.java | 7 ++- .../src/main/java/convex/core/cvm/Ops.java | 10 +-- .../convex/core/cvm/ops/AFlatMultiOp.java | 61 +++++++++++++++++++ .../java/convex/core/cvm/ops/AMultiOp.java | 5 +- .../main/java/convex/core/cvm/ops/Cond.java | 4 +- .../src/main/java/convex/core/cvm/ops/Do.java | 34 +++++------ .../main/java/convex/core/cvm/ops/Invoke.java | 2 +- .../main/java/convex/core/cvm/ops/Let.java | 2 +- .../main/java/convex/core/cvm/ops/Query.java | 2 +- .../main/java/convex/core/cvm/ops/Try.java | 4 +- .../main/java/convex/core/data/Format.java | 6 ++ .../java/convex/core/data/ObjectsTest.java | 2 +- .../test/java/convex/core/lang/OpsTest.java | 24 +++++++- 13 files changed, 126 insertions(+), 37 deletions(-) create mode 100644 convex-core/src/main/java/convex/core/cvm/ops/AFlatMultiOp.java diff --git a/convex-core/src/main/java/convex/core/cvm/CVMTag.java b/convex-core/src/main/java/convex/core/cvm/CVMTag.java index af7414390..12968832e 100644 --- a/convex-core/src/main/java/convex/core/cvm/CVMTag.java +++ b/convex-core/src/main/java/convex/core/cvm/CVMTag.java @@ -50,6 +50,8 @@ public class CVMTag { public static final byte PEER_STATUS = (byte) 0xD9; + // Some ops in here + public static final byte RESULT = (byte)0xDD; // transaction result public static final byte BLOCK_RESULT = (byte) 0xDE; @@ -81,7 +83,10 @@ public class CVMTag { public static final byte OP_DEF = (byte) 0xCD; - + public static final byte OP_DO = (byte)0xDA; // (do ...) + public static final byte OP_INVOKE = (byte)0xDB; // (...) - function Invoke + public static final byte OP_COND = (byte)0xDB; // (cond ...) + public static final byte FN = (byte) 0xCF; diff --git a/convex-core/src/main/java/convex/core/cvm/Ops.java b/convex-core/src/main/java/convex/core/cvm/Ops.java index 67a41d4b8..ac2f09bf6 100644 --- a/convex-core/src/main/java/convex/core/cvm/Ops.java +++ b/convex-core/src/main/java/convex/core/cvm/Ops.java @@ -2,13 +2,13 @@ import convex.core.cvm.ops.Cond; import convex.core.cvm.ops.Constant; -import convex.core.cvm.ops.Do; import convex.core.cvm.ops.Invoke; import convex.core.cvm.ops.Lambda; import convex.core.cvm.ops.Let; import convex.core.cvm.ops.Lookup; import convex.core.cvm.ops.Query; import convex.core.cvm.ops.Set; +import convex.core.cvm.ops.Try; import convex.core.data.ACell; import convex.core.data.Blob; import convex.core.exceptions.BadFormatException; @@ -23,7 +23,7 @@ public class Ops { public static final byte CONSTANT = 0; public static final byte INVOKE = 1; public static final byte COND = 2; - public static final byte DO = 3; + public static final byte TRY = 3; public static final byte LET = 4; public static final byte LOOP = 5; public static final byte DEF = 6; @@ -62,8 +62,8 @@ public static AOp read(byte tag, Blob b, int pos) throws Ba return Invoke.read(b,pos); case Ops.COND: return Cond.read(b,pos); - case Ops.DO: - return Do.read(b,pos); + case Ops.TRY: + return Try.read(b,pos); case Ops.LOOKUP: return Lookup.read(b,pos); case Ops.LAMBDA: @@ -78,7 +78,7 @@ public static AOp read(byte tag, Blob b, int pos) throws Ba return Set.read(b,pos); default: - throw new BadFormatException("Invalide OpCode: " + opCode); + throw new BadFormatException("Invalide OpCode: " + opCode + " with tag "+tag); } } diff --git a/convex-core/src/main/java/convex/core/cvm/ops/AFlatMultiOp.java b/convex-core/src/main/java/convex/core/cvm/ops/AFlatMultiOp.java new file mode 100644 index 000000000..c9bf3eccd --- /dev/null +++ b/convex-core/src/main/java/convex/core/cvm/ops/AFlatMultiOp.java @@ -0,0 +1,61 @@ +package convex.core.cvm.ops; + +import convex.core.cvm.AOp; +import convex.core.data.ACell; +import convex.core.data.AVector; +import convex.core.data.IRefFunction; +import convex.core.data.Ref; +import convex.core.util.ErrorMessages; + +public abstract class AFlatMultiOp extends AMultiOp { + + protected final byte tag; + + protected AFlatMultiOp(byte tag, AVector> ops) { + super(ops); + this.tag=tag; + } + + @Override + public byte getTag() { + return tag; + } + + @Override + public byte opCode() { + // TODO remove from hierarchy + throw new Error(ErrorMessages.UNREACHABLE); + } + + @Override + public int encodeRaw(byte[] bs, int pos) { + int epos=pos; + epos=ops.encodeRaw(bs, epos); + return epos; + } + + @Override + public int encodeAfterOpcode(byte[] bs, int pos) { + throw new Error(ErrorMessages.UNREACHABLE); + } + + @Override + public final int getRefCount() { + return ops.getRefCount(); + } + + + @SuppressWarnings("unchecked") + @Override + public Ref getRef(int i) { + return ops.getRef(i); + } + + @Override + public final AFlatMultiOp updateRefs(IRefFunction func) { + AVector> newOps=(AVector>) ops.updateRefs(func); + return recreate(newOps); + } + + protected abstract AFlatMultiOp recreate(AVector> newOps); +} diff --git a/convex-core/src/main/java/convex/core/cvm/ops/AMultiOp.java b/convex-core/src/main/java/convex/core/cvm/ops/AMultiOp.java index ef13203aa..08103415b 100644 --- a/convex-core/src/main/java/convex/core/cvm/ops/AMultiOp.java +++ b/convex-core/src/main/java/convex/core/cvm/ops/AMultiOp.java @@ -2,7 +2,6 @@ import convex.core.cvm.AOp; import convex.core.data.ACell; -import convex.core.data.ASequence; import convex.core.data.AVector; import convex.core.data.Format; import convex.core.data.IRefFunction; @@ -30,7 +29,7 @@ protected AMultiOp(AVector> ops) { * @param newOps * @return */ - protected abstract AMultiOp recreate(ASequence> newOps); + protected abstract AMultiOp recreate(AVector> newOps); @Override public int encodeAfterOpcode(byte[] bs, int pos) { @@ -45,7 +44,7 @@ public int estimatedEncodingSize() { @Override public AMultiOp updateRefs(IRefFunction func) { - ASequence> newOps = ops.updateRefs(func); + AVector> newOps = ops.updateRefs(func); return recreate(newOps); } diff --git a/convex-core/src/main/java/convex/core/cvm/ops/Cond.java b/convex-core/src/main/java/convex/core/cvm/ops/Cond.java index eef79ed4a..4f27cf4b0 100644 --- a/convex-core/src/main/java/convex/core/cvm/ops/Cond.java +++ b/convex-core/src/main/java/convex/core/cvm/ops/Cond.java @@ -45,7 +45,7 @@ public static Cond create(AOp... ops) { } @Override - protected Cond recreate(ASequence> newOps) { + protected Cond recreate(AVector> newOps) { if (ops==newOps) return this; return new Cond(newOps.toVector()); } @@ -120,7 +120,7 @@ public static Cond read(Blob b, int pos) throws BadFormatEx @Override public Cond updateRefs(IRefFunction func) { - ASequence> newOps= ops.updateRefs(func); + AVector> newOps= ops.updateRefs(func); return recreate(newOps); } diff --git a/convex-core/src/main/java/convex/core/cvm/ops/Do.java b/convex-core/src/main/java/convex/core/cvm/ops/Do.java index 6fb503207..b07bbd72f 100644 --- a/convex-core/src/main/java/convex/core/cvm/ops/Do.java +++ b/convex-core/src/main/java/convex/core/cvm/ops/Do.java @@ -1,15 +1,14 @@ package convex.core.cvm.ops; import convex.core.cvm.AOp; +import convex.core.cvm.CVMTag; import convex.core.cvm.Context; import convex.core.cvm.Juice; -import convex.core.cvm.Ops; import convex.core.data.ACell; import convex.core.data.ASequence; import convex.core.data.AVector; import convex.core.data.Blob; import convex.core.data.Cells; -import convex.core.data.Format; import convex.core.data.Vectors; import convex.core.data.util.BlobBuilder; import convex.core.exceptions.BadFormatException; @@ -23,24 +22,18 @@ * * @param Result type of Do Op */ -public class Do extends AMultiOp { +public class Do extends AFlatMultiOp { public static final Do EMPTY = Do.create(); protected Do(AVector> ops) { - super(ops); + super(CVMTag.OP_DO,ops); } public static Do create(AOp... ops) { return new Do(Vectors.create(ops)); } - - @Override - protected Do recreate(ASequence> newOps) { - if (ops == newOps) return this; - return new Do(newOps.toVector()); - } - + public static Do create(ASequence> ops) { return new Do(ops.toVector()); } @@ -73,12 +66,7 @@ public boolean print(BlobBuilder bb, long limit) { bb.append(')'); return bb.check(limit); } - - @Override - public byte opCode() { - return Ops.DO; - } - + /** * Decodes a Do op from a Blob encoding * @@ -89,13 +77,21 @@ public byte opCode() { * @throws BadFormatException In the event of any encoding error */ public static Do read(Blob b, int pos) throws BadFormatException { - int epos=pos+Ops.OP_DATA_OFFSET; // skip tag and opcode to get to data + int epos=pos; - AVector> ops = Format.read(b,epos); + AVector> ops = Vectors.read(b, epos); epos+=Cells.getEncodingLength(ops); Do result=create(ops); result.attachEncoding(b.slice(pos, epos)); return result; } + + @Override + protected AFlatMultiOp recreate(AVector> newOps) { + if (newOps==ops) return this; + return new Do(newOps); + } + + } diff --git a/convex-core/src/main/java/convex/core/cvm/ops/Invoke.java b/convex-core/src/main/java/convex/core/cvm/ops/Invoke.java index b2dbe9ea8..dd2933470 100644 --- a/convex-core/src/main/java/convex/core/cvm/ops/Invoke.java +++ b/convex-core/src/main/java/convex/core/cvm/ops/Invoke.java @@ -59,7 +59,7 @@ public static , F extends AOp> Invo } @Override - protected Invoke recreate(ASequence> newOps) { + protected Invoke recreate(AVector> newOps) { if (ops == newOps) return this; return create(newOps); } diff --git a/convex-core/src/main/java/convex/core/cvm/ops/Let.java b/convex-core/src/main/java/convex/core/cvm/ops/Let.java index 393838164..86e736016 100644 --- a/convex-core/src/main/java/convex/core/cvm/ops/Let.java +++ b/convex-core/src/main/java/convex/core/cvm/ops/Let.java @@ -68,7 +68,7 @@ public final Ref getRef(int i) { } @Override - protected Let recreate(ASequence> newOps) { + protected Let recreate(AVector> newOps) { return recreate(newOps, symbols); } diff --git a/convex-core/src/main/java/convex/core/cvm/ops/Query.java b/convex-core/src/main/java/convex/core/cvm/ops/Query.java index 89832aa7c..2703b8fe3 100644 --- a/convex-core/src/main/java/convex/core/cvm/ops/Query.java +++ b/convex-core/src/main/java/convex/core/cvm/ops/Query.java @@ -35,7 +35,7 @@ public static Query create(AOp... ops) { } @Override - protected Query recreate(ASequence> newOps) { + protected Query recreate(AVector> newOps) { if (ops == newOps) return this; return new Query(newOps.toVector()); } diff --git a/convex-core/src/main/java/convex/core/cvm/ops/Try.java b/convex-core/src/main/java/convex/core/cvm/ops/Try.java index d8e1d8ed3..e1f863d0e 100644 --- a/convex-core/src/main/java/convex/core/cvm/ops/Try.java +++ b/convex-core/src/main/java/convex/core/cvm/ops/Try.java @@ -33,7 +33,7 @@ public static Try create(AOp... ops) { } @Override - protected Try recreate(ASequence> newOps) { + protected Try recreate(AVector> newOps) { if (ops == newOps) return this; return new Try(newOps.toVector()); } @@ -88,7 +88,7 @@ public boolean print(BlobBuilder bb, long limit) { @Override public byte opCode() { - return Ops.DO; + return Ops.TRY; } /** diff --git a/convex-core/src/main/java/convex/core/data/Format.java b/convex-core/src/main/java/convex/core/data/Format.java index 7c54a21bf..a4a2b9e54 100644 --- a/convex-core/src/main/java/convex/core/data/Format.java +++ b/convex-core/src/main/java/convex/core/data/Format.java @@ -24,6 +24,7 @@ import convex.core.cvm.State; import convex.core.cvm.Syntax; import convex.core.cvm.ops.Def; +import convex.core.cvm.ops.Do; import convex.core.cvm.ops.Local; import convex.core.cvm.ops.Special; import convex.core.cvm.transactions.Call; @@ -719,6 +720,11 @@ private static T readDenseRecord(byte tag, Blob b, int pos) th return (T) BlockResult.read(b,pos); } + if (tag == CVMTag.OP_DO) { + return (T) Do.read(b,pos); + } + + if (tag == CVMTag.PEER_STATUS) return (T) PeerStatus.read(b,pos); if (tag == CVMTag.ACCOUNT_STATUS) return (T) AccountStatus.read(b,pos); } catch (Exception e) { diff --git a/convex-core/src/test/java/convex/core/data/ObjectsTest.java b/convex-core/src/test/java/convex/core/data/ObjectsTest.java index de0250260..0165fee88 100644 --- a/convex-core/src/test/java/convex/core/data/ObjectsTest.java +++ b/convex-core/src/test/java/convex/core/data/ObjectsTest.java @@ -81,7 +81,7 @@ public static void doCellTests(ACell a) { private static final CAD3Encoder CAD3_ENCODER=new CAD3Encoder(); private static final CVMEncoder CVM_ENCODER=new CVMEncoder(); - private static void doCAD3Tests(ACell a) { + public static void doCAD3Tests(ACell a) { Blob enc=Format.encodeMultiCell(a, true); try { ACell cad=CAD3_ENCODER.decodeMultiCell(enc); diff --git a/convex-core/src/test/java/convex/core/lang/OpsTest.java b/convex-core/src/test/java/convex/core/lang/OpsTest.java index 9890b66d9..405d3ae27 100644 --- a/convex-core/src/test/java/convex/core/lang/OpsTest.java +++ b/convex-core/src/test/java/convex/core/lang/OpsTest.java @@ -29,10 +29,12 @@ import convex.core.cvm.ops.Lookup; import convex.core.cvm.ops.Set; import convex.core.cvm.ops.Special; +import convex.core.cvm.ops.Try; import convex.core.data.ACell; import convex.core.data.AMap; import convex.core.data.AString; import convex.core.data.Blob; +import convex.core.data.DenseRecord; import convex.core.data.ExtensionValue; import convex.core.data.Format; import convex.core.data.ObjectsTest; @@ -149,7 +151,7 @@ public void testUndeclaredLookup() { } @Test - public void testDo() { + public void testDo() throws BadFormatException { Context c = context(); AOp op = Do.create(Def.create("foo", Constant.createString("bar")), Lookup.create("foo")); @@ -158,10 +160,30 @@ public void testDo() { long expectedJuice = INITIAL_JUICE - (Juice.CONSTANT + Juice.DEF + Juice.LOOKUP_DYNAMIC + Juice.DO); assertEquals(expectedJuice, c2.getJuiceAvailable()); assertEquals("bar", c2.getResult().toString()); + + Blob enc=op.getEncoding(); + + assertEquals(CVMTag.OP_DO,op.getTag()); + assertEquals(op,DenseRecord.read(CVMTag.OP_DO, enc,0)); + + ObjectsTest.doCAD3Tests(op); + + doOpTest(op); + } + + @Test + public void testTry() throws BadFormatException { + AOp op = Try.create(Invoke.create(Constant.of(CVMLong.ZERO)), Constant.of(CVMLong.ONE)); + + Context c = context(); + Context c2 = c.execute(op); + assertFalse(c2.isExceptional()); + assertEquals(CVMLong.ONE,c2.getResult()); doOpTest(op); } + @Test public void testSpecial() { Context c = context();