Skip to content

Commit

Permalink
Add Type Convert (#196)
Browse files Browse the repository at this point in the history
* this unittest for
#195

* Clean code

* 區分push
pushNumber
pushBoolean
pushDataArray

過去合約中所有的數值是統一的Push
小於等於16的數字 和 byte[0] 和  true false 是Integer
>16的數字 和 byte[n>0] 是 ByteArray

現在在合約中使用數值將直接得到正確的類型

new byte[0] 是ByteArray
true        是Boolean
17          是Integer

* 1.修改了unittest null
因爲現在會返回integer類型了,不再是DataArray

2.修改了TypeConvert
應該現在 new byte[0] 直接是ByteArray類型了

* 1.Use Helper.AsByteArray() to convert to ByteArray
2.Use Helper.AsBigInteger() to convert to BigInteger
3.fix unittest

* fix one small fault.

* add value equal test

* Clean code

* Clean code

* fix format

Co-authored-by: Shargon <shargon@gmail.com>
  • Loading branch information
lightszero and shargon committed Mar 11, 2020
1 parent 5265b24 commit 8acf90f
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 93 deletions.
70 changes: 43 additions & 27 deletions src/Neo.Compiler.MSIL/MSIL/Conv_Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,29 @@ private NeoCode _Convert1by1(VM.OpCode code, OpCode src, NeoMethod to, byte[] da
return _code;
}

private NeoCode _ConvertPush(byte[] data, OpCode src, NeoMethod to)
private void _ConvertPushNumber(System.Numerics.BigInteger i, OpCode src, NeoMethod to)
{
if (i == 0) _Convert1by1(VM.OpCode.PUSH0, src, to);
else if (i == -1) _Convert1by1(VM.OpCode.PUSHM1, src, to);
else if (i > 0 && i <= 16) _Convert1by1(VM.OpCode.PUSH0 + (byte)i, src, to);
else
{
_ConvertPushDataArray(i.ToByteArray(), src, to);
_Insert1(VM.OpCode.CONVERT, "", to, new byte[1] { (byte)VM.Types.StackItemType.Integer });
}
}

private void _ConvertPushBoolean(bool b, OpCode src, NeoMethod to)
{
if (!b)
_Convert1by1(VM.OpCode.PUSH0, src, to);
else
_Convert1by1(VM.OpCode.PUSH1, src, to);
_Insert1(VM.OpCode.CONVERT, "", to, new byte[1] { (byte)VM.Types.StackItemType.Boolean });
}

private void _ConvertPushDataArray(byte[] data, OpCode src, NeoMethod to)
{
if (data.Length == 0) return _Convert1by1(VM.OpCode.PUSH0, src, to);
byte prefixLen;
VM.OpCode code;
if (data.Length <= byte.MaxValue)
Expand All @@ -116,15 +136,13 @@ private NeoCode _ConvertPush(byte[] data, OpCode src, NeoMethod to)
byte[] bytes = new byte[data.Length + prefixLen];
Buffer.BlockCopy(BitConverter.GetBytes(data.Length), 0, bytes, 0, prefixLen);
Buffer.BlockCopy(data, 0, bytes, prefixLen, data.Length);
return _Convert1by1(code, src, to, bytes);
_Convert1by1(code, src, to, bytes);
}

private NeoCode _ConvertPush(long i, OpCode src, NeoMethod to)
private void _ConvertPushString(string str, OpCode src, NeoMethod to)
{
if (i == 0) return _Convert1by1(VM.OpCode.PUSH0, src, to);
if (i == -1) return _Convert1by1(VM.OpCode.PUSHM1, src, to);
if (i > 0 && i <= 16) return _Convert1by1(VM.OpCode.PUSH0 + (byte)i, src, to);
return _ConvertPush(((BigInteger)i).ToByteArray(), src, to);
var data = Encoding.UTF8.GetBytes(str);
_ConvertPushDataArray(data, src, to);
}

private int _ConvertPushI8WithConv(ILMethod from, long i, OpCode src, NeoMethod to)
Expand All @@ -136,30 +154,30 @@ private int _ConvertPushI8WithConv(ILMethod from, long i, OpCode src, NeoMethod
{
ulong v = (ulong)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;
}
else if (code == CodeEx.Conv_U1)
{
byte v = (byte)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else if (code == CodeEx.Conv_U2)
{
ushort v = (ushort)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else if (code == CodeEx.Conv_U4)
{
uint v = (uint)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
Expand All @@ -171,12 +189,12 @@ private int _ConvertPushI8WithConv(ILMethod from, long i, OpCode src, NeoMethod
// Be careful with converting ulong to biginteger
ulong v = (ulong)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;
}
}

_ConvertPush(i, src, to);
_ConvertPushNumber(i, src, to);
return 0;
}

Expand All @@ -190,36 +208,36 @@ private int _ConvertPushI4WithConv(ILMethod from, int i, OpCode src, NeoMethod t
{
ulong v = (uint)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;
}
else if (code == CodeEx.Conv_U1)
{
byte v = (byte)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else if (code == CodeEx.Conv_U2)
{
ushort v = (ushort)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else if (code == CodeEx.Conv_U4)
{
uint v = (uint)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else
{
_ConvertPush(i, src, to);
_ConvertPushNumber(i, src, to);
return 0;
}
}
Expand Down Expand Up @@ -247,29 +265,27 @@ private void _insertSharedStaticVarCode(NeoMethod to)
if (_src is byte[])
{
var bytesrc = (byte[])_src;
_ConvertPush(bytesrc, null, to);
_ConvertPushDataArray(bytesrc, null, to);
}
else if (_src is int intsrc)
{
_ConvertPush(intsrc, null, to);
_ConvertPushNumber(intsrc, null, to);
}
else if (_src is long longsrc)
{
_ConvertPush(longsrc, null, to);
_ConvertPushNumber(longsrc, null, to);
}
else if (_src is bool bsrc)
{
_ConvertPush(bsrc ? 1 : 0, null, to);
_ConvertPushBoolean(bsrc, null, to);
}
else if (_src is string strsrc)
{
var bytesrc = Encoding.UTF8.GetBytes(strsrc);
_ConvertPush(bytesrc, null, to);
_ConvertPushString(strsrc, null, to);
}
else if (_src is BigInteger bisrc)
{
byte[] bytes = bisrc.ToByteArray();
_ConvertPush(bytes, null, to);
_ConvertPushNumber(bisrc, null, to);
}
else
{
Expand Down
48 changes: 24 additions & 24 deletions src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ private int _ConvertCall(OpCode src, NeoMethod to)
}
else if (src.tokenMethod == "System.Char System.String::get_Chars(System.Int32)")
{
_ConvertPush(1, src, to);
_ConvertPushNumber(1, src, to);
_Convert1by1(VM.OpCode.SUBSTR, null, to);
return 0;
}
Expand Down Expand Up @@ -796,16 +796,16 @@ private int _ConvertCall(OpCode src, NeoMethod to)
}
else if (calltype == 4)
{
_ConvertPush(callhash, src, to);
_ConvertPushDataArray(callhash, src, to);
_Insert1(VM.OpCode.SYSCALL, "", to, BitConverter.GetBytes(InteropService.Contract.Call));
}
else if (calltype == 5)
{
var callp = Encoding.UTF8.GetBytes(callname);
_ConvertPush(callp, src, to);
//var callp = Encoding.UTF8.GetBytes(callname);
_ConvertPushString(callname, src, to);

// package the arguments into an array
_ConvertPush(pcount + 1, null, to);
_ConvertPushNumber(pcount + 1, null, to);
_Convert1by1(VM.OpCode.PACK, null, to);

//a syscall
Expand All @@ -820,7 +820,7 @@ private int _ConvertCall(OpCode src, NeoMethod to)
}
else if (calltype == 6)
{
_ConvertPush(callpcount, src, to);
_ConvertPushNumber(callpcount, src, to);
_Convert1by1(VM.OpCode.ROLL, null, to);
_Convert1by1(VM.OpCode.SYSCALL, null, to, BitConverter.GetBytes(InteropService.Contract.Call));
}
Expand Down Expand Up @@ -1078,8 +1078,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
char info = BitConverter.ToChar(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 2, null, to);
_ConvertPush(info, null, to);
_ConvertPushNumber(i / 2, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand All @@ -1090,8 +1090,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
var info = BitConverter.ToUInt32(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 4, null, to);
_ConvertPush(info, null, to);
_ConvertPushNumber(i / 4, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand All @@ -1102,8 +1102,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
var info = BitConverter.ToInt32(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 4, null, to);
_ConvertPush(info, null, to);
_ConvertPushNumber(i / 4, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand All @@ -1114,8 +1114,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
var info = BitConverter.ToInt64(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 8, null, to);
_ConvertPush(info, null, to);
_ConvertPushNumber(i / 8, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand All @@ -1126,8 +1126,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
var info = (System.Numerics.BigInteger)BitConverter.ToUInt64(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 8, null, to);
_ConvertPush(info.ToByteArray(), null, to);
_ConvertPushNumber(i / 8, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand Down Expand Up @@ -1160,7 +1160,7 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)

// System.Byte or System.SByte
var data = method.body_Codes[n2].tokenUnknown as byte[];
this._ConvertPush(data, src, to);
this._ConvertPushDataArray(data, src, to);

return 3;
}
Expand Down Expand Up @@ -1208,7 +1208,7 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
bool bLdLoc = (_code.code == CodeEx.Ldloc || _code.code == CodeEx.Ldloc_0 || _code.code == CodeEx.Ldloc_1 || _code.code == CodeEx.Ldloc_2 || _code.code == CodeEx.Ldloc_3 || _code.code == CodeEx.Ldloc_S);
if (bLdLoc == false)//It means there's no initialization at all
{
this._ConvertPush(outbyte, src, to);
this._ConvertPushDataArray(outbyte, src, to);
return 0;
}
while (true)
Expand Down Expand Up @@ -1237,7 +1237,7 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
else if (bLdLoc && !bStelem)
{
//This is not a predictive array initialization, we lost one case for handling
this._ConvertPush(outbyte, src, to);
this._ConvertPushDataArray(outbyte, src, to);
// Two cases here
if (skip == 1)
{
Expand All @@ -1256,7 +1256,7 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
}
//Sometimes c# will use the real value for initialization. If the value is byte, it may be an error

this._ConvertPush(outbyte, src, to);
this._ConvertPushDataArray(outbyte, src, to);
return skip;
}
}
Expand All @@ -1266,7 +1266,7 @@ private int _ConvertInitObj(OpCode src, NeoMethod to)
{
var type = (src.tokenUnknown as Mono.Cecil.TypeReference).Resolve();
_Convert1by1(VM.OpCode.NOP, src, to);
_ConvertPush(type.Fields.Count, null, to);
_ConvertPushNumber(type.Fields.Count, null, to);
if (type.IsValueType)
{
_Insert1(VM.OpCode.NEWSTRUCT, null, to);
Expand Down Expand Up @@ -1323,7 +1323,7 @@ private int _ConvertNewObj(OpCode src, NeoMethod to)
}

_Convert1by1(VM.OpCode.NOP, src, to);
_ConvertPush(type.DeclaringType.Fields.Count, null, to);
_ConvertPushNumber(type.DeclaringType.Fields.Count, null, to);
if (type.DeclaringType.IsValueType)
{
_Insert1(VM.OpCode.NEWSTRUCT, null, to);
Expand All @@ -1345,7 +1345,7 @@ private int _ConvertStfld(ILMethod method, OpCode src, NeoMethod to)

//_Convert1by1(VM.OpCode.CLONESTRUCTONLY, src, to);

_ConvertPush(id, null, to);//index
_ConvertPushNumber(id, null, to);//index
_Convert1by1(VM.OpCode.SWAP, null, to);//put item top

_Convert1by1(VM.OpCode.SETITEM, null, to);//moidfy //item //index //array
Expand All @@ -1359,7 +1359,7 @@ private int _ConvertLdfld(OpCode src, NeoMethod to)
var id = type.Fields.IndexOf(field);
if (id < 0)
throw new Exception("impossible.");
_ConvertPush(id, src, to);
_ConvertPushNumber(id, src, to);
_Convert1by1(VM.OpCode.PICKITEM, null, to);

return 0;
Expand Down
Loading

0 comments on commit 8acf90f

Please sign in to comment.