From 2a18c0678ebd1632bb3d99dd247e3e55b5840c65 Mon Sep 17 00:00:00 2001 From: mikera Date: Sat, 12 Oct 2024 13:45:29 +0100 Subject: [PATCH] More CAD3 encoding updates --- .../src/main/java/convex/core/data/ACell.java | 6 +-- .../src/main/java/convex/core/data/ACode.java | 21 +++++++++- .../main/java/convex/core/data/ANonCVM.java | 2 +- .../main/java/convex/core/data/Format.java | 13 +++++-- .../java/convex/core/data/impl/DummyCell.java | 2 +- .../java/convex/core/data/impl/KeySet.java | 2 +- .../convex/core/data/prim/CVMBigInteger.java | 2 +- .../main/java/convex/core/lang/ACVMCode.java | 14 +++++++ .../src/main/java/convex/core/lang/AFn.java | 8 +--- .../src/main/java/convex/core/lang/AOp.java | 7 +--- .../java/convex/core/lang/impl/ADataFn.java | 39 ++++++------------- .../java/convex/core/lang/impl/KeywordFn.java | 5 +++ .../java/convex/core/lang/impl/MapFn.java | 5 +++ .../java/convex/core/lang/impl/SeqFn.java | 5 +++ .../java/convex/core/lang/impl/SetFn.java | 7 +++- .../java/convex/core/data/ObjectsTest.java | 2 + 16 files changed, 86 insertions(+), 54 deletions(-) create mode 100644 convex-core/src/main/java/convex/core/lang/ACVMCode.java diff --git a/convex-core/src/main/java/convex/core/data/ACell.java b/convex-core/src/main/java/convex/core/data/ACell.java index 9a5935a5a..eb730b2e2 100644 --- a/convex-core/src/main/java/convex/core/data/ACell.java +++ b/convex-core/src/main/java/convex/core/data/ACell.java @@ -183,7 +183,7 @@ protected static boolean genericEquals(ACell a, ACell b) { * @param pos The offset into the byte array * @return New position after writing */ - protected abstract int encodeRaw(byte[] bs, int pos); + public abstract int encodeRaw(byte[] bs, int pos); /** * Creates the encoding for this cell. Cell must be canonical, or else an error may occur. @@ -399,11 +399,11 @@ protected Ref createRef() { /** * Gets the number of Refs contained within this Cell. This number is - * final / immutable for any given instance and is defined by the Cell encoding rules. + * final / immutable for any given instance and is defined by the Cell,s CAD3 encoding rules. * * Contained Refs may be either external or embedded. * - * @return The number of Refs in this Cell + * @return The number of Refs in this Cell (0-63) */ public int getRefCount() { ACell canonical=getCanonical(); diff --git a/convex-core/src/main/java/convex/core/data/ACode.java b/convex-core/src/main/java/convex/core/data/ACode.java index 791aeba28..4a067a8d2 100644 --- a/convex-core/src/main/java/convex/core/data/ACode.java +++ b/convex-core/src/main/java/convex/core/data/ACode.java @@ -1,8 +1,27 @@ package convex.core.data; +import convex.core.data.impl.ALongBlob; +import convex.core.util.Utils; +import convex.core.exceptions.InvalidDataException; + /** * Abstract base class for CVM code data types */ -public abstract class ACode extends ACell { +public abstract class ACode extends ALongBlob { + + protected byte tag; + + protected ACode(long value) { + super(value); + } + @Override + public void validateCell() throws InvalidDataException { + if ((byte)(this.tag&0xF0)!=Tag.CODE_BASE) { + throw new InvalidDataException("Invalide Code tag: 0x"+Utils.toHexString(tag),this); + } + if (this.value<0) { + throw new InvalidDataException("Negaitive code value",this); + } + } } diff --git a/convex-core/src/main/java/convex/core/data/ANonCVM.java b/convex-core/src/main/java/convex/core/data/ANonCVM.java index f1fbac4d8..b6a8b736e 100644 --- a/convex-core/src/main/java/convex/core/data/ANonCVM.java +++ b/convex-core/src/main/java/convex/core/data/ANonCVM.java @@ -39,7 +39,7 @@ public int encode(byte[] bs, int pos) { } @Override - protected int encodeRaw(byte[] bs, int pos) { + public int encodeRaw(byte[] bs, int pos) { encoding.slice(1).getBytes(bs, pos); return pos+encoding.size()-1; } 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 6bdfc296c..4e3e30185 100644 --- a/convex-core/src/main/java/convex/core/data/Format.java +++ b/convex-core/src/main/java/convex/core/data/Format.java @@ -43,10 +43,9 @@ import convex.core.util.Utils; /** - * Static utility class for message format encoding + * Static utility class for CAD3 encoding format * - * "Standards are always out of date. That's what makes them standards." - Alan - * Bennett + * "Standards are always out of date. That's what makes them standards." - Alan Bennett */ public class Format { @@ -57,7 +56,8 @@ public class Format { *
    *
  • This is the maximum length that can be VLQ encoded in 2 bytes. This simplifies message encoding and decoding.
  • *
  • It is big enough to include a 4096-byte Blob
  • - *
  • It is small enough to fit in a UDP message
  • + *
  • It is big enough to include a Record with 63 directly referenced fields
  • + *
  • It is small enough to guarantee fitting in a UDP message
  • *
*/ public static final int LIMIT_ENCODING_LENGTH = 0x3FFF; @@ -97,6 +97,11 @@ public class Format { */ public static final long FULL_EMBEDDED_MEMORY_SIZE = 0L; + /** + * Maximum number of Refs for any single Cell + */ + public static final int MAX_REF_COUNT = 63; + /** * Gets the length in bytes of VLQ encoding for the given long value * @param x Long value to encode diff --git a/convex-core/src/main/java/convex/core/data/impl/DummyCell.java b/convex-core/src/main/java/convex/core/data/impl/DummyCell.java index 4c9f9ac4f..273c5f301 100644 --- a/convex-core/src/main/java/convex/core/data/impl/DummyCell.java +++ b/convex-core/src/main/java/convex/core/data/impl/DummyCell.java @@ -37,7 +37,7 @@ public int encode(byte[] bs, int pos) { } @Override - protected int encodeRaw(byte[] bs, int pos) { + public int encodeRaw(byte[] bs, int pos) { // Nothing to encode return pos; } diff --git a/convex-core/src/main/java/convex/core/data/impl/KeySet.java b/convex-core/src/main/java/convex/core/data/impl/KeySet.java index 8aec9b648..1b55ad89b 100644 --- a/convex-core/src/main/java/convex/core/data/impl/KeySet.java +++ b/convex-core/src/main/java/convex/core/data/impl/KeySet.java @@ -137,7 +137,7 @@ public boolean equals(ACell a) { } @Override - protected int encodeRaw(byte[] bs, int pos) { + public int encodeRaw(byte[] bs, int pos) { throw new UnsupportedOperationException(); } diff --git a/convex-core/src/main/java/convex/core/data/prim/CVMBigInteger.java b/convex-core/src/main/java/convex/core/data/prim/CVMBigInteger.java index 3e5d735e8..9413e92d1 100644 --- a/convex-core/src/main/java/convex/core/data/prim/CVMBigInteger.java +++ b/convex-core/src/main/java/convex/core/data/prim/CVMBigInteger.java @@ -182,7 +182,7 @@ public int encode(byte[] bs, int pos) { } @Override - protected int encodeRaw(byte[] bs, int pos) { + public int encodeRaw(byte[] bs, int pos) { ABlob b=blob(); return b.encodeRaw(bs, pos); } diff --git a/convex-core/src/main/java/convex/core/lang/ACVMCode.java b/convex-core/src/main/java/convex/core/lang/ACVMCode.java new file mode 100644 index 000000000..35ab876e0 --- /dev/null +++ b/convex-core/src/main/java/convex/core/lang/ACVMCode.java @@ -0,0 +1,14 @@ +package convex.core.lang; + +import convex.core.data.ACell; + +/** + * Abstract base class for CVM code constructs + */ +public abstract class ACVMCode extends ACell { + + @Override public final boolean isCVMValue() { + // CVM code objects are CVM values by definition + return true; + } +} diff --git a/convex-core/src/main/java/convex/core/lang/AFn.java b/convex-core/src/main/java/convex/core/lang/AFn.java index 61668a841..d277feffc 100644 --- a/convex-core/src/main/java/convex/core/lang/AFn.java +++ b/convex-core/src/main/java/convex/core/lang/AFn.java @@ -1,7 +1,6 @@ package convex.core.lang; import convex.core.data.ACell; -import convex.core.data.ACode; import convex.core.data.IRefFunction; import convex.core.data.Tag; import convex.core.data.type.AType; @@ -15,7 +14,7 @@ * * @param Return type of functions. */ -public abstract class AFn extends ACode implements IFn { +public abstract class AFn extends ACVMCode implements IFn { @Override public abstract Context invoke(Context context, ACell[] args); @@ -48,11 +47,6 @@ public boolean supportsArgs(ACell[] args) { */ public abstract boolean hasArity(int arity); - @Override - public boolean isCVMValue() { - return true; - } - @Override public byte getTag() { return Tag.FN; diff --git a/convex-core/src/main/java/convex/core/lang/AOp.java b/convex-core/src/main/java/convex/core/lang/AOp.java index 2960eccca..0ea8ec831 100644 --- a/convex-core/src/main/java/convex/core/lang/AOp.java +++ b/convex-core/src/main/java/convex/core/lang/AOp.java @@ -1,7 +1,6 @@ package convex.core.lang; import convex.core.data.ACell; -import convex.core.data.ACode; import convex.core.data.Format; import convex.core.data.IRefFunction; import convex.core.data.Tag; @@ -20,7 +19,7 @@ * * @param the type of the operation return value */ -public abstract class AOp extends ACode { +public abstract class AOp extends ACVMCode { /** * Executes this op with the given context. Must preserve depth unless an @@ -51,10 +50,6 @@ public boolean isCanonical() { public ACell toCanonical() { return this; } - - @Override public final boolean isCVMValue() { - return true; - } /** * Returns the opcode for this op diff --git a/convex-core/src/main/java/convex/core/lang/impl/ADataFn.java b/convex-core/src/main/java/convex/core/lang/impl/ADataFn.java index 66ad06032..0ca425525 100644 --- a/convex-core/src/main/java/convex/core/lang/impl/ADataFn.java +++ b/convex-core/src/main/java/convex/core/lang/impl/ADataFn.java @@ -4,12 +4,12 @@ import convex.core.data.IRefFunction; import convex.core.exceptions.InvalidDataException; import convex.core.lang.AFn; -import convex.core.lang.Context; +import convex.core.lang.RT; /** - * Abstract base class for data structure lookup functions. + * Abstract base wrapper class for data structure lookup functions. * - * Not a canonical object, can't exist as CVM value. + * Not a canonical object, essentially a wrapper for a data structure interpreted as a function * * @param Type of function return value */ @@ -17,37 +17,32 @@ public abstract class ADataFn extends AFn { @Override public int estimatedEncodingSize() { - throw new UnsupportedOperationException(); - } - - @Override - public Context invoke(Context context, ACell[] args) { - throw new UnsupportedOperationException(); + return getCanonical().estimatedEncodingSize(); } @Override public AFn updateRefs(IRefFunction func) { - throw new UnsupportedOperationException(); + return RT.castFunction(getCanonical().updateRefs(func)); } @Override public boolean hasArity(int n) { - throw new UnsupportedOperationException(); + return (n==1)||(n==2); } @Override public void validateCell() throws InvalidDataException { - throw new UnsupportedOperationException(); + getCanonical().validateCell();; } @Override public int encode(byte[] bs, int pos) { - throw new UnsupportedOperationException(); + return getCanonical().encode(bs, pos); } @Override public int encodeRaw(byte[] bs, int pos) { - throw new UnsupportedOperationException(); + return getCanonical().encodeRaw(bs, pos); } @Override @@ -56,22 +51,10 @@ public boolean isCanonical() { } @Override - public ACell toCanonical() { - throw new UnsupportedOperationException("Can't make canonical!"); - } - - @Override - public boolean isCVMValue() { - return false; - } + public abstract ACell toCanonical(); @Override public byte getTag() { - throw new UnsupportedOperationException(); - } - - @Override - public int getRefCount() { - throw new UnsupportedOperationException(); + return getCanonical().getTag(); } } diff --git a/convex-core/src/main/java/convex/core/lang/impl/KeywordFn.java b/convex-core/src/main/java/convex/core/lang/impl/KeywordFn.java index 05b8630f9..819a7c1f4 100644 --- a/convex-core/src/main/java/convex/core/lang/impl/KeywordFn.java +++ b/convex-core/src/main/java/convex/core/lang/impl/KeywordFn.java @@ -49,5 +49,10 @@ public boolean print(BlobBuilder sb,long limit) { return key.print(sb,limit); } + @Override + public ACell toCanonical() { + return key.getCanonical(); + } + } diff --git a/convex-core/src/main/java/convex/core/lang/impl/MapFn.java b/convex-core/src/main/java/convex/core/lang/impl/MapFn.java index 4dd43034f..1da477f4c 100644 --- a/convex-core/src/main/java/convex/core/lang/impl/MapFn.java +++ b/convex-core/src/main/java/convex/core/lang/impl/MapFn.java @@ -39,4 +39,9 @@ public boolean print(BlobBuilder sb,long limit) { return map.print(sb,limit); } + @Override + public ACell toCanonical() { + return map.getCanonical(); + } + } diff --git a/convex-core/src/main/java/convex/core/lang/impl/SeqFn.java b/convex-core/src/main/java/convex/core/lang/impl/SeqFn.java index 8714f49ce..4ef2ac1d2 100644 --- a/convex-core/src/main/java/convex/core/lang/impl/SeqFn.java +++ b/convex-core/src/main/java/convex/core/lang/impl/SeqFn.java @@ -54,4 +54,9 @@ public boolean print(BlobBuilder sb,long limit) { return seq.print(sb,limit); } + @Override + public ACell toCanonical() { + return seq.getCanonical(); + } + } diff --git a/convex-core/src/main/java/convex/core/lang/impl/SetFn.java b/convex-core/src/main/java/convex/core/lang/impl/SetFn.java index d7182d87d..29bbbd56e 100644 --- a/convex-core/src/main/java/convex/core/lang/impl/SetFn.java +++ b/convex-core/src/main/java/convex/core/lang/impl/SetFn.java @@ -10,7 +10,7 @@ public class SetFn extends ADataFn { private ASet set; - public SetFn(ASet m) { + SetFn(ASet m) { this.set = m; } @@ -35,4 +35,9 @@ public boolean print(BlobBuilder sb,long limit) { return set.print(sb,limit); } + @Override + public ACell toCanonical() { + return set.getCanonical(); + } + } 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 e1220fdb0..92d941df3 100644 --- a/convex-core/src/test/java/convex/core/data/ObjectsTest.java +++ b/convex-core/src/test/java/convex/core/data/ObjectsTest.java @@ -406,7 +406,9 @@ private static void doCellStorageTest(ACell a) throws InvalidDataException, IOEx private static void doRefContainerTests(ACell a) { if (!a.isCanonical()) return; int rc=a.getRefCount(); + assertTrue(rc>=0); + assertTrue(rc<=Format.MAX_REF_COUNT); assertEquals(rc,Cells.refCount(a)); if (rc>0) { long tcount = Refs.totalRefCount(a);