Skip to content

Commit

Permalink
Merge branch 'master' into add-examples
Browse files Browse the repository at this point in the history
# Conflicts:
#	tests/Neo.SmartContract.Framework.TestContracts/Contract_SupportedStandard11Enum.cs
#	tests/Neo.SmartContract.Framework.TestContracts/Contract_SupportedStandard17Enum.cs
  • Loading branch information
Jim8y committed Feb 28, 2024
2 parents 862a2a0 + 277c952 commit 0aaa6dc
Show file tree
Hide file tree
Showing 34 changed files with 743 additions and 91 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ jobs:
run: |
dotnet test ./tests/Neo.SmartContract.Template.UnitTests \
--no-build \
-e "COVERAGE_MERGE_JOIN=${GITHUB_WORKSPACE}/coverage-join/coverage.json" \
-l "console;verbosity=detailed" \
-p:CollectCoverage=true \
-p:CoverletOutput=${GITHUB_WORKSPACE}/coverage/lcov \
Expand Down
1 change: 0 additions & 1 deletion examples/Example.SmartContract.Inscription/Inscription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo;
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Attributes;
using Neo.SmartContract.Framework.Native;
Expand Down
1 change: 0 additions & 1 deletion examples/Example.SmartContract.Modifier/Modifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo;
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Attributes;
using Neo.SmartContract.Framework.Native;
Expand Down
4 changes: 1 addition & 3 deletions examples/Example.SmartContract.NEP17/Nep17Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo;
using Neo.SmartContract;
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Attributes;
using Neo.SmartContract.Framework.Native;
Expand All @@ -29,7 +27,7 @@ namespace NEP17
[ContractSourceCode("https://github.com/neo-project/neo-devpack-dotnet/tree/master/examples/")]
[ContractPermission(Permission.WildCard, Method.WildCard)]
[SupportedStandards(NepStandard.Nep17)]
public class SampleNep17Token : Nep17Token, INep17Payment
public class SampleNep17Token : Nep17Token, INep17Payable
{
#region Owner

Expand Down
1 change: 0 additions & 1 deletion examples/Example.SmartContract.NFT/Loot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo;
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Attributes;
using Neo.SmartContract.Framework.Native;
Expand Down
9 changes: 6 additions & 3 deletions src/Neo.Compiler.CSharp/CompilationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,21 @@ internal void Compile()
RemoveEmptyInitialize();
Instruction[] instructions = GetInstructions().ToArray();
instructions.RebuildOffsets();
if (!Options.NoOptimize) Optimizer.CompressJumps(instructions);
if (Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Basic))
{
Optimizer.CompressJumps(instructions);
}
instructions.RebuildOperands();
}
}

