Skip to content

Commit

Permalink
chore(Compiler): More fixes, and stuff. I did end up breaking some st…
Browse files Browse the repository at this point in the history
…uff though, its getting super close.
  • Loading branch information
DaRacci committed Jun 24, 2024
1 parent 5973b3e commit d530c7f
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 50 deletions.
43 changes: 26 additions & 17 deletions src/Compiler/Module/CompiledModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,27 @@ public string ContentHash
}
}

public static CompiledModule From(Module module, int indentBy = 0) => module switch
public static CompiledModule From(Module module, int indentBy = 0)
{
LocalFileModule localFileModule => new CompiledModule(
ContentType.UTF8String,
localFileModule.ModuleSpec,
localFileModule.Requirements,
CompiledDocument.FromBuilder(localFileModule.Document, indentBy + 4).GetContent(),
indentBy
),
RemoteModule remoteModule => new CompiledModule(
ContentType.ZipHex,
remoteModule.ModuleSpec,
remoteModule.Requirements,
Convert.ToHexString(remoteModule.BytesZip),
indentBy
),
_ => throw new NotImplementedException()
};
return module switch
{
LocalFileModule localFileModule => new CompiledModule(
ContentType.UTF8String,
localFileModule.ModuleSpec,
localFileModule.Requirements,
CompiledDocument.FromBuilder(localFileModule.Document, indentBy + 4).GetContent(),
indentBy
),
RemoteModule remoteModule => new CompiledModule(
ContentType.ZipHex,
remoteModule.ModuleSpec,
remoteModule.Requirements,
Convert.ToHexString(remoteModule.BytesZip),
indentBy
),
_ => throw new NotImplementedException()
};
}

public override string ToString()
{
Expand All @@ -63,6 +66,12 @@ public override string ToString()
sb.Append(contentIndentStr);
sb.AppendLine(requirement.GetInsertableLine());
});
Requirements.GetRequirements<ModuleSpec>().ToList().ForEach(requirement =>
{
sb.Append(contentIndentStr);
sb.AppendLine(requirement.GetInsertableLine());
});

sb.AppendLine(Content);

sb.AppendLine("'@");
Expand Down
47 changes: 36 additions & 11 deletions src/Compiler/Module/CompiledScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using QuikGraph;
using Compiler.Text;
using System.Text.RegularExpressions;
using QuikGraph.Algorithms;
using CommandLine;

namespace Compiler;

Expand All @@ -20,14 +22,14 @@ public partial class CompiledScript : LocalFileModule
private static partial Regex RunMainRegex();

public readonly AdjacencyGraph<ModuleSpec, Edge<ModuleSpec>> ModuleGraph = new();
public readonly Dictionary<string, CompiledModule> ResolvedModules = [];
public readonly List<CompiledModule> ResolvedModules = [];
public readonly ParamBlockAst? ScriptParamBlockAst;

public CompiledScript(
string path
) : this(
path,
new ModuleSpec(Path.GetFileNameWithoutExtension(path)),
new PathedModuleSpec(path, Path.GetFileNameWithoutExtension(path)),
new TextDocument(File.ReadAllLines(path))
)
{ }
Expand Down Expand Up @@ -79,7 +81,7 @@ public string Compile()
script.AppendLine("begin {");

script.AppendLine(" $Global:EmbeddedModules = @{");
ResolvedModules.ToList().ForEach(module => script.AppendLine(module.Value.ToString()));
ResolvedModules.ToList().ForEach(module => script.AppendLine(module.ToString()));
script.AppendLine("};");

