Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim8y committed Jun 25, 2024
1 parent 29289ce commit 554b620
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

extern alias scfx;
using System;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
Expand All @@ -21,14 +22,52 @@ partial class MethodConvert
{
private void ConvertCollectionExpression(SemanticModel model, CollectionExpressionSyntax expression)
{
// IArrayTypeSymbol type = (IArrayTypeSymbol) model.GetTypeInfo(expression).ConvertedType!;
IArrayTypeSymbol type = (IArrayTypeSymbol)model.GetTypeInfo(expression).ConvertedType!;

if (type.ElementType.SpecialType == SpecialType.System_Byte)
{
Optional<object?>[] values = expression.Elements
.Select(p => p is ExpressionElementSyntax exprElement ? model.GetConstantValue(exprElement.Expression) : default)
.ToArray();

if (values.Any(p => !p.HasValue))
{
Push(values.Length);
AddInstruction(OpCode.NEWBUFFER);
for (int i = 0; i < expression.Elements.Count; i++)
{
AddInstruction(OpCode.DUP);
Push(i);
if (expression.Elements[i] is ExpressionElementSyntax exprElement)
{
ConvertExpression(model, exprElement.Expression);
}
else
{
throw new NotSupportedException($"Unsupported collection element type: {expression.Elements[i].GetType()}");
}
AddInstruction(OpCode.SETITEM);
}
}
else
{
byte[] data = values.Select(p => (byte)System.Convert.ChangeType(p.Value, typeof(byte))!).ToArray();
Push(data);
ChangeType(VM.Types.StackItemType.Buffer);
}

return;
}


for (int i = expression.Elements.Count - 1; i >= 0; i--)
{
var element = expression.Elements[i];
switch (element)
{
case ExpressionElementSyntax expressionElementSyntax:
ConvertExpression(model, expressionElementSyntax.Expression);

break;
default:
throw new NotSupportedException($"Unsupported collection element type: {element.GetType()}");
Expand Down
17 changes: 17 additions & 0 deletions tests/Neo.Compiler.CSharp.TestContracts/Contract_Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@ struct State

public class Contract_Array : SmartContract.Framework.SmartContract
{
// Does NOT work:
private static readonly byte[] TreeByteLengthPrefix = [0x01, 0x03];

// Works:
private static readonly byte[] TreeByteLengthPrefix2 = new byte[] { 0x01, 0x03 };


public static byte[] GetTreeByteLengthPrefix()
{
return TreeByteLengthPrefix;
}

public static byte[] GetTreeByteLengthPrefix2()
{
return TreeByteLengthPrefix2;
}

public static int[][] TestJaggedArray()
{
int[] array1 = new int[] { 1, 2, 3, 4 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,26 @@ public abstract class Contract_Array : Neo.SmartContract.Testing.SmartContract
{
#region Compiled data

public static readonly Neo.SmartContract.Manifest.ContractManifest Manifest = Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_Array"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""testJaggedArray"",""parameters"":[],""returntype"":""Array"",""offset"":0,""safe"":false},{""name"":""testJaggedByteArray"",""parameters"":[],""returntype"":""Array"",""offset"":40,""safe"":false},{""name"":""testIntArray"",""parameters"":[],""returntype"":""Array"",""offset"":88,""safe"":false},{""name"":""testDefaultArray"",""parameters"":[],""returntype"":""Boolean"",""offset"":120,""safe"":false},{""name"":""testIntArrayInit"",""parameters"":[],""returntype"":""Array"",""offset"":145,""safe"":false},{""name"":""testIntArrayInit2"",""parameters"":[],""returntype"":""Array"",""offset"":172,""safe"":false},{""name"":""testIntArrayInit3"",""parameters"":[],""returntype"":""Array"",""offset"":199,""safe"":false},{""name"":""testDynamicArrayInit"",""parameters"":[{""name"":""length"",""type"":""Integer""}],""returntype"":""Array"",""offset"":226,""safe"":false},{""name"":""testDynamicArrayStringInit"",""parameters"":[{""name"":""input"",""type"":""String""}],""returntype"":""ByteArray"",""offset"":304,""safe"":false},{""name"":""testStructArray"",""parameters"":[],""returntype"":""Any"",""offset"":313,""safe"":false},{""name"":""testEmptyArray"",""parameters"":[],""returntype"":""Array"",""offset"":351,""safe"":false},{""name"":""testStructArrayInit"",""parameters"":[],""returntype"":""Any"",""offset"":360,""safe"":false},{""name"":""testByteArrayOwner"",""parameters"":[],""returntype"":""ByteArray"",""offset"":421,""safe"":false},{""name"":""testByteArrayOwnerCall"",""parameters"":[],""returntype"":""ByteArray"",""offset"":425,""safe"":false},{""name"":""testSupportedStandards"",""parameters"":[],""returntype"":""Array"",""offset"":430,""safe"":false},{""name"":""testElementBinding"",""parameters"":[],""returntype"":""Void"",""offset"":434,""safe"":false},{""name"":""testCollectionexpressions"",""parameters"":[],""returntype"":""Array"",""offset"":480,""safe"":false},{""name"":""_initialize"",""parameters"":[],""returntype"":""Void"",""offset"":572,""safe"":false}],""events"":[]},""permissions"":[{""contract"":""0x0102030405060708090a0102030405060708090a"",""methods"":[""testArgs1"",""testVoid""]},{""contract"":""0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0"",""methods"":[""itoa""]},{""contract"":""0xda65b600f7124ce6c79950c1772a36403104f2be"",""methods"":[""getBlock""]}],""trusts"":[],""extra"":{}}");
public static readonly Neo.SmartContract.Manifest.ContractManifest Manifest = Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_Array"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""getTreeByteLengthPrefix"",""parameters"":[],""returntype"":""ByteArray"",""offset"":0,""safe"":false},{""name"":""getTreeByteLengthPrefix2"",""parameters"":[],""returntype"":""ByteArray"",""offset"":4,""safe"":false},{""name"":""testJaggedArray"",""parameters"":[],""returntype"":""Array"",""offset"":8,""safe"":false},{""name"":""testJaggedByteArray"",""parameters"":[],""returntype"":""Array"",""offset"":48,""safe"":false},{""name"":""testIntArray"",""parameters"":[],""returntype"":""Array"",""offset"":96,""safe"":false},{""name"":""testDefaultArray"",""parameters"":[],""returntype"":""Boolean"",""offset"":128,""safe"":false},{""name"":""testIntArrayInit"",""parameters"":[],""returntype"":""Array"",""offset"":153,""safe"":false},{""name"":""testIntArrayInit2"",""parameters"":[],""returntype"":""Array"",""offset"":180,""safe"":false},{""name"":""testIntArrayInit3"",""parameters"":[],""returntype"":""Array"",""offset"":207,""safe"":false},{""name"":""testDynamicArrayInit"",""parameters"":[{""name"":""length"",""type"":""Integer""}],""returntype"":""Array"",""offset"":234,""safe"":false},{""name"":""testDynamicArrayStringInit"",""parameters"":[{""name"":""input"",""type"":""String""}],""returntype"":""ByteArray"",""offset"":312,""safe"":false},{""name"":""testStructArray"",""parameters"":[],""returntype"":""Any"",""offset"":321,""safe"":false},{""name"":""testEmptyArray"",""parameters"":[],""returntype"":""Array"",""offset"":359,""safe"":false},{""name"":""testStructArrayInit"",""parameters"":[],""returntype"":""Any"",""offset"":368,""safe"":false},{""name"":""testByteArrayOwner"",""parameters"":[],""returntype"":""ByteArray"",""offset"":429,""safe"":false},{""name"":""testByteArrayOwnerCall"",""parameters"":[],""returntype"":""ByteArray"",""offset"":433,""safe"":false},{""name"":""testSupportedStandards"",""parameters"":[],""returntype"":""Array"",""offset"":438,""safe"":false},{""name"":""testElementBinding"",""parameters"":[],""returntype"":""Void"",""offset"":442,""safe"":false},{""name"":""testCollectionexpressions"",""parameters"":[],""returntype"":""Array"",""offset"":488,""safe"":false},{""name"":""_initialize"",""parameters"":[],""returntype"":""Void"",""offset"":587,""safe"":false}],""events"":[]},""permissions"":[{""contract"":""0x0102030405060708090a0102030405060708090a"",""methods"":[""testArgs1"",""testVoid""]},{""contract"":""0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0"",""methods"":[""itoa""]},{""contract"":""0xda65b600f7124ce6c79950c1772a36403104f2be"",""methods"":[""getBlock""]}],""trusts"":[],""extra"":{}}");

public static readonly Neo.SmartContract.NefFile Nef = Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS+8gQxQDYqd8FQmcfmTBL3ALZl2ghnZXRCbG9jawEAAQ/A7znO4OTpJcbCoGp54UQN2G/OrARpdG9hAQABDwoJCAcGBQQDAgEKCQgHBgUEAwIBCXRlc3RBcmdzMQEAAQ8KCQgHBgUEAwIBCgkIBwYFBAMCAQh0ZXN0Vm9pZAAAAA8AAP1qAlcEABQTEhEUwHAYFxYVFMBxERITERTAchITFBUUwHNramloFMAiAkBXBAAMBAECAwTbMHAMBAUGBwjbMHEMBAEDAgHbMHIMBAUEAwLbMHNramloFMAiAkBXAQATxCFwEEpoEFHQRRFKaBFR0EUSSmgSUdBFaCICQFcBABPEIXBoEM4QlyYHEdsgIgcQ2yAiAkBXAQATEhETwHAUSmgRUdBFFUpoElHQRWgiAkBXAQATEhETwHAUSmgRUdBFFUpoElHQRWgiAkBXAQATEhETwHAUSmgRUdBFFUpoElHQRWgiAkBXAgF4xCFwEHEiPGlKaGlR0EVpSpxKAgAAAIAuBCIKSgL///9/Mh4D/////wAAAACRSgL///9/MgwDAAAAAAEAAACfcUVpeLUkw2giAkBXAAF4yogiAkBXAgDFSgvPSgvPShDPSjQUcBPEAHFoSmkSUdBFaRLOIgJAVwABQFcBAMJwaCICQFcDAMVKC89KC89KEM9KNOVwaBHAcWkQznJqIgJAVwEADBT2ZENJjTh40yuZTk4Sg8aTRCHa/tswcGgiAkBYIgJANNwiAkBZIgJAVwQAARAnNwAAcAERJzcAAHFpaBLAcmpK2CQEEM5za0rYJAcUzjcBAEHP50eWQFcHABgXFhUUExIRGMBwDAV0aHJlZQwDdHdvDANvbmUTwHEZGBcTwBYVFBPAExIRE8ATwHITEhETwHMWFRQTwHQZGBcTwHVtbGsTwHbFSmjPSmnPSmrPSm7PIgJAVgIMFPZkQ0mNOHjTK5lOThKDxpNEIdr+2zBgDAZORVAtMTAMBU5FUC01EsBhQPcHfBg="));
public static readonly Neo.SmartContract.NefFile Nef = Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS+8gQxQDYqd8FQmcfmTBL3ALZl2ghnZXRCbG9jawEAAQ/A7znO4OTpJcbCoGp54UQN2G/OrARpdG9hAQABDwoJCAcGBQQDAgEKCQgHBgUEAwIBCXRlc3RBcmdzMQEAAQ8KCQgHBgUEAwIBCgkIBwYFBAMCAQh0ZXN0Vm9pZAAAAA8AAP2FAlgiAkBZIgJAVwQAFBMSERTAcBgXFhUUwHEREhMRFMByEhMUFRTAc2tqaWgUwCICQFcEAAwEAQIDBNswcAwEBQYHCNswcQwEAQMCAdswcgwEBQQDAtswc2tqaWgUwCICQFcBABPEIXAQSmgQUdBFEUpoEVHQRRJKaBJR0EVoIgJAVwEAE8QhcGgQzhCXJgcR2yAiBxDbICICQFcBABMSERPAcBRKaBFR0EUVSmgSUdBFaCICQFcBABMSERPAcBRKaBFR0EUVSmgSUdBFaCICQFcBABMSERPAcBRKaBFR0EUVSmgSUdBFaCICQFcCAXjEIXAQcSI8aUpoaVHQRWlKnEoCAAAAgC4EIgpKAv///38yHgP/////AAAAAJFKAv///38yDAMAAAAAAQAAAJ9xRWl4tSTDaCICQFcAAXjKiCICQFcCAMVKC89KC89KEM9KNBRwE8QAcWhKaRJR0EVpEs4iAkBXAAFAVwEAwnBoIgJAVwMAxUoLz0oLz0oQz0o05XBoEcBxaRDOcmoiAkBXAQAMFPZkQ0mNOHjTK5lOThKDxpNEIdr+2zBwaCICQFoiAkA03CICQFsiAkBXBAABECc3AABwAREnNwAAcWloEsByakrYJAQQznNrStgkBxTONwEAQc/nR5ZAVwgAExESwHAYFxYVFBMSERjAcQwFdGhyZWUMA3R3bwwDb25lE8ByGRgXE8AWFRQTwBMSERPAE8BzExIRE8B0FhUUE8B1GRgXE8B2bm1sE8B3B8VKac9Kas9Ka89KbwfPIgJAVgQTERLAYAwCAQPbMGEMFPZkQ0mNOHjTK5lOThKDxpNEIdr+2zBiDAZORVAtMTAMBU5FUC01EsBjQFhM9N4="));

#endregion

#region Unsafe methods

/// <summary>
/// Unsafe method
/// </summary>
[DisplayName("getTreeByteLengthPrefix")]
public abstract byte[]? GetTreeByteLengthPrefix();

/// <summary>
/// Unsafe method
/// </summary>
[DisplayName("getTreeByteLengthPrefix2")]
public abstract byte[]? GetTreeByteLengthPrefix2();

/// <summary>
/// Unsafe method
/// </summary>
Expand Down
17 changes: 17 additions & 0 deletions tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,23 @@ public class UnitTest_Array : TestBase<Contract_Array>
{
public UnitTest_Array() : base(Contract_Array.Nef, Contract_Array.Manifest) { }


[TestMethod]
public void Test_GetTreeByteLengthPrefix()
{
var result = Contract.GetTreeByteLengthPrefix();

CollectionAssert.AreEqual(new byte[] { 0x01, 0x03 }, result);
}

[TestMethod]
public void Test_GetTreeByteLengthPrefix2()
{
var result = Contract.GetTreeByteLengthPrefix2();

CollectionAssert.AreEqual(new byte[] { 0x01, 0x03 }, result);
}

[TestMethod]
public void Test_JaggedArray()
{
Expand Down

0 comments on commit 554b620

Please sign in to comment.