diff options
| author | godosa <godosa@godosa.eu> | 2026-10-06 23:39:36 +0200 |
|---|---|---|
| committer | godosa <godosa@godosa.eu> | 2026-10-06 23:39:36 +0200 |
| commit | 39066900773e7857faf2d02e7ed51b71d219d97d (patch) | |
| tree | ffab8e4ddd971626776c3b1f4ce1da2c186c2187 /src/Godosa.Core/Runs/Scripts/ScriptProgram.cs | |
| download | godosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.tar.gz godosa-engine-39066900773e7857faf2d02e7ed51b71d219d97d.zip | |
godosa-engine: initial public history
Diffstat (limited to 'src/Godosa.Core/Runs/Scripts/ScriptProgram.cs')
| -rw-r--r-- | src/Godosa.Core/Runs/Scripts/ScriptProgram.cs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/Godosa.Core/Runs/Scripts/ScriptProgram.cs b/src/Godosa.Core/Runs/Scripts/ScriptProgram.cs new file mode 100644 index 0000000..502e24c --- /dev/null +++ b/src/Godosa.Core/Runs/Scripts/ScriptProgram.cs @@ -0,0 +1,57 @@ +// Provenance: own design — shared run scripts +namespace Godosa.Core.Runs.Scripts; + +public enum Op { Verb, Wait, Expect, Set, Checkpoint, LabelBegin, LabelEnd, ScopeBegin, ScopeEnd, TryBegin, TryEnd, SetupBegin, SetupEnd } + +/// <summary>One flattened instruction. <see cref="Chain"/> = include / call sites, outermost first.</summary> +public sealed record Instr(Op Op, SourceRef At, string Text, IReadOnlyList<SourceRef> Chain, int Format) +{ + public string A { get; init; } = ""; + public string B { get; init; } = ""; + public int Timeout { get; init; } + public IReadOnlyList<KeyValuePair<string, string>> Bindings { get; init; } = []; + public bool LocalVars { get; init; } + public int Jump { get; init; } = -1; +} + +public sealed record ScriptProgram(string Entry, RunMode Mode, ulong? Seed, IReadOnlyDictionary<string, string> Vars, + IReadOnlySet<string> Locked, IReadOnlyList<Instr> Code, IReadOnlyList<ScriptError> Errors); + +public interface IScriptSource +{ + string? Read(string path); +} + +public sealed class MemoryScriptSource(IReadOnlyDictionary<string, string> files) : IScriptSource +{ + public string? Read(string path) => files.GetValueOrDefault(path); +} + +/// <summary>Files under <paramref name="root"/>; paths are '/'-separated and relative to it.</summary> +public sealed class FileScriptSource(string root) : IScriptSource +{ + public string? Read(string path) + { + var full = Path.GetFullPath(Path.Combine(root, path)); + return File.Exists(full) ? File.ReadAllText(full) : null; + } +} + +public static class ScriptPaths +{ + public static string Resolve(string fromFile, string relative) + { + var dir = fromFile.Contains('/') ? fromFile[..fromFile.LastIndexOf('/')] : ""; + var parts = new List<string>(dir.Length == 0 ? [] : dir.Split('/')); + foreach (var part in relative.Replace('\\', '/').Split('/')) + { + if (part is "" or ".") + continue; + if (part == ".." && parts.Count > 0) + parts.RemoveAt(parts.Count - 1); + else if (part != "..") + parts.Add(part); + } + return string.Join('/', parts); + } +} |
