Skip to content

Commit

Permalink
Improve readability in the implementation
Browse files Browse the repository at this point in the history
+ Update namespace of `Result` to reflect the evolved scope.
+ Use new C# features to simplify the program code syntax.
+ Consolidate types reusing the generic `Result` type.
+ Update Elm Editor for compatibility with the new Result type when loading from git repositories. Update volatile process framework to support C# 9.
  • Loading branch information
Viir committed Sep 15, 2021
1 parent d1b2c50 commit 21a7e34
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 216 deletions.
34 changes: 17 additions & 17 deletions implement/elm-fullstack/ElmFullstack/ElmAppCompilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class ElmAppCompilation
{
static readonly System.Diagnostics.Stopwatch cacheItemTimeSource = System.Diagnostics.Stopwatch.StartNew();

static readonly ConcurrentDictionary<string, (Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> compilationResult, TimeSpan lastUseTime)> ElmAppCompilationCache = new();
static readonly ConcurrentDictionary<string, (Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> compilationResult, TimeSpan lastUseTime)> ElmAppCompilationCache = new();

static void ElmAppCompilationCacheRemoveOlderItems(long retainedSizeLimit) =>
Cache.RemoveItemsToLimitRetainedSize(
Expand All @@ -42,7 +42,7 @@ static void ElmAppCompilationCacheRemoveOlderItems(long retainedSizeLimit) =>
item => item.Value.lastUseTime,
retainedSizeLimit);

static public Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> AsCompletelyLoweredElmApp(
static public Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> AsCompletelyLoweredElmApp(
IImmutableDictionary<IImmutableList<string>, IReadOnlyList<byte>> sourceFiles,
ElmAppInterfaceConfig interfaceConfig)
{
Expand All @@ -57,14 +57,14 @@ static public Composition.Result<IReadOnlyList<LocatedCompilationError>, Compila
interfaceConfig,
}))));

Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> compileNew() =>
Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> compileNew() =>
AsCompletelyLoweredElmApp(
sourceFiles,
rootModuleName: interfaceConfig.RootModuleName.Split('.').ToImmutableList(),
interfaceToHostRootModuleName: InterfaceToHostRootModuleName.Split('.').ToImmutableList());

(Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> compilationResult, TimeSpan lastUseTime) BuildNextCacheEntry(
Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> previousEntryCompilationResult)
(Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> compilationResult, TimeSpan lastUseTime) BuildNextCacheEntry(
Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> previousEntryCompilationResult)
{
if (previousEntryCompilationResult?.Ok != null)
return (previousEntryCompilationResult, cacheItemTimeSource.Elapsed);
Expand All @@ -87,7 +87,7 @@ public record CompilationSuccess(
IImmutableDictionary<IImmutableList<string>, IReadOnlyList<byte>> compiledAppFiles,
IImmutableList<CompilationIterationReport> iterationsReports);

static Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> AsCompletelyLoweredElmApp(
static Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> AsCompletelyLoweredElmApp(
IImmutableDictionary<IImmutableList<string>, IReadOnlyList<byte>> sourceFiles,
IImmutableList<string> rootModuleName,
IImmutableList<string> interfaceToHostRootModuleName) =>
Expand All @@ -97,7 +97,7 @@ static Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuc
interfaceToHostRootModuleName,
ImmutableStack<(IImmutableList<(CompilerSerialInterface.DependencyKey key, IReadOnlyList<byte> value)> discoveredDependencies, CompilationIterationReport previousIterationsReports)>.Empty);

static Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> AsCompletelyLoweredElmApp(
static Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> AsCompletelyLoweredElmApp(
IImmutableDictionary<IImmutableList<string>, IReadOnlyList<byte>> sourceFiles,
IImmutableList<string> rootModuleName,
IImmutableList<string> interfaceToHostRootModuleName,
Expand Down Expand Up @@ -130,7 +130,7 @@ static Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuc

if (compilationSuccess != null)
{
return new Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess>(
return new Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess>(
Ok: new CompilationSuccess(compilationSuccess, stack.Select(frame => frame.iterationReport).ToImmutableList().Add(currentIterationReport)));
}

Expand All @@ -151,7 +151,7 @@ static Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuc

if (0 < otherErrors.Count)
{
return new Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess>(
return new Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess>(
Err: otherErrors.Select(error => new LocatedCompilationError(error.location, error: CompilationError.AsCompilationError(error.error))).ToImmutableList());
}

Expand Down Expand Up @@ -190,7 +190,7 @@ TimedReport<CompilationIterationDependencyReport> completeDependencyReport(Compi

if (elmMakeRequest != null)
{
Composition.Result<string, IReadOnlyList<byte>> buildResultValue()
Result<string, IReadOnlyList<byte>> buildResultValue()
{
try
{
Expand All @@ -207,11 +207,11 @@ Composition.Result<string, IReadOnlyList<byte>> buildResultValue()
makeJavascript: elmMakeRequest.outputType.ElmMakeOutputTypeJs != null,
enableDebug: elmMakeRequest.enableDebug);

return Composition.Result<string, IReadOnlyList<byte>>.ok(value);
return Result<string, IReadOnlyList<byte>>.ok(value);
}
catch (Exception e)
{
return Composition.Result<string, IReadOnlyList<byte>>.err("Failed with runtime exception: " + e.ToString());
return Result<string, IReadOnlyList<byte>>.err("Failed with runtime exception: " + e.ToString());
}
}

Expand All @@ -234,13 +234,13 @@ currentIterationReport with
var newDependenciesWithError =
newDependencies.Where(dep => dep.Item1.result.Ok == null).ToImmutableList();

/*
* TODO: Instead of returning here, probably forward the result back into the compiler for packaging, for example adding location info.
* This implies expansion of the dependencies API to model the error cases.
/*
* TODO: Instead of returning here, probably forward the result back into the compiler for packaging, for example adding location info.
* This implies expansion of the dependencies API to model the error cases.
* */
if (0 < newDependenciesWithError.Count)
{
return Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess>.err(
return Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess>.err(
newDependenciesWithError.Select(dep => new LocatedCompilationError(
location: null,
error: new CompilationError(DependencyError: dep.Item2.report.dependencyKeySummary + " " + dep.Item1.result.Err)))
Expand Down Expand Up @@ -523,7 +523,7 @@ static long EstimateCacheItemSizeInMemory(CompilerSerialInterface.LocatedCompila
static long EstimateCacheItemSizeInMemory(CompilerSerialInterface.CompilationError compilationError) =>
compilationError?.MissingDependencyError?.Sum(EstimateCacheItemSizeInMemory) ?? 0;

static long EstimateCacheItemSizeInMemory(Composition.Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> item) =>
static long EstimateCacheItemSizeInMemory(Result<IReadOnlyList<LocatedCompilationError>, CompilationSuccess> item) =>
(item.Err?.Sum(err => EstimateCacheItemSizeInMemory(err)) ?? 0) +
(item.Ok != null ? EstimateCacheItemSizeInMemory(item.Ok) : 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public InteractiveSession(TreeWithStringPath appCodeTree)
this.appCodeTree = appCodeTree;
}

public Result<string, ElmInteractive.SubmissionResponseValueStructure> SubmitAndGetResultingValue(string submission)
public Pine.Result<string, ElmInteractive.SubmissionResponseValueStructure> SubmitAndGetResultingValue(string submission)
{
var result =
ElmInteractive.EvaluateSubmissionAndGetResultingValue(
Expand Down
33 changes: 4 additions & 29 deletions implement/elm-fullstack/Pine/Composition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ static public IReadOnlyList<byte> BlobValueFromSignedInteger(System.Numerics.Big
}

static public System.Numerics.BigInteger UnsignedIntegerFromBlobValue(Span<byte> blobValue) =>
new System.Numerics.BigInteger(blobValue.ToArray(), isUnsigned: true, isBigEndian: true);
new(blobValue.ToArray(), isUnsigned: true, isBigEndian: true);

public class TreeWithStringPath : IEquatable<TreeWithStringPath>
{
Expand All @@ -189,13 +189,13 @@ public TreeWithStringPath(IImmutableList<(string name, TreeWithStringPath compon
}

static public TreeWithStringPath Blob(byte[] blobContent) =>
new TreeWithStringPath(blobContent: blobContent);
new(blobContent: blobContent);

static public TreeWithStringPath Blob(IReadOnlyList<byte> blobContent) =>
new TreeWithStringPath(blobContent: blobContent as byte[] ?? blobContent.ToArray());
new(blobContent: blobContent as byte[] ?? blobContent.ToArray());

static public TreeWithStringPath Tree(IImmutableList<(string name, TreeWithStringPath component)> treeContent) =>
new TreeWithStringPath(treeContent: treeContent);
new(treeContent: treeContent);

static public TreeWithStringPath EmptyTree => Tree(ImmutableList<(string name, TreeWithStringPath component)>.Empty);

Expand Down Expand Up @@ -638,31 +638,6 @@ static public Component FindComponentByHash(Component component, byte[] hash)
return null;
}

public record Result<ErrT, OkT>(ErrT Err = default, OkT Ok = default)
{
static public Result<ErrT, OkT> err(ErrT err) =>
new() { Err = err };

static public Result<ErrT, OkT> ok(OkT ok) =>
new() { Ok = ok };

public Result<ErrT, MappedOkT> map<MappedOkT>(Func<OkT, MappedOkT> okMap)
{
if (Ok == null)
return Result<ErrT, MappedOkT>.err(Err);

return Result<ErrT, MappedOkT>.ok(okMap(Ok));
}

public Result<MappedErrT, OkT> mapError<MappedErrT>(Func<ErrT, MappedErrT> errMap)
{
if (Ok == null)
return Result<MappedErrT, OkT>.err(errMap(Err));

return Result<MappedErrT, OkT>.ok(Ok);
}
}

public record ParseAsTreeWithStringPathResult : Result<IImmutableList<(int index, string name)>, TreeWithStringPath>
{
}
Expand Down
26 changes: 13 additions & 13 deletions implement/elm-fullstack/Pine/LoadFromElmEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,25 +150,25 @@ static public ParseUrlResult ParseUrl(string url)
}
}

static public Composition.Result<string, LoadFromUrlSuccess> LoadFromUrl(string sourceUrl)
static public Result<string, LoadFromUrlSuccess> LoadFromUrl(string sourceUrl)
{
var parsedUrl = ParseUrl(sourceUrl);

if (parsedUrl == null)
return Composition.Result<string, LoadFromUrlSuccess>.err("Failed to parse string '" + sourceUrl + "' as Elm Editor URL.");
return Result<string, LoadFromUrlSuccess>.err("Failed to parse string '" + sourceUrl + "' as Elm Editor URL.");

if (LoadFromGitHubOrGitLab.ParsePathFromUrl(parsedUrl.projectStateString) != null)
{
var loadFromGitHost =
LoadFromGitHubOrGitLab.LoadFromUrl(parsedUrl.projectStateString);

if (loadFromGitHost?.Success == null)
if (loadFromGitHost?.Ok == null)
{
return Composition.Result<string, LoadFromUrlSuccess>.err(
"Failed to load from Git host: " + loadFromGitHost?.Error?.ToString());
return Result<string, LoadFromUrlSuccess>.err(
"Failed to load from Git host: " + loadFromGitHost?.Err?.ToString());
}

return Composition.Result<string, LoadFromUrlSuccess>.ok(new LoadFromUrlSuccess(tree: loadFromGitHost.Success.tree));
return loadFromGitHost.map(loadFromGitHostSuccess => new LoadFromUrlSuccess(tree: loadFromGitHostSuccess.tree));
}

// Support parsing tuples: https://github.com/arogozine/TupleAsJsonArray/tree/e59f8c4edee070b096220b6cab77eba997b19d3a
Expand All @@ -193,7 +193,7 @@ static public Composition.Result<string, LoadFromUrlSuccess> LoadFromUrl(string
throw new Exception("Project state has an unexpected shape: " + parsedUrl.projectStateString);
}

static public Composition.Result<string, LoadFromUrlSuccess> LoadProjectState(ProjectState_2021_01.ProjectState projectState)
static public Result<string, LoadFromUrlSuccess> LoadProjectState(ProjectState_2021_01.ProjectState projectState)
{
Composition.TreeWithStringPath baseComposition = null;

Expand All @@ -202,13 +202,13 @@ static public Composition.Result<string, LoadFromUrlSuccess> LoadProjectState(Pr
var loadFromGitHost =
LoadFromGitHubOrGitLab.LoadFromUrl(projectState.@base);

if (loadFromGitHost?.Success == null)
if (loadFromGitHost?.Ok == null)
{
return Composition.Result<string, LoadFromUrlSuccess>.err(
"Failed to load from Git host: " + loadFromGitHost?.Error?.ToString());
return Result<string, LoadFromUrlSuccess>.err(
"Failed to load from Git host: " + loadFromGitHost?.Err?.ToString());
}

baseComposition = loadFromGitHost.Success.tree;
baseComposition = loadFromGitHost.Ok.tree;
}

return
Expand All @@ -222,7 +222,7 @@ static public Composition.Result<string, LoadFromUrlSuccess> LoadProjectState(Pr
///
/// applyProjectStateDifference_2021_01 : ProjectState_2021_01.ProjectStateDifference -> FileTree.FileTreeNode Bytes.Bytes -> Result String (FileTree.FileTreeNode Bytes.Bytes)
/// </summary>
static public Composition.Result<string, Composition.TreeWithStringPath> ApplyProjectStateDifference_2021_01(
static public Result<string, Composition.TreeWithStringPath> ApplyProjectStateDifference_2021_01(
ProjectState_2021_01.ProjectStateDifference differenceFromBase,
Composition.TreeWithStringPath baseComposition)
{
Expand All @@ -245,7 +245,7 @@ static public Composition.Result<string, LoadFromUrlSuccess> LoadProjectState(Pr
return previousComposition.SetNodeAtPathSorted(blobChange.Item1, Composition.TreeWithStringPath.Blob(changedBlobValue));
});

return Composition.Result<string, Composition.TreeWithStringPath>.ok(projectStateAfterChangeBlobs);
return Result<string, Composition.TreeWithStringPath>.ok(projectStateAfterChangeBlobs);
}
}
}
Loading

0 comments on commit 21a7e34

Please sign in to comment.