public (NefFile nef, ContractManifest manifest, JObject debugInfo) CreateResults(string folder)
public (NefFile nef, ContractManifest manifest, JObject debugInfo) CreateResults(string folder = "")
{
NefFile nef = CreateExecutable();
ContractManifest manifest = CreateManifest();
JObject debugInfo = CreateDebugInformation(folder);

if (!Options.NoOptimize)
if (Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Experimental))
{
try
{
Expand Down
32 changes: 19 additions & 13 deletions src/Neo.Compiler.CSharp/CompilationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,28 @@ public List<CompilationContext> Compile(IEnumerable<string> sourceFiles, IEnumer
return CompileProjectContracts(Compilation);
}

public List<CompilationContext> CompileSources(params string[] sourceFiles) => CompileSources(null, sourceFiles);

public List<CompilationContext> CompileSources((string packageName, string packageVersion) package, params string[] sourceFiles)
public List<CompilationContext> CompileSources(params string[] sourceFiles)
{
return CompileSources(new[] { package }, sourceFiles);
return CompileSources(new CompilationSourceReferences()
{
Packages = new (string, string)[] { new("Neo.SmartContract.Framework", "3.6.2-CI00520") }
},
sourceFiles);
}

public List<CompilationContext> CompileSources(IEnumerable<(string packageName, string packageVersion)>? packages = null, params string[] sourceFiles)
public List<CompilationContext> CompileSources(CompilationSourceReferences references, params string[] sourceFiles)
{
// Generate a dummy csproj

var packageGroup = packages is null ? "" :
$@"
var packageGroup = references.Packages is null ? "" : $@"
<ItemGroup>
{(packages is null ? "" : string.Join(Environment.NewLine, packages.Select(u => $" <PackageReference Include =\"{u.packageName}\" Version=\"{u.packageVersion}\" />")))}
</ItemGroup>
";
{string.Join(Environment.NewLine, references!.Packages!.Select(u => $" <PackageReference Include =\"{u.packageName}\" Version=\"{u.packageVersion}\" />"))}
</ItemGroup>";

var projectsGroup = references.Projects is null ? "" : $@"
<ItemGroup>
{string.Join(Environment.NewLine, references!.Projects!.Select(u => $" <ProjectReference Include =\"{u}\"/>"))}
</ItemGroup>";

var csproj = $@"
<Project Sdk=""Microsoft.NET.Sdk"">
Expand All @@ -97,6 +102,7 @@ public List<CompilationContext> CompileSources(IEnumerable<(string packageName,
</ItemGroup>
{packageGroup}
{projectsGroup}
</Project>";

Expand Down Expand Up @@ -270,8 +276,7 @@ public Compilation GetCompilation(string csproj)

private MetadataReference? GetReference(string name, JObject package, JObject assets, string folder, CSharpCompilationOptions compilationOptions)
{
string assemblyName = Path.GetDirectoryName(name)!;
if (!MetaReferences.TryGetValue(assemblyName, out var reference))
if (!MetaReferences.TryGetValue(name, out var reference))
{
switch (assets["libraries"]![name]!["type"]!.GetString())
{
Expand All @@ -298,6 +303,7 @@ public Compilation GetCompilation(string csproj)
}
else
{
string assemblyName = Path.GetDirectoryName(name)!;
IEnumerable<SyntaxTree> st = files.OrderBy(p => p).Select(p => Path.Combine(packagesPath, namePath, p)).Select(p => CSharpSyntaxTree.ParseText(File.ReadAllText(p), path: p));
CSharpCompilation cr = CSharpCompilation.Create(assemblyName, st, CommonReferences, compilationOptions);
reference = cr.ToMetadataReference();
Expand All @@ -311,7 +317,7 @@ public Compilation GetCompilation(string csproj)
default:
throw new NotSupportedException();
}
MetaReferences.Add(assemblyName, reference);
MetaReferences.Add(name, reference);
}
return reference;
}
Expand Down
13 changes: 12 additions & 1 deletion src/Neo.Compiler.CSharp/CompilationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,26 @@

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System;
using System.Collections.Generic;

namespace Neo.Compiler
{
public class CompilationOptions
{
[Flags]
public enum OptimizationType : byte
{
None = 0,
Basic = 1,
Experimental = 2,

All = Basic | Experimental
}

public NullableContextOptions Nullable { get; set; }
public bool Debug { get; set; }
public bool NoOptimize { get; set; }
public OptimizationType Optimize { get; set; } = OptimizationType.Basic;
public bool Checked { get; set; }
public bool NoInline { get; set; }
public byte AddressVersion { get; set; }
Expand Down
15 changes: 15 additions & 0 deletions src/Neo.Compiler.CSharp/CompilationSourceReferences.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Neo.Compiler
{
public class CompilationSourceReferences
{
/// <summary>
/// Packages
/// </summary>
public (string packageName, string packageVersion)[]? Packages { get; set; } = null;

/// <summary>
/// Projects
/// </summary>
public string[]? Projects { get; set; } = null;
}
}
5 changes: 4 additions & 1 deletion src/Neo.Compiler.CSharp/MethodConvert/ExternConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ namespace Neo.Compiler;

partial class MethodConvert
{

private void ConvertExtern()
{
_inline = true;
Expand All @@ -34,6 +33,8 @@ private void ConvertExtern()
bool emitted = false;
foreach (AttributeData attribute in Symbol.GetAttributes())
{
using var sequencePoint = InsertSequencePoint(attribute.ApplicationSyntaxReference);

switch (attribute.AttributeClass!.Name)
{
case nameof(OpCodeAttribute):
Expand Down Expand Up @@ -79,6 +80,8 @@ private void ConvertExtern()
}
else
{
using var sequencePoint = InsertSequencePoint(contractAttribute.ApplicationSyntaxReference);

UInt160 hash = UInt160.Parse((string)contractAttribute.ConstructorArguments[0].Value!);
if (Symbol.MethodKind == MethodKind.PropertyGet)
{
Expand Down
19 changes: 15 additions & 4 deletions src/Neo.Compiler.CSharp/MethodConvert/MethodConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ private byte AddAnonymousVariable()

private void RemoveAnonymousVariable(byte index)
{
if (!_context.Options.NoOptimize)
if (_context.Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Basic))
_anonymousVariables.Remove(index);
}

private void RemoveLocalVariable(ILocalSymbol symbol)
{
if (!_context.Options.NoOptimize)
if (_context.Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Basic))
_localVariables.Remove(symbol);
}

Expand All @@ -130,10 +130,21 @@ private Instruction AddInstruction(OpCode opcode)
});
}

private SequencePointInserter InsertSequencePoint(SyntaxNodeOrToken syntax)
private SequencePointInserter InsertSequencePoint(SyntaxNodeOrToken? syntax)
{
return new SequencePointInserter(_instructions, syntax);
}

private SequencePointInserter InsertSequencePoint(SyntaxReference? syntax)
{
return new SequencePointInserter(_instructions, syntax);
}

private SequencePointInserter InsertSequencePoint(Location? location)
{
return new SequencePointInserter(_instructions, location);
}

#endregion

#region Convert
Expand Down Expand Up @@ -226,7 +237,7 @@ public void Convert(SemanticModel model)
// it comes from modifier clean up
AddInstruction(OpCode.RET);
}
if (!_context.Options.NoOptimize)
if (_context.Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Basic))
Optimizer.RemoveNops(_instructions);
_startTarget.Instruction = _instructions[0];
}
Expand Down
26 changes: 26 additions & 0 deletions src/Neo.Compiler.CSharp/Optimizer/DumpNef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,32 @@ string TryComment(int catchOffset, int finallyOffset)
}
}

public static (int start, int end) GetMethodStartEndAddress(string name, JToken debugInfo)
{
name = name.Length == 0 ? string.Empty : name[0].ToString().ToUpper() + name.Substring(1); // first letter uppercase
int start = -1, end = -1;
foreach (JToken? method in (JArray)debugInfo["methods"]!)
{
string methodName = method!["name"]!.AsString().Split(",")[1];
if (methodName == name)
{
GroupCollection rangeGroups = RangeRegex.Match(method!["range"]!.AsString()).Groups;
(start, end) = (int.Parse(rangeGroups[1].ToString()), int.Parse(rangeGroups[2].ToString()));
}
}
return (start, end);
}

public static List<int> OpCodeAddressesInMethod(NefFile nef, JToken DebugInfo, string method, OpCode opcode)
{
(int start, int end) = GetMethodStartEndAddress(method, DebugInfo);
List<(int a, VM.Instruction i)> instructions = EnumerateInstructions(nef.Script).ToList();
return instructions.Where(
ai => ai.i.OpCode == opcode &&
ai.a >= start && ai.a <= end
).Select(ai => ai.a).ToList();
}

public static string GenerateDumpNef(NefFile nef, JToken debugInfo)
{
Script script = nef.Script;
Expand Down
4 changes: 2 additions & 2 deletions src/Neo.Compiler.CSharp/Optimizer/Strategies/Optimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class Optimizer
{
public static readonly int[] OperandSizePrefixTable = new int[256];
public static readonly int[] OperandSizeTable = new int[256];
public static readonly Dictionary<string, Func<NefFile, ContractManifest, JToken, (NefFile nef, ContractManifest manifest, JToken debugInfo)>> strategies = new();
public static readonly Dictionary<string, Func<NefFile, ContractManifest, JObject, (NefFile nef, ContractManifest manifest, JObject debugInfo)>> strategies = new();

static Optimizer()
{
Expand All @@ -36,7 +36,7 @@ public static void RegisterStrategies(Type type)
StrategyAttribute attribute = method.GetCustomAttribute<StrategyAttribute>()!;
if (attribute is null) continue;
string name = string.IsNullOrEmpty(attribute.Name) ? method.Name.ToLowerInvariant() : attribute.Name;
strategies[name] = method.CreateDelegate<Func<NefFile, ContractManifest, JToken, (NefFile nef, ContractManifest manifest, JToken debugInfo)>>();
strategies[name] = method.CreateDelegate<Func<NefFile, ContractManifest, JObject, (NefFile nef, ContractManifest manifest, JObject debugInfo)>>();
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/Neo.Compiler.CSharp/Optimizer/Strategies/Reachability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,6 @@ public static (NefFile, ContractManifest, JObject) RemoveUncoveredInstructions(N
if (i.Operand.Length != 0)
simplifiedScript = simplifiedScript.Concat(i.Operand.ToArray()).ToList();
}
foreach (ContractMethodDescriptor method in manifest.Abi.Methods)
method.Offset = (int)simplifiedInstructionsToAddress[oldAddressToInstruction[method.Offset]]!;
Script newScript = new(simplifiedScript.ToArray());
nef.Script = newScript;
nef.Compiler = AppDomain.CurrentDomain.FriendlyName;
nef.CheckSum = NefFile.ComputeChecksum(nef);

//Dictionary<int, (int docId, int startLine, int startCol, int endLine, int endCol)> newAddrToSequencePoint = new();
HashSet<JToken> methodsToRemove = new();
Expand Down Expand Up @@ -143,6 +137,12 @@ public static (NefFile, ContractManifest, JObject) RemoveUncoveredInstructions(N
foreach (JToken method in methodsToRemove)
methods.Remove(method);

foreach (ContractMethodDescriptor method in manifest.Abi.Methods)
method.Offset = (int)simplifiedInstructionsToAddress[oldAddressToInstruction[method.Offset]]!;
Script newScript = new(simplifiedScript.ToArray());
nef.Script = newScript;
nef.Compiler = AppDomain.CurrentDomain.FriendlyName;
nef.CheckSum = NefFile.ComputeChecksum(nef);
return (nef, manifest, debugInfo);
}

Expand Down
14 changes: 9 additions & 5 deletions src/Neo.Compiler.CSharp/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System;

namespace Neo.Compiler
{
public class Options : CompilationOptions
{
public enum GenerateArtifactsKind
[Flags]
public enum GenerateArtifactsKind : byte
{
None,
Source,
Library,
All
None = 0,
Source = 1,
Library = 2,

All = Source | Library
}

public string? Output { get; set; }
Expand Down
4 changes: 2 additions & 2 deletions src/Neo.Compiler.CSharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,14 @@ private static int ProcessOutput(Options options, string folder, CompilationCont
{
var artifact = manifest.GetArtifactsSource(baseName, nef);

if (options.GenerateArtifacts == Options.GenerateArtifactsKind.All || options.GenerateArtifacts == Options.GenerateArtifactsKind.Source)
if (options.GenerateArtifacts.HasFlag(Options.GenerateArtifactsKind.Source))
{
path = Path.Combine(outputFolder, $"{baseName}.artifacts.cs");
File.WriteAllText(path, artifact);
Console.WriteLine($"Created {path}");
}

if (options.GenerateArtifacts == Options.GenerateArtifactsKind.All || options.GenerateArtifacts == Options.GenerateArtifactsKind.Library)
if (options.GenerateArtifacts.HasFlag(Options.GenerateArtifactsKind.Library))
{
try
{
Expand Down
Loading

0 comments on commit 0aaa6dc

Please sign in to comment.