script.AppendLine("""
Expand Down Expand Up @@ -179,22 +181,45 @@ private void ResolveRequirements()
{
var parentPath = Path.GetDirectoryName(local.FilePath);
Logger.Debug($"Trying to resolve {module.Name} from {parentPath}.");
resolved = TryFromFile(parentPath!, module.Name);
resolved = TryFromFile(parentPath!, module);
if (resolved != null)
{
Logger.Debug($"Resolved {module.Name} from {parentPath}.");
ModuleGraph.TryGetOutEdges(module, out var edges);
if (edges != null && edges.Any())
{
Logger.Debug($"Updating graph to use {resolved.Name} instead of {module.Name}.");
ModuleGraph.AddVertex(resolved.ModuleSpec);
edges.ToList().ForEach(edge =>
{
ModuleGraph.RemoveEdge(edge);
ModuleGraph.AddEdge(new Edge<ModuleSpec>(edge.Source, resolved.ModuleSpec));
});
ModuleGraph.RemoveVertex(module);
}
}
}
resolved ??= RemoteModule.FromModuleRequirement(module);
ModuleGraph.AddVertex(module);
ModuleGraph.AddEdge(new Edge<ModuleSpec>(current.ModuleSpec, module));
Logger.Debug($"Adding vertex {resolved.ModuleSpec.Name} to module graph.");
ModuleGraph.AddVertex(resolved.ModuleSpec);
ModuleGraph.AddEdge(new Edge<ModuleSpec>(current.ModuleSpec, resolved.ModuleSpec));
iterating.Enqueue(resolved);
});
}

localModules.FindAll(module => module != this).ForEach(module => ResolvedModules.Add(module.Name, CompiledModule.From(module, 8)));
downloadableModules.ForEach(module => ResolvedModules.Add(module.Name, CompiledModule.From(module, 8)));
var sortedModules = ModuleGraph.TopologicalSort() ?? throw new Exception("Cyclic dependency detected.");
sortedModules.ToList().ForEach(moduleSpec =>
{
var matchingModule = (localModules.Find(module => moduleSpec.CompareTo(module.ModuleSpec) == ModuleMatch.Same).Cast<Module.Module>() ?? downloadableModules.Find(module => moduleSpec.CompareTo(module.ModuleSpec) == ModuleMatch.Same)) ?? throw new Exception($"Could not find module {moduleSpec.Name} in local or downloadable modules.")!;
ResolvedModules.Add(CompiledModule.From(matchingModule, 8));
});

PSVersionRequirement? highestPSVersion = null;
foreach (var module in ResolvedModules.Values)
foreach (var module in ResolvedModules)
{
foreach (var version in module.Requirements.GetRequirements<PSVersionRequirement>())
{
Expand All @@ -211,7 +236,7 @@ private void ResolveRequirements()
}

PSEditionRequirement? foundPSEdition = null;
ResolvedModules.Values.SelectMany(module => module.Requirements.GetRequirements<PSEditionRequirement>())
ResolvedModules.SelectMany(module => module.Requirements.GetRequirements<PSEditionRequirement>())
.ToList()
.ForEach(edition =>
{
Expand All @@ -228,7 +253,7 @@ private void ResolveRequirements()
Requirements.AddRequirement(foundPSEdition);
}

ResolvedModules.Values.SelectMany(module => module.Requirements.GetRequirements<RunAsAdminRequirement>())
ResolvedModules.SelectMany(module => module.Requirements.GetRequirements<RunAsAdminRequirement>())
.ToList()
.ForEach(requirements =>
{
Expand Down
11 changes: 8 additions & 3 deletions src/Compiler/Module/Local.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public partial class LocalFileModule : Module

public LocalFileModule(string path) : this(
path,
new ModuleSpec(Path.GetFileNameWithoutExtension(path)),
new PathedModuleSpec(path, Path.GetFileNameWithoutExtension(path)),
new TextDocument(File.ReadAllLines(path))
)
{ }
Expand Down Expand Up @@ -194,9 +194,14 @@ public override ModuleMatch GetModuleMatchFor(ModuleSpec requirement)
return ModuleMatch.None;
}

public static LocalFileModule? TryFromFile(string relativeFrom, string path)
public static LocalFileModule? TryFromFile(string relativeFrom, ModuleSpec spec)
{
var fullPath = Path.GetFullPath(Path.Combine(relativeFrom, path));
var relativePath = spec switch {
PathedModuleSpec pathedSpec => pathedSpec.RelativePath,
_ => spec.Name
};

var fullPath = Path.GetFullPath(Path.Combine(relativeFrom, relativePath));
Logger.Debug($"Trying to load local file: {fullPath}");
if (!File.Exists(fullPath))
{
Expand Down
12 changes: 10 additions & 2 deletions src/Compiler/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Text;
using CommandLine;
using Compiler;
using Compiler.Requirements;
using NLog;
using QuikGraph;
using QuikGraph.Graphviz;

class Program
Expand Down Expand Up @@ -47,8 +49,14 @@ public static string CompileScript(string inputFile)
{
var compiledScript = new CompiledScript(Path.GetFullPath(inputFile));

var graphViz = compiledScript.ModuleGraph.ToGraphviz();
Console.WriteLine(graphViz);
var graphviz = compiledScript.ModuleGraph.ToGraphviz(alg =>
{
alg.FormatVertex += (sender, args) =>
{
args.VertexFormat.Label = args.Vertex.Name;
};
});
Console.WriteLine(graphviz);

return compiledScript.Compile();
}
Expand Down
29 changes: 22 additions & 7 deletions src/Compiler/Requirements/ModuleSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@

namespace Compiler.Requirements;

public record PathedModuleSpec(
string RelativePath,
string Name,
Guid? Guid = null,
Version? MinimumVersion = null,
Version? MaximumVersion = null,
Version? RequiredVersion = null
) : ModuleSpec(Name, Guid, MinimumVersion, MaximumVersion, RequiredVersion);

public record ModuleSpec(
string Name,
Guid? Guid = null,
Expand Down Expand Up @@ -55,15 +64,21 @@ public ModuleSpec MergeSpecs(ModuleSpec[] merge)

public override string GetInsertableLine()
{
var sb = new StringBuilder("#Requires -Modules @{");

sb.Append($"ModuleName = '{Name}';");
var sb = new StringBuilder("Using module @{");
sb.Append($"ModuleName = '{Path.GetFileNameWithoutExtension(Name)}';");
if (Guid != null) sb.Append($"GUID = {Guid};");
sb.Append($"ModuleVersion = '{(MinimumVersion != null ? MinimumVersion.ToString() : "0.0.0.0")}';");
if (MaximumVersion != null) sb.Append($"MaximumVersion = '{MaximumVersion}';");
if (RequiredVersion != null) sb.Append($"RequiredVersion = '{RequiredVersion}';");
sb.Append('}');

switch (RequiredVersion, MinimumVersion, MaximumVersion)
{
case (null, null, null): break;
case (var req, null, null): sb.Append($"RequiredVersion = '{req}';"); break;
case (null, var min, var max):
if (min != null) sb.Append($"ModuleVersion = '{min}';");
if (max != null) sb.Append($"MaximumVersion = '{max}';");
break;
}

sb.Append('}');
return sb.ToString();
}

Expand Down
50 changes: 44 additions & 6 deletions src/Compiler/Requirements/Requirements.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections;
using CommandLine;
using Compiler.Module;
using NLog;

namespace Compiler.Requirements;
Expand Down Expand Up @@ -36,11 +37,54 @@ public List<T> GetRequirements<T>()
return [];
}

public bool RemoveRequirement(Requirement value)
{
if (StoredRequirements.ContainsKey(value.GetType()))
{
return StoredRequirements[value.GetType()].Cast<List<Requirement>>().Remove(value);
}

return false;
}

public List<Requirement> GetRequirements()
{
return StoredRequirements.Values.Cast<List<Requirement>>().SelectMany(requirements => requirements).ToList();
}

// public void UpdateWithCompiledInplace(string rootPath, List<CompiledModule> compiledModules)
// {
// foreach (var requirement in GetRequirements<ModuleSpec>())
// {
// if (requirement is not ModuleSpec moduleSpec)
// {
// continue;
// }

// var matchingModules = compiledModules.Where(module => module.ModuleSpec.RawSpec.Name == Path.GetFileNameWithoutExtension(moduleSpec.Name));
// if (matchingModules == null || matchingModules.Count() == 0)
// {
// Logger.Warn($"Could not find matching module for {moduleSpec.Name}");
// continue;
// }
// else if (matchingModules.Count() > 1)
// {
// throw new Exception($"Found multiple matching modules for {moduleSpec.Name}, this is a limitation of the current implementation, ensure unique names.");
// }

// var matchingModule = matchingModules.First();

// // FIXME - This may be a bad way of doing this.
// var newSpec = new CompiledModuleSpec(
// $"{matchingModule.ModuleSpec.Name}-{matchingModule.ContentHash}.psm1",
// moduleSpec
// );

// RemoveRequirement(moduleSpec);
// AddRequirement(newSpec);
// }
// }

// FIXME - Not very efficient
public bool VerifyRequirements()
{
Expand Down Expand Up @@ -69,10 +113,4 @@ public abstract record Requirement(bool SupportsMultiple)
public abstract string GetInsertableLine();
}

public enum ModuleType
{
Downloadable,
Local
}

public enum PSEdition { Desktop, Core }
3 changes: 0 additions & 3 deletions src/Compiler/Text/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,11 @@ public static CompiledDocument FromBuilder(TextEditor builder, int indentBy = 0)

public class TextEditor(TextDocument document)
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

public TextDocument Document { get; } = document;
public List<TextSpanUpdater> TextUpdaters { get; } = [];

public void AddEdit(Func<TextSpanUpdater> updater)
{
Logger.Debug($"Adding {updater.GetType().Name} with spec {updater}");
TextUpdaters.Add(updater());
}

Expand Down
1 change: 0 additions & 1 deletion src/Compiler/Text/Updater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ HashSet<Range> skipRanges
var clonedLine = lines[i].Clone().Cast<string>()!;
if (offsetSkipRanges.Any(range => range.Contains(i)))
{
Logger.Debug($"Skipping line {i} due to skip range.");
continue;
}

Expand Down
5 changes: 5 additions & 0 deletions tests/Compiler/CompiledScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public static IEnumerable TestCases
{
yield return new TestCaseData(
new PatternUpdater(
50,
LocalFileModule.MultilineStringOpenRegex(),
LocalFileModule.MultilineStringCloseRegex(),
UpdateOptions.None,
Expand Down Expand Up @@ -173,6 +174,7 @@ It can have multiple lines!

yield return new TestCaseData(
new RegexUpdater(
50,
LocalFileModule.EntireLineCommentRegex(),
UpdateOptions.None,
_ => null
Expand All @@ -189,6 +191,7 @@ It can have multiple lines!

yield return new TestCaseData(
new RegexUpdater(
50,
LocalFileModule.EntireEmptyLineRegex(),
UpdateOptions.None,
_ => null
Expand All @@ -211,6 +214,7 @@ It can have multiple lines!

yield return new TestCaseData(
new PatternUpdater(
50,
LocalFileModule.DocumentationStartRegex(),
LocalFileModule.DocumentationEndRegex(),
UpdateOptions.None,
Expand All @@ -233,6 +237,7 @@ function foo {

yield return new TestCaseData(
new RegexUpdater(
50,
LocalFileModule.EndOfLineComment(),
UpdateOptions.None,
_ => null
Expand Down

0 comments on commit d530c7f

Please sign in to comment.