Skip to content

Commit

Permalink
Add compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
erikzhang committed May 17, 2019
1 parent b5c407c commit ad4f089
Show file tree
Hide file tree
Showing 31 changed files with 7,885 additions and 2 deletions.
19 changes: 19 additions & 0 deletions Neo.Compiler.MSIL.UnitTests/Neo.Compiler.MSIL.UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
<RootNamespace>Neo.Compiler.MSIL</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.3.2" />
<PackageReference Include="MSTest.TestFramework" Version="1.3.2" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Neo.Compiler.MSIL\Neo.Compiler.MSIL.csproj" />
</ItemGroup>

</Project>
70 changes: 70 additions & 0 deletions Neo.Compiler.MSIL.UnitTests/UnitTest1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.Compiler.MSIL.Utils;
using System;

namespace Neo.Compiler.MSIL
{
[TestClass]
public class UnitTest1
{
private static readonly NeonTestTool testtool = new NeonTestTool("net4smartcontract.test.dll");

private static void DumpAVM(NeoMethod avmMethod)
{
Console.WriteLine("dump:" + avmMethod.displayName + " addr in avm:" + avmMethod.funcaddr);
foreach (var c in avmMethod.body_Codes)
{
Console.WriteLine(c.Key.ToString("X04") + "=>" + c.Value.ToString());
}
}

private static void DumpBytes(byte[] data)
{
Console.WriteLine("AVM=");
foreach (var b in data)
{
Console.Write(b.ToString("X02"));
}
Console.WriteLine("");
}

[TestMethod]
public void GetAllILFunction()
{
var names = testtool.GetAllILFunction();
foreach (var n in names)
{
Console.WriteLine("got name:" + n);
}
}

[TestMethod]
public void TestDumpAFunc()
{
var ilmethod = testtool.FindMethod("TestClass1", "UnitTest_001");
var neomethod = testtool.GetNEOVMMethod(ilmethod);
DumpAVM(neomethod);
var bytes = testtool.NeoMethodToBytes(neomethod);
DumpBytes(bytes);
}

[TestMethod]
public void TestRunAFunc()
{
//run this below

//public static byte UnitTest_001()
//{
// var nb = new byte[] { 1, 2, 3, 4 };
// return nb[2];
//}
var ilmethod = testtool.FindMethod("TestClass1", "UnitTest_001");
var neomethod = testtool.GetNEOVMMethod(ilmethod);
var result = testtool.RunScript(neomethod.funcaddr, null);
var resultnum = result.ResultStack.Peek().GetBigInteger();
// and check if the result is 3

Assert.AreEqual(resultnum, 3);
}
}
}
12 changes: 12 additions & 0 deletions Neo.Compiler.MSIL.UnitTests/Utils/DefLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace Neo.Compiler.MSIL.Utils
{
internal class DefLogger : ILogger
{
public void Log(string log)
{
Console.WriteLine(log);
}
}
}
196 changes: 196 additions & 0 deletions Neo.Compiler.MSIL.UnitTests/Utils/NeonTestTool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
using Neo.VM;
using System;
using System.Collections.Generic;
using System.IO;

namespace Neo.Compiler.MSIL.Utils
{
internal class NeonTestTool
{
private readonly ILModule modIL;
private readonly ModuleConverter converterIL;
private readonly byte[] finalAVM;

public NeonTestTool(string filename)
{
string onlyname = Path.GetFileNameWithoutExtension(filename);
string filepdb = onlyname + ".pdb";
var path = Path.GetDirectoryName(filename);
if (!string.IsNullOrEmpty(path))
{
try
{
Directory.SetCurrentDirectory(path);
}
catch (Exception err)
{
Console.WriteLine("Could not find path: " + path);
throw (err);
}
}
var log = new DefLogger();
this.modIL = new ILModule(log);
Stream fs;
Stream fspdb = null;

//open file
try
{
fs = File.OpenRead(filename);

if (File.Exists(filepdb))
{
fspdb = File.OpenRead(filepdb);
}

}
catch (Exception err)
{
log.Log("Open File Error:" + err.ToString());
throw err;
}
//load module
try
{
modIL.LoadModule(fs, fspdb);
}
catch (Exception err)
{
log.Log("LoadModule Error:" + err.ToString());
throw err;
}

converterIL = new ModuleConverter(log);
ConvOption option = new ConvOption()
{
useNep8 = true,
useSysCallInteropHash = true
};
try
{
converterIL.Convert(modIL, option);
finalAVM = converterIL.outModule.Build();
}
catch (Exception err)
{
log.Log("Convert IL->ASM Error:" + err.ToString());
throw err;
}
}

public string[] GetAllILFunction()
{
List<string> lists = new List<string>();
foreach (var _class in modIL.mapType)
{
foreach (var method in _class.Value.methods)
{
var name = method.Key;
lists.Add(name);
}
}
return lists.ToArray();
}

public ILMethod FindMethod(string fromclass, string method)
{
foreach (var _class in modIL.mapType)
{
var indexbegin = _class.Key.LastIndexOf(".");
var classname = _class.Key;
if (indexbegin > 0)
classname = classname.Substring(indexbegin + 1);

if (classname == fromclass)
{
foreach (var _method in _class.Value.methods)
{
var indexmethodname = _method.Key.LastIndexOf("::");
var methodname = _method.Key.Substring(indexmethodname + 2);
var indexparams = methodname.IndexOf("(");
if (indexparams > 0)
{
methodname = methodname.Substring(0, indexparams);
}
if (methodname == method)
return _method.Value;
}
}
}
return null;
}

public string GetFullMethodName(string fromclass, string method)
{
foreach (var _class in modIL.mapType)
{
var indexbegin = _class.Key.LastIndexOf("::");
var classname = _class.Key.Substring(indexbegin + 2);
if (classname == fromclass)
{
foreach (var _method in _class.Value.methods)
{
var indexmethodname = _method.Key.LastIndexOf("::");
var methodname = _method.Key.Substring(indexmethodname + 2);
if (methodname == method)
return _method.Key;
}
}
}
return null;
}

public NeoMethod GetNEOVMMethod(ILMethod method)
{
var neomethod = this.converterIL.methodLink[method];
return neomethod;
}

public byte[] NeoMethodToBytes(NeoMethod method)
{
List<byte> bytes = new List<byte>();
foreach (var c in method.body_Codes.Values)
{
bytes.Add((byte)c.code);
if (c.bytes != null)
for (var i = 0; i < c.bytes.Length; i++)
{
bytes.Add(c.bytes[i]);
}
}
return bytes.ToArray();
}

private ExecutionEngine RunAVM(byte[] data, int addr = 0, StackItem[] _params = null)
{
var engine = new ExecutionEngine(new TestTransaction(), new TestCrypto(), new TestTable(), new TestInteropService());
engine.LoadScript(data);
//從指定地址開始執行
engine.InvocationStack.Peek().InstructionPointer = addr;
if (_params != null)
{
for (var i = 0; i < _params.Length; i++)
{
engine.CurrentContext.EvaluationStack.Push(_params[i]);
}
}
engine.Execute();
//while (((engine.State & VMState.FAULT) == 0) && ((engine.State & VMState.HALT) == 0))
//{
// engine.ExecuteNext();
//}
return engine;
}

public ExecutionEngine RunScript(int addr, StackItem[] _params = null)
{
return RunAVM(finalAVM, addr, _params);
}

public ExecutionEngine RunMethodAsAStandaloneAVM(NeoMethod method, StackItem[] _params = null)
{
var bytes = NeoMethodToBytes(method);
return RunAVM(bytes, 0, _params);
}
}
}
23 changes: 23 additions & 0 deletions Neo.Compiler.MSIL.UnitTests/Utils/TestBlock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Neo.VM;
using System;
using System.Collections.Generic;

namespace Neo.Compiler.MSIL.Utils
{
internal class TestBlock : IScriptContainer
{
public readonly int TxCount = 4;
public readonly List<TestTxInput> Inputs = new List<TestTxInput>();
public readonly List<TestTxOutput> Outputs = new List<TestTxOutput>();

public byte[] GetMessage()
{
return new byte[] { 1 };
}

public byte[] ToArray()
{
throw new NotImplementedException();
}
}
}
23 changes: 23 additions & 0 deletions Neo.Compiler.MSIL.UnitTests/Utils/TestCrypto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Neo.VM;
using System;

namespace Neo.Compiler.MSIL.Utils
{
internal class TestCrypto : ICrypto
{
public byte[] Hash160(byte[] message)
{
return new byte[] { 4, 56, 66, 5 };
}

public byte[] Hash256(byte[] message)
{
throw new NotImplementedException();
}

public bool VerifySignature(byte[] message, byte[] signature, byte[] pubkey)
{
return true;
}
}
}
7 changes: 7 additions & 0 deletions Neo.Compiler.MSIL.UnitTests/Utils/TestHeader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Neo.Compiler.MSIL.Utils
{
internal class TestHeader
{
public readonly byte[] Hash = new byte[] { 06, 05, 01 };
}
}
Loading

2 comments on commit ad4f089

@vncoelho
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, @erikzhang.
How about the NEOJ and and Assembly?

@erikzhang
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assembly is useless now.

Please sign in to comment.